auth->isSuperAdmin()) { return null; } # only if activated $core->blog->settings->addNamespace('tweakStores'); if (!$core->blog->settings->tweakStores->active) { return null; } # admin behaviors if ($core->blog->settings->tweakStores->packman) { $core->addBehavior('packmanBeforeCreatePackage', ['tweakStoresBehaviors', 'packmanBeforeCreatePackage']); } $core->addBehavior('pluginsToolsHeaders', ['tweakStoresBehaviors', 'modulesToolsHeaders']); $core->addBehavior('themesToolsHeaders', ['tweakStoresBehaviors', 'modulesToolsHeaders']); $core->addBehavior('pluginsToolsTabs', ['tweakStoresBehaviors', 'pluginsToolsTabs']); $core->addBehavior('themesToolsTabs', ['tweakStoresBehaviors', 'themesToolsTabs']); class tweakStoresBehaviors { # create dcstore.xml file on the fly when pack a module public static function packmanBeforeCreatePackage(dcCore $core, array $module): void { tweakStores::writeXML($module['id'], $module, $core->blog->settings->tweakStores->file_pattern); } # addd some js public static function modulesToolsHeaders(dcCore $core, bool $is_plugin): string { $core->auth->user_prefs->addWorkspace('interface'); return dcPage::jsVars(['dotclear.ts_copied' => __('Copied to clipboard')]) . dcPage::jsLoad(dcPage::getPF('tweakStores/js/admin.js')) . ( !$core->auth->user_prefs->interface->colorsyntax ? '' : dcPage::jsLoadCodeMirror($core->auth->user_prefs->interface->colorsyntax_theme) . dcPage::jsLoad(dcPage::getPF('tweakStores/js/cms.js')) ); } # admin plugins page tab public static function pluginsToolsTabs(dcCore $core): void { self::modulesToolsTabs($core, $core->plugins->getModules(), explode(',', DC_DISTRIB_PLUGINS), $core->adminurl->get('admin.plugins') . '#tweakStores'); } # admin themes page tab public static function themesToolsTabs(dcCore $core): void { self::modulesToolsTabs($core, $core->themes->getModules(), explode(',', DC_DISTRIB_THEMES), $core->adminurl->get('admin.blog.theme') . '#tweakStores'); } # generic page tab protected static function modulesToolsTabs(dcCore $core, array $modules, array $excludes, string $page_url): void { $core->auth->user_prefs->addWorkspace('interface'); $user_ui_colorsyntax = $core->auth->user_prefs->interface->colorsyntax; $user_ui_colorsyntax_theme = $core->auth->user_prefs->interface->colorsyntax_theme; $combo = self::comboModules($modules, $excludes); $file_pattern = $core->blog->settings->tweakStores->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 = tweakStores::generateXML($_POST['buildxml_id'], $modules[$_POST['buildxml_id']], $file_pattern); } # write dcstore.xml file if (!empty($_POST['write_xml'])) { if (empty($_POST['your_pwd']) || !$core->auth->checkPassword($_POST['your_pwd'])) { $core->error->add(__('Password verification failed')); } else { $ret = tweakStores::writeXML($_POST['buildxml_id'], $modules[$_POST['buildxml_id']], $file_pattern); if (!empty(tweakStores::$failed)) { $core->error->add(implode(' ', tweakStores::$failed)); } } } echo '
' . '

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

'; if (!empty($_POST['write_xml'])) { if ($core->error->flag()) { echo '

' . implode(' ', $core->error->getErrors()) . '

'; } 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'])) . '

' . '

' . $core->formNonce() . '

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

' . __('Repositiory contents') . '

' . '

' . $url . '

' . ( empty($file_content) ? '' : '
' . form::textArea('file_xml', 165, 14, [
                    'default'    => html::escapeHTML(tweakStores::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

', $core->adminurl->get('admin.plugins', ['module' => 'tweakStores', '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'])) . '

' . '

' . $core->formNonce() . '

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

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

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

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

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

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

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

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

'; } echo '
' . form::textArea('gen_xml', 165, 14, [
                    'default'    => html::escapeHTML(tweakStores::prettyXML($xml_content)),
                    'class'      => 'maximal',
                    'extra_html' => 'readonly="true"'
                ]) . '
' . ( !$user_ui_colorsyntax ? '' : dcPage::jsRunCodeMirror('editor', 'gen_xml', 'dotclear', $user_ui_colorsyntax_theme) ); if (empty(tweakStores::$failed) && $modules[$_POST['buildxml_id']]['root_writable'] && $core->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']) . $core->formNonce() . '

'; } echo sprintf( '

%s

', $core->adminurl->get('admin.plugins', ['module' => 'tweakStores', '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; } }