<?php
/**
* @package Dotclear
* @subpackage Backend
*
* @since 2.20
*
* @copyright Olivier Meunier & Association Dotclear
* @copyright GPL-2.0-only
*/
if (!defined('DC_RC_PATH')) {
return;
}
/**
* @brief Generic class for admin list filters form
*/
class adminGenericFilter
{
/** @var dcCore core instance */
protected $core;
/** @var string Filter form type (main id) */
protected $type;
/** @var array Filters objects */
protected $filters = [];
/** @var boolean Show filter indicator */
protected $show = false;
/** @var boolean Has user preferences */
protected $has_user_pref = false;
/**
* Constructs a new instance.
*
* @param dcCore $core core instance
* @param string $type The filter form main id
*/
public function __construct(dcCore $core, string $type)
{
$this->core = &$core;
$this->type = $type;
$this->parseOptions();
}
/**
* Get user defined filter options (sortby, order, nb)
*
* @param string $option The option
*
* @return mixed User option
*/
public function userOptions(?string $option = null)
{
return adminUserPref::getUserFilters($this->type, $option);
}
/**
* Parse _GET user pref options (sortby, order, nb)
*/
protected function parseOptions()
{
$options = adminUserPref::getUserFilters($this->type);
if (!empty($options)) {
$this->has_user_pref = true;
}
if (!empty($options[1])) {
$this->filters['sortby'] = new dcAdminFilter('sortby', $this->userOptions('sortby'));
$this->filters['sortby']->options($options[1]);
if (!empty($_GET['sortby'])
&& in_array($_GET['sortby'], $options[1], true)
&& $_GET['sortby'] != $this->userOptions('sortby')
) {
$this->show(true);
$this->filters['sortby']->value($_GET['sortby']);
}
}
if (!empty($options[3])) {
$this->filters['order'] = new dcAdminFilter('order', $this->userOptions('order'));
$this->filters['order']->options(dcAdminCombos::getOrderCombo());
if (!empty($_GET['order'])
&& in_array($_GET['order'], dcAdminCombos::getOrderCombo(), true)
&& $_GET['order'] != $this->userOptions('order')
) {
$this->show(true);
$this->filters['order']->value($_GET['order']);
}
}
if (!empty($options[4])) {
$this->filters['nb'] = new dcAdminFilter('nb', $this->userOptions('nb'));
$this->filters['nb']->title($options[4][0]);
if (!empty($_GET['nb'])
&& (int) $_GET['nb'] > 0
&& (int) $_GET['nb'] != $this->userOptions('nb')
) {
$this->show(true);
$this->filters['nb']->value((int) $_GET['nb']);
}
}
}
/**
* Get filters key/value pairs
*
* @param boolean $escape Escape widlcard %
* @param boolean $ui_only Limit to filters with ui
*
* @return array The filters
*/
public function values($escape = false, $ui_only = false)
{
$res = [];
foreach ($this->filters as $id => $filter) {
if ($ui_only) {
if (in_array($id, ['sortby', 'order', 'nb']) || $filter->html != '') {
$res[$id] = $filter->value;
}
} else {
$res[$id] = $filter->value;
}
}
return $escape ? preg_replace('/%/', '%%', $res) : $res;
}
/**
* Get a filter value
*
* @param string $id The filter id
* @param string $id The filter value if not exists
*
* @return mixed The filter value
*/
public function value(string $id, $undefined = null)
{
return isset($this->filters[$id]) ? $this->filters[$id]->value : $undefined;
}
/**
* Magic get filter value
*
* @param string $id The filter id
*
* @return mixed The filter value
*/
public function __get($id)
{
return $this->value($id);
}
/**
* Add filter(s)
*
* @param array|string|dcAdminFilter|null $filter The filter(s) array or id or object
* @param mixed $value The filter value if $filter is id
*
* @return mixed The filter value
*/
public function add($filter = null, $value = null)
{
# empty filter (ex: do not show form if there are no categories on a blog)
if (null === $filter) {
return null;
}
# multiple filters
if (is_array($filter)) {
foreach ($filter as $f) {
$this->add($f);
}
return null;
}
# simple filter
if (is_string($filter)) {
$filter = new dcAdminFilter($filter, $value);
}
# not well formed filter or reserved id
if (!($filter instanceof dcAdminFilter) || $filter->id == '') {
return null;
}
# parse _GET values and create html forms
$filter->parse();
# set key/value pair
$this->filters[$filter->id] = $filter;
# has contents
if ($filter->html != '' && $filter->form != 'none') {
# not default value = show filters form
$this->show($filter->value !== '');
}
return $filter->value;
}
/**
* Remove a filter
*
* @param string $id The filter id
*
* @return boolean The success
*/
public function remove(string $id)
{
if (array_key_exists($id, $this->filters)) {
unset($this->filters[$id]);
return true;
}
return false;
}
/**
* Get list query params
*
* @return array The query params
*/
public function params()
{
$filters = $this->values();
$params = [
'from' => '',
'where' => '',
'sql' => '',
'columns' => [],
];
if (!empty($filters['sortby']) && !empty($filters['order'])) {
$params['order'] = $filters['sortby'] . ' ' . $filters['order'];
}
foreach ($this->filters as $filter) {
if ($filter->value !== '') {
$filters[0] = $filter->value;
foreach ($filter->params as $p) {
if (is_callable($p[1])) {
$p[1] = call_user_func($p[1], $filters);
}
if (in_array($p[0], ['from', 'where', 'sql'])) {
$params[$p[0]] .= $p[1];
} elseif ($p[0] == 'columns' && is_array($p[1])) {
$params['columns'] = array_merge($params['columns'], $p[1]);
} else {
$params[$p[0]] = $p[1];
}
}
}
}
return $params;
}
/**
* Show foldable filters form
*
* @param boolean $set Force to show filter form
*
* @return boolean Show filter form
*/
public function show($set = false): bool
{
if ($set === true) {
$this->show = true;
}
return $this->show;
}
/**
* Get js filters foldable form control
*
* @param string $reset_url The filter reset url
*/
public function js(string $reset_url = '')
{
$var = '';
if (!empty($reset_url)) {
$var = dcPage::jsVars(['dotclear.filter_reset_url' => $reset_url]);
}
return $var . dcPage::jsFilterControl($this->show());
}
/**
* Echo filter form
*
* @param array|string $adminurl The registered adminurl
* @param string $extra The extra contents
*/
public function display($adminurl, string $extra = '')
{
$tab = '';
if (is_array($adminurl)) {
$tab = $adminurl[1];
$adminurl = $adminurl[0];
}
echo
'<form action="' . $this->core->adminurl->get($adminurl) . $tab . '" method="get" id="filters-form">' .
'<h3 class="out-of-screen-if-js">' . __('Show filters and display options') . '</h3>' .
'<div class="table">';
$prime = true;
$cols = [];
foreach ($this->filters as $filter) {
if (in_array($filter->id, ['sortby', 'order', 'nb'])) {
continue;
}
if ($filter->html != '') {
$cols[$filter->prime ? 1 : 0][$filter->id] = sprintf('<p>%s</p>', $filter->html);
}
}
sort($cols);
foreach ($cols as $col) {
echo sprintf(
$prime ?
'<div class="cell"><h4>' . __('Filters') . '</h4>%s</div>' :
'<div class="cell filters-sibling-cell">%s</div>',
implode('', $col)
);
$prime = false;
}
if (isset($this->filters['sortby']) || isset($this->filters['order']) || isset($this->filters['nb'])) {
echo
'<div class="cell filters-options">' .
'<h4>' . __('Display options') . '</h4>';
if (isset($this->filters['sortby'])) {
$label = (new formLabel(__('Order by:'), formLabel::OUTSIDE_LABEL_BEFORE, 'sortby'))
->class('ib');
$select = (new formSelect('sortby'))
->default($this->filters['sortby']->value)
->items($this->filters['sortby']->options);
echo sprintf(
'<p>%s</p>',
$label->render($select->render())
);
}
if (isset($this->filters['order'])) {
$label = (new formLabel(__('Sort:'), formLabel::OUTSIDE_LABEL_BEFORE, 'order'))
->class('ib');
$select = (new formSelect('order'))
->default($this->filters['order']->value)
->items($this->filters['order']->options);
echo sprintf(
'<p>%s</p>',
$label->render($select->render())
);
}
if (isset($this->filters['nb'])) {
$label = (new formLabel($this->filters['nb']->title, formLabel::INSIDE_TEXT_AFTER, 'nb'))
->class('classic');
$number = (new formNumber('nb'))
->min(0)
->max(999)
->value($this->filters['nb']->value);
echo sprintf(
'<p><span class="label ib">' . __('Show') . '</span> %s</p>',
$label->render($number->render())
);
}
if ($this->has_user_pref) {
echo
form::hidden('filters-options-id', $this->type) .
'<p class="hidden-if-no-js"><a href="#" id="filter-options-save">' . __('Save current options') . '</a></p>';
}
echo
'</div>';
}
echo
'</div>' .
'<p><input type="submit" value="' . __('Apply filters and display options') . '" />' .
$extra .
'<br class="clear" /></p>' . //Opera sucks
'</form>';
}
}
class adminPostFilter extends adminGenericFilter
{
protected $post_type = 'post';
public function __construct(dcCore $core, string $type = 'posts', string $post_type = '')
{
parent::__construct($core, $type);
if (!empty($post_type) && array_key_exists($post_type, $core->getPostTypes())) {
$this->post_type = $post_type;
$this->add((new dcAdminFilter('post_type', $post_type))->param('post_type'));
}
$filters = new arrayObject([
dcAdminFilters::getPageFilter(),
$this->getPostUserFilter(),
$this->getPostCategoriesFilter(),
$this->getPostStatusFilter(),
$this->getPostFormatFilter(),
$this->getPostPasswordFilter(),
$this->getPostSelectedFilter(),
$this->getPostAttachmentFilter(),
$this->getPostMonthFilter(),
$this->getPostLangFilter(),
$this->getPostCommentFilter(),
$this->getPostTrackbackFilter(),
]);
# --BEHAVIOR-- adminPostFilter
$core->callBehavior('adminPostFilter', $core, $filters);
$filters = $filters->getArrayCopy();
$this->add($filters);
}
/**
* Posts users select
*/
public function getPostUserFilter(): ?dcAdminFilter
{
$users = null;
try {
$users = $this->core->blog->getPostsUsers($this->post_type);
if ($users->isEmpty()) {
return null;
}
} catch (Exception $e) {
$this->core->error->add($e->getMessage());
return null;
}
$combo = dcAdminCombos::getUsersCombo($users);
dcUtils::lexicalKeySort($combo);
return (new dcAdminFilter('user_id'))
->param()
->title(__('Author:'))
->options(array_merge(
['-' => ''],
$combo
))
->prime(true);
}
/**
* Posts categories select
*/
public function getPostCategoriesFilter(): ?dcAdminFilter
{
$categories = null;
try {
$categories = $this->core->blog->getCategories(['post_type' => $this->post_type]);
if ($categories->isEmpty()) {
return null;
}
} catch (Exception $e) {
$this->core->error->add($e->getMessage());
return null;
}
$combo = [
'-' => '',
__('(No cat)') => 'NULL',
];
while ($categories->fetch()) {
$combo[
str_repeat(' ', ($categories->level - 1) * 4) .
html::escapeHTML($categories->cat_title) . ' (' . $categories->nb_post . ')'
] = $categories->cat_id;
}
return (new dcAdminFilter('cat_id'))
->param()
->title(__('Category:'))
->options($combo)
->prime(true);
}
/**
* Posts status select
*/
public function getPostStatusFilter(): dcAdminFilter
{
return (new dcAdminFilter('status'))
->param('post_status')
->title(__('Status:'))
->options(array_merge(
['-' => ''],
dcAdminCombos::getPostStatusesCombo()
))
->prime(true);
}
/**
* Posts format select
*/
public function getPostFormatFilter(): dcAdminFilter
{
$core_formaters = $this->core->getFormaters();
$available_formats = [];
foreach ($core_formaters as $editor => $formats) {
foreach ($formats as $format) {
$available_formats[$format] = $format;
}
}
return (new dcAdminFilter('format'))
->param('where', ['adminPostFilter', 'getPostFormatParam'])
->title(__('Format:'))
->options(array_merge(
['-' => ''],
$available_formats
))
->prime(true);
}
public static function getPostFormatParam($f)
{
return " AND post_format = '" . $f[0] . "' ";
}
/**
* Posts password state select
*/
public function getPostPasswordFilter(): dcAdminFilter
{
return (new dcAdminFilter('password'))
->param('where', ['adminPostFilter', 'getPostPasswordParam'])
->title(__('Password:'))
->options([
'-' => '',
__('With password') => '1',
__('Without password') => '0',
])
->prime(true);
}
public static function getPostPasswordParam($f)
{
return ' AND post_password IS ' . ($f[0] ? 'NOT ' : '') . 'NULL ';
}
/**
* Posts selected state select
*/
public function getPostSelectedFilter(): dcAdminFilter
{
return (new dcAdminFilter('selected'))
->param('post_selected')
->title(__('Selected:'))
->options([
'-' => '',
__('Selected') => '1',
__('Not selected') => '0',
]);
}
/**
* Posts attachment state select
*/
public function getPostAttachmentFilter(): dcAdminFilter
{
return (new dcAdminFilter('attachment'))
->param('media')
->param('link_type', 'attachment')
->title(__('Attachments:'))
->options([
'-' => '',
__('With attachments') => '1',
__('Without attachments') => '0',
]);
}
/**
* Posts by month select
*/
public function getPostMonthFilter(): ?dcAdminFilter
{
$dates = null;
try {
$dates = $this->core->blog->getDates([
'type' => 'month',
'post_type' => $this->post_type,
]);
if ($dates->isEmpty()) {
return null;
}
} catch (Exception $e) {
$this->core->error->add($e->getMessage());
return null;
}
return (new dcAdminFilter('month'))
->param('post_month', ['adminPostFilter', 'getPostMonthParam'])
->param('post_year', ['adminPostFilter', 'getPostYearParam'])
->title(__('Month:'))
->options(array_merge(
['-' => ''],
dcAdminCombos::getDatesCombo($dates)
));
}
public static function getPostMonthParam($f)
{
return substr($f[0], 4, 2);
}
public static function getPostYearParam($f)
{
return substr($f[0], 0, 4);
}
/**
* Posts lang select
*/
public function getPostLangFilter(): ?dcAdminFilter
{
$langs = null;
try {
$langs = $this->core->blog->getLangs(['post_type' => $this->post_type]);
if ($langs->isEmpty()) {
return null;
}
} catch (Exception $e) {
$this->core->error->add($e->getMessage());
return null;
}
return (new dcAdminFilter('lang'))
->param('post_lang')
->title(__('Lang:'))
->options(array_merge(
['-' => ''],
dcAdminCombos::getLangsCombo($langs, false)
));
}
/**
* Posts comments state select
*/
public function getPostCommentFilter(): dcAdminFilter
{
return (new dcAdminFilter('comment'))
->param('where', ['adminPostFilter', 'getPostCommentParam'])
->title(__('Comments:'))
->options([
'-' => '',
__('Opened') => '1',
__('Closed') => '0',
]);
}
public static function getPostCommentParam($f)
{
return " AND post_open_comment = '" . $f[0] . "' ";
}
/**
* Posts trackbacks state select
*/
public function getPostTrackbackFilter(): dcAdminFilter
{
return (new dcAdminFilter('trackback'))
->param('where', ['adminPostFilter', 'getPostTrackbackParam'])
->title(__('Trackbacks:'))
->options([
'-' => '',
__('Opened') => '1',
__('Closed') => '0',
]);
}
public static function getPostTrackbackParam($f)
{
return " AND post_open_tb = '" . $f[0] . "' ";
}
}
class adminCommentFilter extends adminGenericFilter
{
public function __construct(dcCore $core)
{
parent::__construct($core, 'comments');
$filters = new arrayObject([
dcAdminFilters::getPageFilter(),
$this->getCommentAuthorFilter(),
$this->getCommentTypeFilter(),
$this->getCommentStatusFilter(),
$this->getCommentIpFilter(),
dcAdminFilters::getInputFilter('email', __('Email:'), 'comment_email'),
dcAdminFilters::getInputFilter('site', __('Web site:'), 'comment_site'),
]);
# --BEHAVIOR-- adminCommentFilter
$core->callBehavior('adminCommentFilter', $core, $filters);
$filters = $filters->getArrayCopy();
$this->add($filters);
}
/**
* Comment author select
*/
public function getCommentAuthorFilter(): dcAdminFilter
{
return (new dcAdminFilter('author'))
->param('q_author')
->form('input')
->title(__('Author:'));
}
/**
* Comment type select
*/
public function getCommentTypeFilter(): dcAdminFilter
{
return (new dcAdminFilter('type'))
->param('comment_trackback', ['adminCommentFilter', 'getCommentTypeParam'])
->title(__('Type:'))
->options([
'-' => '',
__('Comment') => 'co',
__('Trackback') => 'tb',
])
->prime(true);
}
public static function getCommentTypeParam($f)
{
return $f[0] == 'tb';
}
/**
* Comment status select
*/
public function getCommentStatusFilter(): dcAdminFilter
{
return (new dcAdminFilter('status'))
->param('comment_status')
->title(__('Status:'))
->options(array_merge(
['-' => ''],
dcAdminCombos::getCommentStatusesCombo()
))
->prime(true);
}
/**
* Common IP field
*/
public function getCommentIpFilter(): ?dcAdminFilter
{
if (!$this->core->auth->check('contentadmin', $this->core->blog->id)) {
return null;
}
return (new dcAdminFilter('ip'))
->param('comment_ip')
->form('input')
->title(__('IP address:'));
}
}
class adminUserFilter extends adminGenericFilter
{
public function __construct(dcCore $core)
{
parent::__construct($core, 'users');
$filters = new arrayObject([
dcAdminFilters::getPageFilter(),
dcAdminFilters::getSearchFilter(),
]);
# --BEHAVIOR-- adminUserFilter
$core->callBehavior('adminUserFilter', $core, $filters);
$filters = $filters->getArrayCopy();
$this->add($filters);
}
}
class adminBlogFilter extends adminGenericFilter
{
public function __construct(dcCore $core)
{
parent::__construct($core, 'blogs');
$filters = new arrayObject([
dcAdminFilters::getPageFilter(),
dcAdminFilters::getSearchFilter(),
$this->getBlogStatusFilter(),
]);
# --BEHAVIOR-- adminBlogFilter
$core->callBehavior('adminBlogFilter', $core, $filters);
$filters = $filters->getArrayCopy();
$this->add($filters);
}
/**
* Blog status select
*/
public function getBlogStatusFilter(): dcAdminFilter
{
return (new dcAdminFilter('status'))
->param('blog_status')
->title(__('Status:'))
->options(array_merge(
['-' => ''],
dcAdminCombos::getBlogStatusesCombo()
))
->prime(true);
}
}
class adminMediaFilter extends adminGenericFilter
{
protected $post_type = '';
protected $post_title = '';
public function __construct(dcCore $core, string $type = 'media')
{
parent::__construct($core, $type);
$filters = new arrayObject([
dcAdminFilters::getPageFilter(),
dcAdminFilters::getSearchFilter(),
$this->getPostIdFilter(),
$this->getDirFilter(),
$this->getFileModeFilter(),
$this->getPluginIdFilter(),
$this->getLinkTypeFilter(),
$this->getPopupFilter(),
$this->getSelectFilter(),
]);
# --BEHAVIOR-- adminBlogFilter
$core->callBehavior('adminMediaFilter', $core, $filters);
$filters = $filters->getArrayCopy();
$this->add($filters);
$this->legacyBehavior();
}
/**
* Cope with old behavior
*/
protected function legacyBehavior()
{
$values = new ArrayObject($this->values());
$this->core->callBehavior('adminMediaURLParams', $values);
foreach ($values->getArrayCopy() as $filter => $new_value) {
if (isset($this->filters[$filter])) {
$this->filters[$filter]->value($new_value);
} else {
$this->add($filter, $new_value);
}
}
}
protected function getPostIdFilter()
{
$post_id = !empty($_REQUEST['post_id']) ? (int) $_REQUEST['post_id'] : null;
if ($post_id) {
$post = $this->core->blog->getPosts(['post_id' => $post_id, 'post_type' => '']);
if ($post->isEmpty()) {
$post_id = null;
}
// keep track of post_title_ and post_type without using filters
$this->post_title = $post->post_title;
$this->post_type = $post->post_type;
}
return new dcAdminFilter('post_id', $post_id);
}
public function getPostTitle()
{
return $this->post_title;
}
public function getPostType()
{
return $this->post_type;
}
protected function getDirFilter()
{
$get = $_REQUEST['d'] ?? null;
if ($get === null && isset($_SESSION['media_manager_dir'])) {
// We get session information
$get = $_SESSION['media_manager_dir'];
}
if ($get) {
$_SESSION['media_manager_dir'] = $get;
} else {
unset($_SESSION['media_manager_dir']);
}
return new dcAdminFilter('d', $get);
}
protected function getFileModeFilter()
{
if (!empty($_GET['file_mode'])) {
$_SESSION['media_file_mode'] = $_GET['file_mode'] == 'grid' ? 'grid' : 'list';
}
$get = !empty($_SESSION['media_file_mode']) ? $_SESSION['media_file_mode'] : 'grid';
return new dcAdminFilter('file_mode', $get);
}
protected function getPluginIdFilter()
{
$get = isset($_REQUEST['plugin_id']) ? html::sanitizeURL($_REQUEST['plugin_id']) : '';
return new dcAdminFilter('plugin_id', $get);
}
protected function getLinkTypeFilter()
{
$get = !empty($_REQUEST['link_type']) ? html::escapeHTML($_REQUEST['link_type']) : null;
return new dcAdminFilter('link_type', $get);
}
protected function getPopupFilter()
{
$get = (int) !empty($_REQUEST['popup']);
return new dcAdminFilter('popup', $get);
}
protected function getSelectFilter()
{
// 0 : none, 1 : single media, >1 : multiple media
$get = !empty($_REQUEST['select']) ? (int) $_REQUEST['select'] : 0;
return new dcAdminFilter('select', $get);
}
}
/**
* @brief Admin filter
*
* Dotclear utility class that provides reuseable list filter
* Should be used with adminGenericFilter
*/
class dcAdminFilter
{
/** @var array The filter properties */
protected $properties = [
'id' => '',
'value' => null,
'form' => 'none',
'prime' => false,
'title' => '',
'options' => [],
'html' => '',
'params' => [],
];
/**
* Constructs a new filter.
*
* @param string $id The filter id
* @param mixed $value The filter value
*/
public function __construct(string $id, $value = null)
{
if (!preg_match('/^[A-Za-z0-9_-]+$/', $id)) {
throw new Exception('not a valid id');
}
$this->properties['id'] = $id;
$this->properties['value'] = $value;
}
/**
* Magic isset filter properties
*
* @param string $property The property
*
* @return boolean Is set
*/
public function __isset(string $property)
{
return isset($this->properties[$property]);
}
/**
* Magic get
*
* @param string $property The property
*
* @return mixed Property
*/
public function __get($property)
{
return $this->get($property);
}
/**
* Get a filter property
*
* @param string $property The property
*
* @return mixed The value
*/
public function get(string $property)
{
return $this->properties[$property] ?? null;
}
/**
* Magic set
*
* @param string $property The property
* @param mixed $value The value
*
* @return dcAdminFilter The filter instance
*/
public function __set($property, $value)
{
return $this->set($property, $value);
}
/**
* Set a property value
*
* @param string $property The property
* @param mixed $value The value
*
* @return dcAdminFilter The filter instance
*/
public function set($property, $value)
{
if (isset($this->properties[$property]) && method_exists($this, $property)) {
return call_user_func([$this, $property], $value);
}
return $this;
}
/**
* Set filter form type
*
* @param string $type The type
*
* @return dcAdminFilter The filter instance
*/
public function form(string $type)
{
if (in_array($type, ['none', 'input', 'select', 'html'])) {
$this->properties['form'] = $type;
}
return $this;
}
/**
* Set filter form title
*
* @param string $title The title
*
* @return dcAdminFilter The filter instance
*/
public function title(string $title)
{
$this->properties['title'] = $title;
return $this;
}
/**
* Set filter form options
*
* If filter form is a select box, this is the select options
*
* @param array $options The options
* @param boolean $set_form Auto set form type
*
* @return dcAdminFilter The filter instance
*/
public function options(array $options, $set_form = true)
{
$this->properties['options'] = $options;
if ($set_form) {
$this->form('select');
}
return $this;
}
/**
* Set filter value
*
* @param mixed $value The value
*
* @return dcAdminFilter The filter instance
*/
public function value($value)
{
$this->properties['value'] = $value;
return $this;
}
/**
* Set filter column in form
*
* @param boolean $prime First column
*
* @return dcAdminFilter The filter instance
*/
public function prime(bool $prime)
{
$this->properties['prime'] = $prime;
return $this;
}
/**
* Set filter html contents
*
* @param string $contents The contents
* @param boolean $set_form Auto set form type
*
* @return dcAdminFilter The filter instance
*/
public function html(string $contents, $set_form = true)
{
$this->properties['html'] = $contents;
if ($set_form) {
$this->form('html');
}
return $this;
}
/**
* Set filter param (list query param)
*
* @param string|null $name The param name
* @param mixed $value The param value
*
* @return dcAdminFilter The filter instance
*/
public function param($name = null, $value = null)
{
# filter id as param name
if ($name === null) {
$name = $this->properties['id'];
}
# filter value as param value
if (null === $value) {
$value = fn ($f) => $f[0];
}
$this->properties['params'][] = [$name, $value];
return $this;
}
/**
* Parse the filter properties
*
* Only input and select forms are parsed
*/
public function parse()
{
# form select
if ($this->form == 'select') {
# _GET value
if ($this->value === null) {
$get = $_GET[$this->id] ?? '';
if ($get === '' || !in_array($get, $this->options, true)) {
$get = '';
}
$this->value($get);
}
# HTML field
$select = (new formSelect($this->id))
->default($this->value)
->items($this->options);
$label = (new formLabel($this->title, 2, $this->id))
->class('ib');
$this->html($label->render($select->render()), false);
# form input
} elseif ($this->form == 'input') {
# _GET value
if ($this->value === null) {
$this->value(!empty($_GET[$this->id]) ? $_GET[$this->id] : '');
}
# HTML field
$input = (new formInput($this->id))
->size(20)
->maxlength(255)
->value($this->value);
$label = (new formLabel($this->title, 2, $this->id))
->class('ib');
$this->html($label->render($input->render()), false);
}
}
}
/**
* @brief Admin list filters library
*
* Dotclear utility class that provides reuseable list filters
* Returned null or dcAdminFilter instance
* Should be used with adminGenericFilter
*/
class dcAdminFilters
{
/**
* Common default input field
*/
public static function getInputFilter(string $id, string $title, ?string $param = null): dcAdminFilter
{
return (new dcAdminFilter($id))
->param($param ?: $id)
->form('input')
->title($title);
}
/**
* Common default select field
*/
public static function getSelectFilter(string $id, string $title, array $options, ?string $param = null): ?dcAdminFilter
{
if (empty($options)) {
return null;
}
return (new dcAdminFilter($id))
->param($param ?: $id)
->title($title)
->options($options);
}
/**
* Common page filter (no field)
*/
public static function getPageFilter(string $id = 'page'): dcAdminFilter
{
return (new dcAdminFilter($id))
->value(!empty($_GET[$id]) ? max(1, (int) $_GET[$id]) : 1)
->param('limit', fn ($f) => [(($f[0] - 1) * $f['nb']), $f['nb']]);
}
/**
* Common search field
*/
public static function getSearchFilter(): dcAdminFilter
{
return (new dcAdminFilter('q'))
->param('q', fn ($f) => $f['q'])
->form('input')
->title(__('Search:'))
->prime(true);
}
}