auth->isSuperAdmin() && dcCore::app()->blog->settings->get(basename(__NAMESPACE__))->get('active') ) { dcCore::app()->auth->user_prefs->addWorkspace('interface'); self::$pid = basename(dirname(__DIR__)); self::$init = true; } return self::$init; } public static function process(): ?bool { if (!self::$init) { return false; } if (dcCore::app()->blog->settings->get(self::$pid)->get('packman')) { // create dcstore.xml file on the fly when plugin packman pack a module dcCore::app()->addBehavior('packmanBeforeCreatePackage', function (array $module): void { Core::writeXML($module['id'], $module, dcCore::app()->blog->settings->get(self::$pid)->get('file_pattern')); }); } dcCore::app()->addBehaviors([ // addd some js 'pluginsToolsHeadersV2' => [self::class, 'modulesToolsHeaders'], 'themesToolsHeadersV2' => [self::class, 'modulesToolsHeaders'], // admin plugins page tab 'pluginsToolsTabsV2' => function (): void { self::modulesToolsTabs(dcCore::app()->plugins->getModules(), explode(',', DC_DISTRIB_PLUGINS), dcCore::app()->adminurl->get('admin.plugins')); }, // admin themes page tab 'themesToolsTabsV2' => function (): void { self::modulesToolsTabs(dcCore::app()->themes->getModules(), explode(',', DC_DISTRIB_THEMES), dcCore::app()->adminurl->get('admin.blog.theme')); }, ]); return true; } public static function modulesToolsHeaders(bool $is_plugin): string { return dcPage::jsJson('ts_copied', ['alert' => __('Copied to clipboard')]) . dcPage::jsModuleLoad(self::$pid . '/js/admin.js') . ( !dcCore::app()->auth->user_prefs->interface->colorsyntax ? '' : dcPage::jsLoadCodeMirror(dcCore::app()->auth->user_prefs->interface->colorsyntax_theme) . dcPage::jsModuleLoad(self::$pid . '/js/cms.js') ); } protected static function modulesToolsTabs(array $modules, array $excludes, string $page_url): void { $page_url .= '#' . self::$pid; $user_ui_colorsyntax = dcCore::app()->auth->user_prefs->interface->colorsyntax; $user_ui_colorsyntax_theme = dcCore::app()->auth->user_prefs->interface->colorsyntax_theme; $combo = self::comboModules($modules, $excludes); $file_pattern = dcCore::app()->blog->settings->get(self::$pid)->get('file_pattern'); # check dcstore repo $url = ''; if (!empty($_POST['checkxml_id']) && in_array($_POST['checkxml_id'], $combo)) { if (empty($modules[$_POST['checkxml_id']]['repository'])) { $url = __('This module has no repository set in its _define.php file.'); } else { try { $url = $modules[$_POST['checkxml_id']]['repository']; if (false === strpos($url, 'dcstore.xml')) { $url .= '/dcstore.xml'; } if (function_exists('curl_init')) { $ch = curl_init(); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_HEADER, false); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_REFERER, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $file_content = curl_exec($ch); curl_close($ch); } else { $file_content = file_get_contents($url); } } catch (Exception $e) { $file_content = __('Failed to read third party repository'); } } } # generate xml code if (!empty($_POST['buildxml_id']) && in_array($_POST['buildxml_id'], $combo)) { $xml_content = Core::generateXML($_POST['buildxml_id'], $modules[$_POST['buildxml_id']], $file_pattern); } # write dcstore.xml file if (!empty($_POST['write_xml'])) { if (empty($_POST['your_pwd']) || !dcCore::app()->auth->checkPassword($_POST['your_pwd'])) { dcCore::app()->error->add(__('Password verification failed')); } else { $ret = Core::writeXML($_POST['buildxml_id'], $modules[$_POST['buildxml_id']], $file_pattern); if (!empty(Core::$failed)) { dcCore::app()->error->add(implode(' ', Core::$failed)); } } } echo '
' . '

' . __('Tweak third-party repositories') . '

'; if (!empty($_POST['write_xml'])) { if (dcCore::app()->error->flag()) { echo dcCore::app()->error->toHTML(); } else { echo '

' . __('File successfully written') . '

'; } } if (count($combo) < 2) { echo '
' . __('There is no module to tweak') . '
' . '
'; return; } echo '
' . '

' . __('Check repository') . '

' . '

' . __('This checks if dcstore.xml file is present on third party repository.') . '

' . '

' . form::combo('checkxml_id', $combo, empty($_POST['checkxml_id']) ? '-' : html::escapeHTML($_POST['checkxml_id'])) . '

' . '

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

' . '
'; if (!empty($url)) { echo '
' . '

' . __('Repositiory contents') . '

' . '

' . $url . '

' . ( empty($file_content) ? '' : '
' . form::textArea('file_xml', 165, 14, [
                    'default'    => html::escapeHTML(Core::prettyXML($file_content)),
                    'class'      => 'maximal',
                    'extra_html' => 'readonly="true"',
                ]) . '
