use namespace

master
Jean-Christian Paul Denis 2023-04-08 21:31:29 +02:00
parent bce80b268a
commit 42aa5ec2cd
Signed by: JcDenis
GPG Key ID: 1B5B8C5B90B6C951
7 changed files with 395 additions and 262 deletions

View File

@ -1,17 +0,0 @@
<?php
/**
* @brief alias, a plugin for Dotclear 2
*
* @package Dotclear
* @subpackage Plugin
*
* @author Olivier Meunier and contributors
*
* @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(['dcAliases' => __DIR__ . '/inc/class.dc.aliases.php']);

View File

@ -10,27 +10,30 @@
* @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_RC_PATH')) { declare(strict_types=1);
return null;
}
class dcAliases namespace Dotclear\Plugin\alias;
use dcCore;
use Exception;
class Alias
{ {
protected $aliases; protected array $aliases;
public function __construct() public function __construct()
{ {
} }
public function getAliases() public function getAliases(): array
{ {
if (is_array($this->aliases)) { if (!empty($this->aliases)) {
return $this->aliases; return $this->aliases;
} }
$this->aliases = []; $this->aliases = [];
$sql = 'SELECT alias_url, alias_destination, alias_position ' . $sql = 'SELECT alias_url, alias_destination, alias_position ' .
'FROM ' . dcCore::app()->prefix . initAlias::ALIAS_TABLE_NAME . ' ' . 'FROM ' . dcCore::app()->prefix . My::ALIAS_TABLE_NAME . ' ' .
"WHERE blog_id = '" . dcCore::app()->con->escapeStr((string) dcCore::app()->blog->id) . "' " . "WHERE blog_id = '" . dcCore::app()->con->escapeStr((string) dcCore::app()->blog->id) . "' " .
'ORDER BY alias_position ASC '; 'ORDER BY alias_position ASC ';
$this->aliases = dcCore::app()->con->select($sql)->rows(); $this->aliases = dcCore::app()->con->select($sql)->rows();
@ -38,9 +41,9 @@ class dcAliases
return $this->aliases; return $this->aliases;
} }
public function updateAliases($aliases) public function updateAliases(array $aliases): void
{ {
usort($aliases, [$this,'sortCallback']); usort($aliases, fn ($a, $b) => (int) $a['alias_position'] <=> (int) $b['alias_position']);
foreach ($aliases as $v) { foreach ($aliases as $v) {
if (!isset($v['alias_url']) || !isset($v['alias_destination'])) { if (!isset($v['alias_url']) || !isset($v['alias_destination'])) {
throw new Exception(__('Invalid aliases definitions')); throw new Exception(__('Invalid aliases definitions'));
@ -65,7 +68,7 @@ class dcAliases
} }
} }
public function createAlias($url, $destination, $position) public function createAlias(string $url, string $destination, int $position): void
{ {
if (!$url) { if (!$url) {
throw new Exception(__('Alias URL is empty.')); throw new Exception(__('Alias URL is empty.'));
@ -75,37 +78,28 @@ class dcAliases
throw new Exception(__('Alias destination is empty.')); throw new Exception(__('Alias destination is empty.'));
} }
$cur = dcCore::app()->con->openCursor(dcCore::app()->prefix . initAlias::ALIAS_TABLE_NAME); $cur = dcCore::app()->con->openCursor(dcCore::app()->prefix . My::ALIAS_TABLE_NAME);
$cur->blog_id = (string) dcCore::app()->blog->id; $cur->setField('blog_id', (string) dcCore::app()->blog->id);
$cur->alias_url = (string) $url; $cur->setField('alias_url', (string) $url);
$cur->alias_destination = (string) $destination; $cur->setField('alias_destination', (string) $destination);
$cur->alias_position = abs((int) $position); $cur->setField('alias_position', abs((int) $position));
$cur->insert(); $cur->insert();
} }
public function deleteAlias($url) public function deleteAlias(string $url): void
{ {
dcCore::app()->con->execute( dcCore::app()->con->execute(
'DELETE FROM ' . dcCore::app()->prefix . initAlias::ALIAS_TABLE_NAME . ' ' . 'DELETE FROM ' . dcCore::app()->prefix . My::ALIAS_TABLE_NAME . ' ' .
"WHERE blog_id = '" . dcCore::app()->con->escapeStr((string) dcCore::app()->blog->id) . "' " . "WHERE blog_id = '" . dcCore::app()->con->escapeStr((string) dcCore::app()->blog->id) . "' " .
"AND alias_url = '" . dcCore::app()->con->escapeStr((string) $url) . "' " "AND alias_url = '" . dcCore::app()->con->escapeStr((string) $url) . "' "
); );
} }
public function deleteAliases() public function deleteAliases(): void
{ {
dcCore::app()->con->execute( dcCore::app()->con->execute(
'DELETE FROM ' . dcCore::app()->prefix . initAlias::ALIAS_TABLE_NAME . ' ' . 'DELETE FROM ' . dcCore::app()->prefix . My::ALIAS_TABLE_NAME . ' ' .
"WHERE blog_id = '" . dcCore::app()->con->escapeStr((string) dcCore::app()->blog->id) . "' " "WHERE blog_id = '" . dcCore::app()->con->escapeStr((string) dcCore::app()->blog->id) . "' "
); );
} }
protected function sortCallback($a, $b)
{
if ($a['alias_position'] == $b['alias_position']) {
return 0;
}
return $a['alias_position'] < $b['alias_position'] ? -1 : 1;
}
} }

View File

@ -10,52 +10,73 @@
* @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;
}
dcCore::app()->menu[dcAdmin::MENU_PLUGINS]->addItem( namespace Dotclear\Plugin\alias;
__('Aliases'),
dcCore::app()->adminurl->get('admin.plugin.alias'),
dcPage::getPF('alias/icon.png'),
preg_match('/' . preg_quote(dcCore::app()->adminurl->get('admin.plugin.alias')) . '(&.*)?$/', $_SERVER['REQUEST_URI']),
dcCore::app()->auth->check(dcCore::app()->auth->makePermissions([dcAuth::PERMISSION_ADMIN]), dcCore::app()->blog->id)
);
dcCore::app()->addBehavior('exportFullV2', function ($exp) { use dcAdmin;
$exp->exportTable('alias'); use dcCore;
}); use dcNsProcess;
use dcPage;
use Dotclear\Plugin\importExport\FlatBackupItem;
use Dotclear\Plugin\importExport\FlatExport;
use Dotclear\Plugin\importExport\FlatImportV2;
dcCore::app()->addBehavior('exportSingleV2', function ($exp, $blog_id) { class Backend extends dcNsProcess
{
public static function init(): bool
{
static::$init = defined('DC_CONTEXT_ADMIN')
&& dcCore::app()->auth->check(dcCore::app()->auth->makePermissions([
dcCore::app()->auth::PERMISSION_ADMIN,
]), dcCore::app()->blog->id);
return static::$init;
}
public static function process(): bool
{
if (!static::$init) {
return false;
}
dcCore::app()->menu[dcAdmin::MENU_PLUGINS]->addItem(
My::name(),
dcCore::app()->adminurl->get('admin.plugin.' . My::id()),
dcPage::getPF(My::id() . '/icon.png'),
preg_match('/' . preg_quote(dcCore::app()->adminurl->get('admin.plugin.' . My::id())) . '(&.*)?$/', $_SERVER['REQUEST_URI']),
dcCore::app()->auth->check(dcCore::app()->auth->makePermissions([dcCore::app()->auth::PERMISSION_ADMIN]), dcCore::app()->blog->id)
);
dcCore::app()->addBehaviors([
'exportFullV2' => function (FlatExport $exp): void {
$exp->exportTable(My::ALIAS_TABLE_NAME);
},
'exportSingleV2' => function (FlatExport $exp, ?string $blog_id): void {
$exp->export( $exp->export(
'alias', 'alias',
'SELECT alias_url, alias_destination, alias_position ' . 'SELECT alias_url, alias_destination, alias_position ' .
'FROM ' . dcCore::app()->prefix . initAlias::ALIAS_TABLE_NAME . ' A ' . 'FROM ' . dcCore::app()->prefix . My::ALIAS_TABLE_NAME . ' A ' .
"WHERE A.blog_id = '" . $blog_id . "'" "WHERE A.blog_id = '" . $blog_id . "'"
); );
}); },
'importInitV2' => function (FlatImportV2 $bk): void {
dcCore::app()->addBehavior('importInitV2', function ($bk) { $bk->cur_alias = dcCore::app()->con->openCursor(dcCore::app()->prefix . My::ALIAS_TABLE_NAME);
$bk->cur_alias = dcCore::app()->con->openCursor(dcCore::app()->prefix . initAlias::ALIAS_TABLE_NAME); $bk->alias = new Alias();
$bk->alias = new dcAliases();
$bk->aliases = $bk->alias->getAliases(); $bk->aliases = $bk->alias->getAliases();
}); },
'importFullV2' => function (bool|FlatBackupItem $line, FlatImportV2 $bk): void {
dcCore::app()->addBehavior('importFullV2', function ($line, $bk) { if ($line->__name == My::ALIAS_TABLE_NAME) {
if ($line->__name == 'alias') {
$bk->cur_alias->clean(); $bk->cur_alias->clean();
$bk->cur_alias->setField('blog_id', (string) $line->blog_id);
$bk->cur_alias->blog_id = (string) $line->blog_id; $bk->cur_alias->setField('alias_url', (string) $line->alias_url);
$bk->cur_alias->alias_url = (string) $line->alias_url; $bk->cur_alias->setField('alias_destination', (string) $line->alias_destination);
$bk->cur_alias->alias_destination = (string) $line->alias_destination; $bk->cur_alias->setField('alias_position', (int) $line->alias_position);
$bk->cur_alias->alias_position = (int) $line->alias_position;
$bk->cur_alias->insert(); $bk->cur_alias->insert();
} }
}); },
'importSingleV2' => function (bool|FlatBackupItem $line, FlatImportV2 $bk): void {
dcCore::app()->addBehavior('importSingleV2', function ($line, $bk) { if ($line->__name == My::ALIAS_TABLE_NAME) {
if ($line->__name == 'alias') {
$found = false; $found = false;
foreach ($bk->aliases as $v) { foreach ($bk->aliases as $v) {
if ($v['alias_url'] == $line->alias_url) { if ($v['alias_url'] == $line->alias_url) {
@ -67,4 +88,9 @@ dcCore::app()->addBehavior('importSingleV2', function ($line, $bk) {
} }
$bk->alias->createAlias($line->alias_url, $line->alias_destination, $line->alias_position); $bk->alias->createAlias($line->alias_url, $line->alias_destination, $line->alias_position);
} }
}); },
]);
return true;
}
}

View File

@ -10,16 +10,32 @@
* @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_RC_PATH')) { declare(strict_types=1);
return null;
}
dcCore::app()->url->register('alias', '', '^(.*)$', function ($args) { namespace Dotclear\Plugin\alias;
$o = new dcAliases();
$aliases = $o->getAliases(); use dcCore;
use dcNsProcess;
class Frontend extends dcNsProcess
{
public static function init(): bool
{
static::$init = defined('DC_RC_PATH');
return static::$init;
}
public static function process(): bool
{
if (!static::$init) {
return false;
}
dcCore::app()->url->register('alias', '', '^(.*)$', function (string $args): void {
$part = $args; $part = $args;
foreach ($aliases as $v) { foreach ((new Alias())->getAliases() as $v) {
if (@preg_match('#^/.*/$#', $v['alias_url']) && @preg_match($v['alias_url'], $args)) { if (@preg_match('#^/.*/$#', $v['alias_url']) && @preg_match($v['alias_url'], $args)) {
$part = preg_replace($v['alias_url'], $v['alias_destination'], $args); $part = preg_replace($v['alias_url'], $v['alias_destination'], $args);
@ -39,4 +55,8 @@ dcCore::app()->url->register('alias', '', '^(.*)$', function ($args) {
} else { } else {
dcCore::app()->url->callHandler($type, $args); dcCore::app()->url->callHandler($type, $args);
} }
}); });
return true;
}
}

