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)) { 131*e983bcdaSSzymon Olewniczak $filter = $this->applyFilterVarsStruct($match); 132*e983bcdaSSzymon Olewniczak } elseif(preg_match('/^(.*?)(?:\$USER\.(.*?)\$)(.*?)$/', $filter, $match)) { 133*e983bcdaSSzymon Olewniczak $filter = $this->applyFilterVarsUser($match); 134*e983bcdaSSzymon Olewniczak } 135*e983bcdaSSzymon Olewniczak 136*e983bcdaSSzymon Olewniczak return $filter; 137*e983bcdaSSzymon Olewniczak } 138*e983bcdaSSzymon Olewniczak 139*e983bcdaSSzymon Olewniczak /** 140*e983bcdaSSzymon Olewniczak * Replaces struct placeholders in the given filter value by the proper value 141*e983bcdaSSzymon Olewniczak * 142*e983bcdaSSzymon Olewniczak * @param string $match 143*e983bcdaSSzymon Olewniczak * @return string|string[] Result may be an array when a multi column placeholder is used 144*e983bcdaSSzymon Olewniczak */ 145*e983bcdaSSzymon Olewniczak protected function applyFilterVarsStruct($match) { 146*e983bcdaSSzymon Olewniczak global $INFO; 147*e983bcdaSSzymon 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) { 16106fee43aSMichael Grosse $schemaData = AccessTable::byTableName($table, $INFO['id'], 0); 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 } 184*e983bcdaSSzymon Olewniczak 185*e983bcdaSSzymon Olewniczak return $filter; 186*e983bcdaSSzymon Olewniczak } 187*e983bcdaSSzymon Olewniczak 188*e983bcdaSSzymon Olewniczak /** 189*e983bcdaSSzymon Olewniczak * Replaces user placeholders in the given filter value by the proper value 190*e983bcdaSSzymon Olewniczak * 191*e983bcdaSSzymon Olewniczak * @param string $match 192*e983bcdaSSzymon Olewniczak * @return string|string[] String for name and mail, array for grps 193*e983bcdaSSzymon Olewniczak */ 194*e983bcdaSSzymon Olewniczak protected function applyFilterVarsUser($match) { 195*e983bcdaSSzymon Olewniczak global $INFO; 196*e983bcdaSSzymon 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