use namespace

master
Jean-Christian Paul Denis 2023-03-25 19:16:08 +01:00
parent 27ec7f956c
commit ee33fcb00e
Signed by: JcDenis
GPG Key ID: 1B5B8C5B90B6C951
10 changed files with 731 additions and 516 deletions

View File

@ -1,20 +0,0 @@
<?php
/**
* @brief licenseBootstrap, a plugin for Dotclear 2
*
* @package Dotclear
* @subpackage Plugin
*
* @author Jean-Christian Denis
*
* @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
if (!defined('DC_RC_PATH')) {
return null;
}
Clearbricks::lib()->autoload([
'licenseBootstrap' => __DIR__ . '/inc/class.license.bootstrap.php',
'libLicenseBootstrap' => __DIR__ . '/inc/lib.license.bootstrap.php',
]);

View File

@ -10,32 +10,58 @@
* @copyright Jean-Christian Denis * @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html * @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/ */
if (!defined('DC_CONTEXT_ADMIN')) { declare(strict_types=1);
return null;
namespace Dotclear\Plugin\licenseBootstrap;
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')
&& dcCore::app()->auth?->isSuperAdmin()
&& My::phpCompliant();
return static::$init;
} }
dcCore::app()->blog->settings->addNamespace(basename(__DIR__)); public static function process(): bool
{
if (!static::$init) {
return false;
}
dcCore::app()->addBehavior('adminDashboardFavoritesV2', function ($favs) { dcCore::app()->addBehaviors([
$favs->register(basename(__DIR__), [ 'adminDashboardFavoritesV2' => function (dcFavorites $favs): void {
'title' => __('License bootstrap'), $favs->register(My::id(), [
'url' => dcCore::app()->adminurl->get('admin.plugin.' . basename(__DIR__)), 'title' => My::name(),
'small-icon' => urldecode(dcPage::getPF(basename(__DIR__) . '/icon.svg')), 'url' => dcCore::app()->adminurl->get('admin.plugin.' . My::id()),
'large-icon' => urldecode(dcPage::getPF(basename(__DIR__) . '/icon.svg')), 'small-icon' => dcPage::getPF(My::id() . '/icon.svg'),
'large-icon' => dcPage::getPF(My::id() . '/icon.svg'),
//'permissions' => dcCore::app()->auth->isSuperAdmin(), //'permissions' => dcCore::app()->auth->isSuperAdmin(),
]); ]);
}); },
'packmanBeforeCreatePackage' => function ($module) {
dcCore::app()->addBehavior('packmanBeforeCreatePackage', function ($module) { if (Settings::init()->behavior_packman) {
if (dcCore::app()->blog->settings->get(basename(__DIR__))->get('behavior_packman')) { Utils::addLicense($module);
licenseBootstrap::addLicense($module);
} }
}); },
]);
dcCore::app()->menu[dcAdmin::MENU_PLUGINS]->addItem( dcCore::app()->menu[dcAdmin::MENU_PLUGINS]->addItem(
__('License bootstrap'), My::name(),
dcCore::app()->adminurl->get('admin.plugin.' . basename(__DIR__)), dcCore::app()->adminurl->get('admin.plugin.' . My::id()),
urldecode(dcPage::getPF(basename(__DIR__) . '/icon.svg')), dcPage::getPF(My::id() . '/icon.svg'),
preg_match('/' . preg_quote(dcCore::app()->adminurl->get('admin.plugin.' . basename(__DIR__))) . '(&.*)?$/', $_SERVER['REQUEST_URI']), preg_match('/' . preg_quote(dcCore::app()->adminurl->get('admin.plugin.' . My::id())) . '(&.*)?$/', $_SERVER['REQUEST_URI']),
dcCore::app()->auth->isSuperAdmin() dcCore::app()->auth?->isSuperAdmin()
); );
return true;
}
}

View File

