cf250a3f944c76794e083eb5160217d70e10304f
[core.git] / framework / main / classes / criteria / class_BaseCriteria.php
1 <?php
2 // Own namespace
3 namespace Org\Mxchange\CoreFramework\Criteria;
4
5 // Import framework stuff
6 use Org\Mxchange\CoreFramework\Criteria\Search\SearchCriteria;
7 use Org\Mxchange\CoreFramework\Object\BaseFrameworkSystem;
8 use Org\Mxchange\CoreFramework\String\Utils\StringUtils;
9
10 /**
11  * A general crtieria class
12  *
13  * @author              Roland Haeder <webmaster@shipsimu.org>
14  * @version             0.0.0
15  * @copyright   Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2017 Core Developer Team
16  * @license             GNU GPL 3.0 or any newer version
17  * @link                http://www.shipsimu.org
18  *
19  * This program is free software: you can redistribute it and/or modify
20  * it under the terms of the GNU General Public License as published by
21  * the Free Software Foundation, either version 3 of the License, or
22  * (at your option) any later version.
23  *
24  * This program is distributed in the hope that it will be useful,
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
27  * GNU General Public License for more details.
28  *
29  * You should have received a copy of the GNU General Public License
30  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
31  */
32 abstract class BaseCriteria extends BaseFrameworkSystem implements Criteria {
33         /**
34          * Wrapper class name stored in config entry
35          */
36         private $wrapperConfigEntry = '';
37
38         /**
39          * Protected constructor
40          *
41          * @param       $className      Name of the class
42          * @return      void
43          */
44         protected function __construct ($className) {
45                 // Call parent constructor
46                 parent::__construct($className);
47
48                 // Initialize all criteria arrays
49                 foreach (array('default', 'choice', 'exclude') as $criteriaType) {
50                         // Init it
51                         $this->initGenericArrayKey('criteria', $criteriaType, 'entries');
52                 } // END - foreach
53         }
54
55         /**
56          * Checks whether given key is set
57          *
58          * @param       $criteriaType   Type of this criteria, can be one of 'default' (default), 'choice' or 'exclude'
59          * @param       $criteriaKey    Criteria key
60          * @return      $isSet                  Whether key is set
61          */
62         public function isKeySet ($criteriaType, $criteriaKey) {
63                 // Make sure no 'my-' or 'my_' passes this point
64                 assert((strpos($criteriaKey, 'my-') === false) && (strpos($criteriaKey, 'my_') === false));
65
66                 // Determine it
67                 $isSet = $this->isGenericArrayElementSet('criteria', $criteriaType, 'entries', $criteriaKey);
68
69                 // Return it
70                 return $isSet;
71         }
72
73         /**
74          * Checks whether given key is set for 'choice' type
75          *
76          * @param       $criteriaKey    Criteria key
77          * @return      $isSet                  Whether key is set
78          */
79         public function isChoiceKeySet ($criteriaKey) {
80                 // Call inner method
81                 return $this->isKeySet('choice', $criteriaKey);
82         }
83
84         /**
85          * Checks whether given key is set for 'exclude' type
86          *
87          * @param       $criteriaKey    Criteria key
88          * @return      $isSet                  Whether key is set
89          */
90         public function isExcludeKeySet ($criteriaKey) {
91                 // Call inner method
92                 return $this->isKeySet('exclude', $criteriaKey);
93         }
94
95         /**
96          * Setter for wrapper class name
97          *
98          * @param       $wrapperConfigEntry             Configuration entry which hold the wrapper class' name
99          * @return      void
100          */
101         public final function setWrapperConfigEntry ($wrapperConfigEntry) {
102                 $this->wrapperConfigEntry = (string) $wrapperConfigEntry;
103         }
104
105         /**
106          * Getter for wrapper class name
107          *
108          * @return      $wrapperConfigEntry             Configuration entry which hold the wrapper class' name
109          */
110         public final function getWrapperConfigEntry () {
111                 return $this->wrapperConfigEntry;
112         }
113
114         /**
115          * Getter for criteria array
116          *
117          * @param       $criteriaType   Type of this criteria, can be one of 'default' (default), 'choice' or 'exclude'
118          * @return      $criteria
119          */
120         public final function getCriteriaArray ($criteriaType = 'default') {
121                 return $this->getGenericArrayKey('criteria', $criteriaType, 'entries');
122         }
123
124         /**
125          * Getter for criteria array 'choice' type
126          *
127          * @return      $criteria
128          */
129         public final function getCriteriaChoiceArray () {
130                 return $this->getCriteriaArray('choice');
131         }
132
133         /**
134          * Getter for criteria array 'exclude' type
135          *
136          * @return      $criteria
137          */
138         public final function getCriteriaExcludeArray () {
139                 return $this->getCriteriaArray('exclude');
140         }
141
142         /**
143          * Unsets a criteria key from all criteria types
144          *
145          * @param       $criteriaKey    Criteria key to unset
146          * @return      void
147          */
148         public final function unsetCriteria ($criteriaKey) {
149                 // Make sure no 'my-' or 'my_' passes this point
150                 assert((strpos($criteriaKey, 'my-') === false) && (strpos($criteriaKey, 'my_') === false));
151
152                 // Convert dashes to underscore
153                 $criteriaKey = StringUtils::convertDashesToUnderscores($criteriaKey);
154
155                 // "Walk" through all criterias
156                 foreach ($this->getGenericArray('criteria') as $criteriaType => $dummy) {
157                         // Remove it
158                         $this->unsetGenericArrayElement('criteria', $criteriaType, 'entries', $criteriaKey);
159                 } // END - foreach
160         }
161
162         /**
163          * Add criteria, this method converts dashes to underscores because dashes
164          * are not valid for criteria keys.
165          *
166          * @param       $criteriaKey    Criteria key
167          * @param       $criteriaValue  Criteria value
168          * @param       $criteriaType   Type of this criteria, can be one of 'default' (default), 'choice' or 'exclude'
169          * @return      void
170          */
171         public final function addCriteria ($criteriaKey, $criteriaValue, $criteriaType = 'default') {
172                 // Debug message
173                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(strtoupper($criteriaType) . '-CRITERIA[' . __METHOD__ . ':' . __LINE__ . ']: criteriaKey=' . $criteriaKey . ',criteriaValue=' . $criteriaValue . ',criteriaType=' . $criteriaType . ' - CALLED!');
174
175                 // Make sure no 'my-' or 'my_' passes this point
176                 assert((strpos($criteriaKey, 'my-') === false) && (strpos($criteriaKey, 'my_') === false) && (!is_bool($criteriaValue)));
177
178                 // Convert dashes to underscore
179                 $criteriaKey = StringUtils::convertDashesToUnderscores($criteriaKey);
180
181                 // Debug message
182                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(strtoupper($criteriaType) . '(' . $this->__toString() . ')-CRITERIA[' . __METHOD__ . ':' . __LINE__ . ']: criteriaKey=' . $criteriaKey);
183
184                 // Append it
185                 $this->appendStringToGenericArrayElement('criteria', $criteriaType, 'entries', $criteriaKey, $criteriaValue);
186         }
187
188         /**
189          * Set criteria, this method converts dashes to underscores because dashes
190          * are not valid for criteria keys.
191          *
192          * @param       $criteriaKey    Criteria key
193          * @param       $criteriaValue  Criteria value
194          * @param       $criteriaType   Type of this criteria, can be one of 'default' (default), 'choice' or 'exclude'
195          * @return      void
196          */
197         public final function setCriteria ($criteriaKey, $criteriaValue, $criteriaType = 'default') {
198                 // Debug message
199                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(strtoupper($criteriaType) . '-CRITERIA[' . __METHOD__ . ':' . __LINE__ . ']: criteriaKey=' . $criteriaKey . ',criteriaValue=' . $criteriaValue . ',criteriaType=' . $criteriaType . ' - CALLED!');
200
201                 // Make sure no 'my-' or 'my_' passes this point
202                 assert((strpos($criteriaKey, 'my-') === false) && (strpos($criteriaKey, 'my_') === false) && (!is_bool($criteriaValue)));
203
204                 // Convert dashes to underscore
205                 $criteriaKey = StringUtils::convertDashesToUnderscores($criteriaKey);
206
207                 // Debug message
208                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(strtoupper($criteriaType) . '(' . $this->__toString() . ')-CRITERIA[' . __METHOD__ . ':' . __LINE__ . ']: criteriaKey=' . $criteriaKey);
209
210                 // Set it
211                 $this->setStringGenericArrayElement('criteria', $criteriaType, 'entries', $criteriaKey, $criteriaValue);
212         }
213
214         /**
215          * Add "choice" criteria, this method converts dashes to underscores because
216          * dashes are not valid for criteria keys.
217          *
218          * @param       $criteriaKey    Criteria key
219          * @param       $criteriaValue  Criteria value
220          * @return      void
221          */
222         public final function addChoiceCriteria ($criteriaKey, $criteriaValue) {
223                 // Make sure no 'my-' or 'my_' passes this point
224                 assert((strpos($criteriaKey, 'my-') === false) && (strpos($criteriaKey, 'my_') === false) && (!is_bool($criteriaValue)));
225
226                 // Debug message
227                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(strtoupper($criteriaType) . '(' . $this->__toString() . ')-CRITERIA[' . __METHOD__ . ':' . __LINE__ . ']: criteriaKey=' . $criteriaKey . ',criteriaValue=' . $criteriaValue);
228
229                 // Add it
230                 $this->pushValueToGenericArrayElement('criteria', 'choice', 'entries', StringUtils::convertDashesToUnderscores($criteriaKey), (string) $criteriaValue);
231         }
232
233         /**
234          * Add "exclude" criteria, this method converts dashes to underscores because
235          * dashes are not valid for criteria keys.
236          *
237          * @param       $criteriaKey    Criteria key
238          * @param       $criteriaValue  Criteria value
239          * @return      void
240          */
241         public final function addExcludeCriteria ($criteriaKey, $criteriaValue) {
242                 // Add it with generic method
243                 $this->addCriteria($criteriaKey, $criteriaValue, 'exclude');
244         }
245
246         /**
247          * Add configured criteria
248          *
249          * @param       $criteriaKey    Criteria key
250          * @param       $configEntry    Configuration entry
251          * @param       $criteriaType   Type of this criteria, can be one of 'default' (default), 'choice' or 'exclude'
252          * @return      void
253          */
254         public final function addConfiguredCriteria ($criteriaKey, $configEntry, $criteriaType = 'default') {
255                 // Add the configuration entry as a criteria
256                 $value = $this->getConfigInstance()->getConfigEntry($configEntry);
257                 $this->addCriteria($criteriaKey, $value, $criteriaType);
258         }
259
260         /**
261          * Get criteria element or false if not found
262          *
263          * @param       $criteriaKey    The requested criteria key
264          * @param       $criteriaType   Type of this criteria, can be one of 'default' (default), 'choice' or 'exclude'
265          * @return      $value                  Whether the value of the critera or false
266          */
267         public function getCriteriaElemnent ($criteriaKey, $criteriaType = 'default') {
268                 // Debug message
269                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(strtoupper($criteriaType) . '-CRITERIA[' . __METHOD__ . ':' . __LINE__ . ']: criteriaKey=' . $criteriaKey . ',criteriaType=' . $criteriaType . ' - CALLED!');
270
271                 // Make sure no 'my-' or 'my_' passes this point
272                 assert((strpos($criteriaKey, 'my-') === false) && (strpos($criteriaKey, 'my_') === false));
273
274                 // Convert dashes to underscore
275                 $criteriaKey = StringUtils::convertDashesToUnderscores($criteriaKey);
276
277                 // Debug message
278                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(strtoupper($criteriaType) . '-CRITERIA[' . __METHOD__ . ':' . __LINE__ . ']: criteriaKey=' . $criteriaKey . ',criteria()=' . $this->countGenericArrayGroup('criteria', $criteriaType));
279
280                 // Default is not found
281                 $value = false;
282
283                 // Is the criteria there?
284                 if ($this->isKeySet($criteriaType, $criteriaKey)) {
285                         // Then use it
286                         $value = $this->getGenericArrayElement('criteria', $criteriaType, 'entries', $criteriaKey);
287                 } // END - if
288
289                 // Debug message
290                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(strtoupper($criteriaType) . '-CRITERIA[' . __METHOD__ . ':' . __LINE__ . ']: value=' . $value . ' - EXIT!');
291
292                 // Return the value
293                 return $value;
294         }
295
296         /**
297          * Get criteria element or false if not found for 'choice' type
298          *
299          * @param       $criteriaKey    The requested criteria key
300          * @return      $value                  Whether the value of the critera or false
301          */
302         public function getCriteriaChoiceElemnent ($criteriaKey) {
303                 // Call inner method
304                 return $this->getCriteriaElemnent($criteriaKey, 'choice');
305         }
306
307         /**
308          * Get criteria element or false if not found for 'exclude' type
309          *
310          * @param       $criteriaKey    The requested criteria key
311          * @return      $value                  Whether the value of the critera or false
312          */
313         public function getCriteriaExcludeElemnent ($criteriaKey) {
314                 // Call inner method
315                 return $this->getCriteriaElemnent($criteriaKey, 'exclude');
316         }
317
318         /**
319          * Checks whether given array entry matches
320          *
321          * @param       $entryArray             Array with the entries to find
322          * @param       $criteriaType   Type of this criteria, can be one of 'default' (default), 'choice' or 'exclude'
323          * @return      $matches                Whether the entry matches or not
324          */
325         public function ifEntryMatches (array $entryArray, $criteriaType = 'default') {
326                 // First nothing matches and nothing is counted
327                 $matches = false;
328                 $counted = 0;
329
330                 // Walk through all entries
331                 foreach ($entryArray as $key => $entry) {
332                         // Make sure no 'my-' or 'my_' passes this point
333                         assert((strpos($key, 'my-') === false) && (strpos($key, 'my_') === false));
334
335                         // Convert dashes to underscore
336                         $key = StringUtils::convertDashesToUnderscores($key);
337
338                         // Then walk through all search criteria
339                         foreach ($this->getGenericArrayKey('criteria', $criteriaType, 'entries') as $criteriaKey => $criteriaValue) {
340                                 // Make sure no 'my-' or 'my_' passes this point
341                                 assert((strpos($criteriaKey, 'my-') === false) && (strpos($criteriaKey, 'my_') === false) && (!is_bool($criteriaValue)));
342
343                                 // Convert dashes to underscore
344                                 $criteriaKey = StringUtils::convertDashesToUnderscores($criteriaKey);
345
346                                 // Is the element found and does it match?
347                                 if (($key == $criteriaKey) && ($criteriaValue == $entry)) {
348                                         // Then count this one up
349                                         $counted++;
350                                 } // END - if
351                         } // END - foreach
352                 } // END - foreach
353
354                 // Now check if expected criteria counts match
355                 $matches = ($counted == $this->countGenericArrayGroup('criteria', $criteriaType));
356
357                 // Return the result
358                 return $matches;
359         }
360
361         /**
362          * Checks whether given array 'choice' entry matches
363          *
364          * @param       $entryArray             Array with the entries to find
365          * @return      $matches                Whether the entry matches or not
366          */
367         public function ifChoiceMatches (array $entryArray) {
368                 // Call inner method
369                 return $this->ifEntryMatches($entryArray, 'choice');
370         }
371
372         /**
373          * Checks whether given array 'exclude' entry matches
374          *
375          * @param       $entryArray             Array with the entries to find
376          * @return      $matches                Whether the entry matches or not
377          */
378         public function ifExcludeMatches (array $entryArray) {
379                 // Call inner method
380                 return $this->ifEntryMatches($entryArray, 'exclude');
381         }
382
383         /**
384          * "Getter" for a cache key
385          *
386          * @param       $onlyKeys       Only use these keys for a cache key
387          * @param       $criteriaType   Type of this criteria, can be one of 'default' (default), 'choice' or 'exclude'
388          * @return      $cacheKey       The key suitable for the cache system
389          */
390         public function getCacheKey ($onlyKeys = array(), $criteriaType = 'default') {
391                 // Debug message
392                 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput($this->__toString() . ': criteriaType=' . $criteriaType . ',count()=' . $this->countGenericArray('criteria')));
393
394                 // Make sure the criteria is there
395                 assert($this->isValidGenericArrayGroup('criteria', $criteriaType));
396
397                 // Initialize the key
398                 $cacheKey = '';
399
400                 // Now walk through all criterias
401                 foreach ($this->getGenericArrayKey('criteria', $criteriaType, 'entries') as $criteriaKey => $criteriaValue) {
402                         // Make sure no 'my-' or 'my_' passes this point
403                         assert((strpos($criteriaKey, 'my-') === false) && (strpos($criteriaKey, 'my_') === false) && (!is_bool($criteriaValue)));
404
405                         // $criteriaValue cannot be an array
406                         assert(!is_array($criteriaValue));
407
408                         // Convert dashes to underscore
409                         $criteriaKey = StringUtils::convertDashesToUnderscores($criteriaKey);
410
411                         // Is the value in array or is $onlyKeys empty?
412                         if ((isset($onlyKeys[$criteriaKey])) || (count($onlyKeys) == 0)) {
413                                 // Add the value URL encoded to avoid any trouble with special characters
414                                 $cacheKey .= sprintf('%s=%s;',
415                                         $criteriaKey,
416                                         urlencode($criteriaValue)
417                                 );
418                         } // END - if
419                 } // END - foreach
420
421                 // Remove last semicolon
422                 $cacheKey = substr($cacheKey, 0, -1);
423
424                 // Is the instance SearchCriteria?
425                 if ($this instanceof SearchCriteria) {
426                         // Check if 'limit' and 'skip' are in
427                         if (((isset($onlyKeys['limit'])) && (isset($onlyKeys['skip']))) || (count($onlyKeys) == 0)) {
428                                 // Add limit and skip values
429                                 $cacheKey .= sprintf(';%%limit%%=%s;%%skip%%=%s',
430                                         $this->getLimit(),
431                                         $this->getSkip()
432                                 );
433                         } // END - if
434                 } // END - if
435
436                 // Return the cache key
437                 return $cacheKey;
438         }
439
440         /**
441          * "Getter" for a cache key ('choice' type)
442          *
443          * @param       $onlyKeys       Only use these keys for a cache key
444          * @return      $cacheKey       The key suitable for the cache system
445          */
446         public function getCacheKeyChoice ($onlyKeys = array()) {
447                 // Call inner method
448                 return $this->getCacheKey($onlyKeys, 'choice');
449         }
450
451         /**
452          * "Getter" for a cache key ('exclude' type)
453          *
454          * @param       $onlyKeys       Only use these keys for a cache key
455          * @return      $cacheKey       The key suitable for the cache system
456          */
457         public function getCacheKeyExclude ($onlyKeys = array()) {
458                 // Call inner method
459                 return $this->getCacheKey($onlyKeys, 'exclude');
460         }
461
462         /**
463          * Count the criteria, e.g. useful to find out if a database query has no
464          * limitation (search criteria).
465          *
466          * @param       $criteriaType   Type of this criteria, can be one of 'default' (default), 'choice' or 'exclude'
467          * @return      $count  Count of all criteria entries
468          */
469         public final function count ($criteriaType = 'default') {
470                 // Return it
471                 return $this->countGenericArrayGroup('criteria', $criteriaType);
472         }
473
474         /**
475          * Count 'choice' criteria, e.g. useful to find out if a database query
476          * has no limitation (search criteria).
477          *
478          * @return      $count  Count of all criteria entries
479          */
480         public final function countChoice () {
481                 return $this->count('choice');
482         }
483
484         /**
485          * Count 'exclude' criteria, e.g. useful to find out if a database query
486          * has no limitation (search criteria).
487          *
488          * @return      $count  Count of all criteria entries
489          */
490         public final function countExclude () {
491                 return $this->count('exclude');
492         }
493
494 }