diff --git a/src/Epc.php b/src/Epc.php index 29c2660..039726c 100644 --- a/src/Epc.php +++ b/src/Epc.php @@ -35,8 +35,8 @@ class Epc { public const FLAGGER = 'ççççç%sççççç'; - protected static array $default_filters = []; - public static array $epcFilterLimit = []; + private static EpcFilters $filters; + public static array $epcFilterLimit = []; # # Default definition @@ -110,31 +110,29 @@ class Epc return is_array($rs) ? $rs : self::defaultAllowedPubPages(); } - public static function getFilters(): array + /** + * Get filters. + * + * On first call, we load once filters from behavior. + * + * @return EpcFilters The fitlers instacne + */ + public static function getFilters(): EpcFilters { - if (empty(self::$default_filters)) { - $final = $sort = []; - /** @var ArrayObject $filters The filters stack */ - $filters = new ArrayObject(); + if (empty(self::$filters)) { + $filters = new EpcFilters(); try { - # --BEHAVIOR-- enhancePostContentFilters : ArrayObject + # --BEHAVIOR-- enhancePostContentFilters : EpcFilters dcCore::app()->callBehavior('enhancePostContentFilters', $filters); - - foreach ($filters as $filter) { - if (!isset($final[$filter->id()]) && ($filter instanceof EpcFilter)) { - $sort[$filter->id()] = $filter->priority; - $final[$filter->id()] = $filter; - } - } } catch (Exception $e) { dcCore::app()->error->add($e->getMessage()); } - array_multisort($sort, $final); - self::$default_filters = $final; + + self::$filters = $filters->sort(); } - return self::$default_filters; + return self::$filters; } public static function testContext(string $tag, array $args, EpcFilter $filter): bool @@ -243,7 +241,7 @@ class Epc public static function removeTags(array $m): string { - return $m[1] . preg_replace('#' . sprintf(self::FLAGGER, '(?!') .')#s', '$1', $m[3]) . $m[4]; + return $m[1] . preg_replace('#' . sprintf(self::FLAGGER, '(?!') . ')#s', '$1', $m[3]) . $m[4]; } public static function decodeTags(string $t): array diff --git a/src/EpcFilters.php b/src/EpcFilters.php new file mode 100644 index 0000000..8fb91a1 --- /dev/null +++ b/src/EpcFilters.php @@ -0,0 +1,89 @@ + $satck The filters stack */ + private array $stack = []; + + /** + * Add a filter to the stack. + * + * @return EpcFilters The filters instance + */ + public function add(EpcFilter $filter): EpcFilters + { + $this->stack[$filter->id()] = $filter; + + return $this; + } + + /** + * Get all filters. + * + * @return array The filters stack + */ + public function dump(): array + { + return $this->stack; + } + + /** + * Get a filter. + * + * @param string $id The filter ID + * + * @return null|EpcFilter The filter + */ + public function get(string $id): ?EpcFilter + { + return $this->stack[$id] ?? null; + } + + /** + * Get filters name / id pair. + * + * @return array The nid pairs + */ + public function nid(bool $exclude_widget = false): array + { + $nid = []; + foreach ($this->stack as $filter) { + if ($filter->widget != '') { + $nid[$filter->name] = $filter->id(); + } + } + + return $nid; + } + + /** + * Sort filters stack by filter name. + * + * @return EpcFilters The filters instance + */ + public function sort(): EpcFilters + { + uasort($this->stack, fn ($a, $b) => $a->name <=> $b->name); + + return $this; + } +} diff --git a/src/Frontend.php b/src/Frontend.php index ba52ac4..c19cb62 100644 --- a/src/Frontend.php +++ b/src/Frontend.php @@ -44,7 +44,7 @@ class Frontend extends dcNsProcess }, // Filter template blocks content 'publicBeforeContentFilterV2' => function (string $tag, array $args): void { - foreach (Epc::getFilters() as $id => $filter) { + foreach (Epc::getFilters()->dump() as $filter) { if (!Epc::testContext($tag, $args, $filter)) { continue; } diff --git a/src/Install.php b/src/Install.php index 472c5c8..14c214f 100644 --- a/src/Install.php +++ b/src/Install.php @@ -75,7 +75,7 @@ class Install extends dcNsProcess $s->put('allowedpubpages', json_encode(Epc::defaultAllowedPubPages()), 'string', 'List of allowed template pages', false, true); // Filters settings - foreach (Epc::getFilters() as $id => $filter) { + foreach (Epc::getFilters()->dump() as $filter) { // Only editable options $opt = [ 'nocase' => $filter->nocase, @@ -85,7 +85,7 @@ class Install extends dcNsProcess 'tplValues' => $filter->tplValues, 'pubPages' => $filter->pubPages, ]; - $s->put($id, json_encode($opt), 'string', 'Settings for ' . $id, false, true); + $s->put($filter->id(), json_encode($opt), 'string', 'Settings for ' . $filter->id(), false, true); } return true; @@ -178,13 +178,13 @@ class Install extends dcNsProcess private static function upTo20221120(): void { // list of settings using serialize values to move to json - $ids = [ - 'allowedtplvalues', - 'allowedpubpages', - ]; - foreach (Epc::getFilters() as $id => $f) { - $ids[] = $id; - } + $ids = array_merge( + [ + 'allowedtplvalues', + 'allowedpubpages', + ], + array_values(Epc::getFilters()->nid()) + ); // get all enhancePostContent settings $record = dcCore::app()->con->select( diff --git a/src/Manage.php b/src/Manage.php index 0bb05c6..58126ee 100644 --- a/src/Manage.php +++ b/src/Manage.php @@ -61,20 +61,24 @@ class Manage extends dcNsProcess return false; } - $current = ManageVars::init(); + $action = $_POST['action'] ?? ''; + $filter = Epc::getFilters()->get($_REQUEST['part'] ?? ''); + if (is_null($filter)) { + return true; + } if (dcCore::app()->error->flag()) { return true; } - if (!empty($current->action)) { + if (!empty($action)) { # --BEHAVIOR-- enhancePostContentAdminSave dcCore::app()->callBehavior('enhancePostContentAdminSave'); } try { # Update filter settings - if ($current->action == 'savefiltersetting') { + if ($action == 'savefiltersetting') { # Parse filters options $f = [ 'nocase' => !empty($_POST['filter_nocase']), @@ -86,7 +90,7 @@ class Manage extends dcNsProcess 'pubPages' => (array) $_POST['filter_pubPages'], ]; - dcCore::app()->blog->settings->get(My::id())->put($current->filter->id(), json_encode($f)); + dcCore::app()->blog->settings->get(My::id())->put($filter->id(), json_encode($f)); dcCore::app()->blog->triggerBlog(); @@ -96,18 +100,18 @@ class Manage extends dcNsProcess dcCore::app()->adminurl->redirect( 'admin.plugin.' . My::id(), - ['part' => $current->part], + ['part' => $filter->id()], '#settings' ); } # Add new filter record - if ($current->action == 'savenewrecord' + if ($action == 'savenewrecord' && !empty($_POST['new_key']) && !empty($_POST['new_value']) ) { $cur = EpcRecord::openCursor(); - $cur->setField('epc_filter', $current->filter->id()); + $cur->setField('epc_filter', $filter->id()); $cur->setField('epc_key', Html::escapeHTML($_POST['new_key'])); $cur->setField('epc_value', Html::escapeHTML($_POST['new_value'])); @@ -124,14 +128,14 @@ class Manage extends dcNsProcess } dcCore::app()->adminurl->redirect( 'admin.plugin.' . My::id(), - ['part' => $current->part], + ['part' => $filter->id()], '#record' ); } # Update filter records - if ($current->action == 'deleterecords' - && $current->filter->has_list + if ($action == 'deleterecords' + && $filter->has_list && !empty($_POST['epc_id']) && is_array($_POST['epc_id']) ) { @@ -150,7 +154,7 @@ class Manage extends dcNsProcess } else { dcCore::app()->adminurl->redirect( 'admin.plugin.' . My::id(), - ['part' => $current->part], + ['part' => $filter->id()], '#record' ); } @@ -172,17 +176,21 @@ class Manage extends dcNsProcess return; } - $current = ManageVars::init(); + $filters = Epc::getFilters(); + $filter = $filters->get($_REQUEST['part'] ?? 'link'); + if (is_null($filter)) { + return; + } # -- Prepare page -- $header = ''; - if ($current->filter->has_list) { + if ($filter->has_list) { $sorts = new adminGenericFilterV2('epc'); $sorts->add(dcAdminFilters::getPageFilter()); - $sorts->add('part', $current->part); + $sorts->add('part', $filter->id()); $params = $sorts->params(); - $params['epc_filter'] = $current->filter->id(); + $params['epc_filter'] = $filter->id(); try { $list = EpcRecord::getRecords($params); @@ -192,7 +200,7 @@ class Manage extends dcNsProcess dcCore::app()->error->add($e->getMessage()); } - $header = $sorts->js(dcCore::app()->adminurl->get('admin.plugin.' . My::id(), ['part' => $current->part], '&') . '#record'); + $header = $sorts->js(dcCore::app()->adminurl->get('admin.plugin.' . My::id(), ['part' => $filter->id()], '&') . '#record'); } # Page headers @@ -209,9 +217,9 @@ class Manage extends dcNsProcess # Page title echo dcPage::breadcrumb([ - __('Plugins') => '', - My::name() => '', - $current->filter->name => '', + __('Plugins') => '', + My::name() => '', + $filter->name => '', ]) . dcPage::notices(); @@ -219,7 +227,7 @@ class Manage extends dcNsProcess echo (new Form('filters_menu'))->method('get')->action(dcCore::app()->adminurl->get('admin.plugin.' . My::id()))->fields([ (new Para())->class('anchor-nav')->items([ - (new Select('part'))->items($current->combo)->default($current->part), + (new Select('part'))->items($filters->nid())->default($filter->id()), (new Submit(['do']))->value(__('Ok')), (new Hidden(['p'], My::id())), ]), @@ -227,14 +235,14 @@ class Manage extends dcNsProcess # Filter title and description echo - '

' . $current->filter->name . '

' . - '

' . $current->filter->help . '

'; + '

' . $filter->name . '

' . + '

' . $filter->help . '

'; # Filter settings $form_pages = [(new Text('h4', __('Pages to be filtered')))]; foreach (Epc::blogAllowedPubPages() as $k => $v) { $form_pages[] = (new Para())->items([ - (new Checkbox(['filter_pubPages[]', 'filter_pubPages' . $v], in_array($v, $current->filter->pubPages)))->value($v), + (new Checkbox(['filter_pubPages[]', 'filter_pubPages' . $v], in_array($v, $filter->pubPages)))->value($v), (new Label(__($k), Label::OUTSIDE_LABEL_AFTER))->for('filter_pubPages' . $v)->class('classic'), ]); } @@ -242,16 +250,16 @@ class Manage extends dcNsProcess $form_values = [(new Text('h4', __('Contents to be filtered')))]; foreach (Epc::blogAllowedTplValues() as $k => $v) { $form_values[] = (new Para())->items([ - (new Checkbox(['filter_tplValues[]', 'filter_tplValues' . $v], in_array($v, $current->filter->tplValues)))->value($v), + (new Checkbox(['filter_tplValues[]', 'filter_tplValues' . $v], in_array($v, $filter->tplValues)))->value($v), (new Label(__($k), Label::OUTSIDE_LABEL_AFTER))->for('filter_tplValues' . $v)->class('classic'), ]); } $form_styles = [(new Text('h4', __('Style')))]; - foreach ($current->filter->class as $k => $v) { + foreach ($filter->class as $k => $v) { $form_styles[] = (new Para())->items([ (new Label(sprintf(__('Class "%s":'), $v), Label::OUTSIDE_LABEL_BEFORE))->for('filter_style' . $k), - (new Input(['filter_style[]', 'filter_style' . $k]))->size(60)->maxlenght(255)->value(Html::escapeHTML($current->filter->style[$k])), + (new Input(['filter_style[]', 'filter_style' . $k]))->size(60)->maxlenght(255)->value(Html::escapeHTML($filter->style[$k])), ]); } @@ -262,46 +270,46 @@ class Manage extends dcNsProcess (new Div())->class('two-boxes odd')->items([ (new Text('h4', __('Filtering'))), (new Para())->items([ - (new Checkbox('filter_nocase', $current->filter->nocase))->value(1), + (new Checkbox('filter_nocase', $filter->nocase))->value(1), (new Label(__('Case insensitive'), Label::OUTSIDE_LABEL_AFTER))->for('filter_nocase')->class('classic'), ]), (new Para())->items([ - (new Checkbox('filter_plural', $current->filter->plural))->value(1), + (new Checkbox('filter_plural', $filter->plural))->value(1), (new Label(__('Also use the plural'), Label::OUTSIDE_LABEL_AFTER))->for('filter_plural')->class('classic'), ]), (new Para())->items([ (new Label(__('Limit the number of replacement to:'), Label::OUTSIDE_LABEL_BEFORE))->for('filter_limit'), - (new Number('filter_limit'))->min(0)->max(99)->value((int) $current->filter->limit), + (new Number('filter_limit'))->min(0)->max(99)->value((int) $filter->limit), ]), (new Note())->class('form-note')->text(__('Leave it blank or set it to 0 for no limit')), ]), (new Div())->class('two-boxes even')->items($form_values), (new Div())->class('two-boxes odd')->items(array_merge($form_styles, [ - (new Note())->class('form-note')->text(sprintf(__('The inserted HTML tag looks like: %s'), Html::escapeHTML(str_replace('%s', '...', $current->filter->replace)))), + (new Note())->class('form-note')->text(sprintf(__('The inserted HTML tag looks like: %s'), Html::escapeHTML(str_replace('%s', '...', $filter->replace)))), (new Para())->items([ (new Label(__('Ignore HTML tags:'), Label::OUTSIDE_LABEL_BEFORE))->for('filter_notag'), - (new Input('filter_notag'))->size(60)->maxlenght(255)->value(Html::escapeHTML($current->filter->notag)), + (new Input('filter_notag'))->size(60)->maxlenght(255)->value(Html::escapeHTML($filter->notag)), ]), - (new Note())->class('form-note')->text(__('This is the list of HTML tags where content will be ignored.') . ' ' . ('' != $current->filter->htmltag ? '' : sprintf(__('Tag "%s" always be ignored.'), $current->filter->htmltag))), + (new Note())->class('form-note')->text(__('This is the list of HTML tags where content will be ignored.') . ' ' . ('' != $filter->htmltag ? '' : sprintf(__('Tag "%s" always be ignored.'), $filter->htmltag))), ])), (new Div())->class('clear')->items([ dcCore::app()->formNonce(false), (new Hidden(['action'], 'savefiltersetting')), - (new Hidden(['part'], $current->part)), + (new Hidden(['part'], $filter->id())), (new Submit(['save']))->value(__('Save')), ]), ]), ])->render(); # Filter records list - if ($current->filter->has_list && isset($pager)) { + if ($filter->has_list && isset($pager)) { $pager_url = dcCore::app()->adminurl->get('admin.plugin.' . My::id(), array_diff_key($sorts->values(true), ['page' => ''])) . '&page=%s#record'; echo '
'; - $sorts->display(['admin.plugin.' . My::id(), '#record'], (new Hidden('p', My::id()))->render() . (new Hidden('part', $current->part))->render()); + $sorts->display(['admin.plugin.' . My::id(), '#record'], (new Hidden('p', My::id()))->render() . (new Hidden('part', $filter->id()))->render()); $pager->display( $sorts, @@ -342,7 +350,7 @@ class Manage extends dcNsProcess (new Para())->class('clear')->items([ dcCore::app()->formNonce(false), (new Hidden(['action'], 'savenewrecord')), - (new Hidden(['part'], $current->part)), + (new Hidden(['part'], $filter->id())), (new Submit(['save', 'new-action']))->value(__('Save')), ]), ]), diff --git a/src/ManageVars.php b/src/ManageVars.php deleted file mode 100644 index 9dd94f8..0000000 --- a/src/ManageVars.php +++ /dev/null @@ -1,62 +0,0 @@ - $filter) { - $filters_id[$id] = $filter->name; - $filters_combo[$filter->name] = $id; - } - } - $part = $_REQUEST['part'] ?? key($filters_id); - - if (!isset($_filters[$part])) { - throw new Exception(__('no filters')); - } - - $this->action = $_POST['action'] ?? ''; - $this->part = $part; - $this->filter = $_filters[$part]; - $this->combo = $filters_combo; - } - - public static function init(): ManageVars - { - if (!(self::$container instanceof self)) { - self::$container = new self(); - } - - return self::$container; - } -} diff --git a/src/My.php b/src/My.php index 48adf85..407401f 100644 --- a/src/My.php +++ b/src/My.php @@ -29,16 +29,16 @@ class My /** @var array Distributed filters */ public const DEFAULT_FILTERS = [ - 'Tag', - 'Search', - 'Acronym', - 'Abbreviation', - 'Definition', - 'Citation', - 'Link', - 'Replace', - 'Update', - 'Twitter', + Filter\EpcFilterTag::class, + Filter\EpcFilterSearch::class, + Filter\EpcFilterAcronym::class, + Filter\EpcFilterAbbreviation::class, + Filter\EpcFilterDefinition::class, + Filter\EpcFilterCitation::class, + Filter\EpcFilterLink::class, + Filter\EpcFilterReplace::class, + Filter\EpcFilterUpdate::class, + Filter\EpcFilterTwitter::class, ]; /** diff --git a/src/Prepend.php b/src/Prepend.php index 9408b45..7e30265 100644 --- a/src/Prepend.php +++ b/src/Prepend.php @@ -33,27 +33,21 @@ class Prepend extends dcNsProcess return false; } - $dir = __DIR__ . DIRECTORY_SEPARATOR . 'Filter' . DIRECTORY_SEPARATOR; - $ns = __NAMESPACE__ . '\\Filter\\'; - - dcCore::app()->autoload->addNamespace($ns, $dir); - - foreach (My::DEFAULT_FILTERS as $f) { - dcCore::app()->addBehavior('enhancePostContentFilters', [$ns . 'EpcFilter' . $f, 'create']); - } + // register epc filters + dcCore::app()->addBehavior('enhancePostContentFilters', function (EpcFilters $stack): void { + foreach (My::DEFAULT_FILTERS as $class) { + $stack->add(new $class()); + } + }); + // register epc filters frontend css dcCore::app()->url->register( 'epccss', 'epc.css', '^epc\.css', function (string $args): void { - $css = []; - $filters = Epc::getFilters(); - if (empty($filters)) { - return; - } - - foreach ($filters as $id => $filter) { + $css = []; + foreach (Epc::getFilters()->dump() as $filter) { if ('' == $filter->class || '' == $filter->style) { continue; } @@ -68,7 +62,7 @@ class Prepend extends dcNsProcess } if (!empty($res)) { - $css[] = '/* CSS for enhancePostContent ' . $id . " */ \n" . $res . "\n"; + $css[] = '/* CSS for enhancePostContent ' . $filter->id() . " */ \n" . $res . "\n"; } } diff --git a/src/Widgets.php b/src/Widgets.php index 752402c..f19cd76 100644 --- a/src/Widgets.php +++ b/src/Widgets.php @@ -51,18 +51,12 @@ class Widgets 'text' ); # Type - $types = []; - foreach (Epc::getFilters() as $id => $filter) { - if ($filter->widget != '') { - $types[$filter->name] = $id; - } - } $w->epclist->setting( 'type', __('Type:'), 'Definition', 'combo', - $types + Epc::getFilters()->nid(true) ); # Content foreach (Epc::defaultAllowedWidgetValues() as $k => $v) { @@ -122,11 +116,11 @@ class Widgets } # Filter - $list = new ArrayObject(); - $filters = Epc::getFilters(); + $list = new ArrayObject(); + $filter = Epc::getFilters()->get($w->type); - if (isset($filters[$w->type])) { - $filters[$w->type]->widgetList($content, $w, $list); + if (!is_null($filter)) { + $filter->widgetList($content, $w, $list); } if (!count($list)) {