@ -10,105 +10,140 @@
* @copyright Jean-Christian Denis * @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html * @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/ */
if (!defined('DC_CONTEXT_MODULE')) { declare(strict_types=1);
return null;
namespace Dotclear\Plugin\licenseBootstrap;
use dcCore;
use dcPage;
use dcNsProcess;
use Dotclear\Helper\Html\Form\{
Checkbox,
Div,
Fieldset,
Label,
Legend,
Para,
Radio,
Textarea
};
use Exception;
class Config extends dcNsProcess
{
public static function init(): bool
{
static::$init == defined('DC_CONTEXT_ADMIN')
&& dcCore::app()->auth?->isSuperAdmin()
&& My::phpCompliant();
return static::$init;
} }
$redir = empty($_REQUEST['redir']) ? public static function process(): bool
dcCore::app()->admin->__get('list')->getURL() . '#plugins' : $_REQUEST['redir']; {
if (!static::$init) {
return false;
}
# -- Get settings -- if (empty($_POST['save'])) {
$s = dcCore::app()->blog->settings->addNamespace(basename(__DIR__)); return true;
}
$lb_overwrite = (bool) $s->get('overwrite'); $s = Settings::init();
$lb_write_full = (bool) $s->get('write_full');
$lb_write_php = (bool) $s->get('write_php');
$lb_write_js = (bool) $s->get('write_js');
$lb_exclude_locales = (bool) $s->get('exclude_locales');
$lb_license_name = licenseBootstrap::getName($s->get('license_name'));
$lb_license_head = licenseBootstrap::gethead($s->get('license_name'), licenseBootstrap::decode($s->get('license_head')));
# -- Set settings -- # -- Set settings --
if (!empty($_POST['save'])) {
try { try {
$lb_overwrite = !empty($_POST['lb_overwrite']); $license_name = $_POST['lb_license_name'];
$lb_write_full = !empty($_POST['lb_write_full']); $license_head = Utils::gethead(
$lb_write_php = !empty($_POST['lb_write_php']); $license_name,
$lb_write_js = !empty($_POST['lb_write_js']); !empty($_POST['lb_license_head_' . $license_name]) ? $_POST['lb_license_head_' . $license_name] : ''
$lb_exclude_locales = !empty($_POST['lb_exclude_locales']); );
$lb_license_name = $_POST['lb_license_name'];
$lb_license_head = licenseBootstrap::gethead($lb_license_name, !empty($_POST['lb_license_head_' . $lb_license_name]) ? $_POST['lb_license_head_' . $lb_license_name] : '');
$s->put('overwrite', $lb_overwrite); $s->writeSetting('hide_distrib', !empty($_POST['lb_hide_distrib']));
$s->put('write_full', $lb_write_full); $s->writeSetting('overwrite', !empty($_POST['lb_overwrite']));
$s->put('write_php', $lb_write_php); $s->writeSetting('write_full', !empty($_POST['lb_write_full']));
$s->put('write_js', $lb_write_js); $s->writeSetting('write_php', !empty($_POST['lb_write_php']));
$s->put('exclude_locales', $lb_exclude_locales); $s->writeSetting('write_js', !empty($_POST['lb_write_js']));
$s->put('license_name', licenseBootstrap::getName($lb_license_name)); $s->writeSetting('exclude_locales', !empty($_POST['lb_exclude_locales']));
$s->put('license_head', licenseBootstrap::encode($lb_license_head)); $s->writeSetting('license_name', Utils::getName($license_name));
$s->writeSetting('license_head', Utils::encode($license_head));
dcPage::addSuccessNotice( dcPage::addSuccessNotice(
__('Configuration has been successfully updated.') __('Configuration has been successfully updated.')
); );
http::redirect( dcCore::app()->adminurl?->redirect('admin.plugins', [
dcCore::app()->admin->__get('list')->getURL('module=' . basename(__DIR__) . '&conf=1&redir=' . 'module' => My::id(),
dcCore::app()->admin->__get('list')->getRedir()) 'conf' => '1',
); 'redir' => dcCore::app()->admin->__get('list')->getRedir(),
]);
} catch (Exception $e) { } catch (Exception $e) {
dcCore::app()->error->add($e->getMessage()); dcCore::app()->error->add($e->getMessage());
} }
return true;
} }
# -- Display form -- public static function render(): void
echo ' {
<div class="fieldset"> if (!static::$init) {
<h4>' . __('Files') . '</h4> return;
}
<p><label class="classic" for="lb_overwrite">' . $s = Settings::init();
form::checkbox('lb_overwrite', 1, $lb_overwrite) . ' ' .
__('Overwrite existing licenses') .
'</label></p>
<p><label class="classic" for="lb_write_full">' . $licences = [];
form::checkbox('lb_write_full', 1, $lb_write_full) . ' ' . foreach (Utils::getLicenses() as $name) {
__('Add full LICENSE file to module root') .
'</label></p>
<p><label class="classic" for="lb_write_php">' .
form::checkbox('lb_write_php', 1, $lb_write_php) . ' ' .
__('Add license block to PHP files') .
'</label></p>
<p><label class="classic" for="lb_write_js">' .
form::checkbox('lb_write_js', 1, $lb_write_js) . ' ' .
__('Add license block to JS files') .
'</label></p>
<p><label class="classic" for="lb_exclude_locales">' .
form::checkbox('lb_exclude_locales', 1, $lb_exclude_locales) . ' ' .
__('Do not add license block to files from locales folder') .
'</label></p>
</div>
<div class="fieldset">
<h4>' . __('Licenses') . '</h4>';
foreach (licenseBootstrap::getLicenses() as $name) {
$check = false; $check = false;
$head = licenseBootstrap::getHead($name); $head = Utils::getHead($name);
if ($name == $lb_license_name) { if ($name == Utils::getName($s->license_name)) {
$check = true; $check = true;
$head = licenseBootstrap::getHead($name, $lb_license_head); $head = Utils::getHead($name, Utils::getHead($s->license_name, Utils::decode($s->license_head)));
} }
echo ' $licences[] = (new Para())->items([
<p><label class="classic" for="license_' . $name . '">' . (new Radio(['lb_license_name', 'license_' . $name], $check))->value($name),
form::radio(['lb_license_name', 'license_' . $name], $name, $check) . ' ' . (new Label(sprintf(__('License %s:'), $name), Label::OUTSIDE_LABEL_AFTER))->for('license_' . $name)->class('classic'),
sprintf(__('License %s:'), $name) . '</label></p> ]);
<p class="area">' . $licences[] = (new Para())->items([
form::textarea('lb_license_head_' . $name, 50, 10, html::escapeHTML($head)) . ' (new Textarea('lb_license_head_' . $name, $head))->class('maximal')->cols(50)->rows(10),
</p>'; ]);
} }
echo ' echo
</div>'; (new Div())->items([
(new Fieldset())->class('fieldset')->legend((new Legend(__('Files'))))->fields([
// hide_distrib
(new Para())->items([
(new Checkbox('lb_hide_distrib', $s->hide_distrib))->value(1),
(new Label(__('Hide distributed modules from lists'), Label::OUTSIDE_LABEL_AFTER))->for('lb_hide_distrib')->class('classic'),
]),
// overwrite
(new Para())->items([
(new Checkbox('lb_overwrite', $s->overwrite))->value(1),
(new Label(__('Overwrite existing licenses'), Label::OUTSIDE_LABEL_AFTER))->for('lb_overwrite')->class('classic'),
]),
// write_full
(new Para())->items([
(new Checkbox('lb_write_full', $s->write_full))->value(1),
(new Label(__('Add full LICENSE file to module root'), Label::OUTSIDE_LABEL_AFTER))->for('lb_write_full')->class('classic'),
]),
// write_php
(new Para())->items([
(new Checkbox('lb_write_php', $s->write_php))->value(1),
(new Label(__('Add license block to PHP files'), Label::OUTSIDE_LABEL_AFTER))->for('lb_write_php')->class('classic'),
]),
// write_js
(new Para())->items([
(new Checkbox('lb_write_js', $s->write_js))->value(1),
(new Label(__('Add license block to JS files'), Label::OUTSIDE_LABEL_AFTER))->for('lb_write_js')->class('classic'),
]),
// exclude_locales
(new Para())->items([
(new Checkbox('lb_exclude_locales', $s->exclude_locales))->value(1),
(new Label(__('Do not add license block to files from locales folder'), Label::OUTSIDE_LABEL_AFTER))->for('lb_exclude_locales')->class('classic'),
]),
]),
(new Fieldset())->class('fieldset')->legend((new Legend(__('Licenses'))))->fields($licences),
])->render();
}
}

