diff --git a/_prepend.php b/_prepend.php deleted file mode 100644 index ba52679..0000000 --- a/_prepend.php +++ /dev/null @@ -1,17 +0,0 @@ -autoload(['dcAliases' => __DIR__ . '/inc/class.dc.aliases.php']); diff --git a/src/Alias.php b/src/Alias.php index fc727a6..83feeb6 100644 --- a/src/Alias.php +++ b/src/Alias.php @@ -10,27 +10,30 @@ * @copyright Jean-Christian Denis * @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html */ -if (!defined('DC_RC_PATH')) { - return null; -} +declare(strict_types=1); -class dcAliases +namespace Dotclear\Plugin\alias; + +use dcCore; +use Exception; + +class Alias { - protected $aliases; + protected array $aliases; public function __construct() { } - public function getAliases() + public function getAliases(): array { - if (is_array($this->aliases)) { + if (!empty($this->aliases)) { return $this->aliases; } $this->aliases = []; $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) . "' " . 'ORDER BY alias_position ASC '; $this->aliases = dcCore::app()->con->select($sql)->rows(); @@ -38,9 +41,9 @@ class dcAliases 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) { if (!isset($v['alias_url']) || !isset($v['alias_destination'])) { 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) { throw new Exception(__('Alias URL is empty.')); @@ -75,37 +78,28 @@ class dcAliases throw new Exception(__('Alias destination is empty.')); } - $cur = dcCore::app()->con->openCursor(dcCore::app()->prefix . initAlias::ALIAS_TABLE_NAME); - $cur->blog_id = (string) dcCore::app()->blog->id; - $cur->alias_url = (string) $url; - $cur->alias_destination = (string) $destination; - $cur->alias_position = abs((int) $position); + $cur = dcCore::app()->con->openCursor(dcCore::app()->prefix . My::ALIAS_TABLE_NAME); + $cur->setField('blog_id', (string) dcCore::app()->blog->id); + $cur->setField('alias_url', (string) $url); + $cur->setField('alias_destination', (string) $destination); + $cur->setField('alias_position', abs((int) $position)); $cur->insert(); } - public function deleteAlias($url) + public function deleteAlias(string $url): void { 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) . "' " . "AND alias_url = '" . dcCore::app()->con->escapeStr((string) $url) . "' " ); } - public function deleteAliases() + public function deleteAliases(): void { 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) . "' " ); } - - protected function sortCallback($a, $b) - { - if ($a['alias_position'] == $b['alias_position']) { - return 0; - } - - return $a['alias_position'] < $b['alias_position'] ? -1 : 1; - } } diff --git a/src/Backend.php b/src/Backend.php index cd79b56..6636081 100644 --- a/src/Backend.php +++ b/src/Backend.php @@ -10,61 +10,87 @@ * @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\alias; + +use dcAdmin; +use dcCore; +use dcNsProcess; +use dcPage; +use Dotclear\Plugin\importExport\FlatBackupItem; +use Dotclear\Plugin\importExport\FlatExport; +use Dotclear\Plugin\importExport\FlatImportV2; + +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( + 'alias', + 'SELECT alias_url, alias_destination, alias_position ' . + 'FROM ' . dcCore::app()->prefix . My::ALIAS_TABLE_NAME . ' A ' . + "WHERE A.blog_id = '" . $blog_id . "'" + ); + }, + 'importInitV2' => function (FlatImportV2 $bk): void { + $bk->cur_alias = dcCore::app()->con->openCursor(dcCore::app()->prefix . My::ALIAS_TABLE_NAME); + $bk->alias = new Alias(); + $bk->aliases = $bk->alias->getAliases(); + }, + 'importFullV2' => function (bool|FlatBackupItem $line, FlatImportV2 $bk): void { + if ($line->__name == My::ALIAS_TABLE_NAME) { + $bk->cur_alias->clean(); + $bk->cur_alias->setField('blog_id', (string) $line->blog_id); + $bk->cur_alias->setField('alias_url', (string) $line->alias_url); + $bk->cur_alias->setField('alias_destination', (string) $line->alias_destination); + $bk->cur_alias->setField('alias_position', (int) $line->alias_position); + $bk->cur_alias->insert(); + } + }, + 'importSingleV2' => function (bool|FlatBackupItem $line, FlatImportV2 $bk): void { + if ($line->__name == My::ALIAS_TABLE_NAME) { + $found = false; + foreach ($bk->aliases as $v) { + if ($v['alias_url'] == $line->alias_url) { + $found = true; + } + } + if ($found) { + $bk->alias->deleteAlias($line->alias_url); + } + $bk->alias->createAlias($line->alias_url, $line->alias_destination, $line->alias_position); + } + }, + ]); + + return true; + } } - -dcCore::app()->menu[dcAdmin::MENU_PLUGINS]->addItem( - __('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) { - $exp->exportTable('alias'); -}); - -dcCore::app()->addBehavior('exportSingleV2', function ($exp, $blog_id) { - $exp->export( - 'alias', - 'SELECT alias_url, alias_destination, alias_position ' . - 'FROM ' . dcCore::app()->prefix . initAlias::ALIAS_TABLE_NAME . ' A ' . - "WHERE A.blog_id = '" . $blog_id . "'" - ); -}); - -dcCore::app()->addBehavior('importInitV2', function ($bk) { - $bk->cur_alias = dcCore::app()->con->openCursor(dcCore::app()->prefix . initAlias::ALIAS_TABLE_NAME); - $bk->alias = new dcAliases(); - $bk->aliases = $bk->alias->getAliases(); -}); - -dcCore::app()->addBehavior('importFullV2', function ($line, $bk) { - if ($line->__name == 'alias') { - $bk->cur_alias->clean(); - - $bk->cur_alias->blog_id = (string) $line->blog_id; - $bk->cur_alias->alias_url = (string) $line->alias_url; - $bk->cur_alias->alias_destination = (string) $line->alias_destination; - $bk->cur_alias->alias_position = (int) $line->alias_position; - - $bk->cur_alias->insert(); - } -}); - -dcCore::app()->addBehavior('importSingleV2', function ($line, $bk) { - if ($line->__name == 'alias') { - $found = false; - foreach ($bk->aliases as $v) { - if ($v['alias_url'] == $line->alias_url) { - $found = true; - } - } - if ($found) { - $bk->alias->deleteAlias($line->alias_url); - } - $bk->alias->createAlias($line->alias_url, $line->alias_destination, $line->alias_position); - } -}); diff --git a/src/Frontend.php b/src/Frontend.php index aad4bef..87970bd 100644 --- a/src/Frontend.php +++ b/src/Frontend.php @@ -10,33 +10,53 @@ * @copyright Jean-Christian Denis * @copyright GPL-2.0 https://www.gnu.org/licenses/gpl-2.0.html */ -if (!defined('DC_RC_PATH')) { - return null; -} +declare(strict_types=1); -dcCore::app()->url->register('alias', '', '^(.*)$', function ($args) { - $o = new dcAliases(); - $aliases = $o->getAliases(); - $part = $args; +namespace Dotclear\Plugin\alias; - foreach ($aliases as $v) { - if (@preg_match('#^/.*/$#', $v['alias_url']) && @preg_match($v['alias_url'], $args)) { - $part = preg_replace($v['alias_url'], $v['alias_destination'], $args); +use dcCore; +use dcNsProcess; - break; - } elseif ($v['alias_url'] == $args) { - $part = $v['alias_destination']; +class Frontend extends dcNsProcess +{ + public static function init(): bool + { + static::$init = defined('DC_RC_PATH'); - break; + return static::$init; + } + + public static function process(): bool + { + if (!static::$init) { + return false; } - } - dcCore::app()->url->unregister('alias'); - dcCore::app()->url->getArgs($part, $type, $args); + dcCore::app()->url->register('alias', '', '^(.*)$', function (string $args): void { + $part = $args; - if (!$type) { - dcCore::app()->url->callDefaultHandler($args); - } else { - dcCore::app()->url->callHandler($type, $args); + foreach ((new Alias())->getAliases() as $v) { + if (@preg_match('#^/.*/$#', $v['alias_url']) && @preg_match($v['alias_url'], $args)) { + $part = preg_replace($v['alias_url'], $v['alias_destination'], $args); + + break; + } elseif ($v['alias_url'] == $args) { + $part = $v['alias_destination']; + + break; + } + } + + dcCore::app()->url->unregister('alias'); + dcCore::app()->url->getArgs($part, $type, $args); + + if (!$type) { + dcCore::app()->url->callDefaultHandler($args); + } else { + dcCore::app()->url->callHandler($type, $args); + } + }); + + return true; } -}); +} diff --git a/src/Install.php b/src/Install.php index 96f5a30..4554525 100644 --- a/src/Install.php +++ b/src/Install.php @@ -10,39 +10,53 @@ * @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); -try { - if (!dcCore::app()->newVersion( - basename(__DIR__), - dcCore::app()->plugins->moduleInfo(basename(__DIR__), 'version') - )) { - return null; +namespace Dotclear\Plugin\alias; + +use dbStruct; +use dcCore; +use dcNsProcess; +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; } - $s = new dbStruct(dcCore::app()->con, dcCore::app()->prefix); - $s->{initAlias::ALIAS_TABLE_NAME} - ->blog_id('varchar', 32, false) - ->alias_url('varchar', 255, false) - ->alias_destination('varchar', 255, false) - ->alias_position('smallint', 0, false, 1) + public static function process(): bool + { + if (!static::$init) { + return false; + } - ->primary('pk_alias', 'blog_id', 'alias_url') + try { + $s = new dbStruct(dcCore::app()->con, dcCore::app()->prefix); + $s->{My::ALIAS_TABLE_NAME} + ->blog_id('varchar', 32, false) + ->alias_url('varchar', 255, false) + ->alias_destination('varchar', 255, false) + ->alias_position('smallint', 0, false, 1) - ->index('idx_alias_blog_id', 'btree', 'blog_id') - ->index('idx_alias_blog_id_alias_position', 'btree', 'blog_id', 'alias_position') + ->primary('pk_alias', 'blog_id', 'alias_url') - ->reference('fk_alias_blog', 'blog_id', 'blog', 'blog_id', 'cascade', 'cascade') - ; + ->index('idx_alias_blog_id', 'btree', 'blog_id') + ->index('idx_alias_blog_id_alias_position', 'btree', 'blog_id', 'alias_position') - $si = new dbStruct(dcCore::app()->con, dcCore::app()->prefix); - $changes = $si->synchronize($s); + ->reference('fk_alias_blog', 'blog_id', 'blog', 'blog_id', 'cascade', 'cascade') + ; - return true; -} catch (Exception $e) { - dcCore::app()->error->add($e->getMessage()); + (new dbStruct(dcCore::app()->con, dcCore::app()->prefix))->synchronize($s); + + return true; + } catch (Exception $e) { + dcCore::app()->error->add($e->getMessage()); + + return false; + } + } } - -return false; diff --git a/src/Manage.php b/src/Manage.php index 98e4531..4d89e8c 100644 --- a/src/Manage.php +++ b/src/Manage.php @@ -10,122 +10,176 @@ * @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::check(dcCore::app()->auth->makePermissions([dcAuth::PERMISSION_ADMIN])); +namespace Dotclear\Plugin\alias; -$o = new dcAliases(); -$aliases = $o->getAliases(); -$part = $_REQUEST['part'] ?? 'list'; +use dcCore; +use dcNsProcess; +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'])) { - try { - $o->updateAliases($_POST['a']); - dcAdminNotices::addSuccessNotice(__('Aliases successfully updated.')); - dcCore::app()->adminurl->redirect('admin.plugin.alias'); - } catch (Exception $e) { - dcCore::app()->error->add($e->getMessage()); +/** + * 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; } -} -# New alias -if (isset($_POST['alias_url'])) { - try { - $o->createAlias($_POST['alias_url'], $_POST['alias_destination'], count($aliases) + 1); - dcAdminNotices::addSuccessNotice(__('Alias successfully created.')); - dcCore::app()->adminurl->redirect('admin.plugin.alias'); - } catch (Exception $e) { - dcCore::app()->error->add($e->getMessage()); - } -} -?> - - - <?php echo __('Aliases'); ?> - - - - '', - __('Aliases') => dcCore::app()->adminurl->get('admin.plugin.alias', ['part' => 'list']), - __('New alias') => '', - ]) . - dcPage::notices() . - '

' . __('New alias') . '

' . - '
' . - '

' . - '

' . - '

' . sprintf(__('Do not put blog URL "%s" in fields.'), dcCore::app()->blog->url) . '

' . - '

' . - dcCore::app()->formNonce() . - form::hidden('part', 'new') . - '

' . - '
'; -} else { - echo - dcPage::breadcrumb([ - __('Plugins') => '', - __('Aliases') => '', - ]) . - dcPage::notices() . - '

' . __('New alias') . '

'; - - if (empty($aliases)) { - echo '

' . __('No alias') . '

'; - } else { - echo - '
' . - '

' . sprintf(__('There is %s alias.', 'There are %s aliases.', count($aliases)), count($aliases)) . '

' . - '
' . - '' . - '' . - '' . - '' . - '' . - '' . - '' . - '' . - ''; - - foreach ($aliases as $k => $v) { - echo - '' . - '' . - '' . - '' . - ''; + public static function process(): bool + { + if (!static::$init) { + return false; } - echo - '
' . __('Aliases list') . '
' . __('Alias URL') . '' . __('Alias destination') . '' . __('Alias position') . '
' . - form::field(['a[' . $k . '][alias_url]'], 50, 255, html::escapeHTML($v['alias_url'])) . '' . - form::field(['a[' . $k . '][alias_destination]'], 50, 255, html::escapeHTML($v['alias_destination'])) . '' . - form::number(['a[' . $k . '][alias_position]'], [ - 'min' => 1, - 'max' => count($aliases), - 'default' => (int) $v['alias_position'], - 'class' => 'position', - 'extra_html' => 'title="' . sprintf(__('position of %s'), html::escapeHTML($v['alias_url'])) . '"', - ]) . '
' . - '

' . __('To remove an alias, empty its URL or destination.') . '

' . - '

' . - dcCore::app()->formNonce() . - form::hidden('part', 'list') . - '

' . - '
'; + 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 { + $alias->updateAliases($_POST['a']); + dcPage::addSuccessNotice(__('Aliases successfully updated.')); + dcCore::app()->adminurl->redirect('admin.plugin.' . My::id()); + } catch (Exception $e) { + dcCore::app()->error->add($e->getMessage()); + } + } + + # New alias + if (isset($_POST['alias_url'])) { + try { + $alias->createAlias($_POST['alias_url'], $_POST['alias_destination'], count($aliases) + 1); + dcPage::addSuccessNotice(__('Alias successfully created.')); + dcCore::app()->adminurl->redirect('admin.plugin.' . My::id()); + } catch (Exception $e) { + dcCore::app()->error->add($e->getMessage()); + } + } + + return true; + } + + 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 + dcPage::breadcrumb([ + __('Plugins') => '', + My::name() => dcCore::app()->adminurl->get('admin.plugin.' . My::id(), ['part' => 'list']), + __('New alias') => '', + ]) . + dcPage::notices() . + + (new Div())->items([ + (new Text('h3', __('New alias'))), + (new Form(My::id() . '_form'))->method('post')->action(dcCore::app()->admin->getPageURL())->fields([ + (new Para())->class('field')->items([ + (new Label(__('Alias URL:')))->for('alias_url'), + (new Input('alias_url'))->size(50)->maxlenght(255), + ]), + (new Para())->class('field')->items([ + (new Label(__('Alias destination:')))->for('alias_destination'), + (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 + dcPage::breadcrumb([ + __('Plugins') => '', + My::name() => '', + ]) . + dcPage::notices() . + '

' . __('New alias') . '

'; + + if (empty($aliases)) { + echo '

' . __('No alias') . '

'; + } else { + echo + '
' . + '

' . sprintf(__('There is %s alias.', 'There are %s aliases.', count($aliases)), count($aliases)) . '

' . + '
' . + '' . + '' . + '' . + '' . + '' . + '' . + '' . + '' . + ''; + + foreach ($aliases as $k => $v) { + echo + '' . + '' . + '' . + '' . + ''; + } + + echo + '
' . __('Aliases list') . '
' . __('Alias URL') . '' . __('Alias destination') . '' . __('Alias position') . '
' . + (new Input(['a[' . $k . '][alias_url]']))->size(50)->maxlenght(255)->value(Html::escapeHTML($v['alias_url']))->render() . '' . + (new Input(['a[' . $k . '][alias_destination]']))->size(50)->maxlenght(255)->value(Html::escapeHTML($v['alias_destination']))->render() . '' . + (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() . '
' . + '

' . __('To remove an alias, empty its URL or destination.') . '

' . + (new Para())->items([ + dcCore::app()->formNonce(false), + (new Hidden('part', 'list')), + (new Submit(['upd']))->value(__('Update')), + ])->render() . + '
'; + } + } + + dcPage::helpBlock('alias'); + dcPage::closeModule(); } } - -dcPage::helpBlock('alias'); -?> - - diff --git a/src/My.php b/src/My.php new file mode 100644 index 0000000..d753ba2 --- /dev/null +++ b/src/My.php @@ -0,0 +1,42 @@ +plugins->moduleInfo(self::id(), 'name')); + } +}