UI review

This commit is contained in:
Jean-Christian Denis 2023-04-29 15:38:22 +02:00
parent f5d1c8a216
commit c28d1e679a
Signed by: JcDenis
GPG key ID: 1B5B8C5B90B6C951
7 changed files with 251 additions and 323 deletions

View file

@ -1,20 +1,28 @@
/*global $, dotclear */ /*global $, dotclear */
'use strict'; 'use strict';
Object.assign(dotclear.msg, dotclear.getData('ts_copied')); Object.assign(dotclear.msg, dotclear.getData('tweakstore_copied'));
$(function(){ $(() => {
$("#ts_copy_button").click(function() {
var style = $("#gen_xml").attr('style'); $('#tweakstore_form #tweakstore_submit').hide();
$("#gen_xml").attr('style', '').attr("contenteditable", true) $('#tweakstore_form #tweakstore_id').on('change', function () {
if (this.value != '0'){this.form.submit();}
});
dotclear.condSubmit('#tweakstore_form #tweakstore_id', '#tweakstore_form #tweakstore_submit');
$("#tweakstore_copy").click(function() {
var style = $("#tweakstore_gen").attr('style');
$("#tweakstore_gen").attr('style', '').attr("contenteditable", true)
.select() .select()
.on("focus", function() { .on("focus", function() {
document.execCommand('selectAll', false, null) document.execCommand('selectAll', false, null)
}) })
.focus() .focus()
document.execCommand("Copy"); document.execCommand("Copy");
$("#gen_xml").removeAttr("contenteditable").attr('style', style); $("#tweakstore_gen").removeAttr("contenteditable").attr('style', style);
$("#ts_copy_button").focus(); $("#tweakstore_copy").focus();
alert(dotclear.msg.alert); alert(dotclear.msg.alert);
return false; return false;

View file

@ -12,35 +12,28 @@
use Dotclear\Helper\L10n; use Dotclear\Helper\L10n;
L10n::$locales['Copied to clipboard'] = 'Copié dans le presse-papier'; L10n::$locales['Copied to clipboard'] = 'Copié dans le presse-papier';
L10n::$locales['Module to parse:'] = 'Module à traiter :';
L10n::$locales['This module has no repository set in its _define.php file.'] = 'Ce module n\'a aucun dépôt tiers définie dans son fichier _define.php'; L10n::$locales['This module has no repository set in its _define.php file.'] = 'Ce module n\'a aucun dépôt tiers définie dans son fichier _define.php';
L10n::$locales['Failed to read third party repository'] = 'Impossible de lire le dépôt tiers'; L10n::$locales['Failed to read third party repository'] = 'Impossible de lire le dépôt tiers';
L10n::$locales['Tweak third-party repositories'] = 'Gestion de dépôts tiers'; L10n::$locales['Tweak third-party repositories'] = 'Gestion de dépôts tiers';
L10n::$locales['File successfully written'] = 'Fichier enregistré avec succès';
L10n::$locales['There is no module to tweak'] = 'Il n\'y a pas de module à gérer'; L10n::$locales['There is no module to tweak'] = 'Il n\'y a pas de module à gérer';
L10n::$locales['Check repository'] = 'Vérifier un dépôt tiers'; L10n::$locales['Contents from distant repositiory'] = 'Contenu provenant du dépôt distant';
L10n::$locales['This checks if dcstore.xml file is present on third party repository.'] = 'Ceci vérifie la présence du fichier dcstore.xml sur le dépôt tiers.'; L10n::$locales['Contents generated from local module definiton'] = 'Contenu généré depuis la définition locale du module';
L10n::$locales['Module to parse:'] = 'Module à traiter :';
L10n::$locales['Check'] = 'Obtenir';
L10n::$locales['Repositiory contents'] = 'Contenu du dépôts tiers';
L10n::$locales['Generate xml code'] = 'Générer le code XML';
L10n::$locales['You must configure zip file pattern to complete xml code automatically.'] = 'Vous devez configurer le modèle de fichier zip pour compléter le code XML automatiquement.';
L10n::$locales['This helps to generate content of dcstore.xml for seleted module.'] = 'Ceci aide à générer le contenu du fichier dcstore.xml pour le module selectionné.';
L10n::$locales['Generate'] = 'Générer';
L10n::$locales['Generated code for module: %s'] = 'Code généré pour le module : %s';
L10n::$locales['Failed to parse XML code: %s'] = 'Impossible de traiter le code XML : %s'; L10n::$locales['Failed to parse XML code: %s'] = 'Impossible de traiter le code XML : %s';
L10n::$locales['Code is not fully filled: %s'] = 'Le code n\'est pas complet : %s'; L10n::$locales['Code is not fully filled: %s'] = 'Le code n\'est pas complet : %s';
L10n::$locales['File successfully writed'] = 'Fichier écrit avec succès';
L10n::$locales['Code is complete'] = 'Le code est complet'; L10n::$locales['Code is complete'] = 'Le code est complet';
L10n::$locales['Save to module directory'] = 'Enregistrer dans le répertoire du module'; L10n::$locales['Save to module directory'] = 'Enregistrer dans le répertoire du module';
L10n::$locales['Copy to clipboard'] = 'Copier dans le presse-papier'; L10n::$locales['Copy to clipboard'] = 'Copier dans le presse-papier';
L10n::$locales['You can edit zip file pattern from configuration page.'] = 'Vous pouvez modifier le modèle de fichier zip sur la page de configuration.'; L10n::$locales['Check'] = 'Obtenir';
L10n::$locales['Select a module'] = 'Sélectionner un module'; L10n::$locales['You must configure zip file pattern to complete xml code automatically.'] = 'Vous devez configurer le modèle de fichier zip pour compléter le code XML automatiquement.';
L10n::$locales['Enable plugin'] = 'Activer le plugin';
L10n::$locales['If enabled, new tab "Tweak stores" allows your to perfom actions relative to third-party repositories.'] = 'Si activé, un nouvel onglet "Tweak stores" vous permettra de mener des actions relatives aux dépôts tiers.';
L10n::$locales['Enable packman behaviors'] = 'Activer les comportements avec pacKman';
L10n::$locales['If enabled, plugin pacKman will (re)generate on the fly dcstore.xml file at root directory of the module.'] = 'Si activé, le plugin pacKman (re)génèrera à la volée le fichier dcstore.xml';
L10n::$locales['Predictable URL to zip file on the external repository'] = 'URL prédictive du fichier zip sur le dépôt externe'; L10n::$locales['Predictable URL to zip file on the external repository'] = 'URL prédictive du fichier zip sur le dépôt externe';
L10n::$locales['You can use widcard like %author%, %type%, %id%, %version%.'] = 'Vous pouvez utiliser les remplacements automatiques tels que %author%, %type%, %id%, %version%.'; L10n::$locales['You can use widcard like %author%, %type%, %id%, %version%.'] = 'Vous pouvez utiliser les remplacements automatiques tels que %author%, %type%, %id%, %version%.';
L10n::$locales['For example on github https://github.com/MyGitName/%id%/releases/download/v%version%/%type%-%id%.zip'] = 'Par exemple sur github https://github.com/MyGitName/%id%/releases/download/v%version%/%type%-%id%.zip'; L10n::$locales['For example on github https://github.com/MyGitName/%id%/releases/download/v%version%/%type%-%id%.zip'] = 'Par exemple sur github https://github.com/MyGitName/%id%/releases/download/v%version%/%type%-%id%.zip';
L10n::$locales['Note: on github, you must create a release and join to it the module zip file.'] = 'Note : sur github, vous devez créer un release et y joindre le fichier zip du module.'; L10n::$locales['Note: on github, you must create a release and join to it the module zip file.'] = 'Note : sur github, vous devez créer un release et y joindre le fichier zip du module.';
L10n::$locales['Enable packman behaviors'] = 'Activer les comportements avec pacKman';
L10n::$locales['If enabled, plugin pacKman will (re)generate on the fly dcstore.xml file at root directory of the module.'] = 'Si activé, le plugin pacKman (re)génèrera à la volée le fichier dcstore.xml';
L10n::$locales['Select a module'] = 'Sélectionner un module';
L10n::$locales['Enable plugin'] = 'Activer le plugin';
L10n::$locales['Helper to manage external repositories'] = 'Aide à la gestion de dépôts externes'; L10n::$locales['Helper to manage external repositories'] = 'Aide à la gestion de dépôts externes';
L10n::$locales['Tweak stores'] = 'Tweak stores'; L10n::$locales['Tweak stores'] = 'Tweak stores';

View file

@ -1,108 +1,116 @@
# Language: Français
# Module: tweakStores - 0.7.1
# Date: 2023-04-29 13:33:18
# Author: Jean-Christian Denis
# Translated with translater 2023.04.23
msgid "" msgid ""
msgstr "" msgstr ""
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Project-Id-Version: tweakStores 0.5\n" "Project-Id-Version: tweakStores 0.7.1\n"
"POT-Creation-Date: \n" "POT-Creation-Date: \n"
"PO-Revision-Date: 2023-01-06T08:29:42+00:00\n" "PO-Revision-Date: 2023-04-29T13:33:18+00:00\n"
"Last-Translator: Jean-Christian Denis\n" "Last-Translator: Jean-Christian Denis\n"
"Language-Team: \n" "Language-Team: \n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n"
#: src/BackendBehaviors.php:89
msgid "Copied to clipboard" msgid "Copied to clipboard"
msgstr "Copié dans le presse-papier" msgstr "Copié dans le presse-papier"
msgid "This module has no repository set in its _define.php file." #: src/BackendBehaviors.php:126
msgstr "Ce module n'a aucun dépôt tiers définie dans son fichier _define.php"
msgid "Failed to read third party repository"
msgstr "Impossible de lire le dépôt tiers"
msgid "Tweak third-party repositories"
msgstr "Gestion de dépôts tiers"
msgid "File successfully written"
msgstr "Fichier enregistré avec succès"
msgid "There is no module to tweak"
msgstr "Il n'y a pas de module à gérer"
msgid "Check repository"
msgstr "Vérifier un dépôt tiers"
msgid "This checks if dcstore.xml file is present on third party repository."
msgstr "Ceci vérifie la présence du fichier dcstore.xml sur le dépôt tiers."
msgid "Module to parse:" msgid "Module to parse:"
msgstr "Module à traiter :" msgstr "Module à traiter :"
msgid "Check" #: src/BackendBehaviors.php:134
msgstr "Obtenir" msgid "This module has no repository set in its _define.php file."
msgstr "Ce module n'a aucun dépôt tiers définie dans son fichier _define.php"
msgid "Repositiory contents" #: src/BackendBehaviors.php:156
msgstr "Contenu du dépôts tiers" msgid "Failed to read third party repository"
msgstr "Impossible de lire le dépôt tiers"
msgid "Generate xml code" #: src/BackendBehaviors.php:179
msgstr "Générer le code XML" msgid "Tweak third-party repositories"
msgstr "Gestion de dépôts tiers"
msgid "You must configure zip file pattern to complete xml code automatically." #: src/BackendBehaviors.php:184
msgstr "Vous devez configurer le modèle de fichier zip pour compléter le code XML automatiquement." msgid "There is no module to tweak"
msgstr "Il n'y a pas de module à gérer"
msgid "This helps to generate content of dcstore.xml for seleted module." #: src/BackendBehaviors.php:198
msgstr "Ceci aide à générer le contenu du fichier dcstore.xml pour le module selectionné." msgid "Contents from distant repositiory"
msgstr "Contenu provenant du dépôt distant"
msgid "Generate" #: src/BackendBehaviors.php:222
msgstr "Générer" msgid "Contents generated from local module definiton"
msgstr "Contenu généré depuis la définition locale du module"
msgid "Generated code for module: %s"
msgstr "Code généré pour le module : %s"
#: src/BackendBehaviors.php:225
msgid "Failed to parse XML code: %s" msgid "Failed to parse XML code: %s"
msgstr "Impossible de traiter le code XML : %s" msgstr "Impossible de traiter le code XML : %s"
#: src/BackendBehaviors.php:228
msgid "Code is not fully filled: %s" msgid "Code is not fully filled: %s"
msgstr "Le code n'est pas complet : %s" msgstr "Le code n'est pas complet : %s"
#: src/BackendBehaviors.php:232
msgid "File successfully writed"
msgstr "Fichier écrit avec succès"
#: src/BackendBehaviors.php:234
msgid "Code is complete" msgid "Code is complete"
msgstr "Le code est complet" msgstr "Le code est complet"
#: src/BackendBehaviors.php:259
msgid "Save to module directory" msgid "Save to module directory"
msgstr "Enregistrer dans le répertoire du module" msgstr "Enregistrer dans le répertoire du module"
#: src/BackendBehaviors.php:260
msgid "Copy to clipboard" msgid "Copy to clipboard"
msgstr "Copier dans le presse-papier" msgstr "Copier dans le presse-papier"
msgid "You can edit zip file pattern from configuration page." #: src/BackendBehaviors.php:271
msgstr "Vous pouvez modifier le modèle de fichier zip sur la page de configuration." msgid "Check"
msgstr "Obtenir"
#: src/BackendBehaviors.php:280
msgid "You must configure zip file pattern to complete xml code automatically."
msgstr "Vous devez configurer le modèle de fichier zip pour compléter le code XML automatiquement."
#: src/BackendBehaviors.php:285
msgid "Predictable URL to zip file on the external repository"
msgstr "URL prédictive du fichier zip sur le dépôt externe"
#: src/BackendBehaviors.php:288
msgid "You can use widcard like %author%, %type%, %id%, %version%."
msgstr "Vous pouvez utiliser les remplacements automatiques tels que %author%, %type%, %id%, %version%."
#: src/BackendBehaviors.php:289
msgid "For example on github https://github.com/MyGitName/%id%/releases/download/v%version%/%type%-%id%.zip"
msgstr "Par exemple sur github https://github.com/MyGitName/%id%/releases/download/v%version%/%type%-%id%.zip"
#: src/BackendBehaviors.php:290
msgid "Note: on github, you must create a release and join to it the module zip file."
msgstr "Note : sur github, vous devez créer un release et y joindre le fichier zip du module."
#: src/BackendBehaviors.php:294
msgid "Enable packman behaviors"
msgstr "Activer les comportements avec pacKman"
#: src/BackendBehaviors.php:296
msgid "If enabled, plugin pacKman will (re)generate on the fly dcstore.xml file at root directory of the module."
msgstr "Si activé, le plugin pacKman (re)génèrera à la volée le fichier dcstore.xml"
#: src/BackendBehaviors.php:322
msgid "Select a module" msgid "Select a module"
msgstr "Sélectionner un module" msgstr "Sélectionner un module"
msgid "Enable plugin" msgid "Enable plugin"
msgstr "Activer le plugin" msgstr "Activer le plugin"
msgid "If enabled, new tab \"Tweak stores\" allows your to perfom actions relative to third-party repositories."
msgstr "Si activé, un nouvel onglet \"Tweak stores\" vous permettra de mener des actions relatives aux dépôts tiers."
msgid "Enable packman behaviors"
msgstr "Activer les comportements avec pacKman"
msgid "If enabled, plugin pacKman will (re)generate on the fly dcstore.xml file at root directory of the module."
msgstr "Si activé, le plugin pacKman (re)génèrera à la volée le fichier dcstore.xml"
msgid "Predictable URL to zip file on the external repository"
msgstr "URL prédictive du fichier zip sur le dépôt externe"
msgid "You can use widcard like %author%, %type%, %id%, %version%."
msgstr "Vous pouvez utiliser les remplacements automatiques tels que %author%, %type%, %id%, %version%."
msgid "For example on github https://github.com/MyGitName/%id%/releases/download/v%version%/%type%-%id%.zip"
msgstr "Par exemple sur github https://github.com/MyGitName/%id%/releases/download/v%version%/%type%-%id%.zip"
msgid "Note: on github, you must create a release and join to it the module zip file."
msgstr "Note : sur github, vous devez créer un release et y joindre le fichier zip du module."
msgid "Helper to manage external repositories" msgid "Helper to manage external repositories"
msgstr "Aide à la gestion de dépôts externes" msgstr "Aide à la gestion de dépôts externes"

View file

@ -22,10 +22,9 @@ class Backend extends dcNsProcess
public static function init(): bool public static function init(): bool
{ {
static::$init = defined('DC_CONTEXT_ADMIN') static::$init = defined('DC_CONTEXT_ADMIN')
&& !is_null(dcCore::app()->auth) && !is_null(dcCore::app()->blog)
&& My::phpCompliant() && My::phpCompliant()
&& dcCore::app()->auth->isSuperAdmin() && !is_null(dcCore::app()->auth)
&& dcCore::app()->blog->settings->get(My::id())->get('active'); && dcCore::app()->auth->isSuperAdmin();
return static::$init; return static::$init;
} }

View file

@ -20,11 +20,18 @@ use dcModules;
use dcPage; use dcPage;
use Dotclear\Helper\File\Files; use Dotclear\Helper\File\Files;
use Dotclear\Helper\Html\Form\{ use Dotclear\Helper\Html\Form\{
Checkbox,
Div,
Fieldset,
Hidden, Hidden,
Input,
Label, Label,
Legend,
Note,
Para, Para,
Password, Password,
Select, Select,
Submit,
Textarea Textarea
}; };
use Dotclear\Helper\Html\Html; use Dotclear\Helper\Html\Html;
@ -54,14 +61,31 @@ class BackendBehaviors
self::writeXML($define, dcCore::app()->blog->settings->get(My::id())->get('file_pattern')); self::writeXML($define, dcCore::app()->blog->settings->get(My::id())->get('file_pattern'));
} }
public static function modulesToolsHeaders(bool $is_plugin): string public static function modulesToolsHeaders(bool $is_theme): string
{ {
if (is_null(dcCore::app()->auth) || is_null(dcCore::app()->auth->user_prefs)) { if (is_null(dcCore::app()->auth) || is_null(dcCore::app()->auth->user_prefs)) {
return ''; return '';
} }
//save settings (before page header sent)
if (!empty($_POST['tweakstore_save'])) {
try {
$s = new Settings();
foreach ($s->dump() as $key => $value) {
$s->set($key, $_POST['ts_' . $key] ?? $value);
}
dcPage::addSuccessNotice(
__('Configuration successfully updated')
);
dcCore::app()->adminurl?->redirect($is_theme ? 'admin.blog.theme' : 'admin.plugins', ['tab' => My::id()]);
} catch (Exception $e) {
dcCore::app()->error->add($e->getMessage());
}
}
return return
dcPage::jsJson('ts_copied', ['alert' => __('Copied to clipboard')]) . dcPage::jsJson('tweakstore_copied', ['alert' => __('Copied to clipboard')]) .
dcPage::jsModuleLoad(My::id() . '/js/backend.js') . dcPage::jsModuleLoad(My::id() . '/js/backend.js') .
( (
!dcCore::app()->auth->user_prefs->get('interface')->get('colorsyntax') ? '' : !dcCore::app()->auth->user_prefs->get('interface')->get('colorsyntax') ? '' :
@ -72,38 +96,39 @@ class BackendBehaviors
public static function pluginsToolsTabsV2(): void public static function pluginsToolsTabsV2(): void
{ {
self::modulesToolsTabs(dcCore::app()->plugins, explode(',', DC_DISTRIB_PLUGINS), (string) dcCore::app()->adminurl?->get('admin.plugins')); self::modulesToolsTabs(dcCore::app()->plugins, (string) dcCore::app()->adminurl?->get('admin.plugins'));
} }
public static function themesToolsTabsV2(): void public static function themesToolsTabsV2(): void
{ {
self::modulesToolsTabs(dcCore::app()->themes, explode(',', DC_DISTRIB_THEMES), (string) dcCore::app()->adminurl?->get('admin.blog.theme')); self::modulesToolsTabs(dcCore::app()->themes, (string) dcCore::app()->adminurl?->get('admin.blog.theme'));
} }
private static function modulesToolsTabs(dcModules $modules, array $excludes, string $page_url): void private static function modulesToolsTabs(dcModules $modules, string $page_url): void
{ {
if (is_null(dcCore::app()->adminurl) || is_null(dcCore::app()->auth) || is_null(dcCore::app()->auth->user_prefs)) { if (is_null(dcCore::app()->adminurl) || is_null(dcCore::app()->auth) || is_null(dcCore::app()->auth->user_prefs)) {
return; return;
} }
// settings
$s = new Settings();
$page_url .= '#' . My::id(); $page_url .= '#' . My::id();
$user_ui_colorsyntax = dcCore::app()->auth->user_prefs->get('interface')->get('colorsyntax'); $user_ui_colorsyntax = dcCore::app()->auth->user_prefs->get('interface')->get('colorsyntax');
$user_ui_colorsyntax_theme = dcCore::app()->auth->user_prefs->get('interface')->get('colorsyntax_theme'); $user_ui_colorsyntax_theme = dcCore::app()->auth->user_prefs->get('interface')->get('colorsyntax_theme');
$file_pattern = (new Settings())->file_pattern; $file_pattern = $s->file_pattern;
$local_content = $distant_content = '';
$module = $modules->getDefine($_POST['ts_id'] ?? '-'); // load module
$combo = self::comboModules($modules, $excludes); $module = $modules->getDefine($_POST['tweakstore_id'] ?? '0');
$form = (new Para())->class('field')->items([ $combo = self::comboModules($modules);
(new Label(__('Module to parse:')))->for('ts_id')->class('required'),
(new Select('ts_id'))->default($module->isDefined() ? Html::escapeHTML($module->get('id')) : '-')->items($combo),
])->render();
# check dcstore repo // execute form actions
$url = ''; $url = '';
if (!empty($_POST['check_xml']) && $module->isDefined()) { if (!empty($_POST['tweakstore_do']) && $module->isDefined()) {
if (empty($module->get('repository'))) { if (empty($module->get('repository'))) {
$url = __('This module has no repository set in its _define.php file.'); $url = __('This module has no repository set in its _define.php file.');
} else { } else {
// read distant module xml content
try { try {
$url = $module->get('repository'); $url = $module->get('repository');
if (false === strpos($url, 'dcstore.xml')) { if (false === strpos($url, 'dcstore.xml')) {
@ -117,70 +142,63 @@ class BackendBehaviors
curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_REFERER, $url); curl_setopt($ch, CURLOPT_REFERER, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$file_content = (string) curl_exec($ch); $distant_content = (string) curl_exec($ch);
curl_close($ch); curl_close($ch);
} else { } else {
$file_content = (string) file_get_contents($url); $distant_content = (string) file_get_contents($url);
} }
} catch (Exception $e) { } catch (Exception $e) {
$file_content = __('Failed to read third party repository'); $distant_content = __('Failed to read third party repository');
}
} }
} }
# generate xml code // generate local module xml content
if (!empty($_POST['build_xml']) && $module->isDefined()) { $local_content = self::generateXML($module, $s->file_pattern);
$xml_content = self::generateXML($module, $file_pattern);
}
# write dcstore.xml file // write dcstore.xml file
if (!empty($_POST['write_xml'])) { if (!empty($_POST['tweakstore_write'])) {
if (empty($_POST['your_pwd']) || !dcCore::app()->auth->checkPassword($_POST['your_pwd'])) { if (empty($_POST['your_pwd']) || !dcCore::app()->auth->checkPassword($_POST['your_pwd'])) {
dcCore::app()->error->add(__('Password verification failed')); dcCore::app()->error->add(__('Password verification failed'));
} else { } else {
$ret = self::writeXML($module, $file_pattern); self::writeXML($module, $s->file_pattern);
if (!empty(self::$failed)) { if (!empty(self::$failed)) {
dcCore::app()->error->add(implode(' ', self::$failed)); dcCore::app()->error->add(implode(' ', self::$failed));
} }
} }
} }
}
// display
echo echo
'<div class="multi-part" id="' . My::id() . '" title="' . My::name() . '">' . '<div class="multi-part" id="' . My::id() . '" title="' . My::name() . '">' .
'<h3>' . __('Tweak third-party repositories') . '</h3>'; '<h3>' . __('Tweak third-party repositories') . '</h3>';
if (!empty($_POST['write_xml'])) { // nothing to display
if (dcCore::app()->error->flag()) {
echo dcCore::app()->error->toHTML();
} else {
echo '<p class="success">' . __('File successfully written') . '</p>';
}
}
if (count($combo) < 2) { if (count($combo) < 2) {
echo echo
'<div class="info">' . __('There is no module to tweak') . '</div>' . '<p class="warning">' . __('There is no module to tweak') . '</p> ' .
'</div>'; '</div>';
return; return;
} }
echo echo
'<form method="post" action="' . $page_url . '" id="checkxml" class="fieldset">' . '<form method="post" action="' . $page_url . '" id="tweakstore_form">' .
'<h4>' . __('Check repository') . '</h4>' . (new Para())->class('field')->items([
'<p>' . __('This checks if dcstore.xml file is present on third party repository.') . '</p>' . (new Label(__('Module to parse:')))->for('tweakstore_id')->class('required'),
$form . (new Select('tweakstore_id'))->default($module->isDefined() ? Html::escapeHTML($module->getId()) : '0')->items($combo),
'<p><input type="submit" name="check_xml" value="' . __('Check') . '" />' . ])->render();
dcCore::app()->formNonce() . '</p>' .
'</form>';
// distant content
if (!empty($url)) { if (!empty($url)) {
echo echo
'<div class="fieldset">' . '<div class="fieldset">' .
'<h4>' . __('Repositiory contents') . '</h4>' . '<h4>' . __('Contents from distant repositiory') . '</h4>' .
'<p>' . $url . '</p>' . '<p>' . $url . '</p>' .
( (
empty($file_content) ? '' : empty($distant_content) ? '' :
'<pre>' . '<pre>' .
(new Textarea('file_xml', Html::escapeHTML(self::prettyXML($file_content)))) (new Textarea('distant_content', Html::escapeHTML(self::prettyXML($distant_content))))
->cols(165) ->cols(165)
->rows(14) ->rows(14)
->readonly(true) ->readonly(true)
@ -189,46 +207,34 @@ class BackendBehaviors
'</pre>' . '</pre>' .
( (
!$user_ui_colorsyntax ? '' : !$user_ui_colorsyntax ? '' :
dcPage::jsRunCodeMirror('editor', 'file_xml', 'dotclear', $user_ui_colorsyntax_theme) dcPage::jsRunCodeMirror('editor', 'distant_content', 'dotclear', $user_ui_colorsyntax_theme)
) )
) . ) .
'</div>'; '</div>';
} }
if (empty($file_pattern)) { // local_content
echo sprintf( if (!empty($local_content) || !empty(self::$failed) || !empty(self::$notice)) {
'<div class="fieldset"><h4>' . __('Generate xml code') . '</h4><p class="info"><a href="%s">%s</a></p></div>',
dcCore::app()->adminurl->get('admin.plugins', ['module' => My::id(), 'conf' => 1, 'redir' => $page_url]),
__('You must configure zip file pattern to complete xml code automatically.')
);
} else {
echo echo
'<form method="post" action="' . $page_url . '" id="buildxml" class="fieldset">' . '<div class="fieldset">' .
'<h4>' . __('Generate xml code') . '</h4>' . '<h4>' . __('Contents generated from local module definiton') . '</h4>';
'<p>' . __('This helps to generate content of dcstore.xml for seleted module.') . '</p>' .
$form .
'<p><input type="submit" name="build_xml" value="' . __('Generate') . '" />' .
dcCore::app()->formNonce() . '</p>' .
'</form>';
}
if (!empty($_POST['build_xml'])) {
echo
'<form method="post" action="' . $page_url . '" id="writexml" class="fieldset">' .
'<h4>' . sprintf(__('Generated code for module: %s'), Html::escapeHTML($module->get('id'))) . '</h4>';
if (!empty(self::$failed)) { if (!empty(self::$failed)) {
echo '<p class="info">' . sprintf(__('Failed to parse XML code: %s'), implode(', ', self::$failed)) . '</p> '; echo '<p class="warning">' . sprintf(__('Failed to parse XML code: %s'), implode(', ', self::$failed)) . '</p> ';
} }
if (!empty(self::$notice)) { if (!empty(self::$notice)) {
echo '<p class="info">' . sprintf(__('Code is not fully filled: %s'), implode(', ', self::$notice)) . '</p> '; echo '<p class="warning">' . sprintf(__('Code is not fully filled: %s'), implode(', ', self::$notice)) . '</p> ';
} }
if (!empty($xml_content)) {
if (empty(self::$failed) && empty(self::$notice)) { if (empty(self::$failed) && empty(self::$notice)) {
if (!empty($_POST['tweakstore_write'])) {
echo '<p class="info">' . __('File successfully writed') . '</p> ';
}
echo '<p class="info">' . __('Code is complete') . '</p> '; echo '<p class="info">' . __('Code is complete') . '</p> ';
} }
echo echo
'<pre>' . '<pre>' .
(new Textarea('gen_xml', Html::escapeHTML(self::prettyXML($xml_content)))) (new Textarea('local_content', Html::escapeHTML(self::prettyXML($local_content))))
->cols(165) ->cols(165)
->rows(14) ->rows(14)
->readonly(true) ->readonly(true)
@ -237,48 +243,81 @@ class BackendBehaviors
'</pre>' . '</pre>' .
( (
!$user_ui_colorsyntax ? '' : !$user_ui_colorsyntax ? '' :
dcPage::jsRunCodeMirror('editor', 'gen_xml', 'dotclear', $user_ui_colorsyntax_theme) dcPage::jsRunCodeMirror('editor', 'local_content', 'dotclear', $user_ui_colorsyntax_theme)
); );
if (empty(self::$failed) if ($module->get('root_writable')
&& $module->get('root_writable')
&& dcCore::app()->auth->isSuperAdmin() && dcCore::app()->auth->isSuperAdmin()
) { ) {
echo echo
(new Para())->class('field')->items([ (new Para())->class('field')->items([
(new Label(__('Your password:')))->for('your_pwd2')->class('required'), (new Label(__('Your password:')))->for('tweakstore_pwd')->class('required'),
(new Password(['your_pwd', 'your_pwd2']))->size(20)->maxlenght(255)->required(true)->placeholder(__('Password'))->autocomplete('current-password'), (new Password(['your_pwd', 'tweakstore_pwd']))->size(20)->maxlenght(255)->required(true)->placeholder(__('Password'))->autocomplete('current-password'),
])->render() . ])->render() .
'<p><input type="submit" name="write_xml" value="' . __('Save to module directory') . '" /> ' . '<p><input type="submit" name="tweakstore_write" id="tweakstore_write" value="' . __('Save to module directory') . '" /> ' .
'<a class="hidden-if-no-js button" href="#' . My::id() . '" id="ts_copy_button">' . __('Copy to clipboard') . '</a>' . '<a class="hidden-if-no-js button" href="#' . My::id() . '" id="tweakstore_copy">' . __('Copy to clipboard') . '</a>' .
(new Hidden('ts_id', $_POST['ts_id']))->render() .
dcCore::app()->formNonce() . '</p>'; dcCore::app()->formNonce() . '</p>';
} }
echo sprintf(
'<p class="info"><a href="%s">%s</a></p>',
dcCore::app()->adminurl->get('admin.plugins', ['module' => My::id(), 'conf' => 1, 'redir' => $page_url]),
__('You can edit zip file pattern from configuration page.')
);
}
echo
'</form>';
}
echo echo
'</div>'; '</div>';
} }
// submit form button (hide by js)
echo
(new Para())->items([
(new Submit('tweakstore_submit'))->value(__('Check')),
(new Hidden('tweakstore_do', '1')),
dcCore::app()->formNonce(false),
])->render() .
'</form>' .
// settings
'<form method="post" action="' . $page_url . '" id="tweakstore_setting">' .
'<div class="fieldset"><h4>' . sprintf(__('%s configuration'), My::name()) . '</h4>' .
(empty($s->file_pattern) ? '<p class="warning">' . __('You must configure zip file pattern to complete xml code automatically.') . '</p>' : '') .
(new Div())->items([
// s_file_pattern
(new Para())->items([
(new Label(__('Predictable URL to zip file on the external repository')))->for('ts_file_pattern'),
(new Input('ts_file_pattern'))->size(65)->maxlenght(255)->class('maximal')->value($s->file_pattern),
]),
(new Note())->text(__('You can use widcard like %author%, %type%, %id%, %version%.'))->class('form-note'),
(new Note())->text(__('For example on github https://github.com/MyGitName/%id%/releases/download/v%version%/%type%-%id%.zip'))->class('form-note'),
(new Note())->text(__('Note: on github, you must create a release and join to it the module zip file.'))->class('form-note'),
// s_packman
(new Para())->items([
(new Checkbox('ts_packman', $s->packman))->value(1),
(new Label(__('Enable packman behaviors'), Label::OUTSIDE_LABEL_AFTER))->for('ts_packman')->class('classic'),
]),
(new Note())->text(__('If enabled, plugin pacKman will (re)generate on the fly dcstore.xml file at root directory of the module.'))->class('form-note'),
])->render() .
(new Para())->items([
(new Submit('tweakstore_save'))->value(__('Save')),
dcCore::app()->formNonce(false),
])->render() .
'</div>' .
'</form>' .
'</div>';
}
# create list of module for combo and remove official modules # create list of module for combo and remove official modules
private static function comboModules(dcModules $modules, array $excludes): array private static function comboModules(dcModules $modules): array
{ {
$combo = [__('Select a module') => '0']; $combo = [];
foreach ($modules->getDefines() as $module) { foreach ($modules->getDefines() as $module) {
if (in_array($module->get('id'), $excludes)) { if ($module->get('distributed')) {
continue; continue;
} }
$combo[$module->get('name') . ' ' . $module->get('version')] = $module->get('id'); $combo[$module->get('name') . ' ' . $module->get('version')] = $module->get('id');
} }
return $combo; uasort($combo, fn ($a, $b) => strtolower($a) <=> strtolower($b));
return array_merge([__('Select a module') => '0'], $combo);
} }
private static function parseFilePattern(dcModuleDefine $module, string $file_pattern): string private static function parseFilePattern(dcModuleDefine $module, string $file_pattern): string

View file

@ -1,110 +0,0 @@
<?php
/**
* @brief tweakStores, a plugin for Dotclear 2
*
* @package Dotclear
* @subpackage Plugin
*
* @author Jean-Christian Denis and Contributors
*
* @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
declare(strict_types=1);
namespace Dotclear\Plugin\tweakStores;
use dcCore;
use dcNsProcess;
use dcPage;
use Dotclear\Helper\Html\Form\{
Checkbox,
Div,
Fieldset,
Input,
Label,
Legend,
Note,
Para
};
use Exception;
class Config extends dcNsProcess
{
public static function init(): bool
{
static::$init = My::phpCompliant()
&& defined('DC_CONTEXT_ADMIN')
&& !is_null(dcCore::app()->auth)
&& dcCore::app()->auth->isSuperAdmin();
return static::$init;
}
public static function process(): bool
{
if (!static::$init) {
return false;
}
if (empty($_POST['save'])) {
return true;
}
$s = new Settings();
try {
foreach ($s->listSettings() as $key => $value) {
$s->writeSetting($key, $_POST['ts_' . $key] ?? $value);
}
dcPage::addSuccessNotice(
__('Configuration successfully updated')
);
dcCore::app()->adminurl?->redirect(
'admin.plugins',
['module' => My::id(), 'conf' => 1, 'redir' => dcCore::app()->admin->__get('list')->getRedir()]
);
} catch (Exception $e) {
dcCore::app()->error->add($e->getMessage());
}
return true;
}
public static function render(): void
{
if (!static::$init) {
return;
}
$s = new Settings();
echo (new Div())->items([
(new Fieldset())->class('fieldset')->legend(new Legend(__('Interface')))->fields([
// s_active
(new Para())->items([
(new Checkbox('ts_active', $s->active))->value(1),
(new Label(__('Enable plugin'), Label::OUTSIDE_LABEL_AFTER))->for('ts_active')->class('classic'),
]),
(new Note())->text(__('If enabled, new tab "Tweak stores" allows your to perfom actions relative to third-party repositories.'))->class('form-note'),
// s_file_pattern
(new Para())->items([
(new Label(__('Predictable URL to zip file on the external repository')))->for('ts_file_pattern'),
(new Input('ts_file_pattern'))->size(65)->maxlenght(255)->class('maximal')->value($s->file_pattern),
]),
(new Note())->text(__('You can use widcard like %author%, %type%, %id%, %version%.'))->class('form-note'),
(new Note())->text(__('For example on github https://github.com/MyGitName/%id%/releases/download/v%version%/%type%-%id%.zip'))->class('form-note'),
(new Note())->text(__('Note: on github, you must create a release and join to it the module zip file.'))->class('form-note'),
]),
(new Fieldset())->class('fieldset')->legend(new Legend(__('Behaviors')))->fields([
// s_packman
(new Para())->items([
(new Checkbox('ts_packman', $s->packman))->value(1),
(new Label(__('Enable packman behaviors'), Label::OUTSIDE_LABEL_AFTER))->for('ts_packman')->class('classic'),
]),
(new Note())->text(__('If enabled, plugin pacKman will (re)generate on the fly dcstore.xml file at root directory of the module.'))->class('form-note'),
]),
])->render();
}
}

View file

@ -19,9 +19,6 @@ use Exception;
class Settings class Settings
{ {
// Enable this plugin
public readonly bool $active;
// Enable plugin pacKman behavior // Enable plugin pacKman behavior
public readonly bool $packman; public readonly bool $packman;
@ -39,16 +36,10 @@ class Settings
$s = dcCore::app()->blog->settings->get(My::id()); $s = dcCore::app()->blog->settings->get(My::id());
$this->active = (bool) ($s->get('active') ?? false);
$this->packman = (bool) ($s->get('packman') ?? false); $this->packman = (bool) ($s->get('packman') ?? false);
$this->file_pattern = (string) ($s->get('file_pattern') ?? ''); $this->file_pattern = (string) ($s->get('file_pattern') ?? '');
} }
public function getSetting(string $key): mixed
{
return $this->{$key} ?? null;
}
/** /**
* Overwrite a plugin settings (in db) * Overwrite a plugin settings (in db)
* *
@ -57,7 +48,7 @@ class Settings
* *
* @return bool True on success * @return bool True on success
*/ */
public function writeSetting(string $key, mixed $value): bool public function set(string $key, mixed $value): bool
{ {
if (is_null(dcCore::app()->blog)) { if (is_null(dcCore::app()->blog)) {
throw new Exception('blog is not set'); throw new Exception('blog is not set');
@ -78,7 +69,7 @@ class Settings
* *
* @return array The settings keys * @return array The settings keys
*/ */
public function listSettings(): array public function dump(): array
{ {
return get_object_vars($this); return get_object_vars($this);
} }