code review and doc
This commit is contained in:
parent
dd0e90cd5e
commit
2948be39fd
20 changed files with 640 additions and 419 deletions
|
@ -48,7 +48,7 @@ class Backend extends dcNsProcess
|
|||
return false;
|
||||
}
|
||||
|
||||
# Admin menu
|
||||
// backend sidebar menu icon
|
||||
dcCore::app()->menu[dcAdmin::MENU_PLUGINS]->addItem(
|
||||
My::name(),
|
||||
dcCore::app()->adminurl?->get('admin.plugin.' . My::id()),
|
||||
|
@ -58,7 +58,7 @@ class Backend extends dcNsProcess
|
|||
);
|
||||
|
||||
dcCore::app()->addBehaviors([
|
||||
# Dashboard favorites
|
||||
// backend user dashboard favorites icon
|
||||
'adminDashboardFavoritesV2' => function (dcFavorites $favs): void {
|
||||
$favs->register(My::id(), [
|
||||
'title' => My::name(),
|
||||
|
@ -68,11 +68,11 @@ class Backend extends dcNsProcess
|
|||
'permissions' => dcCore::app()->auth?->makePermissions([dcCore::app()->auth::PERMISSION_CONTENT_ADMIN]),
|
||||
]);
|
||||
},
|
||||
# Preference form
|
||||
// backend user preference form
|
||||
'adminBlogPreferencesFormV2' => function (dcSettings $blog_settings): void {
|
||||
$active = (bool) $blog_settings->get(My::id())->get('active');
|
||||
$allowedtplvalues = Epc::blogAllowedTplValues();
|
||||
$allowedpubpages = Epc::blogAllowedPubPages();
|
||||
$allowedtplvalues = Epc::blogAllowedTemplateValue();
|
||||
$allowedpubpages = Epc::blogAllowedTemplatePage();
|
||||
|
||||
echo
|
||||
'<div class="fieldset"><h4 id="epc_params">' . My::name() . '</h4>' .
|
||||
|
@ -95,13 +95,13 @@ class Backend extends dcNsProcess
|
|||
// allowedtplvalues
|
||||
(new Para())->items([
|
||||
(new Label(__('Allowed DC template values:'), Label::OUTSIDE_LABEL_BEFORE))->for('epc_allowedtplvalues'),
|
||||
(new Input('epc_allowedtplvalues'))->size(100)->maxlenght(0)->value(Epc::implode($allowedtplvalues)),
|
||||
(new Input('epc_allowedtplvalues'))->size(100)->maxlenght(0)->value(Epc::encodeMulti($allowedtplvalues)),
|
||||
])->render() .
|
||||
'<p class="form-note">' . __('Use "readable_name1:template_value1;readable_name2:template_value2;" like "entry content:EntryContent;entry excerpt:EntryExcerpt;".') . '</p>' .
|
||||
// allowedpubpages
|
||||
(new Para())->items([
|
||||
(new Label(__('Allowed public pages:'), Label::OUTSIDE_LABEL_BEFORE))->for('epc_allowedpubpages'),
|
||||
(new Input('epc_allowedpubpages'))->size(100)->maxlenght(0)->value(Epc::implode($allowedpubpages)),
|
||||
(new Input('epc_allowedpubpages'))->size(100)->maxlenght(0)->value(Epc::encodeMulti($allowedpubpages)),
|
||||
])->render() .
|
||||
'<p class="form-note">' . __('Use "readable_name1:template_page1;readable_name2:template_page2;" like "post page:post.html;home page:home.html;".') . '</p>' .
|
||||
'</div>' .
|
||||
|
@ -109,17 +109,17 @@ class Backend extends dcNsProcess
|
|||
'<br class="clear" />' .
|
||||
'</div>';
|
||||
},
|
||||
# Save preference
|
||||
// backend user preference save
|
||||
'adminBeforeBlogSettingsUpdate' => function (dcSettings $blog_settings): void {
|
||||
$active = !empty($_POST['epc_active']);
|
||||
$allowedtplvalues = Epc::explode($_POST['epc_allowedtplvalues']);
|
||||
$allowedpubpages = Epc::explode($_POST['epc_allowedpubpages']);
|
||||
$allowedtplvalues = Epc::decodeMulti($_POST['epc_allowedtplvalues']);
|
||||
$allowedpubpages = Epc::decodeMulti($_POST['epc_allowedpubpages']);
|
||||
|
||||
$blog_settings->get(My::id())->put('active', $active);
|
||||
$blog_settings->get(My::id())->put('allowedtplvalues', json_encode($allowedtplvalues));
|
||||
$blog_settings->get(My::id())->put('allowedpubpages', json_encode($allowedpubpages));
|
||||
},
|
||||
# List filter
|
||||
// backend epc list filter
|
||||
'adminFiltersListsV2' => function (ArrayObject $sorts): void {
|
||||
$sorts['epc'] = [
|
||||
My::name(),
|
||||
|
@ -134,7 +134,7 @@ class Backend extends dcNsProcess
|
|||
[__('records per page'), 20],
|
||||
];
|
||||
},
|
||||
# Widgets
|
||||
// widgets registration
|
||||
'initWidgets' => [Widgets::class, 'initWidgets'],
|
||||
]);
|
||||
|
||||
|
|
|
@ -22,19 +22,27 @@ use Dotclear\Helper\Html\Form\Checkbox;
|
|||
use Dotclear\Helper\Html\Html;
|
||||
|
||||
/**
|
||||
* @ingroup DC_PLUGIN_PERIODICAL
|
||||
* @brief Periodical - admin pager methods.
|
||||
* @since 2.6
|
||||
* Backend filters values list.
|
||||
*/
|
||||
class BackendList extends adminGenericListV2
|
||||
{
|
||||
public function display(adminGenericFilterV2 $filter, string $pager_url, string $enclose_block): void
|
||||
/**
|
||||
* Display list.
|
||||
*
|
||||
* @param adminGenericFilterV2 $filter The filter
|
||||
* @param string $url The pager URL
|
||||
* @param string $block The enclose bloc
|
||||
*/
|
||||
public function display(adminGenericFilterV2 $filter, string $url, string $block): void
|
||||
{
|
||||
if ($this->rs->isEmpty()) {
|
||||
echo '<p><strong>' . ($filter->show() ? __('No record matches the filter') : __('No record')) . '</strong></p>';
|
||||
} else {
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$pager = new dcPager($filter->value('page'), $this->rs_count, $filter->value('nb'), 10);
|
||||
$pager->base_url = $pager_url;
|
||||
$pager->base_url = $url;
|
||||
|
||||
$epc_id = [];
|
||||
if (isset($_REQUEST['epc_id'])) {
|
||||
|
@ -49,30 +57,30 @@ class BackendList extends adminGenericListV2
|
|||
'date' => '<th scope="col">' . __('Date') . '</th>',
|
||||
];
|
||||
|
||||
$html_block = '<div class="table-outer"><table><caption>' .
|
||||
(
|
||||
$content = '<div class="table-outer"><table><caption>' . (
|
||||
$filter->show() ?
|
||||
sprintf(__('List of %s records matching the filter.'), $this->rs_count) :
|
||||
sprintf(__('List of %s records.'), $this->rs_count)
|
||||
) . '</caption>' .
|
||||
'<tr>' . implode($cols) . '</tr>%s</table>%s</div>';
|
||||
|
||||
if ($enclose_block) {
|
||||
$html_block = sprintf($enclose_block, $html_block);
|
||||
}
|
||||
$blocks = explode('%s', $html_block);
|
||||
$blocks = explode('%s', sprintf($block, $content));
|
||||
|
||||
echo $pager->getLinks() . $blocks[0];
|
||||
|
||||
while ($this->rs->fetch()) {
|
||||
echo $this->line(isset($epc_id[$this->rs->epc_id]));
|
||||
$this->line(isset($epc_id[$this->rs->epc_id]));
|
||||
}
|
||||
|
||||
echo $blocks[1] . $blocks[2] . $pager->getLinks();
|
||||
}
|
||||
}
|
||||
|
||||
private function line(bool $checked): string
|
||||
/**
|
||||
* Dispay a list line.
|
||||
*
|
||||
* @param bool $checked Checkbox checked
|
||||
*/
|
||||
private function line(bool $checked): void
|
||||
{
|
||||
$cols = [
|
||||
'check' => '<td class="nowrap">' . (new Checkbox(['epc_id[]'], $checked))->value($this->rs->epc_id)->render() . '</td>',
|
||||
|
@ -81,7 +89,7 @@ class BackendList extends adminGenericListV2
|
|||
'date' => '<td class="nowrap count">' . Date::dt2str(__('%Y-%m-%d %H:%M'), $this->rs->epc_upddt) . '</td>',
|
||||
];
|
||||
|
||||
return
|
||||
echo
|
||||
'<tr class="line" id="p' . $this->rs->epc_id . '">' .
|
||||
implode($cols) .
|
||||
'</tr>';
|
||||
|
|
405
src/Epc.php
405
src/Epc.php
|
@ -33,39 +33,54 @@ __('RSS feeds');
|
|||
|
||||
class Epc
|
||||
{
|
||||
/** @var string The temporary pattern to tag words to replace */
|
||||
public const FLAGGER = 'ççççç%sççççç';
|
||||
|
||||
/** @var EpcFilters $filters THe filters stack */
|
||||
private static EpcFilters $filters;
|
||||
public static array $epcFilterLimit = [];
|
||||
|
||||
#
|
||||
# Default definition
|
||||
#
|
||||
/** @var array<string,int> $limits The replacment limit per filtre */
|
||||
private static array $limits = [];
|
||||
|
||||
public static function defaultAllowedTplValues(): array
|
||||
/**
|
||||
* Get list of default allowed templates name->tag.
|
||||
*
|
||||
* @return array<string,string> The templates name->tag pairs
|
||||
*/
|
||||
public static function defaultAllowedTemplateValue(): array
|
||||
{
|
||||
$rs = new ArrayObject([
|
||||
$list = new ArrayObject([
|
||||
'entry excerpt' => 'EntryExcerpt',
|
||||
'entry content' => 'EntryContent',
|
||||
'comment content' => 'CommentContent',
|
||||
]);
|
||||
|
||||
# --BEHAVIOR-- enhancePostContentAllowedTplValues : ArrayObject
|
||||
dcCore::app()->callBehavior('enhancePostContentAllowedTplValues', $rs);
|
||||
dcCore::app()->callBehavior('enhancePostContentAllowedTplValues', $list);
|
||||
|
||||
return iterator_to_array($rs, true);
|
||||
return iterator_to_array($list, true);
|
||||
}
|
||||
|
||||
public static function blogAllowedTplValues(): array
|
||||
/**
|
||||
* Get list of allowed templates name->tag set on current blog.
|
||||
*
|
||||
* @return array<string,string> The templates name->tag pairs
|
||||
*/
|
||||
public static function blogAllowedTemplateValue(): array
|
||||
{
|
||||
$rs = json_decode((string) dcCore::app()->blog?->settings->get(My::id())->get('allowedtplvalues'), true);
|
||||
$list = json_decode((string) dcCore::app()->blog?->settings->get(My::id())->get('allowedtplvalues'), true);
|
||||
|
||||
return is_array($rs) ? $rs : self::defaultAllowedTplValues();
|
||||
return is_array($list) ? $list : self::defaultAllowedTemplateValue();
|
||||
}
|
||||
|
||||
public static function defaultAllowedWidgetValues(): array
|
||||
/**
|
||||
* Get list of allowed templates name->[tag,callback] to list on epc widgets.
|
||||
*
|
||||
* @return array The templates name->[id,cb] values
|
||||
*/
|
||||
public static function widgetAllowedTemplateValue(): array
|
||||
{
|
||||
$rs = new ArrayObject([
|
||||
$list = new ArrayObject([
|
||||
'entry excerpt' => [
|
||||
'id' => 'entryexcerpt',
|
||||
'cb' => [self::class, 'widgetContentEntryExcerpt'],
|
||||
|
@ -81,14 +96,19 @@ class Epc
|
|||
]);
|
||||
|
||||
# --BEHAVIOR-- enhancePostContentAllowedWidgetValues : ArrayObject
|
||||
dcCore::app()->callBehavior('enhancePostContentAllowedWidgetValues', $rs);
|
||||
dcCore::app()->callBehavior('enhancePostContentAllowedWidgetValues', $list);
|
||||
|
||||
return iterator_to_array($rs, true);
|
||||
return iterator_to_array($list, true);
|
||||
}
|
||||
|
||||
public static function defaultAllowedPubPages(): array
|
||||
/**
|
||||
* Get list of default allowed templates name->page to list on epc widgets.
|
||||
*
|
||||
* @return array<string,string> The templates name->page pairs
|
||||
*/
|
||||
public static function defaultAllowedTemplatePage(): array
|
||||
{
|
||||
$rs = new ArrayObject([
|
||||
$list = new ArrayObject([
|
||||
'home page' => 'home.html',
|
||||
'post page' => 'post.html',
|
||||
'category page' => 'category.html',
|
||||
|
@ -98,16 +118,21 @@ class Epc
|
|||
]);
|
||||
|
||||
# --BEHAVIOR-- enhancePostContentAllowedPubPages : ArrayObject
|
||||
dcCore::app()->callBehavior('enhancePostContentAllowedPubPages', $rs);
|
||||
dcCore::app()->callBehavior('enhancePostContentAllowedPubPages', $list);
|
||||
|
||||
return iterator_to_array($rs, true);
|
||||
return iterator_to_array($list, true);
|
||||
}
|
||||
|
||||
public static function blogAllowedPubPages(): array
|
||||
/**
|
||||
* Get list of allowed templates name->page set on blog to list on epc widgets.
|
||||
*
|
||||
* @return array<string,string> The templates name->page pairs
|
||||
*/
|
||||
public static function blogAllowedTemplatePage(): array
|
||||
{
|
||||
$rs = json_decode((string) dcCore::app()->blog?->settings->get(My::id())->get('allowedpubpages'), true);
|
||||
$list = json_decode((string) dcCore::app()->blog?->settings->get(My::id())->get('allowedpubpages'), true);
|
||||
|
||||
return is_array($rs) ? $rs : self::defaultAllowedPubPages();
|
||||
return is_array($list) ? $list : self::defaultAllowedTemplatePage();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -135,153 +160,193 @@ class Epc
|
|||
return self::$filters;
|
||||
}
|
||||
|
||||
public static function testContext(string $tag, array $args, EpcFilter $filter): bool
|
||||
{
|
||||
return in_array((string) dcCore::app()->ctx?->__get('current_tpl'), $filter->pubPages)
|
||||
&& in_array($tag, $filter->tplValues)
|
||||
&& $args[0] != '' //content
|
||||
&& empty($args['encode_xml'])
|
||||
&& empty($args['encode_html'])
|
||||
&& empty($args['remove_html'])
|
||||
&& empty($args['strip_tags'])
|
||||
;
|
||||
}
|
||||
|
||||
public static function replaceString(string $p, string $r, string $s, EpcFilter $filter, string $before = '\b', string $after = '\b'): string
|
||||
{
|
||||
# Limit
|
||||
/**
|
||||
* Apply filter to content.
|
||||
*
|
||||
* @param string $search The search
|
||||
* @param string $replacement The replacement
|
||||
* @param string $content The content
|
||||
* @param EpcFilter $filter The filter
|
||||
* @param string $before The start limit pattern
|
||||
* @param string $after The end limit pattern
|
||||
*/
|
||||
public static function replaceString(
|
||||
string $search,
|
||||
string $replacement,
|
||||
string $content,
|
||||
EpcFilter $filter,
|
||||
string $before = '\b',
|
||||
string $after = '\b'
|
||||
): string {
|
||||
// Limit
|
||||
if ($filter->limit > 0) {
|
||||
$limit = array_key_exists($filter->id() . '_' . $p, self::$epcFilterLimit) ? self::$epcFilterLimit[$filter->id() . '_' . $p] : $filter->limit;
|
||||
// memorize limit between two template values
|
||||
$limit = array_key_exists($filter->id() . '_' . $search, self::$limits) ? self::$limits[$filter->id() . '_' . $search] : $filter->limit;
|
||||
if ($limit < 1) {
|
||||
return $s;
|
||||
return $content;
|
||||
}
|
||||
} else {
|
||||
$limit = -1;
|
||||
}
|
||||
# Case sensitive
|
||||
$i = $filter->nocase ? 'i' : '';
|
||||
# Plural
|
||||
$x = $filter->plural ? $p . 's|' . $p : $p;
|
||||
|
||||
# Mark words
|
||||
$ret = preg_replace('#(' . $before . ')(' . $x . ')(' . $after . ')#su' . $i, '$1' . sprintf(self::FLAGGER, '$2') . '$3', $s, -1, $count);
|
||||
// Case sensitive
|
||||
$caseless = $filter->nocase ? 'i' : '';
|
||||
|
||||
# Plural
|
||||
$plural = $filter->plural ? 's?' : '';
|
||||
|
||||
// Mark words
|
||||
$ret = preg_replace('#(' . $before . ')(' . $search . $plural . ')(' . $after . ')#su' . $caseless, '$1' . sprintf(self::FLAGGER, '$2') . '$3', $content, -1, $count);
|
||||
if (is_string($ret)) {
|
||||
$s = $ret;
|
||||
$content = $ret;
|
||||
}
|
||||
# Nothing to parse
|
||||
|
||||
// Nothing to parse
|
||||
if (!$count) {
|
||||
return $s;
|
||||
return $content;
|
||||
}
|
||||
|
||||
# Remove words that are into unwanted html tags
|
||||
$ignore_tags = array_merge(self::decodeTags($filter->htmltag), self::decodeTags($filter->notag));
|
||||
if (!empty($ignore_tags)) {
|
||||
$tags = implode('|', array_unique($ignore_tags));
|
||||
|
||||
$ret = preg_replace_callback('#(<(' . $tags . ')[^>]*?>)(.*?)(</\\2>)#s', [self::class, 'removeTags'], $s);
|
||||
if (is_string($ret)) {
|
||||
$s = $ret;
|
||||
}
|
||||
}
|
||||
|
||||
# Remove words inside html tag (class, title, alt, href, ...)
|
||||
$ret = preg_replace('#(' . sprintf(self::FLAGGER, '(' . $x . '(s|))') . ')(?=[^<]*>)#s' . $i, '$2$4', $s);
|
||||
if (is_string($ret)) {
|
||||
$s = $ret;
|
||||
}
|
||||
|
||||
# Replace words by what you want (with limit)
|
||||
$ret = preg_replace('#' . sprintf(self::FLAGGER, '(' . $p . '(s|))') . '#s' . $i, $r, $s, $limit, $count);
|
||||
if (is_string($ret)) {
|
||||
$s = $ret;
|
||||
}
|
||||
|
||||
# update limit
|
||||
self::$epcFilterLimit[$filter->id() . '_' . $p] = $limit - $count;
|
||||
|
||||
# Clean rest
|
||||
$ret = preg_replace('#' . sprintf(self::FLAGGER, '(.*?)') . '#s', '$1', $s);
|
||||
if (is_string($ret)) {
|
||||
$s = $ret;
|
||||
}
|
||||
|
||||
return $s;
|
||||
}
|
||||
|
||||
public static function matchString(string $p, string $r, string $s, EpcFilter $filter, string $before = '\b', string $after = '\b'): array
|
||||
{
|
||||
# Case sensitive
|
||||
$i = $filter->nocase ? 'i' : '';
|
||||
# Plural
|
||||
$x = $filter->plural ? $p . 's|' . $p : $p;
|
||||
# Mark words
|
||||
$t = preg_match_all('#' . $before . '(' . $x . ')' . $after . '#su' . $i, $s, $matches);
|
||||
# Nothing to parse
|
||||
if (!$t) {
|
||||
return ['total' => 0, 'matches' => []];
|
||||
}
|
||||
|
||||
# Build array
|
||||
$m = [];
|
||||
$loop = 0;
|
||||
foreach ($matches[1] as $match) {
|
||||
$m[$loop]['key'] = $match;
|
||||
$m[$loop]['match'] = preg_replace('#(' . $p . '(s|))#s' . $i, $r, $match, -1, $count);
|
||||
$m[$loop]['num'] = $count;
|
||||
$loop++;
|
||||
}
|
||||
|
||||
return ['total' => $t, 'matches' => $m];
|
||||
}
|
||||
|
||||
public static function quote(string $s): string
|
||||
{
|
||||
return preg_quote($s, '#');
|
||||
}
|
||||
|
||||
public static function removeTags(array $m): string
|
||||
{
|
||||
// Remove words that are into unwanted html tags
|
||||
$ignore = array_merge(self::decodeSingle($filter->ignore), self::decodeSingle($filter->notag));
|
||||
if (!empty($ignore)) {
|
||||
$ret = preg_replace_callback('#(<(' . implode('|', array_unique($ignore)) . ')[^>]*?>)(.*?)(</\\2>)#s', function (array $m): string {
|
||||
return $m[1] . preg_replace('#' . sprintf(self::FLAGGER, '(?!') . ')#s', '$1', $m[3]) . $m[4];
|
||||
}, $content);
|
||||
if (is_string($ret)) {
|
||||
$content = $ret;
|
||||
}
|
||||
}
|
||||
|
||||
public static function decodeTags(string $t): array
|
||||
// Remove words inside html tag (class, title, alt, href, ...)
|
||||
$ret = preg_replace('#(' . sprintf(self::FLAGGER, '(' . $search . '(' . $plural . '))') . ')(?=[^<]*>)#s' . $caseless, '$2$4', $content);
|
||||
if (is_string($ret)) {
|
||||
$content = $ret;
|
||||
}
|
||||
|
||||
// Replace words by what you want (with limit)
|
||||
$ret = preg_replace('#' . sprintf(self::FLAGGER, '(' . $search . '(' . $plural . '))') . '#s' . $caseless, $replacement, $content, $limit, $count);
|
||||
if (is_string($ret)) {
|
||||
$content = $ret;
|
||||
}
|
||||
|
||||
// update limit
|
||||
self::$limits[$filter->id() . '_' . $search] = $limit - $count;
|
||||
|
||||
// Clean rest
|
||||
$ret = preg_replace('#' . sprintf(self::FLAGGER, '(.*?)') . '#s', '$1', $content);
|
||||
if (is_string($ret)) {
|
||||
$content = $ret;
|
||||
}
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find filter on content.
|
||||
*
|
||||
* @param string $search The search
|
||||
* @param string $replacement The replacement
|
||||
* @param string $content The content
|
||||
* @param EpcFilter $filter The filter
|
||||
* @param string $before The start limit pattern
|
||||
* @param string $after The end limit pattern
|
||||
*/
|
||||
public static function matchString(
|
||||
string $search,
|
||||
string $replacement,
|
||||
string $content,
|
||||
EpcFilter $filter,
|
||||
string $before = '\b',
|
||||
string $after = '\b'
|
||||
): array {
|
||||
return [
|
||||
'total' => (int) preg_match_all('#' . $before . '(' . $search . ($filter->plural ? 's?' : '') . ')' . $after . '#su' . ($filter->nocase ? 'i' : ''), $content),
|
||||
'search' => $search,
|
||||
'replacement' => preg_replace('#(' . $search . ')#', $replacement, $search),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Quote regular expression according to epc parser.
|
||||
*
|
||||
* @param string $string The string
|
||||
*
|
||||
* @return string The quoted string
|
||||
*/
|
||||
public static function quote(string $string): string
|
||||
{
|
||||
return preg_match_all('#([A-Za-z0-9]+)#', (string) $t, $m) ? $m[1] : [];
|
||||
return preg_quote($string, '#');
|
||||
}
|
||||
|
||||
public static function implode(array|string $a): string
|
||||
/**
|
||||
* Implode simple array into string a,b,c.
|
||||
*
|
||||
* @param array|string $values The values
|
||||
*
|
||||
* @return string The value
|
||||
*/
|
||||
public static function encodeSingle(array|string $values): string
|
||||
{
|
||||
if (is_string($a)) {
|
||||
return $a;
|
||||
}
|
||||
if (!is_array($a)) {
|
||||
return '';
|
||||
return implode(',', self::decodeSingle($values));
|
||||
}
|
||||
|
||||
$r = '';
|
||||
foreach ($a as $k => $v) {
|
||||
$r .= $k . ':' . $v . ';';
|
||||
}
|
||||
|
||||
return $r;
|
||||
}
|
||||
|
||||
public static function explode(array|string $s): array
|
||||
/**
|
||||
* Explode string into simple array [a,b,c].
|
||||
*
|
||||
* @param array|string $value The value
|
||||
*
|
||||
* @return array The values
|
||||
*/
|
||||
public static function decodeSingle(array|string $value): array
|
||||
{
|
||||
if (is_array($s)) {
|
||||
return $s;
|
||||
if (is_array($value)) {
|
||||
$value = implode(',', $value);
|
||||
}
|
||||
if (!is_string($s)) {
|
||||
|
||||
return preg_match_all('#([A-Za-z0-9]+)#', (string) $value, $matches) ? $matches[1] : [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Implode complexe array into string a:aa:b:bb;c:cc.
|
||||
*
|
||||
* @param array|string $values The values
|
||||
*
|
||||
* @return string The value
|
||||
*/
|
||||
public static function encodeMulti(array|string $values): string
|
||||
{
|
||||
if (is_string($values)) {
|
||||
return $values;
|
||||
}
|
||||
|
||||
$string = '';
|
||||
foreach ($values as $key => $value) {
|
||||
$string .= $key . ':' . $value . ';';
|
||||
}
|
||||
|
||||
return $string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Explode string into complexe array [a=>aa,b=>aa,c=>cc].
|
||||
*
|
||||
* @param array|string $value The value
|
||||
*
|
||||
* @return array The values
|
||||
*/
|
||||
public static function decodeMulti(array|string $value): array
|
||||
{
|
||||
if (is_array($value)) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
$values = [];
|
||||
$exp = explode(';', (string) $value);
|
||||
if (!is_array($exp)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$r = [];
|
||||
$s = explode(';', (string) $s);
|
||||
if (!is_array($s)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
foreach ($s as $cpl) {
|
||||
foreach ($exp as $cpl) {
|
||||
$cur = explode(':', $cpl);
|
||||
|
||||
if (!is_array($cur) || !isset($cur[1])) {
|
||||
|
@ -295,59 +360,75 @@ class Epc
|
|||
continue;
|
||||
}
|
||||
|
||||
$r[$key] = $val;
|
||||
$values[$key] = $val;
|
||||
}
|
||||
|
||||
return $r;
|
||||
return $values;
|
||||
}
|
||||
|
||||
#
|
||||
# Widgets
|
||||
#
|
||||
|
||||
public static function widgetContentEntryExcerpt(?WidgetsElement $w = null): string
|
||||
/**
|
||||
* Send entries excerpts to widget.
|
||||
*
|
||||
* @param WidgetsElement|null $widget The widgets
|
||||
*
|
||||
* @return string The entries exceprts
|
||||
*/
|
||||
public static function widgetContentEntryExcerpt(?WidgetsElement $widget = null): string
|
||||
{
|
||||
if (is_null(dcCore::app()->ctx) || !dcCore::app()->ctx->exists('posts')) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$res = '';
|
||||
$content = '';
|
||||
while (dcCore::app()->ctx->__get('posts')?->fetch()) {
|
||||
$res .= dcCore::app()->ctx->__get('posts')->f('post_excerpt');
|
||||
$content .= dcCore::app()->ctx->__get('posts')->f('post_excerpt');
|
||||
}
|
||||
|
||||
return $res;
|
||||
return $content;
|
||||
}
|
||||
|
||||
public static function widgetContentEntryContent(): string
|
||||
/**
|
||||
* Send entries contents to widget.
|
||||
*
|
||||
* @param WidgetsElement|null $widget The widgets
|
||||
*
|
||||
* @return string The entries contents
|
||||
*/
|
||||
public static function widgetContentEntryContent(?WidgetsElement $widget = null): string
|
||||
{
|
||||
if (is_null(dcCore::app()->ctx) || !dcCore::app()->ctx->exists('posts')) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$res = '';
|
||||
$content = '';
|
||||
while (dcCore::app()->ctx->__get('posts')?->fetch()) {
|
||||
$res .= dcCore::app()->ctx->__get('posts')->f('post_content');
|
||||
$content .= dcCore::app()->ctx->__get('posts')->f('post_content');
|
||||
}
|
||||
|
||||
return $res;
|
||||
return $content;
|
||||
}
|
||||
|
||||
public static function widgetContentCommentContent(): string
|
||||
/**
|
||||
* Send entries comments to widget.
|
||||
*
|
||||
* @param WidgetsElement|null $widget The widgets
|
||||
*
|
||||
* @return string The entries comments
|
||||
*/
|
||||
public static function widgetContentCommentContent(?WidgetsElement $widget = null): string
|
||||
{
|
||||
if (is_null(dcCore::app()->ctx) || !dcCore::app()->ctx->exists('posts')) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$res = '';
|
||||
$post_ids = [];
|
||||
$content = '';
|
||||
while (dcCore::app()->ctx->__get('posts')?->fetch()) {
|
||||
$comments = dcCore::app()->blog?->getComments(['post_id' => dcCore::app()->ctx->__get('posts')->f('post_id')]);
|
||||
while ($comments?->fetch()) {
|
||||
$res .= $comments->getContent();
|
||||
$content .= $comments->getContent();
|
||||
}
|
||||
}
|
||||
|
||||
return $res;
|
||||
return $content;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,31 +20,67 @@ use dcRecord;
|
|||
use Dotclear\Plugin\widgets\WidgetsElement;
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Filter abstract class.
|
||||
*
|
||||
* All filter must extends this class.
|
||||
*/
|
||||
abstract class EpcFilter
|
||||
{
|
||||
/** @var string $id The filter id */
|
||||
protected string $id = 'undefined';
|
||||
|
||||
/** @var dcRecord $records The filter record if any */
|
||||
private ?dcRecord $records = null;
|
||||
|
||||
// properties
|
||||
/** @var int $priority The filter priority (property) */
|
||||
public readonly int $priority;
|
||||
|
||||
/** @var string $name The filter name (property) */
|
||||
public readonly string $name;
|
||||
public readonly string $help;
|
||||
|
||||
/** @var string $description The filter description (property) */
|
||||
public readonly string $description;
|
||||
|
||||
/** @var bool $has_list Filter has list of records (property) */
|
||||
public readonly bool $has_list;
|
||||
public readonly string $htmltag;
|
||||
|
||||
/** @var array $ignore The filter disabled html tags (property) */
|
||||
public readonly array $ignore;
|
||||
|
||||
/** @var array $class The css class that apply to filter (property) */
|
||||
public readonly array $class;
|
||||
|
||||
/** @var string $replace The filter replacement bloc in content (property) */
|
||||
public readonly string $replace;
|
||||
|
||||
/** @var string $widget The filter replacement bloc in widget (property) */
|
||||
public readonly string $widget;
|
||||
|
||||
// settings
|
||||
/** @var bool $nocase The filter caseless match (settings) */
|
||||
public readonly bool $nocase;
|
||||
public readonly bool $plural;
|
||||
public readonly int $limit;
|
||||
public readonly array $style;
|
||||
public readonly string $notag;
|
||||
public readonly array $tplValues;
|
||||
public readonly array $pubPages;
|
||||
|
||||
/** @var bool $plural The filter caseless match (settings) */
|
||||
public readonly bool $plural;
|
||||
|
||||
/** @var bool $plural The replacement limit per filter (settings) */
|
||||
public readonly int $limit;
|
||||
|
||||
/** @var array $style The style applied to filter class (settings) */
|
||||
public readonly array $style;
|
||||
|
||||
/** @var array $notag The filter disabled html tags (settings) */
|
||||
public readonly array $notag;
|
||||
|
||||
/** @var array $template The extra template value to scan (settings) */
|
||||
public readonly array $template;
|
||||
|
||||
/** @var array $page The extra frontend pages to scan (settings) */
|
||||
public readonly array $page;
|
||||
|
||||
/**
|
||||
* Constructor sets filter properties and settings.
|
||||
*/
|
||||
final public function __construct()
|
||||
{
|
||||
if ($this->id == 'undefined') {
|
||||
|
@ -63,9 +99,9 @@ abstract class EpcFilter
|
|||
// from filter defautl properties
|
||||
$this->priority = isset($properties['priority']) ? abs((int) $properties['priority']) : 500;
|
||||
$this->name = isset($properties['name']) ? (string) $properties['name'] : 'undefined';
|
||||
$this->help = isset($properties['help']) ? (string) $properties['help'] : 'undefined';
|
||||
$this->description = isset($properties['description']) ? (string) $properties['description'] : 'undefined';
|
||||
$this->has_list = isset($properties['has_list']) ? (bool) $properties['has_list'] : false;
|
||||
$this->htmltag = isset($properties['htmltag']) ? (string) $properties['htmltag'] : '';
|
||||
$this->ignore = isset($properties['ignore']) && is_array($properties['ignore']) ? $properties['ignore'] : [];
|
||||
$this->class = isset($properties['class']) && is_array($properties['class']) ? $properties['class'] : [];
|
||||
$this->replace = isset($properties['replace']) ? (string) $properties['replace'] : '';
|
||||
$this->widget = isset($properties['widget']) ? (string) $properties['widget'] : '';
|
||||
|
@ -75,41 +111,52 @@ abstract class EpcFilter
|
|||
$plural = isset($settings['plural']) ? (bool) $settings['plural'] : false;
|
||||
$limit = isset($settings['limit']) ? abs((int) $settings['limit']) : 0;
|
||||
$style = isset($settings['style']) && is_array($settings['style']) ? $settings['style'] : [];
|
||||
$notag = isset($settings['notag']) ? (string) $settings['notag'] : '';
|
||||
$tplValues = isset($settings['tplValues']) && is_array($settings['tplValues']) ? $settings['tplValues'] : [];
|
||||
$pubPages = isset($settings['pubPages']) && is_array($settings['pubPages']) ? $settings['pubPages'] : [];
|
||||
$notag = isset($settings['notag']) && is_array($settings['notag']) ? $settings['notag'] : [];
|
||||
$template = isset($settings['template']) && is_array($settings['template']) ? $settings['template'] : [];
|
||||
$page = isset($settings['page']) && is_array($settings['page']) ? $settings['page'] : [];
|
||||
|
||||
// from blog settings
|
||||
$this->nocase = isset($s['nocase']) ? (bool) $s['nocase'] : $nocase;
|
||||
$this->plural = isset($s['plural']) ? (bool) $s['plural'] : $plural;
|
||||
$this->limit = isset($s['limit']) ? abs((int) $s['limit']) : $limit;
|
||||
$this->style = isset($s['style']) && is_array($s['style']) ? $s['style'] : $style;
|
||||
$this->notag = isset($s['notag']) ? (string) $s['notag'] : $notag;
|
||||
$this->tplValues = isset($s['tplValues']) && is_array($s['tplValues']) ? $s['tplValues'] : $tplValues;
|
||||
$this->pubPages = isset($s['pubPages']) && is_array($s['pubPages']) ? $s['pubPages'] : $pubPages;
|
||||
$this->notag = isset($s['notag']) && is_array($s['notag']) ? $s['notag'] : $notag;
|
||||
$this->template = isset($s['template']) && is_array($s['template']) ? $s['template'] : $template;
|
||||
$this->page = isset($s['page']) && is_array($s['page']) ? $s['page'] : $page;
|
||||
}
|
||||
|
||||
protected function initProperties(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
/**
|
||||
* Return filter default properties.
|
||||
*
|
||||
* @return array The properties
|
||||
*/
|
||||
abstract protected function initProperties(): array;
|
||||
|
||||
protected function initSettings(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
public static function create(ArrayObject $o): void
|
||||
{
|
||||
$c = static::class;
|
||||
$o->append(new $c());
|
||||
}
|
||||
/**
|
||||
* Return filter default settings.
|
||||
*
|
||||
* @return array The settings
|
||||
*/
|
||||
abstract protected function initSettings(): array;
|
||||
|
||||
/**
|
||||
* Get fitler ID.
|
||||
*
|
||||
* @return string The filter ID
|
||||
*/
|
||||
final public function id(): string
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get fitler record.
|
||||
*
|
||||
* Fitler records are usefull to store and retrieve
|
||||
* list of keyword / replacement etc...
|
||||
*
|
||||
* @return dcRecord The filter record instance
|
||||
*/
|
||||
final public function records(): dcRecord
|
||||
{
|
||||
if ($this->records === null && $this->has_list) {
|
||||
|
@ -119,11 +166,27 @@ abstract class EpcFilter
|
|||
return $this->records ?? dcRecord::newFromArray([]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter frontend contents in situ.
|
||||
*
|
||||
* @param string $tag The tempale block tag
|
||||
* @param array $args The template block arguments
|
||||
*/
|
||||
public function publicContent(string $tag, array $args): void
|
||||
{
|
||||
}
|
||||
|
||||
public function widgetList(string $content, WidgetsElement $w, ArrayObject $list): void
|
||||
/**
|
||||
* Filter frontend contents for widgets.
|
||||
*
|
||||
* Filter the contents and return matching results infos
|
||||
* into the list of current widget.
|
||||
*
|
||||
* @param string $content The contents
|
||||
* @param WidgetsElement $widget The widget
|
||||
* @param ArrayObject $list The list
|
||||
*/
|
||||
public function widgetList(string $content, WidgetsElement $widget, ArrayObject $list): void
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ class EpcFilters
|
|||
{
|
||||
$nid = [];
|
||||
foreach ($this->stack as $filter) {
|
||||
if ($filter->widget != '') {
|
||||
if (!$exclude_widget || $filter->widget != '') {
|
||||
$nid[$filter->name] = $filter->id();
|
||||
}
|
||||
}
|
||||
|
@ -76,13 +76,17 @@ class EpcFilters
|
|||
}
|
||||
|
||||
/**
|
||||
* Sort filters stack by filter name.
|
||||
* Sort filters stack by filter name or priority.
|
||||
*
|
||||
* @return EpcFilters The filters instance
|
||||
*/
|
||||
public function sort(): EpcFilters
|
||||
public function sort(bool $by_name = false): EpcFilters
|
||||
{
|
||||
if ($by_name) {
|
||||
uasort($this->stack, fn ($a, $b) => $a->name <=> $b->name);
|
||||
} else {
|
||||
uasort($this->stack, fn ($a, $b) => $a->priority <=> $b->priority);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
|
|
@ -19,8 +19,19 @@ use dcCore;
|
|||
use dcRecord;
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Filter records.
|
||||
*/
|
||||
class EpcRecord
|
||||
{
|
||||
/**
|
||||
* Get records.
|
||||
*
|
||||
* @param array $params The query params
|
||||
* @param bool $count_only Count only
|
||||
*
|
||||
* @return dcRecord The records instance
|
||||
*/
|
||||
public static function getRecords(array $params, bool $count_only = false): dcRecord
|
||||
{
|
||||
if ($count_only) {
|
||||
|
@ -99,6 +110,13 @@ class EpcRecord
|
|||
return new dcRecord(dcCore::app()->con->select($strReq));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add record.
|
||||
*
|
||||
* @param cursor $cur The cursor
|
||||
*
|
||||
* @return int The record ID
|
||||
*/
|
||||
public static function addRecord(cursor $cur): int
|
||||
{
|
||||
dcCore::app()->con->writeLock(dcCore::app()->prefix . My::TABLE_NAME);
|
||||
|
@ -117,7 +135,7 @@ class EpcRecord
|
|||
|
||||
throw $e;
|
||||
}
|
||||
self::trigger();
|
||||
dcCore::app()->blog?->triggerBlog();
|
||||
|
||||
# --BEHAVIOR-- enhancePostContentAfterAddRecord : cursor
|
||||
dcCore::app()->callBehavior('enhancePostContentAfterAddRecord', $cur);
|
||||
|
@ -125,6 +143,12 @@ class EpcRecord
|
|||
return (int) $cur->getField('epc_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a record.
|
||||
*
|
||||
* @param int $id The record ID
|
||||
* @param cursor $cur The cursor
|
||||
*/
|
||||
public static function updRecord(int $id, cursor $cur): void
|
||||
{
|
||||
if (empty($id)) {
|
||||
|
@ -134,12 +158,21 @@ class EpcRecord
|
|||
$cur->setField('epc_upddt', date('Y-m-d H:i:s'));
|
||||
|
||||
$cur->update('WHERE epc_id = ' . $id . " AND blog_id = '" . dcCore::app()->con->escapeStr((string) dcCore::app()->blog?->id) . "' ");
|
||||
self::trigger();
|
||||
dcCore::app()->blog?->triggerBlog();
|
||||
|
||||
# --BEHAVIOR-- enhancePostContentAfterUpdRecord : cursor, int
|
||||
dcCore::app()->callBehavior('enhancePostContentAfterUpdRecord', $cur, $id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a record exists.
|
||||
*
|
||||
* @param null|string $filter The filter ID
|
||||
* @param null|string $key The record key
|
||||
* @param null|int $not_id Exclude an id
|
||||
*
|
||||
* @return bool True if it exists
|
||||
*/
|
||||
public static function isRecord(?string $filter, ?string $key, ?int $not_id = null): bool
|
||||
{
|
||||
return 0 < self::getRecords([
|
||||
|
@ -149,6 +182,11 @@ class EpcRecord
|
|||
], true)->f(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a record.
|
||||
*
|
||||
* @param int $id The record ID
|
||||
*/
|
||||
public static function delRecord(int $id): void
|
||||
{
|
||||
if (empty($id)) {
|
||||
|
@ -164,9 +202,14 @@ class EpcRecord
|
|||
"AND blog_id = '" . dcCore::app()->con->escapeStr((string) dcCore::app()->blog?->id) . "' "
|
||||
);
|
||||
|
||||
self::trigger();
|
||||
dcCore::app()->blog?->triggerBlog();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get next record ID.
|
||||
*
|
||||
* @return int The next record ID
|
||||
*/
|
||||
private static function getNextId(): int
|
||||
{
|
||||
return (int) dcCore::app()->con->select(
|
||||
|
@ -174,11 +217,21 @@ class EpcRecord
|
|||
)->f(0) + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Open filter cursor.
|
||||
*
|
||||
* @return cursor The cursor
|
||||
*/
|
||||
public static function openCursor(): cursor
|
||||
{
|
||||
return dcCore::app()->con->openCursor(dcCore::app()->prefix . My::TABLE_NAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean up a cursor.
|
||||
*
|
||||
* @param cursor $cur The cursor
|
||||
*/
|
||||
private static function getCursor(cursor $cur): void
|
||||
{
|
||||
if ($cur->getField('epc_key') == '') {
|
||||
|
@ -191,9 +244,4 @@ class EpcRecord
|
|||
throw new Exception(__('No record filter'));
|
||||
}
|
||||
}
|
||||
|
||||
private static function trigger(): void
|
||||
{
|
||||
dcCore::app()->blog?->triggerBlog();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,9 +28,9 @@ class EpcFilterAbbreviation extends EpcFilter
|
|||
return [
|
||||
'priority' => 400,
|
||||
'name' => __('Abbreviation'),
|
||||
'help' => __('Explain some abbreviation. First term of the list is the abbreviation and second term the explanation.'),
|
||||
'description' => __('Explain some abbreviation. First term of the list is the abbreviation and second term the explanation.'),
|
||||
'has_list' => true,
|
||||
'htmltag' => 'pre,code,a',
|
||||
'ignore' => ['pre','code','a'],
|
||||
'class' => ['abbr.epc-abbr'],
|
||||
'replace' => '<abbr class="epc-abbr" title="%s">%s</abbr>',
|
||||
'widget' => '<abbr title="%s">%s</abbr>',
|
||||
|
@ -41,9 +41,9 @@ class EpcFilterAbbreviation extends EpcFilter
|
|||
{
|
||||
return [
|
||||
'style' => ['font-weight: bold;'],
|
||||
'notag' => 'a,acronym,abbr,dfn,h1,h2,h3',
|
||||
'tplValues' => ['EntryContent'],
|
||||
'pubPages' => ['post.html'],
|
||||
'notag' => ['acronym','abbr','dfn','h1','h2','h3'],
|
||||
'template' => ['EntryContent'],
|
||||
'page' => ['post.html'],
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
@ -28,9 +28,9 @@ class EpcFilterAcronym extends EpcFilter
|
|||
return [
|
||||
'priority' => 700,
|
||||
'name' => __('Acronym'),
|
||||
'help' => __('Explain some acronyms. First term of the list is the acornym and second term the explanation.'),
|
||||
'description' => __('Explain some acronyms. First term of the list is the acornym and second term the explanation.'),
|
||||
'has_list' => true,
|
||||
'htmltag' => 'pre,code,acronym',
|
||||
'ignore' => ['pre','code','acronym'],
|
||||
'class' => ['acronym.epc-acronym'],
|
||||
'replace' => '<acronym class="epc-acronym" title="%s">%s</acronym>',
|
||||
'widget' => '<acronym title="%s">%s</acronym>',
|
||||
|
@ -41,9 +41,9 @@ class EpcFilterAcronym extends EpcFilter
|
|||
{
|
||||
return [
|
||||
'style' => ['font-weight: bold;'],
|
||||
'notag' => 'a,acronym,abbr,dfn,h1,h2,h3',
|
||||
'tplValues' => ['EntryContent'],
|
||||
'pubPages' => ['post.html'],
|
||||
'notag' => ['a','acronym','abbr','dfn','h1','h2','h3'],
|
||||
'template' => ['EntryContent'],
|
||||
'page' => ['post.html'],
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
@ -28,9 +28,9 @@ class EpcFilterCitation extends EpcFilter
|
|||
return [
|
||||
'priority' => 600,
|
||||
'name' => __('Citation'),
|
||||
'help' => __('Highlight citation of people. First term of the list is the citation and second term the author.'),
|
||||
'description' => __('Highlight citation of people. First term of the list is the citation and second term the author.'),
|
||||
'has_list' => true,
|
||||
'htmltag' => 'pre,code,cite',
|
||||
'ignore' => ['pre','code','cite'],
|
||||
'class' => ['cite.epc-cite'],
|
||||
'replace' => '<cite class="epc-cite" title="%s">%s</cite>',
|
||||
'widget' => '<cite title="%s">%s</cite>',
|
||||
|
@ -42,9 +42,9 @@ class EpcFilterCitation extends EpcFilter
|
|||
return [
|
||||
'nocase' => true,
|
||||
'style' => ['font-style: italic;'],
|
||||
'notag' => 'a,h1,h2,h3',
|
||||
'tplValues' => ['EntryContent'],
|
||||
'pubPages' => ['post.html'],
|
||||
'notag' => ['a','h1','h2','h3'],
|
||||
'template' => ['EntryContent'],
|
||||
'page' => ['post.html'],
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
@ -28,9 +28,9 @@ class EpcFilterDefinition extends EpcFilter
|
|||
return [
|
||||
'priority' => 800,
|
||||
'name' => __('Definition'),
|
||||
'help' => __('Explain some definition. First term of the list is the sample to define and second term the explanation.'),
|
||||
'description' => __('Explain some definition. First term of the list is the sample to define and second term the explanation.'),
|
||||
'has_list' => true,
|
||||
'htmltag' => 'pre,code,dfn',
|
||||
'ignore' => ['pre','code','dfn'],
|
||||
'class' => ['dfn.epc-dfn'],
|
||||
'replace' => '<dfn class="epc-dfn" title="%s">%s</dfn>',
|
||||
'widget' => '<dfn class="epc-dfn" title="%s">%s</dfn>',
|
||||
|
@ -41,9 +41,9 @@ class EpcFilterDefinition extends EpcFilter
|
|||
{
|
||||
return [
|
||||
'style' => ['font-weight: bold;'],
|
||||
'notag' => 'a,acronym,abbr,dfn,h1,h2,h3',
|
||||
'tplValues' => ['EntryContent'],
|
||||
'pubPages' => ['post.html'],
|
||||
'notag' => ['a','acronym','abbr','dfn','h1','h2','h3'],
|
||||
'template' => ['EntryContent'],
|
||||
'page' => ['post.html'],
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
@ -28,9 +28,9 @@ class EpcFilterLink extends EpcFilter
|
|||
return [
|
||||
'priority' => 500,
|
||||
'name' => __('Link'),
|
||||
'help' => __('Link some words. First term of the list is the term to link and second term the link.'),
|
||||
'description' => __('Link some words. First term of the list is the term to link and second term the link.'),
|
||||
'has_list' => true,
|
||||
'htmltag' => 'pre,code,a',
|
||||
'ignore' => ['pre','code','a'],
|
||||
'class' => ['a.epc-link'],
|
||||
'replace' => '<a class="epc-link" title="%s" href="%s">%s</a>',
|
||||
'widget' => '<a title="%s" href="%s">%s</a>',
|
||||
|
@ -41,9 +41,9 @@ class EpcFilterLink extends EpcFilter
|
|||
{
|
||||
return [
|
||||
'style' => ['text-decoration: none; font-style: italic; color: #0000FF;'],
|
||||
'notag' => 'a,h1,h2,h3',
|
||||
'tplValues' => ['EntryContent'],
|
||||
'pubPages' => ['post.html'],
|
||||
'notag' => ['h1','h2','h3'],
|
||||
'template' => ['EntryContent'],
|
||||
'page' => ['post.html'],
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
@ -26,9 +26,9 @@ class EpcFilterReplace extends EpcFilter
|
|||
return [
|
||||
'priority' => 200,
|
||||
'name' => __('Replace'),
|
||||
'help' => __('Replace some text. First term of the list is the text to replace and second term the replacement.'),
|
||||
'description' => __('Replace some text. First term of the list is the text to replace and second term the replacement.'),
|
||||
'has_list' => true,
|
||||
'htmltag' => 'pre,code',
|
||||
'ignore' => ['pre','code'],
|
||||
'class' => ['span.epc-replace'],
|
||||
'replace' => '<span class="epc-replace">%s</span>',
|
||||
];
|
||||
|
@ -40,9 +40,9 @@ class EpcFilterReplace extends EpcFilter
|
|||
'nocase' => true,
|
||||
'plural' => true,
|
||||
'style' => ['font-style: italic;'],
|
||||
'notag' => 'h1,h2,h3',
|
||||
'tplValues' => ['EntryContent'],
|
||||
'pubPages' => ['post.html'],
|
||||
'notag' => ['h1','h2','h3'],
|
||||
'template' => ['EntryContent'],
|
||||
'page' => ['post.html'],
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
@ -27,8 +27,8 @@ class EpcFilterSearch extends EpcFilter
|
|||
return [
|
||||
'priority' => 100,
|
||||
'name' => __('Search'),
|
||||
'help' => __('Highlight searched words.'),
|
||||
'htmltag' => '',
|
||||
'description' => __('Highlight searched words.'),
|
||||
'ignore' => [],
|
||||
'class' => ['span.epc-search'],
|
||||
'replace' => '<span class="epc-search" title="' . __('Search') . '">%s</span>',
|
||||
];
|
||||
|
@ -40,9 +40,9 @@ class EpcFilterSearch extends EpcFilter
|
|||
'nocase' => true,
|
||||
'plural' => true,
|
||||
'style' => ['color: #FFCC66;'],
|
||||
'notag' => 'h1,h2,h3',
|
||||
'notag' => ['h1','h2','h3'],
|
||||
'tplValues' => ['EntryContent'],
|
||||
'pubPages' => ['search.html'],
|
||||
'page' => ['search.html'],
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
@ -29,8 +29,8 @@ class EpcFilterTag extends EpcFilter
|
|||
return [
|
||||
'priority' => 900,
|
||||
'name' => __('Tag'),
|
||||
'help' => __('Highlight tags of your blog.'),
|
||||
'htmltag' => 'pre,code,a',
|
||||
'description' => __('Highlight tags of your blog.'),
|
||||
'ignore' => ['pre','code','a'],
|
||||
'class' => ['a.epc-tag'],
|
||||
'replace' => '<a class="epc-tag" href="%s" title="' . __('Tag') . '">%s</a>',
|
||||
'widget' => '<a href="%s" title="' . __('Tag') . '">%s</a>',
|
||||
|
@ -41,9 +41,9 @@ class EpcFilterTag extends EpcFilter
|
|||
{
|
||||
return [
|
||||
'style' => ['text-decoration: none; border-bottom: 3px double #CCCCCC;'],
|
||||
'notag' => 'pre,code,a,h1,h2,h3',
|
||||
'tplValues' => ['EntryContent'],
|
||||
'pubPages' => ['post.html'],
|
||||
'notag' => ['h1','h2','h3'],
|
||||
'template' => ['EntryContent'],
|
||||
'page' => ['post.html'],
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
@ -26,8 +26,8 @@ class EpcFilterTwitter extends EpcFilter
|
|||
return [
|
||||
'priority' => 1000,
|
||||
'name' => __('Twitter'),
|
||||
'help' => __('Add link to twitter user page. Every word started with "@" will be considered as twitter user.'),
|
||||
'htmltag' => 'pre,code,a',
|
||||
'description' => __('Add link to twitter user page. Every word started with "@" will be considered as twitter user.'),
|
||||
'ingore' => ['pre','code','a'],
|
||||
'class' => ['a.epc-twitter'],
|
||||
'replace' => '<a class="epc-twitter" title="' . __("View this user's twitter page") . '" href="%s">%s</a>',
|
||||
];
|
||||
|
@ -37,9 +37,9 @@ class EpcFilterTwitter extends EpcFilter
|
|||
{
|
||||
return [
|
||||
'style' => ['text-decoration: none; font-weight: bold; font-style: italic; color: #0000FF;'],
|
||||
'notag' => 'a,h1,h2,h3',
|
||||
'tplValues' => ['EntryContent'],
|
||||
'pubPages' => ['post.html'],
|
||||
'notag' => ['h1','h2','h3'],
|
||||
'template' => ['EntryContent'],
|
||||
'page' => ['post.html'],
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
@ -26,9 +26,9 @@ class EpcFilterUpdate extends EpcFilter
|
|||
return [
|
||||
'priority' => 300,
|
||||
'name' => __('Update'),
|
||||
'help' => __('Update and show terms. First term of the list is the term to update and second term the new term.'),
|
||||
'description' => __('Update and show terms. First term of the list is the term to update and second term the new term.'),
|
||||
'has_list' => true,
|
||||
'htmltag' => 'pre,code,del,ins',
|
||||
'ignore' => ['pre','code','del','ins'],
|
||||
'class' => ['del.epc-update', 'ins.epc-update'],
|
||||
'replace' => '<del class="epc-update">%s</del> <ins class="epc-update">%s</ins>',
|
||||
];
|
||||
|
@ -40,9 +40,9 @@ class EpcFilterUpdate extends EpcFilter
|
|||
'nocase' => true,
|
||||
'plural' => true,
|
||||
'style' => ['text-decoration: line-through;', 'font-style: italic;'],
|
||||
'notag' => 'h1,h2,h3',
|
||||
'tplValues' => ['EntryContent'],
|
||||
'pubPages' => ['post.html'],
|
||||
'notag' => ['h1','h2','h3'],
|
||||
'template' => ['EntryContent'],
|
||||
'page' => ['post.html'],
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
@ -38,18 +38,25 @@ class Frontend extends dcNsProcess
|
|||
}
|
||||
|
||||
dcCore::app()->addBehaviors([
|
||||
// add CSS URL to header
|
||||
// Add CSS URL to frontend header
|
||||
'publicHeadContent' => function (): void {
|
||||
echo dcUtils::cssLoad(dcCore::app()->blog?->url . dcCore::app()->url->getURLFor('epccss'));
|
||||
},
|
||||
// Filter template blocks content
|
||||
'publicBeforeContentFilterV2' => function (string $tag, array $args): void {
|
||||
foreach (Epc::getFilters()->dump() as $filter) {
|
||||
if (!Epc::testContext($tag, $args, $filter)) {
|
||||
continue;
|
||||
}
|
||||
// test context
|
||||
if (in_array((string) dcCore::app()->ctx?->__get('current_tpl'), $filter->page)
|
||||
&& in_array($tag, $filter->template)
|
||||
&& $args[0] != '' //content
|
||||
&& empty($args['encode_xml'])
|
||||
&& empty($args['encode_html'])
|
||||
&& empty($args['remove_html'])
|
||||
&& empty($args['strip_tags'])
|
||||
) {
|
||||
$filter->publicContent($tag, $args);
|
||||
}
|
||||
}
|
||||
},
|
||||
// Widgets
|
||||
'initWidgets' => [Widgets::class, 'initWidgets'],
|
||||
|
|
|
@ -71,8 +71,8 @@ class Install extends dcNsProcess
|
|||
$s->put('list_sortby', 'epc_key', 'string', 'Admin records list field order', false, true);
|
||||
$s->put('list_order', 'desc', 'string', 'Admin records list order', false, true);
|
||||
$s->put('list_nb', 20, 'integer', 'Admin records list nb per page', false, true);
|
||||
$s->put('allowedtplvalues', json_encode(Epc::defaultAllowedTplValues()), 'string', 'List of allowed template values', false, true);
|
||||
$s->put('allowedpubpages', json_encode(Epc::defaultAllowedPubPages()), 'string', 'List of allowed template pages', false, true);
|
||||
$s->put('allowedtplvalues', json_encode(Epc::defaultAllowedTemplateValue()), 'string', 'List of allowed template values', false, true);
|
||||
$s->put('allowedpubpages', json_encode(Epc::defaultAllowedTemplatePage()), 'string', 'List of allowed template pages', false, true);
|
||||
|
||||
// Filters settings
|
||||
foreach (Epc::getFilters()->dump() as $filter) {
|
||||
|
@ -82,8 +82,8 @@ class Install extends dcNsProcess
|
|||
'plural' => $filter->plural,
|
||||
'style' => $filter->style,
|
||||
'notag' => $filter->notag,
|
||||
'tplValues' => $filter->tplValues,
|
||||
'pubPages' => $filter->pubPages,
|
||||
'template' => $filter->template,
|
||||
'page' => $filter->page,
|
||||
];
|
||||
$s->put($filter->id(), json_encode($opt), 'string', 'Settings for ' . $filter->id(), false, true);
|
||||
}
|
||||
|
@ -114,10 +114,12 @@ class Install extends dcNsProcess
|
|||
if ($current && version_compare($current, '2022.11.20', '<=')) {
|
||||
self::upTo20221120();
|
||||
}
|
||||
|
||||
// 2023.04.22: not replaced: tplValues->template and pubPages->page
|
||||
}
|
||||
|
||||
/**
|
||||
* 0.6.6
|
||||
* Upgrade from 0.6.6
|
||||
*
|
||||
* - filters move from settings to dedicated table
|
||||
*/
|
||||
|
@ -150,7 +152,7 @@ class Install extends dcNsProcess
|
|||
}
|
||||
|
||||
/**
|
||||
* 2021.10.06
|
||||
* Upgrade from 2021.10.06
|
||||
*
|
||||
* - filters change name to id
|
||||
*/
|
||||
|
@ -169,7 +171,7 @@ class Install extends dcNsProcess
|
|||
}
|
||||
|
||||
/**
|
||||
* 2022.11.20
|
||||
* Upgrade from 2022.11.20
|
||||
*
|
||||
* - setting id changes to shorter one,
|
||||
* - setting ns changes to abstract one (no real changes),
|
||||
|
|
|
@ -57,27 +57,31 @@ class Manage extends dcNsProcess
|
|||
return false;
|
||||
}
|
||||
|
||||
// nullsafe check
|
||||
if (is_null(dcCore::app()->blog) || is_null(dcCore::app()->adminurl)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// get filter and post values
|
||||
$action = $_POST['action'] ?? '';
|
||||
$filter = Epc::getFilters()->get($_REQUEST['part'] ?? '');
|
||||
if (is_null($filter)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// check errors
|
||||
if (dcCore::app()->error->flag()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// open save to other plugins
|
||||
if (!empty($action)) {
|
||||
# --BEHAVIOR-- enhancePostContentAdminSave
|
||||
dcCore::app()->callBehavior('enhancePostContentAdminSave');
|
||||
}
|
||||
|
||||
try {
|
||||
# Update filter settings
|
||||
// Update filter settings
|
||||
if ($action == 'savefiltersetting') {
|
||||
# Parse filters options
|
||||
$f = [
|
||||
|
@ -85,9 +89,9 @@ class Manage extends dcNsProcess
|
|||
'plural' => !empty($_POST['filter_plural']),
|
||||
'limit' => abs((int) $_POST['filter_limit']),
|
||||
'style' => (array) $_POST['filter_style'],
|
||||
'notag' => (string) $_POST['filter_notag'],
|
||||
'tplValues' => (array) $_POST['filter_tplValues'],
|
||||
'pubPages' => (array) $_POST['filter_pubPages'],
|
||||
'notag' => Epc::decodeSingle($_POST['filter_notag']),
|
||||
'template' => (array) $_POST['filter_template'],
|
||||
'page' => (array) $_POST['filter_page'],
|
||||
];
|
||||
|
||||
dcCore::app()->blog->settings->get(My::id())->put($filter->id(), json_encode($f));
|
||||
|
@ -105,7 +109,7 @@ class Manage extends dcNsProcess
|
|||
);
|
||||
}
|
||||
|
||||
# Add new filter record
|
||||
// Add new filter record
|
||||
if ($action == 'savenewrecord'
|
||||
&& !empty($_POST['new_key'])
|
||||
&& !empty($_POST['new_value'])
|
||||
|
@ -133,7 +137,7 @@ class Manage extends dcNsProcess
|
|||
);
|
||||
}
|
||||
|
||||
# Update filter records
|
||||
// Update filter records
|
||||
if ($action == 'deleterecords'
|
||||
&& $filter->has_list
|
||||
&& !empty($_POST['epc_id'])
|
||||
|
@ -172,17 +176,22 @@ class Manage extends dcNsProcess
|
|||
return;
|
||||
}
|
||||
|
||||
// nullsafe check
|
||||
if (is_null(dcCore::app()->blog) || is_null(dcCore::app()->adminurl)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// get filters
|
||||
$filters = Epc::getFilters();
|
||||
$filter = $filters->get($_REQUEST['part'] ?? 'link');
|
||||
if (is_null($filter)) {
|
||||
return;
|
||||
}
|
||||
|
||||
# -- Prepare page --
|
||||
// sort filters by name on backend
|
||||
Epc::getFilters()->sort(true);
|
||||
|
||||
// Prepare tabs and lists
|
||||
$header = '';
|
||||
if ($filter->has_list) {
|
||||
$sorts = new adminGenericFilterV2('epc');
|
||||
|
@ -203,7 +212,7 @@ class Manage extends dcNsProcess
|
|||
$header = $sorts->js(dcCore::app()->adminurl->get('admin.plugin.' . My::id(), ['part' => $filter->id()], '&') . '#record');
|
||||
}
|
||||
|
||||
# Page headers
|
||||
// display
|
||||
dcPage::openModule(
|
||||
My::name(),
|
||||
dcPage::jsPageTabs() .
|
||||
|
@ -214,7 +223,6 @@ class Manage extends dcNsProcess
|
|||
dcCore::app()->callBehavior('enhancePostContentAdminHeader')
|
||||
);
|
||||
|
||||
# Page title
|
||||
echo
|
||||
dcPage::breadcrumb([
|
||||
__('Plugins') => '',
|
||||
|
@ -223,7 +231,7 @@ class Manage extends dcNsProcess
|
|||
]) .
|
||||
dcPage::notices();
|
||||
|
||||
# Filters select menu list
|
||||
// filters select menu
|
||||
echo
|
||||
(new Form('filters_menu'))->method('get')->action(dcCore::app()->adminurl->get('admin.plugin.' . My::id()))->fields([
|
||||
(new Para())->class('anchor-nav')->items([
|
||||
|
@ -233,25 +241,25 @@ class Manage extends dcNsProcess
|
|||
]),
|
||||
])->render();
|
||||
|
||||
# Filter title and description
|
||||
// selected filter
|
||||
echo
|
||||
'<h3>' . $filter->name . '</h3>' .
|
||||
'<p>' . $filter->help . '</p>';
|
||||
'<p>' . $filter->description . '</p>';
|
||||
|
||||
# Filter settings
|
||||
// Filter settings
|
||||
$form_pages = [(new Text('h4', __('Pages to be filtered')))];
|
||||
foreach (Epc::blogAllowedPubPages() as $k => $v) {
|
||||
foreach (Epc::blogAllowedTemplatePage() as $k => $v) {
|
||||
$form_pages[] = (new Para())->items([
|
||||
(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'),
|
||||
(new Checkbox(['filter_page[]', 'filter_page' . $v], in_array($v, $filter->page)))->value($v),
|
||||
(new Label(__($k), Label::OUTSIDE_LABEL_AFTER))->for('filter_page' . $v)->class('classic'),
|
||||
]);
|
||||
}
|
||||
|
||||
$form_values = [(new Text('h4', __('Contents to be filtered')))];
|
||||
foreach (Epc::blogAllowedTplValues() as $k => $v) {
|
||||
foreach (Epc::blogAllowedTemplateValue() as $k => $v) {
|
||||
$form_values[] = (new Para())->items([
|
||||
(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'),
|
||||
(new Checkbox(['filter_template[]', 'filter_template' . $v], in_array($v, $filter->template)))->value($v),
|
||||
(new Label(__($k), Label::OUTSIDE_LABEL_AFTER))->for('filter_template' . $v)->class('classic'),
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -288,9 +296,9 @@ class Manage extends dcNsProcess
|
|||
(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($filter->notag)),
|
||||
(new Input('filter_notag'))->size(60)->maxlenght(255)->value(Epc::encodeSingle($filter->notag)),
|
||||
]),
|
||||
(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 Note())->class('form-note')->text(__('This is the list of HTML tags where content will be ignored.') . '<br />' . (empty($filter->ignore) ? '' : sprintf(__('Tags "%s" will allways be ignored.'), Epc::encodeSingle($filter->ignore)))),
|
||||
|
||||
])),
|
||||
(new Div())->class('clear')->items([
|
||||
|
@ -302,7 +310,7 @@ class Manage extends dcNsProcess
|
|||
]),
|
||||
])->render();
|
||||
|
||||
# Filter records list
|
||||
// Filter records list (if any)
|
||||
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';
|
||||
|
||||
|
@ -335,7 +343,7 @@ class Manage extends dcNsProcess
|
|||
|
||||
echo '</div>';
|
||||
|
||||
# New record
|
||||
// New record
|
||||
echo
|
||||
(new Div('newrecord'))->class('multi-part')->title(__('New record'))->items([
|
||||
(new Form('form-create'))->method('post')->action(dcCore::app()->adminurl->get('admin.plugin.' . My::id()) . '#record')->fields([
|
||||
|
|
|
@ -59,10 +59,10 @@ class Widgets
|
|||
Epc::getFilters()->nid(true)
|
||||
);
|
||||
# Content
|
||||
foreach (Epc::defaultAllowedWidgetValues() as $k => $v) {
|
||||
foreach (Epc::widgetAllowedTemplateValue() as $name => $info) {
|
||||
$w->epclist->setting(
|
||||
'content' . $v['id'],
|
||||
sprintf(__('Enable filter on %s'), __($k)),
|
||||
'content' . $info['id'],
|
||||
sprintf(__('Enable filter on %s'), __($name)),
|
||||
1,
|
||||
'check'
|
||||
);
|
||||
|
@ -101,11 +101,11 @@ class Widgets
|
|||
|
||||
# Content
|
||||
$content = '';
|
||||
foreach (Epc::defaultAllowedWidgetValues() as $k => $v) {
|
||||
$ns = 'content' . $v['id'];
|
||||
if ($w->$ns && is_callable($v['cb'])) {
|
||||
foreach (Epc::widgetAllowedTemplateValue() as $info) {
|
||||
$ns = 'content' . $info['id'];
|
||||
if ($w->$ns && is_callable($info['cb'])) {
|
||||
$content .= call_user_func(
|
||||
$v['cb'],
|
||||
$info['cb'],
|
||||
$w
|
||||
);
|
||||
}
|
||||
|
@ -130,11 +130,11 @@ class Widgets
|
|||
# Parse result
|
||||
$res = '';
|
||||
foreach ($list as $line) {
|
||||
if (empty($line['matches'][0]['match'])) {
|
||||
if ((int) $line['total'] == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$res .= '<li>' . $line['matches'][0]['match'] .
|
||||
$res .= '<li>' . $line['replacement'] .
|
||||
($w->show_total ? ' (' . $line['total'] . ')' : '') .
|
||||
'</li>';
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue