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

View File

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

View File

@ -10,112 +10,66 @@
* @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
if (!defined('DC_CONTEXT_ADMIN')) {
return null;
}
declare(strict_types=1);
# -- Module specs --
namespace Dotclear\Plugin\licenseBootstrap;
$mod_conf = [
[
'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',
],
];
use dcCore;
use dcNamespace;
use dcNsProcess;
use Exception;
# -- Nothing to change below --
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'));
try {
# Check module version
if (!dcCore::app()->newVersion(
basename(__DIR__),
dcCore::app()->plugins->moduleInfo(basename(__DIR__), 'version')
)) {
return null;
return static::$init;
}
// 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();
public static function process(): bool
{
if (!static::$init) {
return false;
}
try {
// Upgrade
self::growUp();
return true;
} catch (Exception $e) {
dcCore::app()->error->add($e->getMessage());
return false;
}
}
# 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
);
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();
}
}
}
return true;
} catch (Exception $e) {
dcCore::app()->error->add($e->getMessage());
return false;
}

View File

@ -10,94 +10,214 @@
* @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
if (!defined('DC_CONTEXT_ADMIN')) {
return null;
}
declare(strict_types=1);
dcPage::checkSuper();
namespace Dotclear\Plugin\licenseBootstrap;
# Queries
$action = $_POST['action'] ?? '';
$type = isset($_POST['type']) && in_array($_POST['type'], ['plugins', 'themes']) ? $_POST['type'] : '';
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;
# Settings
$s = dcCore::app()->blog->settings->addNamespace(basename(__DIR__));
class Manage extends dcNsProcess
{
public static function init(): bool
{
static::$init = defined('DC_CONTEXT_ADMIN')
&& dcCore::app()->auth?->isSuperAdmin()
&& My::phpCompliant();
# 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;
return static::$init;
}
# Rights
$is_editable = !empty($type)
&& !empty($_POST['modules'])
&& is_array($_POST['modules']);
# Actions
try {
# Add license to modules
if ($action == 'addlicense' && $is_editable) {
$modules = array_keys($_POST['modules']);
foreach ($modules as $id) {
if (!${$type}->moduleExists($id)) {
throw new Exception('No such module');
}
$module = ${$type}->getModules($id);
$module['id'] = $id;
$module['type'] = $type == 'themes' ? 'theme' : 'plugin';
licenseBootstrap::addLicense($module);
public static function process(): bool
{
if (!static::$init) {
return false;
}
dcAdminNotices::addSuccessNotice(
__('License successfully added.')
);
http::redirect(
empty($_POST['redir']) ?
dcCore::app()->admin->getPageURL() : $_POST['redir']
);
$type = in_array($_POST['type'] ?? '', ['plugins', 'themes']) ? $_POST['type'] : '';
if (($_POST['action'] ?? '') != 'addlicense'
|| empty($type)
|| empty($_POST['modules'])
|| !is_array($_POST['modules'])
) {
return true;
}
$m = self::loadModules();
# Actions
try {
$modules = array_values($_POST['modules']);
foreach ($modules as $id) {
if (!$m[$type]->moduleExists($id)) {
throw new Exception('No such module');
}
$module = $m[$type]->getModules($id);
$module['id'] = $id;
$module['type'] = $type == 'themes' ? 'theme' : 'plugin';
Utils::addLicense($module);
}
dcPage::addSuccessNotice(
__('License successfully added.')
);
http::redirect(
empty($_POST['redir']) ?
dcCore::app()->admin->getPageURL() : $_POST['redir']
);
} catch(Exception $e) {
dcCore::app()->error->add($e->getMessage());
}
return true;
}
public static function render(): void
{
if (!static::$init) {
return;
}
$m = self::loadModules();
# Display
dcPage::openModule(
My::name(),
dcPage::jsPageTabs() .
dcPage::jsModuleLoad(My::id() . '/js/licensebootstrap.js') .
# --BEHAVIOR-- licenseBootstrapAdminHeader
dcCore::app()->callBehavior('licenseBootstrapAdminHeader')
);
echo
dcPage::breadcrumb([
__('Plugins') => '',
My::name() => '',
]) .
dcPage::notices();
self::displayModulesList(
$m['plugins']->getModules(),
'plugins',
__('Installed plugins')
);
self::displayModulesList(
$m['themes']->getModules(),
'themes',
__('Installed themes')
);
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
'<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,
];
}
} catch(Exception $e) {
dcCore::app()->error->add($e->getMessage());
}
# Display
echo
'<html><head><title>' . __('License bootstrap') . '</title>' .
dcPage::jsPageTabs() .
dcPage::jsModuleLoad(basename(__DIR__) . '/js/licensebootstrap.js') .
# --BEHAVIOR-- licenseBootstrapAdminHeader
dcCore::app()->callBehavior('licenseBootstrapAdminHeader') .
'</head><body>' .
dcPage::breadcrumb(
[
__('Plugins') => '',
__('License bootstrap') => '',
]
) .
dcPage::notices();
libLicenseBootstrap::modules(
$plugins->getModules(),
'plugins',
__('Installed plugins')
);
libLicenseBootstrap::modules(
$themes->getModules(),
'themes',
__('Installed themes')
);
dcPage::helpBlock('licenseBootstrap');
echo
'</body></html>';

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

View File

@ -10,13 +10,19 @@
* @copyright Jean-Christian Denis
* @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html
*/
if (!defined('DC_CONTEXT_ADMIN')) {
return null;
}
declare(strict_types=1);
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.
@ -26,9 +32,9 @@ class licenseBootstrap
*
* @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
dcCore::app()->callBehavior(
@ -36,22 +42,22 @@ class licenseBootstrap
$module
);
if ($s->get('write_full')) {
licenseBootstrap::writeFullContent(
$s->get('license_name'),
if ($s->write_full) {
self::writeFullContent(
$s->license_name,
$module,
$s->get('overwrite')
$s->overwrite
);
}
licenseBootstrap::writeHeadContent(
$s->get('license_name'),
licenseBootstrap::decode($s->get('license_head')),
self::writeHeadContent(
$s->license_name,
self::decode($s->license_head),
$module,
dcCore::app()->auth,
$s->get('overwrite'),
$s->get('write_php'),
$s->get('write_js'),
$s->get('exclude_locales')
$s->overwrite,
$s->write_php,
$s->write_js,
$s->exclude_locales
);
# --BEHAVIOR-- licenseBootstrapAfterAddLicense
@ -66,20 +72,20 @@ class licenseBootstrap
*
* @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$/';
$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)) {
$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
* @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';
}
@ -102,7 +108,7 @@ class licenseBootstrap
* @param string $content 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())) {
$name = 'gpl2';
@ -119,7 +125,7 @@ class licenseBootstrap
* @param string $name License name
* @return string Full license content
*/
public static function getFull($name = 'gpl2')
public static function getFull(string $name = 'gpl2'): string
{
return self::getContent($name, 'full');
}
@ -131,7 +137,7 @@ class licenseBootstrap
* @param string $part License part (head or full)
* @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())) {
$name = 'gpl2';
@ -140,8 +146,8 @@ class licenseBootstrap
$part = 'head';
}
return file_get_contents(
dirname(__FILE__) . '/licenses/' . $name . '.' . $part . '.txt'
return (string) file_get_contents(
implode(DIRECTORY_SEPARATOR, [__DIR__, My::TEMPLATE_FOLDER, $name . '.' . $part . '.txt'])
);
}
@ -151,13 +157,13 @@ class licenseBootstrap
* @param string $name License name
* @param string $content License block content
* @param array $module Module info
* @param object $user dcAuth instance
* @param dcAuth $user dcAuth instance
* @param boolean $overwrite Overwrite existing license
* @param boolean $php Write license in PHP
* @param boolean $js Write license in JS
* @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'])) {
throw new Exception();
@ -174,14 +180,14 @@ class licenseBootstrap
continue;
}
$path = $module['root'] . '/' . $file;
$extension = files::getExtension($file);
$path = $module['root'] . DIRECTORY_SEPARATOR . $file;
$extension = Files::getExtension($file);
if ($php && $extension == 'php') {
file_put_contents(
$file,
self::replacePhpContent(
file_get_contents($file),
(string) file_get_contents($file),
$license,
$overwrite
)
@ -190,7 +196,7 @@ class licenseBootstrap
file_put_contents(
$file,
self::replaceJsContent(
file_get_contents($file),
(string) file_get_contents($file),
$license,
$overwrite
)
@ -206,17 +212,17 @@ class licenseBootstrap
* @param array $module Module info
* @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'])) {
throw new Exception();
}
if (file_exists($module['root'] . '/LICENSE') && !$overwrite) {
return null;
if (file_exists($module['root'] . DIRECTORY_SEPARATOR . 'LICENSE') && !$overwrite) {
return;
}
file_put_contents(
$module['root'] . '/LICENSE',
$module['root'] . DIRECTORY_SEPARATOR . 'LICENSE',
self::getFull($name)
);
}
@ -229,7 +235,7 @@ class licenseBootstrap
* @param boolean $overwrite Overwrite existing license
* @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(
'/((# -- BEGIN LICENSE BLOCK ([-]+))(.*?)' .
@ -263,7 +269,7 @@ class licenseBootstrap
* @param boolean $overwrite Overwrite existing license
* @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(
'/((\/\* -- BEGIN LICENSE BLOCK ([-]+))(.*?)' .
@ -290,10 +296,10 @@ class licenseBootstrap
*
* @param string $content License content
* @param array $module Module info
* @param object $user User info
* @param dcAuth $user User info
* @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(
[
@ -330,10 +336,10 @@ class licenseBootstrap
* @param array $res Ignore
* @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);
if (!is_dir($path) || !is_readable($path)) {
$path = Path::real($path);
if ($path === false || !is_dir($path) || !is_readable($path)) {
return [];
}
@ -341,34 +347,38 @@ class licenseBootstrap
$dir = $path;
}
$files = files::scandir($path);
$files = Files::scandir($path);
foreach ($files as $file) {
if (substr($file, 0, 1) == '.') {
continue;
}
if (is_dir($path . '/' . $file)) {
if (is_dir($path . DIRECTORY_SEPARATOR . $file)) {
$res = self::getModuleFiles(
$path . '/' . $file,
$dir . '/' . $file,
$path . DIRECTORY_SEPARATOR . $file,
$dir . DIRECTORY_SEPARATOR . $file,
$res
);
} else {
$res[] = empty($dir) ? $file : $dir . '/' . $file;
$res[] = empty($dir) ? $file : $dir . DIRECTORY_SEPARATOR . $file;
}
}
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;
}
}