View File

@ -10,108 +10,35 @@
* @copyright Jean-Christian Denis * @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html * @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/ */
if (!defined('DC_CONTEXT_ADMIN')) { declare(strict_types=1);
return null;
namespace Dotclear\Plugin\licenseBootstrap;
use dcCore;
use dcNamespace;
use dcNsProcess;
use Exception;
class Install extends dcNsProcess
{
public static function init(): bool
{
static::$init = defined('DC_CONTEXT_ADMIN')
&& My::phpCompliant()
&& dcCore::app()->newVersion(My::id(), dcCore::app()->plugins->moduleInfo(My::id(), 'version'));
return static::$init;
} }
# -- Module specs -- public static function process(): bool
{
$mod_conf = [ if (!static::$init) {
[ return false;
'overwrite', }
'Overwrite existing licence',
false,
'boolean',
],
[
'write_full',
'Add complete licence file',
true,
'boolean',
],
[
'write_php',
'Write license into php files',
true,
'boolean',
],
[
'write_js',
'Write license into js files',
false,
'boolean',
],
[
'exclude_locales',
'Exclude locales from license',
true,
'boolean',
],
[
'license_name',
'License short name',
'gpl2',
'string',
],
[
'license_head',
'File header licence text',
licenseBootstrap::encode(
licenseBootstrap::getHead('gpl2')
),
'string',
],
[
'behavior_packman',
'Add LicenceBootstrap to plugin pacKman',
false,
'boolean',
],
];
# -- Nothing to change below --
try { try {
# Check module version // Upgrade
if (!dcCore::app()->newVersion( self::growUp();
basename(__DIR__),
dcCore::app()->plugins->moduleInfo(basename(__DIR__), 'version')
)) {
return null;
}
// version < 2022.12.22 : upgrade settings ns and array
$current = dcCore::app()->getVersion(basename(__DIR__));
if ($current && version_compare($current, '2022.12.22', '<')) {
$record = dcCore::app()->con->select(
'SELECT * FROM ' . dcCore::app()->prefix . dcNamespace::NS_TABLE_NAME . ' ' .
"WHERE setting_ns = 'licenseBootstrap' "
);
$cur = dcCore::app()->con->openCursor(dcCore::app()->prefix . dcNamespace::NS_TABLE_NAME);
while ($record->fetch()) {
if (in_array($record->setting_id, ['license_head'])) {
$cur->setting_value = (string) unserialize(base64_decode($record->setting_value));
}
$cur->setting_ns = basename(__DIR__);
$cur->update(
"WHERE setting_id = '" . $record->setting_id . "' and setting_ns = 'licenseBootstrap' " .
'AND blog_id ' . (null === $record->blog_id ? 'IS NULL ' : ("= '" . dcCore::app()->con->escape($record->blog_id) . "' "))
);
$cur->clean();
}
}
# Set module settings
dcCore::app()->blog->settings->addNamespace(basename(__DIR__));
foreach ($mod_conf as $v) {
dcCore::app()->blog->settings->__get(basename(__DIR__))->put(
$v[0],
$v[2],
$v[3],
$v[1],
false,
true
);
}
return true; return true;
} catch (Exception $e) { } catch (Exception $e) {
@ -119,3 +46,30 @@ try {
return false; return false;
} }
}
public static function growUp(): void
{
$current = dcCore::app()->getVersion(My::id());
// Update settings id, ns
if ($current && version_compare($current, '2022.12.22', '<')) {
$record = dcCore::app()->con->select(
'SELECT * FROM ' . dcCore::app()->prefix . dcNamespace::NS_TABLE_NAME . ' ' .
"WHERE setting_ns = 'licenseBootstrap' "
);
$cur = dcCore::app()->con->openCursor(dcCore::app()->prefix . dcNamespace::NS_TABLE_NAME);
while ($record->fetch()) {
if (in_array($record->f('setting_id'), ['license_head'])) {
$cur->setField('setting_value', (string) unserialize(base64_decode($record->f('setting_value'))));
}
$cur->setField('setting_ns', My::id());
$cur->update(
"WHERE setting_id = '" . $record->f('setting_id') . "' and setting_ns = 'licenseBootstrap' " .
'AND blog_id ' . (null === $record->f('blog_id') ? 'IS NULL ' : ("= '" . dcCore::app()->con->escapeStr($record->f('blog_id')) . "' "))
);
$cur->clean();
}
}
}
}

View File

@ -10,94 +10,214 @@
* @copyright Jean-Christian Denis * @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html * @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/ */
if (!defined('DC_CONTEXT_ADMIN')) { declare(strict_types=1);
return null;
namespace Dotclear\Plugin\licenseBootstrap;
use dcCore;
use dcPage;
use dcThemes;
use dcNsProcess;
use Dotclear\Helper\Html\Html;
use Dotclear\Helper\Html\Form\{
Checkbox,
Hidden,
Label,
Para,
Submit,
Text
};
use Dotclear\Helper\File\Path;
use Exception;
use http;
class Manage extends dcNsProcess
{
public static function init(): bool
{
static::$init = defined('DC_CONTEXT_ADMIN')
&& dcCore::app()->auth?->isSuperAdmin()
&& My::phpCompliant();
return static::$init;
} }
dcPage::checkSuper(); public static function process(): bool
{
# Queries if (!static::$init) {
$action = $_POST['action'] ?? ''; return false;
$type = isset($_POST['type']) && in_array($_POST['type'], ['plugins', 'themes']) ? $_POST['type'] : '';
# Settings
$s = dcCore::app()->blog->settings->addNamespace(basename(__DIR__));
# Modules
if (!(dcCore::app()->themes instanceof dcThemes)) {
dcCore::app()->themes = new dcThemes();
dcCore::app()->themes->loadModules(dcCore::app()->blog->themes_path, null);
} }
$themes = dcCore::app()->themes;
$plugins = dcCore::app()->plugins;
# Rights $type = in_array($_POST['type'] ?? '', ['plugins', 'themes']) ? $_POST['type'] : '';
$is_editable = !empty($type)
&& !empty($_POST['modules']) if (($_POST['action'] ?? '') != 'addlicense'
&& is_array($_POST['modules']); || empty($type)
|| empty($_POST['modules'])
|| !is_array($_POST['modules'])
) {
return true;
}
$m = self::loadModules();
# Actions # Actions
try { try {
# Add license to modules $modules = array_values($_POST['modules']);
if ($action == 'addlicense' && $is_editable) {
$modules = array_keys($_POST['modules']);
foreach ($modules as $id) { foreach ($modules as $id) {
if (!${$type}->moduleExists($id)) { if (!$m[$type]->moduleExists($id)) {
throw new Exception('No such module'); throw new Exception('No such module');
} }
$module = ${$type}->getModules($id); $module = $m[$type]->getModules($id);
$module['id'] = $id; $module['id'] = $id;
$module['type'] = $type == 'themes' ? 'theme' : 'plugin'; $module['type'] = $type == 'themes' ? 'theme' : 'plugin';
licenseBootstrap::addLicense($module); Utils::addLicense($module);
} }
dcAdminNotices::addSuccessNotice( dcPage::addSuccessNotice(
__('License successfully added.') __('License successfully added.')
); );
http::redirect( http::redirect(
empty($_POST['redir']) ? empty($_POST['redir']) ?
dcCore::app()->admin->getPageURL() : $_POST['redir'] dcCore::app()->admin->getPageURL() : $_POST['redir']
); );
}
} catch(Exception $e) { } catch(Exception $e) {
dcCore::app()->error->add($e->getMessage()); dcCore::app()->error->add($e->getMessage());
} }
return true;
}
public static function render(): void
{
if (!static::$init) {
return;
}
$m = self::loadModules();
# Display # Display
echo dcPage::openModule(
'<html><head><title>' . __('License bootstrap') . '</title>' . My::name(),
dcPage::jsPageTabs() . dcPage::jsPageTabs() .
dcPage::jsModuleLoad(basename(__DIR__) . '/js/licensebootstrap.js') . dcPage::jsModuleLoad(My::id() . '/js/licensebootstrap.js') .
# --BEHAVIOR-- licenseBootstrapAdminHeader # --BEHAVIOR-- licenseBootstrapAdminHeader
dcCore::app()->callBehavior('licenseBootstrapAdminHeader') . dcCore::app()->callBehavior('licenseBootstrapAdminHeader')
);
'</head><body>' . echo
dcPage::breadcrumb([
dcPage::breadcrumb(
[
__('Plugins') => '', __('Plugins') => '',
__('License bootstrap') => '', My::name() => '',
] ]) .
) .
dcPage::notices(); dcPage::notices();
libLicenseBootstrap::modules( self::displayModulesList(
$plugins->getModules(), $m['plugins']->getModules(),
'plugins', 'plugins',
__('Installed plugins') __('Installed plugins')
); );
libLicenseBootstrap::modules( self::displayModulesList(
$themes->getModules(), $m['themes']->getModules(),
'themes', 'themes',
__('Installed themes') __('Installed themes')
); );
dcPage::helpBlock('licenseBootstrap'); dcPage::helpBlock('licenseBootstrap');
dcPage::closeModule();
}
private static function displayModulesList(array $modules, string $type, string $title): void
{
if (Settings::init()->hide_distrib) {
$modules = array_diff_key($modules, array_flip(array_values(array_merge(explode(',', DC_DISTRIB_PLUGINS), explode(',', DC_DISTRIB_THEMES)))));
}
echo echo
'</body></html>'; '<div class="multi-part" ' .
'id="packman-' . $type . '" title="' . $title . '">' .
'<h3>' . $title . '</h3>';
if (empty($modules)) {
echo
'<p><strong>' . __('There are no modules.') . '</strong></p>' .
'<div>';
return;
}
echo
'<form action="plugin.php" method="post">' .
'<table class="clear"><tr>' .
'<th class="nowrap">' . __('Id') . '</th>' .
'<th class="nowrap">' . __('Version') . '</th>' .
'<th class="nowrap maximal">' . __('Name') . '</th>' .
'<th class="nowrap">' . __('Root') . '</th>' .
'</tr>';
foreach (self::sortModules($modules) as $id => $module) {
echo
'<tr class="line">' .
'<td class="nowrap">' .
(new Para())->items([
(new Checkbox(['modules[]', 'modules_' . Html::escapeHTML($id)], false))->value(Html::escapeHTML($id)),
(new Label(Html::escapeHTML($id), Label::OUTSIDE_LABEL_AFTER))->for('modules_' . Html::escapeHTML($id))->class('classic'),
])->render() .
'</label></td>' .
'<td class="nowrap count">' .
Html::escapeHTML($module['version']) .
'</td>' .
'<td class="nowrap maximal">' .
__(Html::escapeHTML($module['name'])) .
'</td>' .
'<td class="nowrap">' .
dirname((string) Path::real($module['root'], false)) .
'</td>' .
'</tr>';
}
echo
'</table>' .
'<p class="checkboxes-helpers"></p>' .
(new Para())->items([
(new Hidden(['redir'], empty($_REQUEST['redir']) ? '' : Html::escapeHTML($_REQUEST['redir']))),
(new Hidden(['p'], My::id())),
(new Hidden(['type'], $type)),
(new Hidden(['action'], 'addlicense')),
(new Submit('addlicense'))->accesskey('s')->value(__('Add license to selected modules')),
dcCore::app()->formNonce(false),
])->render() .
'</form>' .
'</div>';
}
private static function sortModules(array $modules): array
{
$sorter = [];
foreach ($modules as $id => $module) {
$sorter[$id] = $id;
}
array_multisort($sorter, SORT_ASC, $modules);
return $modules;
}
private static function loadModules(): array
{
if (!(dcCore::app()->themes instanceof dcThemes)) {
dcCore::app()->themes = new dcThemes();
dcCore::app()->themes->loadModules(dcCore::app()->blog->themes_path, null);
}
return [
'themes' => dcCore::app()->themes,
'plugins' => dcCore::app()->plugins,
];
}
}

