tweakStores/src/Backend.php

284 lines
12 KiB
PHP
Raw Normal View History

2021-08-26 22:38:34 +00:00
<?php
2021-09-27 22:45:10 +00:00
/**
* @brief tweakStores, a plugin for Dotclear 2
2021-11-04 10:17:26 +00:00
*
2021-09-27 22:45:10 +00:00
* @package Dotclear
* @subpackage Plugin
2021-11-04 10:17:26 +00:00
*
2021-09-27 22:45:10 +00:00
* @author Jean-Christian Denis and Contributors
2021-11-04 10:17:26 +00:00
*
2021-09-27 22:45:10 +00:00
* @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
2023-01-06 08:31:44 +00:00
declare(strict_types=1);
2021-08-26 22:38:34 +00:00
2023-01-06 08:31:44 +00:00
namespace Dotclear\Plugin\tweakStores;
2021-08-26 22:38:34 +00:00
2023-01-06 08:31:44 +00:00
/* dotclear ns */
use dcCore;
use dcPage;
2021-08-26 22:38:34 +00:00
2023-01-06 08:31:44 +00:00
/* clearbricks ns */
use form;
use html;
/* php ns */
use Exception;
2021-08-26 22:38:34 +00:00
2023-01-06 08:31:44 +00:00
class Admin
2021-08-26 22:38:34 +00:00
{
2023-01-07 14:52:02 +00:00
private static $pid = '';
2023-01-06 08:31:44 +00:00
protected static $init = false;
public static function init(): bool
{
2023-01-06 08:31:44 +00:00
if (defined('DC_CONTEXT_ADMIN')
&& dcCore::app()->auth->isSuperAdmin()
&& dcCore::app()->blog->settings->get(basename(__NAMESPACE__))->get('active')
) {
dcCore::app()->auth->user_prefs->addWorkspace('interface');
2023-01-07 14:52:02 +00:00
self::$pid = basename(dirname(__DIR__));
2023-01-06 08:31:44 +00:00
self::$init = true;
}
return self::$init;
}
2023-01-06 08:31:44 +00:00
public static function process(): ?bool
2021-11-04 10:17:26 +00:00
{
2023-01-06 08:31:44 +00:00
if (!self::$init) {
return false;
}
2023-01-07 14:52:02 +00:00
if (dcCore::app()->blog->settings->get(self::$pid)->get('packman')) {
2023-01-06 08:31:44 +00:00
// create dcstore.xml file on the fly when plugin packman pack a module
dcCore::app()->addBehavior('packmanBeforeCreatePackage', function (array $module): void {
2023-01-07 14:52:02 +00:00
Core::writeXML($module['id'], $module, dcCore::app()->blog->settings->get(self::$pid)->get('file_pattern'));
2023-01-06 08:31:44 +00:00
});
}
2023-01-06 08:31:44 +00:00
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
{
2021-11-04 10:17:26 +00:00
return
2023-01-06 08:31:44 +00:00
dcPage::jsJson('ts_copied', ['alert' => __('Copied to clipboard')]) .
2023-01-07 14:52:02 +00:00
dcPage::jsModuleLoad(self::$pid . '/js/admin.js') .
(
2022-11-14 22:52:56 +00:00
!dcCore::app()->auth->user_prefs->interface->colorsyntax ? '' :
dcPage::jsLoadCodeMirror(dcCore::app()->auth->user_prefs->interface->colorsyntax_theme) .
2023-01-07 14:52:02 +00:00
dcPage::jsModuleLoad(self::$pid . '/js/cms.js')
);
2021-11-04 10:17:26 +00:00
}
2022-11-14 22:52:56 +00:00
protected static function modulesToolsTabs(array $modules, array $excludes, string $page_url): void
2021-08-26 22:38:34 +00:00
{
2023-01-07 14:52:02 +00:00
$page_url .= '#' . self::$pid;
2022-11-14 22:52:56 +00:00
$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);
2023-01-07 14:52:02 +00:00
$file_pattern = dcCore::app()->blog->settings->get(self::$pid)->get('file_pattern');
2021-09-27 22:45:10 +00:00
# check dcstore repo
2021-11-05 00:16:44 +00:00
$url = '';
if (!empty($_POST['checkxml_id']) && in_array($_POST['checkxml_id'], $combo)) {
if (empty($modules[$_POST['checkxml_id']]['repository'])) {
2021-11-05 00:16:44 +00:00
$url = __('This module has no repository set in its _define.php file.');
} else {
try {
2021-11-04 23:58:34 +00:00
$url = $modules[$_POST['checkxml_id']]['repository'];
if (false === strpos($url, 'dcstore.xml')) {
$url .= '/dcstore.xml';
}
if (function_exists('curl_init')) {
$ch = curl_init();
2021-11-04 23:46:25 +00:00
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
2021-11-04 23:58:34 +00:00
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_REFERER, $url);
2021-11-04 23:46:25 +00:00
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$file_content = curl_exec($ch);
curl_close($ch);
} else {
2021-11-04 23:58:34 +00:00
$file_content = file_get_contents($url);
}
} catch (Exception $e) {
$file_content = __('Failed to read third party repository');
}
}
}
2021-08-27 13:23:17 +00:00
# generate xml code
2021-08-28 00:45:38 +00:00
if (!empty($_POST['buildxml_id']) && in_array($_POST['buildxml_id'], $combo)) {
2023-01-06 08:31:44 +00:00
$xml_content = Core::generateXML($_POST['buildxml_id'], $modules[$_POST['buildxml_id']], $file_pattern);
2021-08-26 22:38:34 +00:00
}
2021-08-27 13:23:17 +00:00
# write dcstore.xml file
2021-08-27 09:47:27 +00:00
if (!empty($_POST['write_xml'])) {
2022-11-14 22:52:56 +00:00
if (empty($_POST['your_pwd']) || !dcCore::app()->auth->checkPassword($_POST['your_pwd'])) {
dcCore::app()->error->add(__('Password verification failed'));
2021-08-27 09:47:27 +00:00
} else {
2023-01-06 08:31:44 +00:00
$ret = Core::writeXML($_POST['buildxml_id'], $modules[$_POST['buildxml_id']], $file_pattern);
if (!empty(Core::$failed)) {
dcCore::app()->error->add(implode(' ', Core::$failed));
2021-08-27 09:47:27 +00:00
}
}
}
2021-08-26 22:38:34 +00:00
echo
2023-01-07 14:52:02 +00:00
'<div class="multi-part" id="' . self::$pid . '" title="' . dcCore::app()->plugins->moduleInfo(self::$pid, 'name') . '">' .
2021-08-27 13:23:17 +00:00
'<h3>' . __('Tweak third-party repositories') . '</h3>';
2021-09-27 22:45:10 +00:00
if (!empty($_POST['write_xml'])) {
2022-11-14 22:52:56 +00:00
if (dcCore::app()->error->flag()) {
echo dcCore::app()->error->toHTML();
2021-09-27 22:45:10 +00:00
} else {
2021-11-04 08:22:34 +00:00
echo '<p class="success">' . __('File successfully written') . '</p>';
2021-09-27 22:45:10 +00:00
}
}
2021-08-27 13:23:17 +00:00
if (count($combo) < 2) {
2021-11-04 10:17:26 +00:00
echo
2021-11-04 08:22:34 +00:00
'<div class="info">' . __('There is no module to tweak') . '</div>' .
2021-08-27 13:23:17 +00:00
'</div>';
return;
}
echo
'<form method="post" action="' . $page_url . '" id="checkxml" class="fieldset">' .
'<h4>' . __('Check repository') . '</h4>' .
'<p>' . __('This checks if dcstore.xml file is present on third party repository.') . '</p>' .
'<p class="field"><label for="buildxml_id" class="classic required"><abbr title="' . __('Required field') . '">*</abbr> ' . __('Module to parse:') . '</label> ' .
form::combo('checkxml_id', $combo, empty($_POST['checkxml_id']) ? '-' : html::escapeHTML($_POST['checkxml_id'])) .
'</p>' .
'<p><input type="submit" name="check_xml" value="' . __('Check') . '" />' .
2022-11-14 22:52:56 +00:00
dcCore::app()->formNonce() . '</p>' .
'</form>';
2021-11-05 00:16:44 +00:00
if (!empty($url)) {
echo
'<div class="fieldset">' .
'<h4>' . __('Repositiory contents') . '</h4>' .
2021-11-05 00:16:44 +00:00
'<p>' . $url . '</p>' .
2021-11-06 14:00:41 +00:00
(
empty($file_content) ? '' :
2021-11-05 00:16:44 +00:00
'<pre>' . form::textArea('file_xml', 165, 14, [
2023-01-06 08:31:44 +00:00
'default' => html::escapeHTML(Core::prettyXML($file_content)),
2021-11-05 00:16:44 +00:00
'class' => 'maximal',
2022-11-14 22:52:56 +00:00
'extra_html' => 'readonly="true"',
]) . '</pre>' .
(
!$user_ui_colorsyntax ? '' :
dcPage::jsRunCodeMirror('editor', 'file_xml', 'dotclear', $user_ui_colorsyntax_theme)
)
2021-11-05 00:16:44 +00:00
) .
'</div>';
}
2021-09-27 22:45:10 +00:00
if (empty($file_pattern)) {
echo sprintf(
'<div class="fieldset"><h4>' . __('Generate xml code') . '</h4><p class="info"><a href="%s">%s</a></p></div>',
2023-01-07 14:52:02 +00:00
dcCore::app()->adminurl->get('admin.plugins', ['module' => self::$pid, 'conf' => 1, 'redir' => $page_url]),
2021-11-04 08:22:34 +00:00
__('You must configure zip file pattern to complete xml code automatically.')
2021-09-27 22:45:10 +00:00
);
} else {
2021-11-04 10:17:26 +00:00
echo
2021-09-27 22:45:10 +00:00
'<form method="post" action="' . $page_url . '" id="buildxml" class="fieldset">' .
'<h4>' . __('Generate xml code') . '</h4>' .
2021-11-04 08:22:34 +00:00
'<p>' . __('This helps to generate content of dcstore.xml for seleted module.') . '</p>' .
2021-09-27 22:45:10 +00:00
'<p class="field"><label for="buildxml_id" class="classic required"><abbr title="' . __('Required field') . '">*</abbr> ' . __('Module to parse:') . '</label> ' .
form::combo('buildxml_id', $combo, empty($_POST['buildxml_id']) ? '-' : html::escapeHTML($_POST['buildxml_id'])) .
'</p>' .
'<p><input type="submit" name="build_xml" value="' . __('Generate') . '" />' .
2022-11-14 22:52:56 +00:00
dcCore::app()->formNonce() . '</p>' .
2021-09-27 22:45:10 +00:00
'</form>';
}
2021-08-26 22:38:34 +00:00
if (!empty($_POST['buildxml_id'])) {
2021-11-04 10:17:26 +00:00
echo
2021-08-27 13:23:17 +00:00
'<form method="post" action="' . $page_url . '" id="writexml" class="fieldset">' .
2021-11-04 08:22:34 +00:00
'<h4>' . sprintf(__('Generated code for module: %s'), html::escapeHTML($_POST['buildxml_id'])) . '</h4>';
2021-08-26 22:38:34 +00:00
2023-01-06 08:31:44 +00:00
if (!empty(Core::$failed)) {
echo '<p class="info">' . sprintf(__('Failed to parse XML code: %s'), implode(', ', Core::$failed)) . '</p> ';
2021-08-26 22:38:34 +00:00
}
2023-01-06 08:31:44 +00:00
if (!empty(Core::$notice)) {
echo '<p class="info">' . sprintf(__('Code is not fully filled: %s'), implode(', ', Core::$notice)) . '</p> ';
2021-08-26 22:38:34 +00:00
}
if (!empty($xml_content)) {
2023-01-06 08:31:44 +00:00
if (empty(Core::$failed) && empty(Core::$notice)) {
2021-09-27 22:45:10 +00:00
echo '<p class="info">' . __('Code is complete') . '</p>';
2021-08-26 22:38:34 +00:00
}
echo
'<pre>' . form::textArea('gen_xml', 165, 14, [
2023-01-06 08:31:44 +00:00
'default' => html::escapeHTML(Core::prettyXML($xml_content)),
'class' => 'maximal',
2022-11-14 22:52:56 +00:00
'extra_html' => 'readonly="true"',
]) . '</pre>' .
(
!$user_ui_colorsyntax ? '' :
dcPage::jsRunCodeMirror('editor', 'gen_xml', 'dotclear', $user_ui_colorsyntax_theme)
);
2021-08-26 22:38:34 +00:00
2023-01-06 08:31:44 +00:00
if (empty(Core::$failed)
2021-11-04 10:17:26 +00:00
&& $modules[$_POST['buildxml_id']]['root_writable']
2022-11-14 22:52:56 +00:00
&& dcCore::app()->auth->isSuperAdmin()
2021-10-28 21:18:49 +00:00
) {
2021-11-04 10:17:26 +00:00
echo
2021-08-26 22:38:34 +00:00
'<p class="field"><label for="your_pwd2" class="classic required"><abbr title="' . __('Required field') . '">*</abbr> ' . __('Your password:') . '</label> ' .
2021-11-04 10:17:26 +00:00
form::password(
['your_pwd', 'your_pwd2'],
20,
255,
2021-08-26 22:38:34 +00:00
[
'extra_html' => 'required placeholder="' . __('Password') . '"',
2022-11-14 22:52:56 +00:00
'autocomplete' => 'current-password',
2021-08-26 22:38:34 +00:00
]
) . '</p>' .
2021-11-04 10:17:26 +00:00
'<p><input type="submit" name="write_xml" value="' . __('Save to module directory') . '" /> ' .
2023-01-07 14:52:02 +00:00
'<a class="hidden-if-no-js button" href="#' . self::$pid . '" id="ts_copy_button">' . __('Copy to clipboard') . '</a>' .
2021-11-04 10:17:26 +00:00
form::hidden('buildxml_id', $_POST['buildxml_id']) .
2022-11-14 22:52:56 +00:00
dcCore::app()->formNonce() . '</p>';
2021-08-26 22:38:34 +00:00
}
2021-09-27 22:45:10 +00:00
echo sprintf(
'<p class="info"><a href="%s">%s</a></p>',
2023-01-07 14:52:02 +00:00
dcCore::app()->adminurl->get('admin.plugins', ['module' => self::$pid, 'conf' => 1, 'redir' => $page_url]),
2021-09-27 22:45:10 +00:00
__('You can edit zip file pattern from configuration page.')
);
2021-08-26 22:38:34 +00:00
}
2021-08-27 09:47:27 +00:00
echo
'</form>';
2021-08-26 22:38:34 +00:00
}
2021-11-04 10:17:26 +00:00
echo
2021-08-26 22:38:34 +00:00
'</div>';
}
2021-08-27 13:23:17 +00:00
# create list of module for combo and remove official modules
2021-11-08 21:36:38 +00:00
protected static function comboModules(array $modules, array $excludes): array
2021-08-27 13:23:17 +00:00
{
2021-11-04 10:17:26 +00:00
$combo = [__('Select a module') => '0'];
2021-08-27 13:23:17 +00:00
foreach ($modules as $id => $module) {
2021-08-28 00:45:38 +00:00
if (in_array($id, $excludes)) {
2021-08-27 13:23:17 +00:00
continue;
}
2021-11-04 10:17:26 +00:00
$combo[$module['name'] . ' ' . $module['version']] = $id;
2021-08-27 13:23:17 +00:00
}
2021-11-04 10:17:26 +00:00
2021-08-27 13:23:17 +00:00
return $combo;
}
2021-11-04 10:17:26 +00:00
}