diff --git a/inc/models.php b/inc/models.php deleted file mode 100644 index 5802be4..0000000 --- a/inc/models.php +++ /dev/null @@ -1,48 +0,0 @@ -__('Model name'), // Nom du modèle prédéfini, éventuellement - // traduit dans un fichier de langue - 's_html'=>'[HTML code]', // Code HTML du sélecteur de thème - 'e_html'=>'[HTML code]', // Code HTML d'un item pouvant être sélectionné - 'a_html'=>'[HTML code]' // Code HTML d'un item actif (thème sélectionné) -); - -//*/ - -$mt_models[] = [ - 'name' => __('Bullets list'), - 's_html' => '', - 'e_html' => '
  • %4$s
  • ', - 'a_html' => '
  • %4$s
  • ', -]; - -$mt_models[] = [ - 'name' => __('Scrolled list'), - 's_html' => '
    ' . "\n" . - '

    ' . "\n" . - '

    ' . "\n" . - '
    ', - 'e_html' => '', - 'a_html' => '', -]; diff --git a/src/Backend.php b/src/Backend.php index ea6f4e7..e397059 100644 --- a/src/Backend.php +++ b/src/Backend.php @@ -7,38 +7,66 @@ * * @author Oleksandr Syenchuk, Pierre Van Glabeke and contributors * - * @copyright Jean-Crhistian Denis + * @copyright Jean-Christian Denis * @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html */ -if (!defined('DC_CONTEXT_ADMIN')) { - return; +declare(strict_types=1); + +namespace Dotclear\Plugin\arlequin; + +use dcAdmin; +use dcCore; +use dcFavorites; +use dcNsProcess; +use dcPage; + +class Backend extends dcNsProcess +{ + public static function init(): bool + { + static::$init = defined('DC_CONTEXT_ADMIN') + && My::phpCompliant() + && dcCore::app()->auth->check(dcCore::app()->auth->makePermissions([ + dcCore::app()->auth::PERMISSION_CONTENT_ADMIN, + ]), dcCore::app()->blog->id); + + return static::$init; + } + + public static function process(): bool + { + if (!static::$init) { + return false; + } + + dcCore::app()->menu[dcAdmin::MENU_BLOG]->addItem( + My::name(), + dcCore::app()->adminurl->get('admin.plugin.' . My::id()), + dcPage::getPF(My::id() . '/icon.png'), + preg_match( + '/' . preg_quote(dcCore::app()->adminurl->get('admin.plugin.' . My::id())) . '(&.*)?$/', + $_SERVER['REQUEST_URI'] + ), + dcCore::app()->auth->check(dcCore::app()->auth->makePermissions([ + dcCore::app()->auth::PERMISSION_CONTENT_ADMIN, + ]), dcCore::app()->blog->id) + ); + + dcCore::app()->addBehaviors([ + 'adminDashboardFavoritesV2' => function (dcFavorites $favs): void { + $favs->register(My::id(), [ + 'title' => My::name(), + 'url' => dcCore::app()->adminurl->get('admin.plugin.' . My::id()), + 'small-icon' => dcPage::getPF(My::id() . '/icon.png'), + 'large-icon' => dcPage::getPF(My::id() . '/icon-big.png'), + 'permissions' => dcCore::app()->auth->makePermissions([ + dcCore::app()->auth::PERMISSION_CONTENT_ADMIN, + ]), + ]); + }, + 'initWidgets' => [Widgets::class, 'initWidgets'], + ]); + + return true; + } } - -require __DIR__ . '/_widgets.php'; - -// Admin sidebar menu -dcCore::app()->menu[dcAdmin::MENU_BLOG]->addItem( - __('Arlequin'), - dcCore::app()->adminurl->get('admin.plugin.' . basename(__DIR__)), - dcPage::getPF(basename(__DIR__) . '/icon.png'), - preg_match( - '/' . preg_quote(dcCore::app()->adminurl->get('admin.plugin.' . basename(__DIR__))) . '(&.*)?$/', - $_SERVER['REQUEST_URI'] - ), - dcCore::app()->auth->check(dcCore::app()->auth->makePermissions([ - dcAuth::PERMISSION_CONTENT_ADMIN, - ]), dcCore::app()->blog->id) -); - -// Admin dashbaord favorite -dcCore::app()->addBehavior('adminDashboardFavoritesV2', function ($favs) { - $favs->register(basename(__DIR__), [ - 'title' => __('Arlequin'), - 'url' => dcCore::app()->adminurl->get('admin.plugin.' . basename(__DIR__)), - 'small-icon' => dcPage::getPF(basename(__DIR__) . '/icon.png'), - 'large-icon' => dcPage::getPF(basename(__DIR__) . '/icon-big.png'), - 'permissions' => dcCore::app()->auth->makePermissions([ - dcAuth::PERMISSION_CONTENT_ADMIN, - ]), - ]); -}); diff --git a/src/Frontend.php b/src/Frontend.php index 482cfe2..bfe9253 100644 --- a/src/Frontend.php +++ b/src/Frontend.php @@ -7,168 +7,81 @@ * * @author Oleksandr Syenchuk, Pierre Van Glabeke and contributors * - * @copyright Jean-Crhistian Denis + * @copyright Jean-Christian Denis * @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html */ -if (!defined('DC_RC_PATH')) { - return; -} +declare(strict_types=1); -require __DIR__ . '/_widgets.php'; +namespace Dotclear\Plugin\arlequin; -publicArlequinEngine::init(); -dcCore::app()->addBehavior('publicBeforeDocumentV2', ['publicArlequinEngine','adjustCache']); -dcCore::app()->tpl->addValue('themesList', ['publicArlequinInterface','template']); +use dcCore; +use dcNsProcess; +use Dotclear\Helper\Network\Http; -class publicArlequinEngine +class Frontend extends dcNsProcess { - public static $cookie_theme; - public static $cookie_upddt; + public const COOKIE_THEME_PREFIX = 'dc_theme_'; + public const COOKIE_UPDDT_PREFIX = 'dc_user_upddt_'; - public static function init() + public static function init(): bool { - $cname = base_convert(dcCore::app()->blog->uid, 16, 36); - self::$cookie_theme = 'dc_theme_' . $cname; - self::$cookie_upddt = 'dc_user_upddt_' . $cname; + static::$init = true; + + return static::$init; + } + + public static function process(): bool + { + if (!static::$init) { + return false; + } if (!empty($_REQUEST['theme'])) { # Set cookie for 365 days - setcookie(self::$cookie_theme, $_REQUEST['theme'], time() + 31536000, '/'); - setcookie(self::$cookie_upddt, (string) time(), time() + 31536000, '/'); + setcookie(self::COOKIE_THEME_PREFIX . self::cookieSuffix(), $_REQUEST['theme'], time() + 31536000, '/'); + setcookie(self::COOKIE_UPDDT_PREFIX . self::cookieSuffix(), (string) time(), time() + 31536000, '/'); # Redirect if needed if (isset($_GET['theme'])) { $p = '/(\?|&)theme(=.*)?$/'; - http::redirect(preg_replace($p, '', http::getSelfURI())); + Http::redirect(preg_replace($p, '', Http::getSelfURI())); } # Switch theme self::switchTheme($_REQUEST['theme']); - } elseif (!empty($_COOKIE[self::$cookie_theme])) { - self::switchTheme($_COOKIE[self::$cookie_theme]); + } elseif (!empty($_COOKIE[self::COOKIE_THEME_PREFIX . self::cookieSuffix()])) { + self::switchTheme($_COOKIE[self::COOKIE_THEME_PREFIX . self::cookieSuffix()]); + } + + dcCore::app()->addBehaviors([ + 'publicBeforeDocumentV2' => [self::class, 'adjustCache'], + 'initWidgets' => [Widgets::class, 'initWidgets'], + ]); + + return true; + } + + protected static function cookieSuffix(): string + { + return base_convert(dcCore::app()->blog->uid, 16, 36); + } + + public static function adjustCache(): void + { + if (!empty($_COOKIE[self::COOKIE_UPDDT_PREFIX . self::cookieSuffix()])) { + dcCore::app()->cache['mod_ts'][] = (int) $_COOKIE[self::COOKIE_UPDDT_PREFIX . self::cookieSuffix()]; } } - public static function adjustCache() + public static function switchTheme(string $theme): void { - if (!empty($_COOKIE[self::$cookie_upddt])) { - dcCore::app()->cache['mod_ts'][] = (int) $_COOKIE[self::$cookie_upddt]; - } - } - - public static function switchTheme($theme) - { - if (dcCore::app()->blog->settings->arlequinMulti->mt_exclude) { - if (in_array($theme, explode('/', dcCore::app()->blog->settings->arlequinMulti->mt_exclude))) { + if (dcCore::app()->blog->settings->get(My::id())->get('mt_exclude')) { + if (in_array($theme, explode('/', dcCore::app()->blog->settings->get(My::id())->get('mt_exclude')))) { return; } } - dcCore::app()->public->theme = dcCore::app()->blog->settings->system->theme = $theme; - } -} - -class publicArlequinInterface -{ - public static function arlequinWidget($w) - { - return self::getHTML($w); - } - - public static function template($attr) - { - return ''; - } - - public static function getHTML($w = false) - { - if ($w->offline) { - return; - } - - if (!$w->checkHomeOnly(dcCore::app()->url->type)) { - return; - } - - $cfg = @unserialize(dcCore::app()->blog->settings->arlequinMulti->get('mt_cfg')); - if ($cfg === false || ($names = self::getNames()) === false) { - return; - } - - # Current page URL and the associated query string. Note : the URL for - # the switcher ($s_url) is different to the URL for an item ($e_url) - $s_url = $e_url = http::getSelfURI(); - - # If theme setting is already present in URL, we will replace its value - $replace = preg_match('/(\\?|&)theme\\=[^&]*/', $e_url); - - # URI extension to send theme setting by query string - if ($replace) { - $ext = ''; - } elseif (strpos($e_url, '?') === false) { - $ext = '?theme='; - } else { - $ext = (substr($e_url, -1) == '?' ? '' : '&') . 'theme='; - } - - $res = ''; - foreach ($names as $k => $v) { - if ($k == dcCore::app()->public->theme) { - $format = $cfg['a_html']; - } else { - $format = $cfg['e_html']; - } - - if ($replace) { - $e_url = preg_replace( - '/(\\?|&)(theme\\=)([^&]*)/', - '$1${2}' . addcslashes($k, '$\\'), - $e_url - ); - $val = ''; - } else { - $val = html::escapeHTML(rawurlencode($k)); - } - $res .= sprintf( - $format, - $e_url, - $ext, - $val, - html::escapeHTML($v['name']), - html::escapeHTML($v['desc']), - html::escapeHTML($k) - ); - } - - # Nothing to display - if (!trim($res)) { - return; - } - - $res = sprintf($cfg['s_html'], $s_url, $res); - - if ($w) { - return $w->renderDiv( - $w->content_only, - 'arlequin ' . $w->class, - '', - ($w->title ? $w->renderTitle(html::escapeHTML($w->title)) : '') . $res - ); - } - - return $res; - } - - public static function getNames() - { - $mt_exclude = dcCore::app()->blog->settings->arlequinMulti->mt_exclude; - $exclude = []; - if (!empty($mt_exclude)) { - $exclude = array_flip(explode('/', dcCore::app()->blog->settings->arlequinMulti->mt_exclude)); - } - - $names = array_diff_key(dcCore::app()->themes->getModules(), $exclude); - - return empty($names) ? false : $names; + dcCore::app()->blog->settings->get('system')->set('theme', $theme); + dcCore::app()->public->theme = $theme; } } diff --git a/src/Manage.php b/src/Manage.php index 66d99c2..7eb35f3 100644 --- a/src/Manage.php +++ b/src/Manage.php @@ -7,109 +7,183 @@ * * @author Oleksandr Syenchuk, Pierre Van Glabeke and contributors * - * @copyright Jean-Crhistian Denis + * @copyright Jean-Christian Denis * @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html */ -if (!defined('DC_CONTEXT_ADMIN')) { - return; +declare(strict_types=1); + +namespace Dotclear\Plugin\arlequin; + +use ArrayObject; +use dcCore; +use dcNsProcess; +use dcPage; +use Dotclear\Helper\Html\Form\{ + Div, + Form, + Input, + Label, + Note, + Para, + Submit, + Text, + Textarea +}; +use Dotclear\Helper\Html\Html; +use Exception; + +class Manage extends dcNsProcess +{ + public static function init(): bool + { + static::$init = defined('DC_CONTEXT_ADMIN') + && My::phpCompliant() + && dcCore::app()->auth->check(dcCore::app()->auth->makePermissions([ + dcCore::app()->auth::PERMISSION_CONTENT_ADMIN, + ]), dcCore::app()->blog->id); + + return static::$init; + } + + public static function process(): bool + { + if (!static::$init) { + return false; + } + + try { + $s = dcCore::app()->blog->settings->get(My::id()); + + $model = json_decode((string) $s->get('model'), true); + $exclude = $s->get('exclude'); + + // initialize settings + $initialized = false; + if ($model === false || $exclude === null || !(isset($model['e_html']) && isset($model['a_html']) && isset($model['s_html']))) { + $model = My::defaultModel(); + $s->put('model', json_encode($model), 'string', 'Arlequin configuration'); + $s->put('exclude', 'customCSS', 'string', 'Excluded themes'); + + dcPage::AddSuccessNotice(__('Settings have been reinitialized.')); + dcCore::app()->blog->triggerBlog(); + } + + // collect settings + if (isset($_POST['mt_action_config'])) { + $model['e_html'] = $_POST['e_html']; + $model['a_html'] = $_POST['a_html']; + $model['s_html'] = $_POST['s_html']; + $exclude = $_POST['exclude']; + } + + // save settings + if (isset($_POST['mt_action_config'])) { + $s->put('model', json_encode($model)); + $s->put('exclude', $exclude); + + dcPage::AddSuccessNotice(__('System settings have been updated.')); + dcCore::app()->blog->triggerBlog(); + dcCore::app()->adminurl->redirect('admin.plugin.' . My::id(), ['config' => 1]); + } + + // restore settings + if (isset($_POST['mt_action_restore'])) { + $s->drop('model'); + $s->drop('exclude'); + + dcPage::AddSuccessNotice(__('Settings have been reinitialized.')); + dcCore::app()->blog->triggerBlog(); + dcCore::app()->adminurl->redirect('admin.plugin.' . My::id(), ['restore' => 1]); + } + } catch (Exception $e) { + dcCore::app()->error->add($e->getMessage()); + } + + return true; + } + + public static function render(): void + { + if (!static::$init) { + return; + } + + $models = new ArrayObject(My::distributedModels()); + + dcCore::app()->callBehavior('arlequinAddModels', $models); + + $models = iterator_to_array($models); + $s = dcCore::app()->blog->settings->get(My::id()); + $model = json_decode((string) $s->get('model'), true); + $header = ''; + + foreach ($models as $m) { + $header .= "\t" . + 'arlequin.addModel(' . + '"' . Html::escapeJS($m['name']) . '",' . + '"' . addcslashes($m['s_html'], "\n\"\'") . '",' . + '"' . addcslashes($m['e_html'], "\n\"\'") . '",' . + '"' . addcslashes($m['a_html'], "\n\"\'") . '"' . + ");\n"; + } + + dcPage::openModule( + My::name(), + dcPage::jsModuleLoad(My::id() . '/js/models.js') . ' + ' + ); + + echo + dcPage::breadcrumb([ + Html::escapeHTML(dcCore::app()->blog->name) => '', + My::name() => '', + ]) . + dcPage::notices() . + + (new Form(My::id() . 'form'))->method('post')->action(dcCore::app()->adminurl->get('admin.plugin.' . My::id()))->fields([ + (new Text('h4', __('Switcher display format'))), + (new Div())->id('models'), + (new Div())->class('two-boxes odd')->items([ + (new Para())->items([ + (new Label(__('Switcher HTML code:'), Label::OUTSIDE_LABEL_BEFORE))->for('s_html'), + (new Textarea('s_html', Html::escapeHTML($model['s_html'])))->cols(50)->rows(10), + ]), + ]), + (new Div())->class('two-boxes even')->items([ + (new Para())->items([ + (new Label(__('Item HTML code:'), Label::OUTSIDE_LABEL_BEFORE))->for('e_html'), + (new Input('e_html'))->size(50)->maxlenght(200)->value(Html::escapeHTML($model['e_html'])), + ]), + (new Para())->items([ + (new Label(__('Active item HTML code:'), Label::OUTSIDE_LABEL_BEFORE))->for('a_html'), + (new Input('a_html'))->size(50)->maxlenght(200)->value(Html::escapeHTML($model['a_html'])), + ]), + ]), + (new Div())->class('two-boxes odd')->items([ + (new Para())->items([ + (new Label(__('Excluded themes:'), Label::OUTSIDE_LABEL_BEFORE))->for('exclude'), + (new Input('exclude'))->size(50)->maxlenght(200)->value(Html::escapeHTML($s->exclude)), + ]), + (new Note())->class('form-note')->text('Semicolon separated list of themes IDs (theme folder name). Ex: ductile;berlin'), + ]), + (new Para())->separator(' ')->items([ + dcCore::app()->formNonce(false), + (new Submit(['mt_action_config']))->value(__('Save')), + (new Submit(['mt_action_restore']))->value(__('Restore defaults')), + ]), + ])->render(); + + dcPage::helpBlock('arlequin'); + dcPage::closeModule(); + } } - -$mt_models = []; - -try { - include __DIR__ . '/inc/models.php'; - - // Initialisation - dcCore::app()->blog->settings->addNamespace('arlequinMulti'); - [$mt_cfg, $mt_exclude] = adminArlequin::loadSettings(dcCore::app()->blog->settings); - if (adminArlequin::$initialized) { - dcAdminNotices::AddSuccessNotice(__('Settings have been reinitialized.')); - } - - // Enregistrement des données depuis les formulaires - if (isset($_POST['mt_action_config'])) { - $mt_cfg['e_html'] = $_POST['e_html']; - $mt_cfg['a_html'] = $_POST['a_html']; - $mt_cfg['s_html'] = $_POST['s_html']; - $mt_exclude = $_POST['mt_exclude']; - } - - // Traitement des requêtes - if (isset($_POST['mt_action_config'])) { - dcCore::app()->blog->settings->arlequinMulti->put('mt_cfg', serialize($mt_cfg)); - dcCore::app()->blog->settings->arlequinMulti->put('mt_exclude', $mt_exclude); - dcAdminNotices::AddSuccessNotice(__('System settings have been updated.')); - dcCore::app()->blog->triggerBlog(); - dcCore::app()->adminurl->redirect('admin.plugin.' . basename(__DIR__), ['config' => 1]); - } - if (isset($_POST['mt_action_restore'])) { - dcCore::app()->blog->settings->arlequinMulti->drop('mt_cfg'); - dcCore::app()->blog->settings->arlequinMulti->drop('mt_exclude'); - dcAdminNotices::AddSuccessNotice(__('Settings have been reinitialized.')); - dcCore::app()->blog->triggerBlog(); - dcCore::app()->adminurl->redirect('admin.plugin.' . basename(__DIR__), ['restore' => 1]); - } -} catch (Exception $e) { - dcCore::app()->error->add($e->getMessage()); -} - -// Headers -$jsModels = ''; -$cslashes = "\n\"\'"; -foreach ($mt_models as $m) { // @phpstan-ignore-line - $jsModels .= "\t" . - 'arlequin.addModel(' . - '"' . html::escapeJS($m['name']) . '",' . - '"' . addcslashes($m['s_html'], $cslashes) . '",' . - '"' . addcslashes($m['e_html'], $cslashes) . '",' . - '"' . addcslashes($m['a_html'], $cslashes) . '"' . - ");\n"; -} - -// DISPLAY -echo ' -' . __('Arlequin') . '' . -dcPage::jsLoad(dcPage::getPF(basename(__DIR__) . '/js/models.js')) . ' - -' . -dcPage::breadcrumb([ - html::escapeHTML(dcCore::app()->blog->name) => '', - '' . __('Arlequin') . '' => '', -]) . -dcPage::notices() . ' - -
    -

    ' . __('Switcher display format') . '

    -
    - -
    -

    ' . - form::textArea('s_html', 50, 10, html::escapeHTML($mt_cfg['s_html'])) . '

    -
    -

    ' . - form::field('e_html', 50, 200, html::escapeHTML($mt_cfg['e_html'])) . '

    -

    ' . - form::field('a_html', 50, 200, html::escapeHTML($mt_cfg['a_html'])) . '

    -
    -

    ' . - form::field('mt_exclude', 50, 200, html::escapeHTML($mt_exclude)) . '

    -

    ' . __('The names to be taken into account are those of the theme files.') . '

    -
    -

    - - ' . - dcCore::app()->formNonce() . '

    -
    '; - -dcPage::helpBlock('arlequin'); ?> - diff --git a/src/My.php b/src/My.php new file mode 100644 index 0000000..284bbe8 --- /dev/null +++ b/src/My.php @@ -0,0 +1,93 @@ +plugins->moduleInfo(self::id(), 'name')); + } + + /** + * Check php version. + */ + public static function phpCompliant(): bool + { + return version_compare(phpversion(), self::PHP_MIN, '>='); + } + + /** + * Get distributed models. + * + * Use Behavior arlequinAddModels to add models with synthax: + * [ + * 'name'=>__('Model name'), // Nom du modèle prédéfini + * 's_html'=>'[HTML code]', // Code HTML du sélecteur de thème + * 'e_html'=>'[HTML code]', // Code HTML d'un item pouvant être sélectionné + * 'a_html'=>'[HTML code]' // Code HTML d'un item actif (thème sélectionné) + * ] + */ + public static function distributedModels(): array + { + return [ + [ + 'name' => __('Bullets list'), + 's_html' => '', + 'e_html' => '
  • %4$s
  • ', + 'a_html' => '
  • %4$s
  • ', + ], + [ + 'name' => __('Scrolled list'), + 's_html' => '
    ' . "\n" . + '

    ' . "\n" . + '

    ' . "\n" . + '
    ', + 'e_html' => '', + 'a_html' => '', + ], + ]; + } + + public static function defaultModel(): array + { + return [ + 'e_html' => '
  • %4$s
  • ', + 'a_html' => '
  • %4$s
  • ', + 's_html' => '', + ]; + } +} diff --git a/src/Widgets.php b/src/Widgets.php index 45931d7..65bd3fc 100644 --- a/src/Widgets.php +++ b/src/Widgets.php @@ -7,25 +7,28 @@ * * @author Oleksandr Syenchuk, Pierre Van Glabeke and contributors * - * @copyright Jean-Crhistian Denis + * @copyright Jean-Christian Denis * @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html */ -if (!defined('DC_RC_PATH')) { - return; -} +declare(strict_types=1); -dcCore::app()->addBehavior('initWidgets', ['adminArlequin','initWidgets']); +namespace Dotclear\Plugin\arlequin; -class adminArlequin +use dcCore; +use dcModuleDefine; +use Dotclear\Helper\Html\Html; +use Dotclear\Helper\Network\Http; +use Dotclear\Plugin\widgets\WidgetsStack; +use Dotclear\Plugin\widgets\WidgetsElement; + +class Widgets { - public static $initialized = false; - - public static function initWidgets($w) + public static function initWidgets(WidgetsStack $w): void { $w->create( 'arlequin', - __('Arlequin'), - ['publicArlequinInterface','arlequinWidget'], + My::name(), + [self::class,'parseWidget'], null, __('Theme switcher') ) @@ -36,31 +39,80 @@ class adminArlequin ->addOffline(); } - public static function getDefaults() + public static function parseWidget(WidgetsElement $w): string { - return [ - 'e_html' => '
  • %4$s
  • ', - 'a_html' => '
  • %4$s
  • ', - 's_html' => '', - ]; - } - - public static function loadSettings($settings) - { - self::$initialized = false; - $mt_cfg = @unserialize($settings->arlequinMulti->get('mt_cfg')); - $mt_exclude = $settings->arlequinMulti->get('mt_exclude'); - - // Paramètres corrompus ou inexistants - if ($mt_cfg === false || $mt_exclude === null || !(isset($mt_cfg['e_html']) && isset($mt_cfg['a_html']) && isset($mt_cfg['s_html']))) { - $mt_cfg = adminArlequin::getDefaults(); - $settings->addNamespace('arlequinMulti'); - $settings->arlequinMulti->put('mt_cfg', serialize($mt_cfg), 'string', 'Arlequin configuration'); - $settings->arlequinMulti->put('mt_exclude', 'customCSS', 'string', 'Excluded themes'); - self::$initialized = true; - dcCore::app()->blog->triggerBlog(); + if ($w->offline || !$w->checkHomeOnly(dcCore::app()->url->type)) { + return ''; } - return [$mt_cfg,$mt_exclude]; + $model = json_decode((string) dcCore::app()->blog->settings->get(My::id())->get('model'), true); + $names = self::getNames(); + if (!is_array($model) || empty($names)) { + return ''; + } + + # Current page URL and the associated query string. Note : the URL for + # the switcher ($s_url) is different to the URL for an item ($e_url) + $s_url = $e_url = Http::getSelfURI(); + + # If theme setting is already present in URL, we will replace its value + $replace = preg_match('/(\\?|&)theme\\=[^&]*/', $e_url); + + # URI extension to send theme setting by query string + if ($replace) { + $ext = ''; + } elseif (strpos($e_url, '?') === false) { + $ext = '?theme='; + } else { + $ext = (substr($e_url, -1) == '?' ? '' : '&') . 'theme='; + } + + $res = ''; + foreach ($names as $k => $v) { + if ($k == dcCore::app()->public->theme) { + $format = $model['a_html']; + } else { + $format = $model['e_html']; + } + + if ($replace) { + $e_url = preg_replace( + '/(\\?|&)(theme\\=)([^&]*)/', + '$1${2}' . addcslashes($k, '$\\'), + $e_url + ); + $val = ''; + } else { + $val = Html::escapeHTML(rawurlencode($k)); + } + $res .= sprintf( + $format, + $e_url, + $ext, + $val, + Html::escapeHTML($v['name']), + Html::escapeHTML($v['desc']), + Html::escapeHTML($k) + ); + } + + # Nothing to display + if (!trim($res)) { + return ''; + } + + return $w->renderDiv( + (bool) $w->content_only, + 'arlequin ' . $w->class, + '', + ($w->title ? $w->renderTitle(Html::escapeHTML($w->title)) : '') . sprintf($model['s_html'], $s_url, $res) + ); + } + + public static function getNames(): array + { + $exclude = explode(';', (string) dcCore::app()->blog->settings->get(My::id())->get('exclude')); + + return array_diff_key(dcCore::app()->themes->getDefines(['state' => dcModuleDefine::STATE_ENABLED], true), array_flip($exclude)); } }