View File

@ -1,96 +0,0 @@
<?php
/**
* @brief licenseBootstrap, a plugin for Dotclear 2
*
* @package Dotclear
* @subpackage Plugin
*
* @author Jean-Christian Denis
*
* @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
if (!defined('DC_CONTEXT_ADMIN')) {
return null;
}
class libLicenseBootstrap
{
public static function modules($modules, $type, $title)
{
$type = $type == 'themes' ? 'themes' : 'plugins';
echo
'<div class="multi-part" ' .
'id="packman-' . $type . '" title="' . $title . '">' .
'<h3>' . $title . '</h3>';
if (empty($modules) && !is_array($modules)) {
echo
'<p><strong>' . __('There are no modules.') . '</strong></p>' .
'<div>';
return null;
}
echo
'<form action="plugin.php" method="post">' .
'<table class="clear"><tr>' .
'<th class="nowrap">' . __('Id') . '</th>' .
'<th class="nowrap">' . __('Version') . '</th>' .
'<th class="nowrap maximal">' . __('Name') . '</th>' .
'<th class="nowrap">' . __('Root') . '</th>' .
'</tr>';
foreach (self::sort($modules) as $id => $module) {
echo
'<tr class="line">' .
'<td class="nowrap"><label class="classic">' .
form::checkbox(['modules[' . html::escapeHTML($id) . ']'], 1) .
html::escapeHTML($id) .
'</label></td>' .
'<td class="nowrap count">' .
html::escapeHTML($module['version']) .
'</td>' .
'<td class="nowrap maximal">' .
__(html::escapeHTML($module['name'])) .
'</td>' .
'<td class="nowrap">' .
dirname(path::real($module['root'], false)) .
'</td>' .
'</tr>';
}
echo
'</table>' .
'<p class="checkboxes-helpers"></p>' .
'<p>' .
(
!empty($_REQUEST['redir']) ?
form::hidden(
['redir'],
html::escapeHTML($_REQUEST['redir'])
) : ''
) .
form::hidden(['p'], 'licenseBootstrap') .
form::hidden(['type'], $type) .
form::hidden(['action'], 'addlicense') .
'<input type="submit" name="addlicense" value="' .
__('Add license to selected modules') . '" />' .
dcCore::app()->formNonce() . '</p>' .
'</form>' .
'</div>';
}
protected static function sort($modules)
{
$sorter = [];
foreach ($modules as $id => $module) {
$sorter[$id] = $id;
}
array_multisort($sorter, SORT_ASC, $modules);
return $modules;
}
}

53
src/My.php 100644
View File

@ -0,0 +1,53 @@
<?php
/**
* @brief licenseBootstrap, a plugin for Dotclear 2
*
* @package Dotclear
* @subpackage Plugin
*
* @author Jean-Christian Denis
*
* @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
declare(strict_types=1);
namespace Dotclear\Plugin\licenseBootstrap;
use dcCore;
/**
* Plugin definitions
*/
class My
{
/** @var string Required php version */
public const PHP_MIN = '8.1';
/** @var string Licenses default templates folder name */
public const TEMPLATE_FOLDER = 'licenses';
/**
* This module id
*/
public static function id(): string
{
return basename(dirname(__DIR__));
}
/**
* This module name
*/
public static function name(): string
{
return __((string) dcCore::app()->plugins->moduleInfo(self::id(), 'name'));
}
/**
* Check php version
*/
public static function phpCompliant(): bool
{
return version_compare(phpversion(), self::PHP_MIN, '>=');
}
}

