xref: /plugin/struct/meta/SearchConfig.php (revision 387ee21016a7563cdd2c65a487aa6c785b1d5de4)
15511bd5bSAndreas Gohr<?php
25511bd5bSAndreas Gohr
3ba766201SAndreas Gohrnamespace dokuwiki\plugin\struct\meta;
45511bd5bSAndreas Gohr
55511bd5bSAndreas Gohr/**
65511bd5bSAndreas Gohr * Class SearchConfig
75511bd5bSAndreas Gohr *
85511bd5bSAndreas Gohr * The same as @see Search but can be initialized by a configuration array
95511bd5bSAndreas Gohr *
10ba766201SAndreas Gohr * @package dokuwiki\plugin\struct\meta
115511bd5bSAndreas Gohr */
125511bd5bSAndreas Gohrclass SearchConfig extends Search {
135511bd5bSAndreas Gohr
1416b7d914SAndreas Gohr    /** @var int default aggregation caching (depends on last struct save) */
1516b7d914SAndreas Gohr    static public $CACHE_DEFAULT = 1;
1616b7d914SAndreas Gohr    /** @var int caching depends on current user */
1716b7d914SAndreas Gohr    static public $CACHE_USER = 2;
1816b7d914SAndreas Gohr    /** @var int caching depends on current date */
1916b7d914SAndreas Gohr    static public $CACHE_DATE = 4;
2016b7d914SAndreas Gohr
21668e4f8eSAndreas Gohr    /**
22668e4f8eSAndreas Gohr     * @var array hold the configuration as parsed and extended by dynamic params
23668e4f8eSAndreas Gohr     */
241a07b696SMichael Große    protected $config;
251a07b696SMichael Große
26668e4f8eSAndreas Gohr    /**
27668e4f8eSAndreas Gohr     * @var SearchConfigParameters manages dynamic parameters
28668e4f8eSAndreas Gohr     */
2900f6af48SAndreas Gohr    protected $dynamicParameters;
3000f6af48SAndreas Gohr
315511bd5bSAndreas Gohr    /**
3216b7d914SAndreas Gohr     * @var int the cache flag to use (binary flags)
3316b7d914SAndreas Gohr     */
3416b7d914SAndreas Gohr    protected $cacheFlag;
3516b7d914SAndreas Gohr
3616b7d914SAndreas Gohr    /**
375511bd5bSAndreas Gohr     * SearchConfig constructor.
3800f6af48SAndreas Gohr     * @param array $config The parsed configuration for this search
395511bd5bSAndreas Gohr     */
405511bd5bSAndreas Gohr    public function __construct($config) {
415511bd5bSAndreas Gohr        parent::__construct();
425511bd5bSAndreas Gohr
433ad292a8SAndreas Gohr        // setup schemas and columns
440215a637SAndreas Gohr        if(!empty($config['schemas'])) foreach($config['schemas'] as $schema) {
453ad292a8SAndreas Gohr            $this->addSchema($schema[0], $schema[1]);
463ad292a8SAndreas Gohr        }
470215a637SAndreas Gohr        if(!empty($config['cols'])) foreach($config['cols'] as $col) {
483ad292a8SAndreas Gohr            $this->addColumn($col);
493ad292a8SAndreas Gohr        }
503ad292a8SAndreas Gohr
5116b7d914SAndreas Gohr        // cache flag setting
5216b7d914SAndreas Gohr        $this->cacheFlag = self::$CACHE_DEFAULT;
5316b7d914SAndreas Gohr        if(!empty($config['filters'])) $this->cacheFlag = $this->determineCacheFlag($config['filters']);
5416b7d914SAndreas Gohr
5500f6af48SAndreas Gohr        // apply dynamic paramters
5600f6af48SAndreas Gohr        $this->dynamicParameters = new SearchConfigParameters($this);
57668e4f8eSAndreas Gohr        $config = $this->dynamicParameters->updateConfig($config);
5800f6af48SAndreas Gohr
5900f6af48SAndreas Gohr        // configure search from configuration
6000f6af48SAndreas Gohr        if(!empty($config['filter'])) foreach($config['filter'] as $filter) {
615625b985SAndreas Gohr            $this->addFilter($filter[0], $this->applyFilterVars($filter[2]), $filter[1], $filter[3]);
625511bd5bSAndreas Gohr        }
6300f6af48SAndreas Gohr
6400f6af48SAndreas Gohr        if(!empty($config['sort'])) foreach($config['sort'] as $sort) {
65aa124708SAndreas Gohr            $this->addSort($sort[0], $sort[1]);
661a07b696SMichael Große        }
671a07b696SMichael Große
681a07b696SMichael Große        if(!empty($config['limit'])) {
691a07b696SMichael Große            $this->setLimit($config['limit']);
701a07b696SMichael Große        }
7100f6af48SAndreas Gohr
7200f6af48SAndreas Gohr        if(!empty($config['offset'])) {
73d2a8ce05SPaweł Czochański            $this->setOffset($config['offset']);
7400f6af48SAndreas Gohr        }
75668e4f8eSAndreas Gohr
76668e4f8eSAndreas Gohr        $this->config = $config;
771a07b696SMichael Große    }
785511bd5bSAndreas Gohr
7900f6af48SAndreas Gohr    /**
8016b7d914SAndreas Gohr     * Set the cache flag accordingly to the set filter placeholders
8116b7d914SAndreas Gohr     *
8216b7d914SAndreas Gohr     * @param array $filters
8316b7d914SAndreas Gohr     * @return int
8416b7d914SAndreas Gohr     */
8516b7d914SAndreas Gohr    protected function determineCacheFlag($filters) {
8616b7d914SAndreas Gohr        $flags = self::$CACHE_DEFAULT;
8716b7d914SAndreas Gohr
8816b7d914SAndreas Gohr        foreach($filters as $filter) {
8916b7d914SAndreas Gohr            if(is_array($filter)) $filter = $filter[2]; // this is the format we get fro the config parser
9016b7d914SAndreas Gohr
9116b7d914SAndreas Gohr            if(strpos($filter, '$USER$') !== false) {
9216b7d914SAndreas Gohr                $flags |= self::$CACHE_USER;
9316b7d914SAndreas Gohr            } else if(strpos($filter, '$TODAY$') !== false) {
9416b7d914SAndreas Gohr                $flags |= self::$CACHE_DATE;
9516b7d914SAndreas Gohr            }
9616b7d914SAndreas Gohr        }
9716b7d914SAndreas Gohr
9816b7d914SAndreas Gohr        return $flags;
9916b7d914SAndreas Gohr    }
10016b7d914SAndreas Gohr
10116b7d914SAndreas Gohr    /**
1025625b985SAndreas Gohr     * Replaces placeholders in the given filter value by the proper value
1035625b985SAndreas Gohr     *
1045625b985SAndreas Gohr     * @param string $filter
10553528ecfSAndreas Gohr     * @return string|string[] Result may be an array when a multi column placeholder is used
1065625b985SAndreas Gohr     */
1075625b985SAndreas Gohr    protected function applyFilterVars($filter) {
10806fee43aSMichael Grosse        global $INFO;
1095625b985SAndreas Gohr
1105625b985SAndreas Gohr        // apply inexpensive filters first
1115625b985SAndreas Gohr        $filter = str_replace(
1125625b985SAndreas Gohr            array(
1135625b985SAndreas Gohr                '$ID$',
1145625b985SAndreas Gohr                '$NS$',
1155625b985SAndreas Gohr                '$PAGE$',
1165625b985SAndreas Gohr                '$USER$',
1175625b985SAndreas Gohr                '$TODAY$'
1185625b985SAndreas Gohr            ),
1195625b985SAndreas Gohr            array(
12006fee43aSMichael Grosse                $INFO['id'],
12106fee43aSMichael Grosse                getNS($INFO['id']),
12206fee43aSMichael Grosse                noNS($INFO['id']),
1235625b985SAndreas Gohr                isset($_SERVER['REMOTE_USER']) ? $_SERVER['REMOTE_USER'] : '',
1245625b985SAndreas Gohr                date('Y-m-d')
1255625b985SAndreas Gohr            ),
1265625b985SAndreas Gohr            $filter
1275625b985SAndreas Gohr        );
1285625b985SAndreas Gohr
12953528ecfSAndreas Gohr        // apply struct column placeholder (we support only one!)
13053528ecfSAndreas Gohr        if(preg_match('/^(.*?)(?:\$STRUCT\.(.*?)\$)(.*?)$/', $filter, $match)) {
131e983bcdaSSzymon Olewniczak            $filter = $this->applyFilterVarsStruct($match);
132e983bcdaSSzymon Olewniczak        } elseif(preg_match('/^(.*?)(?:\$USER\.(.*?)\$)(.*?)$/', $filter, $match)) {
133e983bcdaSSzymon Olewniczak            $filter = $this->applyFilterVarsUser($match);
134e983bcdaSSzymon Olewniczak        }
135e983bcdaSSzymon Olewniczak
136e983bcdaSSzymon Olewniczak        return $filter;
137e983bcdaSSzymon Olewniczak    }
138e983bcdaSSzymon Olewniczak
139e983bcdaSSzymon Olewniczak    /**
140e983bcdaSSzymon Olewniczak     * Replaces struct placeholders in the given filter value by the proper value
141e983bcdaSSzymon Olewniczak     *
142e983bcdaSSzymon Olewniczak     * @param string $match
143e983bcdaSSzymon Olewniczak     * @return string|string[] Result may be an array when a multi column placeholder is used
144e983bcdaSSzymon Olewniczak     */
145e983bcdaSSzymon Olewniczak    protected function applyFilterVarsStruct($match) {
146e983bcdaSSzymon Olewniczak        global $INFO;
147e983bcdaSSzymon Olewniczak
14853528ecfSAndreas Gohr        $key = $match[2];
149d19ba4b1SAndreas Gohr
150aec9051bSAndreas Gohr        // we try to resolve the key via current schema aliases first, otherwise take it literally
151aec9051bSAndreas Gohr        $column = $this->findColumn($key);
1525625b985SAndreas Gohr        if($column) {
1535625b985SAndreas Gohr            $label = $column->getLabel();
1545625b985SAndreas Gohr            $table = $column->getTable();
155aec9051bSAndreas Gohr        } else {
156aec9051bSAndreas Gohr            list($table, $label) = explode('.', $key);
157aec9051bSAndreas Gohr        }
158aec9051bSAndreas Gohr
159aec9051bSAndreas Gohr        // get the data from the current page
160aec9051bSAndreas Gohr        if($table && $label) {
161*387ee210SAnna Dabrowska            $schemaData = AccessTable::byTableName($table, $INFO['id'], time());
1627717c082SMichael Große            $data = $schemaData->getData();
16334db2096SMichael Große            if (!isset($data[$label])) {
164e87d1e74SMichael Große                throw new StructException("column not in table", $label, $table);
16534db2096SMichael Große            }
1667717c082SMichael Große            $value = $data[$label]->getCompareValue();
167c75f25cfSAndreas Gohr
168c75f25cfSAndreas Gohr            if(is_array($value) && !count($value)) {
169c75f25cfSAndreas Gohr                $value = '';
170c75f25cfSAndreas Gohr            }
1715625b985SAndreas Gohr        } else {
1725625b985SAndreas Gohr            $value = '';
1735625b985SAndreas Gohr        }
1748b8243b2SAndreas Gohr
17553528ecfSAndreas Gohr        // apply any pre and postfixes, even when multi value
17653528ecfSAndreas Gohr        if(is_array($value)) {
17753528ecfSAndreas Gohr            $filter = array();
17853528ecfSAndreas Gohr            foreach($value as $item) {
17953528ecfSAndreas Gohr                $filter[] = $match[1] . $item . $match[3];
18053528ecfSAndreas Gohr            }
18153528ecfSAndreas Gohr        } else {
18253528ecfSAndreas Gohr            $filter = $match[1] . $value . $match[3];
18353528ecfSAndreas Gohr        }
184e983bcdaSSzymon Olewniczak
185e983bcdaSSzymon Olewniczak        return $filter;
186e983bcdaSSzymon Olewniczak    }
187e983bcdaSSzymon Olewniczak
188e983bcdaSSzymon Olewniczak    /**
189e983bcdaSSzymon Olewniczak     * Replaces user placeholders in the given filter value by the proper value
190e983bcdaSSzymon Olewniczak     *
191e983bcdaSSzymon Olewniczak     * @param string $match
192e983bcdaSSzymon Olewniczak     * @return string|string[] String for name and mail, array for grps
193e983bcdaSSzymon Olewniczak     */
194e983bcdaSSzymon Olewniczak    protected function applyFilterVarsUser($match) {
195e983bcdaSSzymon Olewniczak        global $INFO;
196e983bcdaSSzymon Olewniczak
197daa4b09dSSzymon Olewniczak        $key = strtolower($match[2]);
198daa4b09dSSzymon Olewniczak
199daa4b09dSSzymon Olewniczak        if (!in_array($key, array('name', 'mail', 'grps'))) {
200daa4b09dSSzymon Olewniczak            throw new StructException('"%s" is not a valid USER key', $key);
201daa4b09dSSzymon Olewniczak        }
202daa4b09dSSzymon Olewniczak
203daa4b09dSSzymon Olewniczak        if (empty($INFO['userinfo'])) {
204daa4b09dSSzymon Olewniczak            $filter = '';
205daa4b09dSSzymon Olewniczak        } else {
206daa4b09dSSzymon Olewniczak            $filter = $INFO['userinfo'][$key];
207daa4b09dSSzymon Olewniczak        }
2085625b985SAndreas Gohr
2095625b985SAndreas Gohr        return $filter;
2105625b985SAndreas Gohr    }
2115625b985SAndreas Gohr
2125625b985SAndreas Gohr    /**
21316b7d914SAndreas Gohr     * @return int cacheflag for this search
21416b7d914SAndreas Gohr     */
21516b7d914SAndreas Gohr    public function getCacheFlag() {
21616b7d914SAndreas Gohr        return $this->cacheFlag;
21716b7d914SAndreas Gohr    }
21816b7d914SAndreas Gohr
21916b7d914SAndreas Gohr    /**
22000f6af48SAndreas Gohr     * Access the dynamic paramters of this search
22100f6af48SAndreas Gohr     *
222668e4f8eSAndreas Gohr     * Note: This call returns a clone of the parameters as they were initialized
22300f6af48SAndreas Gohr     *
22400f6af48SAndreas Gohr     * @return SearchConfigParameters
22500f6af48SAndreas Gohr     */
22600f6af48SAndreas Gohr    public function getDynamicParameters() {
22700f6af48SAndreas Gohr        return clone $this->dynamicParameters;
2285511bd5bSAndreas Gohr    }
2295511bd5bSAndreas Gohr
23000f6af48SAndreas Gohr    /**
23107993756SAndreas Gohr     * @return array the current config
23200f6af48SAndreas Gohr     */
23307993756SAndreas Gohr    public function getConf() {
2341a07b696SMichael Große        return $this->config;
2351a07b696SMichael Große    }
2361a07b696SMichael Große
2375511bd5bSAndreas Gohr}
238