' . ( !$user_ui_colorsyntax ? '' : dcPage::jsRunCodeMirror('editor', 'file_xml', 'dotclear', $user_ui_colorsyntax_theme) ) ) . '
'; } if (empty($file_pattern)) { echo sprintf( '

' . __('Generate xml code') . '

%s

', dcCore::app()->adminurl->get('admin.plugins', ['module' => self::$pid, 'conf' => 1, 'redir' => $page_url]), __('You must configure zip file pattern to complete xml code automatically.') ); } else { echo '
' . '

' . __('Generate xml code') . '

' . '

' . __('This helps to generate content of dcstore.xml for seleted module.') . '

' . '

' . form::combo('buildxml_id', $combo, empty($_POST['buildxml_id']) ? '-' : html::escapeHTML($_POST['buildxml_id'])) . '

' . '

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

' . '
'; } if (!empty($_POST['buildxml_id'])) { echo '
' . '

' . sprintf(__('Generated code for module: %s'), html::escapeHTML($_POST['buildxml_id'])) . '

'; if (!empty(Core::$failed)) { echo '

' . sprintf(__('Failed to parse XML code: %s'), implode(', ', Core::$failed)) . '

'; } if (!empty(Core::$notice)) { echo '

' . sprintf(__('Code is not fully filled: %s'), implode(', ', Core::$notice)) . '

'; } if (!empty($xml_content)) { if (empty(Core::$failed) && empty(Core::$notice)) { echo '

' . __('Code is complete') . '

'; } echo '
' . form::textArea('gen_xml', 165, 14, [
                    'default'    => html::escapeHTML(Core::prettyXML($xml_content)),
                    'class'      => 'maximal',
                    'extra_html' => 'readonly="true"',
                ]) . '
' . ( !$user_ui_colorsyntax ? '' : dcPage::jsRunCodeMirror('editor', 'gen_xml', 'dotclear', $user_ui_colorsyntax_theme) ); if (empty(Core::$failed) && $modules[$_POST['buildxml_id']]['root_writable'] && dcCore::app()->auth->isSuperAdmin() ) { echo '

' . form::password( ['your_pwd', 'your_pwd2'], 20, 255, [ 'extra_html' => 'required placeholder="' . __('Password') . '"', 'autocomplete' => 'current-password', ] ) . '

' . '

' . '' . __('Copy to clipboard') . '' . form::hidden('buildxml_id', $_POST['buildxml_id']) . dcCore::app()->formNonce() . '

'; } echo sprintf( '

%s

', dcCore::app()->adminurl->get('admin.plugins', ['module' => self::$pid, 'conf' => 1, 'redir' => $page_url]), __('You can edit zip file pattern from configuration page.') ); } echo '
'; } echo ''; } # create list of module for combo and remove official modules protected static function comboModules(array $modules, array $excludes): array { $combo = [__('Select a module') => '0']; foreach ($modules as $id => $module) { if (in_array($id, $excludes)) { continue; } $combo[$module['name'] . ' ' . $module['version']] = $id; } return $combo; } }