View File

@ -10,20 +10,33 @@
* @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;
}
try { namespace Dotclear\Plugin\alias;
if (!dcCore::app()->newVersion(
basename(__DIR__), use dbStruct;
dcCore::app()->plugins->moduleInfo(basename(__DIR__), 'version') use dcCore;
)) { use dcNsProcess;
return null; use Exception;
class Install extends dcNsProcess
{
public static function init(): bool
{
static::$init = defined('DC_CONTEXT_ADMIN') && dcCore::app()->newVersion(My::id(), dcCore::app()->plugins->moduleInfo(My::id(), 'version'));
return static::$init;
} }
public static function process(): bool
{
if (!static::$init) {
return false;
}
try {
$s = new dbStruct(dcCore::app()->con, dcCore::app()->prefix); $s = new dbStruct(dcCore::app()->con, dcCore::app()->prefix);
$s->{initAlias::ALIAS_TABLE_NAME} $s->{My::ALIAS_TABLE_NAME}
->blog_id('varchar', 32, false) ->blog_id('varchar', 32, false)
->alias_url('varchar', 255, false) ->alias_url('varchar', 255, false)
->alias_destination('varchar', 255, false) ->alias_destination('varchar', 255, false)
@ -37,12 +50,13 @@ try {
->reference('fk_alias_blog', 'blog_id', 'blog', 'blog_id', 'cascade', 'cascade') ->reference('fk_alias_blog', 'blog_id', 'blog', 'blog_id', 'cascade', 'cascade')
; ;
$si = new dbStruct(dcCore::app()->con, dcCore::app()->prefix); (new dbStruct(dcCore::app()->con, dcCore::app()->prefix))->synchronize($s);
$changes = $si->synchronize($s);
return true; return true;
} catch (Exception $e) { } catch (Exception $e) {
dcCore::app()->error->add($e->getMessage()); dcCore::app()->error->add($e->getMessage());
}
return false; return false;
}
}
}

View File

@ -10,73 +10,132 @@
* @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;
}
dcPage::check(dcCore::app()->auth->makePermissions([dcAuth::PERMISSION_ADMIN])); namespace Dotclear\Plugin\alias;
$o = new dcAliases(); use dcCore;
$aliases = $o->getAliases(); use dcNsProcess;
$part = $_REQUEST['part'] ?? 'list'; use dcPage;
use Dotclear\Helper\Html\Form\{
Div,
Form,
Hidden,
Input,
Label,
Note,
Number,
Para,
Submit,
Text
};
use Dotclear\Helper\Html\Html;
use Exception;
# Update aliases /**
if (isset($_POST['a']) && is_array($_POST['a'])) { * Manage contributions list
*/
class Manage extends dcNsProcess
{
public static function init(): bool
{
static::$init = defined('DC_CONTEXT_ADMIN')
&& dcCore::app()->auth->check(
dcCore::app()->auth->makePermissions([
dcCore::app()->auth::PERMISSION_ADMIN,
]),
dcCore::app()->blog->id
);
return static::$init;
}
public static function process(): bool
{
if (!static::$init) {
return false;
}
if (empty($_POST) || empty($_POST['a']) && empty($_POST['alias_url'])) {
return true;
}
$alias = new Alias();
$aliases = $alias->getAliases();
# Update aliases
if (isset($_POST['a']) && is_array($_POST['a'])) {
try { try {
$o->updateAliases($_POST['a']); $alias->updateAliases($_POST['a']);
dcAdminNotices::addSuccessNotice(__('Aliases successfully updated.')); dcPage::addSuccessNotice(__('Aliases successfully updated.'));
dcCore::app()->adminurl->redirect('admin.plugin.alias'); dcCore::app()->adminurl->redirect('admin.plugin.' . My::id());
} catch (Exception $e) { } catch (Exception $e) {
dcCore::app()->error->add($e->getMessage()); dcCore::app()->error->add($e->getMessage());
} }
} }
# New alias # New alias
if (isset($_POST['alias_url'])) { if (isset($_POST['alias_url'])) {
try { try {
$o->createAlias($_POST['alias_url'], $_POST['alias_destination'], count($aliases) + 1); $alias->createAlias($_POST['alias_url'], $_POST['alias_destination'], count($aliases) + 1);
dcAdminNotices::addSuccessNotice(__('Alias successfully created.')); dcPage::addSuccessNotice(__('Alias successfully created.'));
dcCore::app()->adminurl->redirect('admin.plugin.alias'); dcCore::app()->adminurl->redirect('admin.plugin.' . My::id());
} catch (Exception $e) { } catch (Exception $e) {
dcCore::app()->error->add($e->getMessage()); dcCore::app()->error->add($e->getMessage());
} }
} }
?>
<html>
<head>
<title><?php echo __('Aliases'); ?></title>
</head>
<body> return true;
<?php }
if ($part == 'new') { public static function render(): void
{
if (!static::$init) {
return;
}
$alias = new Alias();
$aliases = $alias->getAliases();
dcPage::openModule(My::name());
if (($_REQUEST['part'] ?? 'list') == 'new') {
echo echo
dcPage::breadcrumb([ dcPage::breadcrumb([
__('Plugins') => '', __('Plugins') => '',
__('Aliases') => dcCore::app()->adminurl->get('admin.plugin.alias', ['part' => 'list']), My::name() => dcCore::app()->adminurl->get('admin.plugin.' . My::id(), ['part' => 'list']),
__('New alias') => '', __('New alias') => '',
]) . ]) .
dcPage::notices() . dcPage::notices() .
'<h3>' . __('New alias') . '</h3>' .
'<form action="' . dcCore::app()->admin->getPageURL() . '" method="post">' . (new Div())->items([
'<p class="field"><label>' . __('Alias URL:') . ' ' . form::field('alias_url', 50, 255) . '</label></p>' . (new Text('h3', __('New alias'))),
'<p class="field"><label>' . __('Alias destination:') . ' ' . form::field('alias_destination', 50, 255) . '</label></p>' . (new Form(My::id() . '_form'))->method('post')->action(dcCore::app()->admin->getPageURL())->fields([
'<p class="form-note">' . sprintf(__('Do not put blog URL "%s" in fields.'), dcCore::app()->blog->url) . '</p>' . (new Para())->class('field')->items([
'<p>' . (new Label(__('Alias URL:')))->for('alias_url'),
dcCore::app()->formNonce() . (new Input('alias_url'))->size(50)->maxlenght(255),
form::hidden('part', 'new') . ]),
'<input type="submit" value="' . __('Save') . '" /></p>' . (new Para())->class('field')->items([
'</form>'; (new Label(__('Alias destination:')))->for('alias_destination'),
} else { (new Input('alias_destination'))->size(50)->maxlenght(255),
]),
(new Note())->text(sprintf(__('Do not put blog URL "%s" in fields.'), dcCore::app()->blog->url)),
(new Para())->items([
dcCore::app()->formNonce(false),
(new Hidden('part', 'new')),
(new Submit(['do']))->value(__('Save')),
]),
]),
])->render();
} else {
echo echo
dcPage::breadcrumb([ dcPage::breadcrumb([
__('Plugins') => '', __('Plugins') => '',
__('Aliases') => '', My::name() => '',
]) . ]) .
dcPage::notices() . dcPage::notices() .
'<p class="top-add"><a class="button add" href="' . '<p class="top-add"><a class="button add" href="' .
dcCore::app()->adminurl->get('admin.plugin.alias', ['part' => 'new']) . dcCore::app()->adminurl->get('admin.plugin.' . My::id(), ['part' => 'new']) .
'">' . __('New alias') . '</a></p>'; '">' . __('New alias') . '</a></p>';
if (empty($aliases)) { if (empty($aliases)) {
@ -100,32 +159,27 @@ if ($part == 'new') {
echo echo
'<tr class="line" id="l_' . $k . '">' . '<tr class="line" id="l_' . $k . '">' .
'<td>' . '<td>' .
form::field(['a[' . $k . '][alias_url]'], 50, 255, html::escapeHTML($v['alias_url'])) . '</td>' . (new Input(['a[' . $k . '][alias_url]']))->size(50)->maxlenght(255)->value(Html::escapeHTML($v['alias_url']))->render() . '</td>' .
'<td class="maximal">' . '<td class="maximal">' .
form::field(['a[' . $k . '][alias_destination]'], 50, 255, html::escapeHTML($v['alias_destination'])) . '</td>' . (new Input(['a[' . $k . '][alias_destination]']))->size(50)->maxlenght(255)->value(Html::escapeHTML($v['alias_destination']))->render() . '</td>' .
'<td class="minimal">' . '<td class="minimal">' .
form::number(['a[' . $k . '][alias_position]'], [ (new Number(['a[' . $k . '][alias_position]']))->min(1)->max(count($aliases))->default((int) $v['alias_position'])->class('position')->title(sprintf(__('position of %s'), Html::escapeHTML($v['alias_url'])))->render() . '</td>' .
'min' => 1,
'max' => count($aliases),
'default' => (int) $v['alias_position'],
'class' => 'position',
'extra_html' => 'title="' . sprintf(__('position of %s'), html::escapeHTML($v['alias_url'])) . '"',
]) . '</td>' .
'</tr>'; '</tr>';
} }
echo echo
'</tbody></table></div>' . '</tbody></table></div>' .
'<p class="form-note">' . __('To remove an alias, empty its URL or destination.') . '</p>' . '<p class="form-note">' . __('To remove an alias, empty its URL or destination.') . '</p>' .
'<p>' . (new Para())->items([
dcCore::app()->formNonce() . dcCore::app()->formNonce(false),
form::hidden('part', 'list') . (new Hidden('part', 'list')),
'<input type="submit" value="' . __('Update') . '" /></p>' . (new Submit(['upd']))->value(__('Update')),
])->render() .
'</form>'; '</form>';
} }
} }
dcPage::helpBlock('alias'); dcPage::helpBlock('alias');
?> dcPage::closeModule();
</body> }
</html> }

42
src/My.php 100644
View File

@ -0,0 +1,42 @@
<?php
/**
* @brief alias, a plugin for Dotclear 2
*
* @package Dotclear
* @subpackage Plugin
*
* @author Olivier Meunier 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\alias;
use dcCore;
/**
* Plugin definitions
*/
class My
{
/** @var string Plugin table name */
public const ALIAS_TABLE_NAME = 'alias';
/**
* 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'));
}
}