112
src/Settings.php 100644
View File

@ -0,0 +1,112 @@
<?php
/**
* @brief licenseBootstrap, a plugin for Dotclear 2
*
* @package Dotclear
* @subpackage Plugin
*
* @author Jean-Christian Denis
*
* @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
declare(strict_types=1);
namespace Dotclear\Plugin\licenseBootstrap;
use dcCore;
class Settings
{
/** @var Settings self instance */
private static $settings;
// Hide distributed modules from lists
public readonly bool $hide_distrib;
// Overwrite existing licence
public readonly bool $overwrite;
// Add complete licence file
public readonly bool $write_full;
// Write license into php files
public readonly bool $write_php;
// Write license into js files
public readonly bool $write_js;
// Exclude locales from license
public readonly bool $exclude_locales;
// License short name
public readonly string $license_name;
// File header licence text
public readonly string $license_head;
// Add LicenceBootstrap to plugin pacKman
public readonly bool $behavior_packman;
/**
* Constructor set up plugin settings
*/
public function __construct()
{
$s = dcCore::app()->blog?->settings->get(My::id());
$this->hide_distrib = (bool) ($s?->get('hide_distrib') ?? false);
$this->overwrite = (bool) ($s?->get('overwrite') ?? false);
$this->write_full = (bool) ($s?->get('write_full') ?? true);
$this->write_php = (bool) ($s?->get('pack_overwrite') ?? true);
$this->write_js = (bool) ($s?->get('pack_filename') ?? false);
$this->exclude_locales = (bool) ($s?->get('exclude_locales') ?? true);
$this->license_name = (string) ($s?->get('license_name') ?? 'gpl2');
$this->license_head = (string) ($s?->get('license_head') ?? Utils::encode(Utils::getHead('gpl2')));
$this->behavior_packman = (bool) ($s?->get('behavior_packman') ?? false);
}
public static function init(): Settings
{
if (!(self::$settings instanceof self)) {
self::$settings = new self();
}
return self::$settings;
}
public function getSetting(string $key): mixed
{
return $this->{$key} ?? null;
}
/**
* Overwrite a plugin settings (in db)
*
* @param string $key The setting ID
* @param mixed $value The setting value
*
* @return bool True on success
*/
public function writeSetting(string $key, mixed $value): bool
{
if (property_exists($this, $key) && settype($value, gettype($this->{$key})) === true) {
dcCore::app()->blog?->settings->get(My::id())->drop($key);
dcCore::app()->blog?->settings->get(My::id())->put($key, $value, gettype($this->{$key}), '', true, true);
return true;
}
return false;
}
/**
* List defined settings keys
*
* @return array The settings keys
*/
public function listSettings(): array
{
return array_keys(get_class_vars(Settings::class));
}
}

