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