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