View File

@ -10,50 +10,71 @@
* @copyright Jean-Christian Denis * @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html * @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/ */
if (!defined('DC_CONTEXT_ADMIN')) { declare(strict_types=1);
return null;
namespace Dotclear\Plugin\licenseBootstrap;
class Uninstall
{
protected static $init = false;
public static function init(): bool
{
self::$init = defined('DC_RC_PATH');
return self::$init;
} }
$this->addUserAction( public static function process($uninstaller): ?bool
{
if (!self::$init) {
return false;
}
$uninstaller->addUserAction(
/* type */ /* type */
'settings', 'settings',
/* action */ /* action */
'delete_all', 'delete_all',
/* ns */ /* ns */
basename(__DIR__), My::id(),
/* desc */ /* desc */
__('delete all settings') __('delete all settings')
); );
$this->addUserAction( $uninstaller->addUserAction(
/* type */ /* type */
'plugins', 'plugins',
/* action */ /* action */
'delete', 'delete',
/* ns */ /* ns */
basename(__DIR__), My::id(),
/* desc */ /* desc */
__('delete plugin files') __('delete plugin files')
); );
$this->addDirectAction( $uninstaller->addDirectAction(
/* type */ /* type */
'settings', 'settings',
/* action */ /* action */
'delete_all', 'delete_all',
/* ns */ /* ns */
basename(__DIR__), My::id(),
/* desc */ /* desc */
sprintf(__('delete all %s settings'), basename(__DIR__)) sprintf(__('delete all %s settings'), My::id())
); );
$this->addDirectAction( $uninstaller->addDirectAction(
/* type */ /* type */
'plugins', 'plugins',
/* action */ /* action */
'delete', 'delete',
/* ns */ /* ns */
basename(__DIR__), My::id(),
/* desc */ /* desc */
sprintf(__('delete %s plugin files'), basename(__DIR__)) sprintf(__('delete %s plugin files'), My::id())
); );
return true;
}
}

View File

@ -10,13 +10,19 @@
* @copyright Jean-Christian Denis * @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html * @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/ */
if (!defined('DC_CONTEXT_ADMIN')) { declare(strict_types=1);
return null;
}
class licenseBootstrap namespace Dotclear\Plugin\licenseBootstrap;
use dcAuth;
use dcCore;
use Dotclear\Helper\File\Files;
use Dotclear\Helper\File\Path;
use Exception;
class Utils
{ {
protected static $licenses = []; protected static array $licenses = [];
/** /**
* Add license to a module. * Add license to a module.
@ -26,9 +32,9 @@ class licenseBootstrap
* *
* @param array $module Module info * @param array $module Module info
*/ */
public static function addLicense($module) public static function addLicense(array $module): void
{ {
$s = dcCore::app()->blog->settings->get(basename(__DIR__)); $s = Settings::init();
# --BEHAVIOR-- licenseBootstrapBeforeAddLicense # --BEHAVIOR-- licenseBootstrapBeforeAddLicense
dcCore::app()->callBehavior( dcCore::app()->callBehavior(
@ -36,22 +42,22 @@ class licenseBootstrap
$module $module
); );
if ($s->get('write_full')) { if ($s->write_full) {
licenseBootstrap::writeFullContent( self::writeFullContent(
$s->get('license_name'), $s->license_name,
$module, $module,
$s->get('overwrite') $s->overwrite
); );
} }
licenseBootstrap::writeHeadContent( self::writeHeadContent(
$s->get('license_name'), $s->license_name,
licenseBootstrap::decode($s->get('license_head')), self::decode($s->license_head),
$module, $module,
dcCore::app()->auth, dcCore::app()->auth,
$s->get('overwrite'), $s->overwrite,
$s->get('write_php'), $s->write_php,
$s->get('write_js'), $s->write_js,
$s->get('exclude_locales') $s->exclude_locales
); );
# --BEHAVIOR-- licenseBootstrapAfterAddLicense # --BEHAVIOR-- licenseBootstrapAfterAddLicense
@ -66,20 +72,20 @@ class licenseBootstrap
* *
* @return array List of licenses names * @return array List of licenses names
*/ */
public static function getLicenses() public static function getLicenses(): array
{ {
if (empty(licenseBootstrap::$licenses)) { if (empty(self::$licenses)) {
$file_reg = '/^([a-z0-9]+)\.head\.txt$/'; $file_reg = '/^([a-z0-9]+)\.head\.txt$/';
$res = []; $res = [];
foreach (files::scandir(dirname(__FILE__) . '/licenses/') as $file) { foreach (Files::scandir(__DIR__ . DIRECTORY_SEPARATOR . My::TEMPLATE_FOLDER . DIRECTORY_SEPARATOR) as $file) {
if (preg_match($file_reg, $file, $matches)) { if (preg_match($file_reg, $file, $matches)) {
$res[] = $matches[1]; $res[] = $matches[1];
} }
} }
licenseBootstrap::$licenses = $res; self::$licenses = $res;
} }
return licenseBootstrap::$licenses; return self::$licenses;
} }
/** /**
@ -90,7 +96,7 @@ class licenseBootstrap
* @param string $name License name * @param string $name License name
* @return string License name * @return string License name
*/ */
public static function getName($name = 'gpl2') public static function getName(string $name = 'gpl2'): string
{ {
return in_array($name, self::getLicenses()) ? $name : 'gpl2'; return in_array($name, self::getLicenses()) ? $name : 'gpl2';
} }
@ -102,7 +108,7 @@ class licenseBootstrap
* @param string $content Header content * @param string $content Header content
* @return string Header content * @return string Header content
*/ */
public static function getHead($name = 'gpl2', $content = '') public static function getHead(string $name = 'gpl2', string $content = ''): string
{ {
if (!in_array($name, self::getLicenses())) { if (!in_array($name, self::getLicenses())) {
$name = 'gpl2'; $name = 'gpl2';
@ -119,7 +125,7 @@ class licenseBootstrap
* @param string $name License name * @param string $name License name
* @return string Full license content * @return string Full license content
*/ */
public static function getFull($name = 'gpl2') public static function getFull(string $name = 'gpl2'): string
{ {
return self::getContent($name, 'full'); return self::getContent($name, 'full');
} }
@ -131,7 +137,7 @@ class licenseBootstrap
* @param string $part License part (head or full) * @param string $part License part (head or full)
* @return string License content * @return string License content
*/ */
public static function getContent($name = 'gpl2', $part = 'head') public static function getContent(string $name = 'gpl2', string $part = 'head'): string
{ {
if (!in_array($name, self::getLicenses())) { if (!in_array($name, self::getLicenses())) {
$name = 'gpl2'; $name = 'gpl2';
@ -140,8 +146,8 @@ class licenseBootstrap
$part = 'head'; $part = 'head';
} }
return file_get_contents( return (string) file_get_contents(
dirname(__FILE__) . '/licenses/' . $name . '.' . $part . '.txt' implode(DIRECTORY_SEPARATOR, [__DIR__, My::TEMPLATE_FOLDER, $name . '.' . $part . '.txt'])
); );
} }
@ -151,13 +157,13 @@ class licenseBootstrap
* @param string $name License name * @param string $name License name
* @param string $content License block content * @param string $content License block content
* @param array $module Module info * @param array $module Module info
* @param object $user dcAuth instance * @param dcAuth $user dcAuth instance
* @param boolean $overwrite Overwrite existing license * @param boolean $overwrite Overwrite existing license
* @param boolean $php Write license in PHP * @param boolean $php Write license in PHP
* @param boolean $js Write license in JS * @param boolean $js Write license in JS
* @param boolean $locales Excludes locales folder * @param boolean $locales Excludes locales folder
*/ */
public static function writeHeadContent($name, $content, $module, $user, $overwrite, $php, $js, $locales) public static function writeHeadContent(string $name, string $content, array $module, dcAuth $user, bool $overwrite, bool $php, bool $js, bool $locales): void
{ {
if (!isset($module['root']) || !is_writable($module['root'])) { if (!isset($module['root']) || !is_writable($module['root'])) {
throw new Exception(); throw new Exception();
@ -174,14 +180,14 @@ class licenseBootstrap
continue; continue;
} }
$path = $module['root'] . '/' . $file; $path = $module['root'] . DIRECTORY_SEPARATOR . $file;
$extension = files::getExtension($file); $extension = Files::getExtension($file);
if ($php && $extension == 'php') { if ($php && $extension == 'php') {
file_put_contents( file_put_contents(
$file, $file,
self::replacePhpContent( self::replacePhpContent(
file_get_contents($file), (string) file_get_contents($file),
$license, $license,
$overwrite $overwrite
) )
@ -190,7 +196,7 @@ class licenseBootstrap
file_put_contents( file_put_contents(
$file, $file,
self::replaceJsContent( self::replaceJsContent(
file_get_contents($file), (string) file_get_contents($file),
$license, $license,
$overwrite $overwrite
) )
@ -206,17 +212,17 @@ class licenseBootstrap
* @param array $module Module info * @param array $module Module info
* @param boolean $overwrite Overwrite existing license * @param boolean $overwrite Overwrite existing license
*/ */
public static function writeFullContent($name, $module, $overwrite) public static function writeFullContent(string $name, array $module, bool $overwrite): void
{ {
if (!isset($module['root']) || !is_writable($module['root'])) { if (!isset($module['root']) || !is_writable($module['root'])) {
throw new Exception(); throw new Exception();
} }
if (file_exists($module['root'] . '/LICENSE') && !$overwrite) { if (file_exists($module['root'] . DIRECTORY_SEPARATOR . 'LICENSE') && !$overwrite) {
return null; return;
} }
file_put_contents( file_put_contents(
$module['root'] . '/LICENSE', $module['root'] . DIRECTORY_SEPARATOR . 'LICENSE',
self::getFull($name) self::getFull($name)
); );
} }
@ -229,7 +235,7 @@ class licenseBootstrap
* @param boolean $overwrite Overwrite existing license * @param boolean $overwrite Overwrite existing license
* @return string File content * @return string File content
*/ */
protected static function replacePhpContent($content, $license, $overwrite) protected static function replacePhpContent(string $content, string $license, bool $overwrite): string
{ {
$clean = preg_replace( $clean = preg_replace(
'/((# -- BEGIN LICENSE BLOCK ([-]+))(.*?)' . '/((# -- BEGIN LICENSE BLOCK ([-]+))(.*?)' .
@ -263,7 +269,7 @@ class licenseBootstrap
* @param boolean $overwrite Overwrite existing license * @param boolean $overwrite Overwrite existing license
* @return string File content * @return string File content
*/ */
protected static function replaceJsContent($content, $license, $overwrite) protected static function replaceJsContent(string $content, string $license, bool $overwrite): string
{ {
$clean = preg_replace( $clean = preg_replace(
'/((\/\* -- BEGIN LICENSE BLOCK ([-]+))(.*?)' . '/((\/\* -- BEGIN LICENSE BLOCK ([-]+))(.*?)' .
@ -290,10 +296,10 @@ class licenseBootstrap
* *
* @param string $content License content * @param string $content License content
* @param array $module Module info * @param array $module Module info
* @param object $user User info * @param dcAuth $user User info
* @return string License content * @return string License content
*/ */
protected static function replaceInfo($content, $module, $user) protected static function replaceInfo(string $content, array $module, dcAuth $user): string
{ {
return str_replace( return str_replace(
[ [
@ -330,10 +336,10 @@ class licenseBootstrap
* @param array $res Ignore * @param array $res Ignore
* @return array List of files * @return array List of files
*/ */
protected static function getModuleFiles($path, $dir = '', $res = []) protected static function getModuleFiles(string $path, string $dir = '', array $res = []): array
{ {
$path = path::real($path); $path = Path::real($path);
if (!is_dir($path) || !is_readable($path)) { if ($path === false || !is_dir($path) || !is_readable($path)) {
return []; return [];
} }
@ -341,34 +347,38 @@ class licenseBootstrap
$dir = $path; $dir = $path;
} }
$files = files::scandir($path); $files = Files::scandir($path);
foreach ($files as $file) { foreach ($files as $file) {
if (substr($file, 0, 1) == '.') { if (substr($file, 0, 1) == '.') {
continue; continue;
} }
if (is_dir($path . '/' . $file)) { if (is_dir($path . DIRECTORY_SEPARATOR . $file)) {
$res = self::getModuleFiles( $res = self::getModuleFiles(
$path . '/' . $file, $path . DIRECTORY_SEPARATOR . $file,
$dir . '/' . $file, $dir . DIRECTORY_SEPARATOR . $file,
$res $res
); );
} else { } else {
$res[] = empty($dir) ? $file : $dir . '/' . $file; $res[] = empty($dir) ? $file : $dir . DIRECTORY_SEPARATOR . $file;
} }
} }
return $res; return $res;
} }
public static function encode($a) public static function encode(string $a): string
{ {
return json_encode($a); $r = json_encode($a);
return $r === false ? '' : $r;
} }
public static function decode($a) public static function decode(string $a): string
{ {
return json_decode($a, true); $r = json_decode($a, true);
return $r === false ? '' : $r;
} }
} }