3 namespace Org\Mxchange\CoreFramework\Criteria;
5 // Import framework stuff
6 use Org\Mxchange\CoreFramework\Bootstrap\FrameworkBootstrap;
7 use Org\Mxchange\CoreFramework\Criteria\Search\SearchCriteria;
8 use Org\Mxchange\CoreFramework\Generic\FrameworkInterface;
9 use Org\Mxchange\CoreFramework\Object\BaseFrameworkSystem;
10 use Org\Mxchange\CoreFramework\Utils\Strings\StringUtils;
13 use \BadMethodCallException;
14 use \InvalidArgumentException;
15 use \UnexpectedValueException;
18 * A general crtieria class
20 * @author Roland Haeder <webmaster@shipsimu.org>
22 * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2023 Core Developer Team
23 * @license GNU GPL 3.0 or any newer version
24 * @link http://www.shipsimu.org
26 * This program is free software: you can redistribute it and/or modify
27 * it under the terms of the GNU General Public License as published by
28 * the Free Software Foundation, either version 3 of the License, or
29 * (at your option) any later version.
31 * This program is distributed in the hope that it will be useful,
32 * but WITHOUT ANY WARRANTY; without even the implied warranty of
33 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
34 * GNU General Public License for more details.
36 * You should have received a copy of the GNU General Public License
37 * along with this program. If not, see <http://www.gnu.org/licenses/>.
39 abstract class BaseCriteria extends BaseFrameworkSystem implements Criteria {
41 * Frontend class name stored in config entry
43 private $frontendConfigEntry = '';
46 * All supported criteria types
48 private static $CRITERIA_TYPES = [];
51 * Protected constructor
53 * @param $className Name of the class
56 protected function __construct (string $className) {
57 // Call parent constructor
58 parent::__construct($className);
60 // Initialize valid criteria types array
61 self::$CRITERIA_TYPES = [Criteria::CRITERIA_TYPE_DEFAULT, Criteria::CRITERIA_TYPE_CHOICE, Criteria::CRITERIA_TYPE_EXCLUDE];
63 // Initialize all criteria arrays
64 foreach (self::$CRITERIA_TYPES as $criteriaType) {
66 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-CRITERIA: Initializing criteriaType=%s ...', $criteriaType));
67 $this->initGenericArrayKey('criteria', $criteriaType, 'entries');
72 * Count the criteria, e.g. useful to find out if a database query has no
73 * limitation (search criteria).
75 * @param $criteriaType Type of this criteria, can be one of 'default' (default), 'choice' or 'exclude'
76 * @return $count Count of all criteria entries
77 * @throws InvalidArgumentException If a parameter is not valid
79 protected final function count (string $criteriaType = Criteria::CRITERIA_TYPE_DEFAULT) {
81 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('%s-CRITERIA: criteriaType=%s - CALLED!', strtoupper($criteriaType), $criteriaType));
82 if (empty($criteriaType)) {
84 throw new InvalidArgumentException('Parameter "criteriaType" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
85 } elseif (!in_array($criteriaType, self::$CRITERIA_TYPES)) {
87 throw new InvalidArgumentException(sprintf('criteriaType=%s is not supported', $criteriaType));
90 // Invoke inner method
91 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('%s-CRITERIA: Invoking this->countGenericArrayGroup(criteria, %s) ...', strtoupper($criteriaType), $criteriaType));
92 return $this->countGenericArrayGroup('criteria', $criteriaType);
96 * Checks whether given key is set
98 * @param $criteriaType Type of this criteria, can be one of 'default' (default), 'choice' or 'exclude'
99 * @param $criteriaKey Criteria key
100 * @return $isset Whether key is set
101 * @throws InvalidArgumentException If a parameter is not valid
102 * @throws UnexpectedValueException If a parameter contains an unexpected/unsupported value
104 public function isKeySet (string $criteriaType, string $criteriaKey) {
106 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('%s-CRITERIA: criteriaType=%s,criteriaKey=%s - CALLED!', strtoupper($criteriaType), $criteriaType, $criteriaKey));
107 if (empty($criteriaType)) {
109 throw new InvalidArgumentException('Parameter "criteriaType" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
110 } elseif (!in_array($criteriaType, self::$CRITERIA_TYPES)) {
112 throw new UnexpectedValueException(sprintf('criteriaType=%s is not supported', $criteriaType));
113 } elseif (empty($criteriaKey)) {
115 throw new InvalidArgumentException('Parameter "criteriaKey" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
116 } elseif ((strpos($criteriaKey, 'my-') !== false) || (strpos($criteriaKey, 'my_') !== false)) {
118 throw new InvalidArgumentException(sprintf('criteriaKey=%s has illegal prefix "my"', $criteriaKey));
122 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('%s-CRITERIA: Invoking this->isGenericArrayElementSet(criteria,%s,entries,%s) ...', strtoupper($criteriaType), $criteriaType, $criteriaKey));
123 $isset = $this->isGenericArrayElementSet('criteria', $criteriaType, 'entries', $criteriaKey);
126 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('%s-CRITERIA: isset=%d - EXIT!', strtoupper($criteriaType), intval($isset)));
131 * Checks whether given key is set for 'choice' type
133 * @param $criteriaKey Criteria key
134 * @return $isset Whether key is set
135 * @throws InvalidArgumentException If a parameter is not valid
137 public function isChoiceKeySet (string $criteriaKey) {
138 // Validate parameter
139 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-CRITERIA: criteriaKey=%s - CALLED!', $criteriaKey));
140 if (empty($criteriaKey)) {
142 throw new InvalidArgumentException('Parameter "criteriaKey" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
145 // Invoke inner method
146 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-CRITERIA: Invoking this->isKeySet(%s,%s) ...', Criteria::CRITERIA_TYPE_CHOICE, $criteriaKey));
147 return $this->isKeySet(Criteria::CRITERIA_TYPE_CHOICE, $criteriaKey);
151 * Checks whether given key is set for 'exclude' type
153 * @param $criteriaKey Criteria key
154 * @return $isset Whether key is set
155 * @throws InvalidArgumentException If a parameter is not valid
157 public function isExcludeKeySet (string $criteriaKey) {
158 // Validate parameter
159 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-CRITERIA: criteriaKey=%s - CALLED!', $criteriaKey));
160 if (empty($criteriaKey)) {
162 throw new InvalidArgumentException('Parameter "criteriaKey" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
165 // Invoke inner method
166 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-CRITERIA: Invoking this->isKeySet(%s,%s) ...', Criteria::CRITERIA_TYPE_EXCLUDE, $criteriaKey));
167 return $this->isKeySet(Criteria::CRITERIA_TYPE_EXCLUDE, $criteriaKey);
171 * Setter for frontend class name
173 * @param $frontendConfigEntry Configuration entry which hold the frontend class' name
176 public final function setFrontendConfigEntry (string $frontendConfigEntry) {
177 $this->frontendConfigEntry = $frontendConfigEntry;
181 * Getter for frontend class name
183 * @return $frontendConfigEntry Configuration entry which hold the frontend class' name
185 public final function getFrontendConfigEntry () {
186 return $this->frontendConfigEntry;
190 * Getter for criteria array
192 * @param $criteriaType Type of this criteria, can be one of 'default' (default), 'choice' or 'exclude'
194 * @throws InvalidArgumentException If a parameter is not valid
195 * @throws UnexpectedValueException If a parameter contains an unexpected/unsupported value
197 public final function getCriteriaArray (string $criteriaType = Criteria::CRITERIA_TYPE_DEFAULT) {
199 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('%s-CRITERIA: criteriaType=%s - CALLED!', strtoupper($criteriaType), $criteriaType));
200 if (empty($criteriaType)) {
202 throw new InvalidArgumentException('Parameter "criteriaType" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
203 } elseif (!in_array($criteriaType, self::$CRITERIA_TYPES)) {
205 throw new UnexpectedValueException(sprintf('criteriaType=%s is not supported', $criteriaType));
208 // Invoke inner method
209 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('%s-CRITERIA: Invoking this->getGenericArrayKey(criteria,%s,entries) ...', strtoupper($criteriaType), $criteriaType));
210 return $this->getGenericArrayKey('criteria', $criteriaType, 'entries');
214 * Getter for criteria array 'choice' type
218 public final function getCriteriaChoiceArray () {
219 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('%s-CRITERIA: CALLED!', strtoupper($criteriaType)));
220 return $this->getCriteriaArray(Criteria::CRITERIA_TYPE_CHOICE);
224 * Getter for criteria array 'exclude' type
228 public final function getCriteriaExcludeArray () {
229 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('%s-CRITERIA: CALLED!', strtoupper($criteriaType)));
230 return $this->getCriteriaArray(Criteria::CRITERIA_TYPE_EXCLUDE);
234 * Unsets a criteria key from all criteria types
236 * @param $criteriaKey Criteria key to unset
239 public final function unsetCriteria (string $criteriaKey) {
241 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-CRITERIA: criteriaKey=%s - CALLED!', $criteriaKey));
242 if (empty($criteriaKey)) {
244 throw new InvalidArgumentException('Parameter "criteriaKey" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
245 } elseif ((strpos($criteriaKey, 'my-') !== false) || (strpos($criteriaKey, 'my_') !== false)) {
247 throw new InvalidArgumentException(sprintf('criteriaKey=%s has illegal prefix "my"', $criteriaKey));
250 // Convert dashes to underscore
251 $criteriaKey = StringUtils::convertDashesToUnderscores($criteriaKey);
253 // "Walk" through all criterias
254 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('%s-CRITERIA: criteriaKey=%s', strtoupper($criteriaType), $criteriaKey));
255 foreach ($this->getGenericArray('criteria') as $criteriaType => $dummy) {
257 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('%s-CRITERIA: Removing criteriaType=%s,criteriaKey=%s ...', strtoupper($criteriaType), $criteriaType, $criteriaKey));
258 $this->unsetGenericArrayElement('criteria', $criteriaType, 'entries', $criteriaKey);
262 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-CRITERIA: EXIT!');
266 * Add criteria, this method converts dashes to underscores because dashes
267 * are not valid for criteria keys.
269 * @param $criteriaKey Criteria key
270 * @param $criteriaValue Criteria value
271 * @param $criteriaType Type of this criteria, can be one of 'default' (default), 'choice' or 'exclude'
273 * @throws InvalidArgumentException If a parameter is not valid
274 * @throws UnexpectedValueException If a parameter contains an unexpected/unsupported value
276 public final function addCriteria (string $criteriaKey, $criteriaValue, string $criteriaType = Criteria::CRITERIA_TYPE_DEFAULT) {
278 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('%s-CRITERIA: criteriaKey=%s,criteriaValue[]=%s,criteriaType=%s - CALLED!', strtoupper($criteriaType), $criteriaKey, gettype($criteriaValue), $criteriaType));
279 if (empty($criteriaKey)) {
281 throw new InvalidArgumentException('Parameter "criteriaKey" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
282 } elseif ((strpos($criteriaKey, 'my-') !== false) || (strpos($criteriaKey, 'my_') !== false)) {
284 throw new InvalidArgumentException(sprintf('criteriaKey=%s has illegal prefix "my"', $criteriaKey));
285 } elseif (is_array($criteriaValue) || is_bool($criteriaValue) || is_object($criteriaValue) || is_resource($criteriaValue)) {
287 throw new InvalidArgumentException(sprintf('value[]=%s is not supported', gettype($criteriaValue)));
288 } elseif (empty($criteriaType)) {
290 throw new InvalidArgumentException('Parameter "criteriaType" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
291 } elseif (!in_array($criteriaType, self::$CRITERIA_TYPES)) {
293 throw new UnexpectedValueException(sprintf('criteriaType=%s is not supported', $criteriaType));
296 // Convert dashes to underscore
297 $criteriaKey = StringUtils::convertDashesToUnderscores($criteriaKey);
300 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('%s-CRITERIA: Invoking this->setGenericArrayElement(criteria,%s,entries,%s,criteriaValue[]=%s) ...', strtoupper($criteriaType), $criteriaType, $criteriaKey, gettype($criteriaValue)));
301 $this->setGenericArrayElement('criteria', $criteriaType, 'entries', $criteriaKey, $criteriaValue);
304 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('%s-CRITERIA: EXIT!', strtoupper($criteriaType)));
308 * Set criteria, this method converts dashes to underscores because dashes
309 * are not valid for criteria keys.
311 * @param $criteriaKey Criteria key
312 * @param $criteriaValue Criteria value
313 * @param $criteriaType Type of this criteria, can be one of 'default' (default), 'choice' or 'exclude'
315 * @throws InvalidArgumentException If a parameter is not valid
316 * @throws UnexpectedValueException If a parameter contains an unexpected/unsupported value
318 public final function setCriteria (string $criteriaKey, $criteriaValue, string $criteriaType = Criteria::CRITERIA_TYPE_DEFAULT) {
320 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('%s-CRITERIA: criteriaKey=%s,criteriaValue[]=%s$criteriaValue,criteriaType=%s - CALLED!', strtoupper($criteriaType), $criteriaKey, gettype($criteriaValue), $criteriaType));
321 if (empty($criteriaKey)) {
323 throw new InvalidArgumentException('Parameter "criteriaKey" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
324 } elseif ((strpos($criteriaKey, 'my-') !== false) || (strpos($criteriaKey, 'my_') !== false)) {
326 throw new InvalidArgumentException(sprintf('criteriaKey=%s has illegal prefix "my"', $criteriaKey));
327 } elseif (is_array($criteriaValue) || is_bool($criteriaValue) || is_object($criteriaValue) || is_resource($criteriaValue)) {
329 throw new InvalidArgumentException(sprintf('value[]=%s is not supported', gettype($criteriaValue)));
330 } elseif (empty($criteriaType)) {
332 throw new InvalidArgumentException('Parameter "criteriaType" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
333 } elseif (!in_array($criteriaType, self::$CRITERIA_TYPES)) {
335 throw new UnexpectedValueException(sprintf('criteriaType=%s is not supported', $criteriaType));
338 // Convert dashes to underscore
339 $criteriaKey = StringUtils::convertDashesToUnderscores($criteriaKey);
342 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('%s-CRITERIA: Invoking this->setGenericArrayElement(criteria,%s,entries,%s,criteriaValue[]=%s) ...', strtoupper($criteriaType), $criteriaKey, gettype($criteriaValue)));
343 $this->setGenericArrayElement('criteria', $criteriaType, 'entries', $criteriaKey, $criteriaValue);
346 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-CRITERIA: EXIT!');
350 * Add "choice" criteria, this method converts dashes to underscores because
351 * dashes are not valid for criteria keys.
353 * @param $criteriaKey Criteria key
354 * @param $criteriaValue Criteria value
356 * @throws InvalidArgumentException If a parameter is not valid
357 * @throws UnexpectedValueException If $criteriaValue has an unexpected type
359 public final function addChoiceCriteria (string $criteriaKey, $criteriaValue) {
361 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-CRITERIA: criteriaKey=%s,criteriaValue[]=%s - CALLED!', $criteriaKey, gettype($criteriaValue)));
362 if (empty($criteriaKey)) {
364 throw new InvalidArgumentException('Parameter "criteriaKey" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
365 } elseif ((strpos($criteriaKey, 'my-') !== false) || (strpos($criteriaKey, 'my_') !== false)) {
367 throw new InvalidArgumentException(sprintf('criteriaKey=%s has illegal prefix "my"', $criteriaKey));
368 } elseif (is_array($criteriaValue) || is_bool($criteriaValue) || is_object($criteriaValue) || is_resource($criteriaValue)) {
370 throw new UnexpectedValueException(sprintf('criteriaValue[]=%s is not accepted', gettype($criteriaValue)));
374 $this->pushValueToGenericArrayElement('criteria', Criteria::CRITERIA_TYPE_CHOICE, 'entries', StringUtils::convertDashesToUnderscores($criteriaKey), (string) $criteriaValue);
377 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-CRITERIA: EXIT!');
381 * Add "exclude" criteria, this method converts dashes to underscores because
382 * dashes are not valid for criteria keys.
384 * @param $criteriaKey Criteria key
385 * @param $criteriaValue Criteria value
387 * @throws InvalidArgumentException If a parameter is not valid
388 * @throws UnexpectedValueException If $criteriaValue has an unexpected type
390 public final function addExcludeCriteria (string $criteriaKey, $criteriaValue) {
392 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-CRITERIA: criteriaKey=%s,criteriaValue[%s]=%s - CALLED!', $criteriaKey, gettype($criteriaValue), $criteriaValue));
393 if (empty($criteriaKey)) {
395 throw new InvalidArgumentException('Parameter "criteriaKey" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
396 } elseif ((strpos($criteriaKey, 'my-') !== false) || (strpos($criteriaKey, 'my_') !== false)) {
398 throw new InvalidArgumentException(sprintf('criteriaKey=%s has illegal prefix "my"', $criteriaKey));
399 } elseif (is_array($criteriaValue) || is_bool($criteriaValue) || is_object($criteriaValue) || is_resource($criteriaValue)) {
401 throw new UnexpectedValueException(sprintf('criteriaValue[]=%s is not accepted', gettype($criteriaValue)));
404 // Add it with generic method
405 $this->addCriteria($criteriaKey, $criteriaValue, Criteria::CRITERIA_TYPE_EXCLUDE);
408 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-CRITERIA: EXIT!');
412 * Add configured criteria
414 * @param $criteriaKey Criteria key
415 * @param $configEntry Configuration entry
416 * @param $criteriaType Type of this criteria, can be one of 'default' (default), 'choice' or 'exclude'
418 * @throws InvalidArgumentException If a parameter is not valid
419 * @throws UnexpectedValueException If a parameter contains an unexpected/unsupported value
421 public final function addConfiguredCriteria (string $criteriaKey, string $configEntry, string $criteriaType = Criteria::CRITERIA_TYPE_DEFAULT) {
423 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('%s-CRITERIA: criteriaKey=%s,configEntry=%s,criteriaType=%s - CALLED!', strtoupper($criteriaType), $criteriaKey, $configEntry, $criteriaType));
424 if (empty($criteriaKey)) {
426 throw new InvalidArgumentException('Parameter "criteriaKey" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
427 } elseif ((strpos($criteriaKey, 'my-') !== false) || (strpos($criteriaKey, 'my_') !== false)) {
429 throw new InvalidArgumentException(sprintf('criteriaKey=%s has illegal prefix "my"', $criteriaKey));
430 } elseif (empty($configEntry)) {
432 throw new InvalidArgumentException('Parameter "configEntry" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
433 } elseif (empty($criteriaType)) {
435 throw new InvalidArgumentException('Parameter "criteriaType" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
436 } elseif (!in_array($criteriaType, self::$CRITERIA_TYPES)) {
438 throw new UnexpectedValueException(sprintf('criteriaType=%s is not supported', $criteriaType));
441 // Add the configuration entry as a criteria
442 $value = FrameworkBootstrap::getConfigurationInstance()->getConfigEntry($configEntry);
444 // Invoke inner method
445 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('%s-CRITERIA: Invoking this->addCriteria(%s,value[%s]=%s,%s) ...', strtoupper($criteriaType), $criteriaKey, gettype($value), $value, $criteriaType));
446 $this->addCriteria($criteriaKey, $value, $criteriaType);
449 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('%s-CRITERIA: EXIT!', strtoupper($criteriaType)));
453 * Get criteria element or false if not found
455 * @param $criteriaKey The requested criteria key
456 * @param $criteriaType Type of this criteria, can be one of 'default' (default), 'choice' or 'exclude'
457 * @return $value Whether the value of the critera or false
458 * @throws InvalidArgumentException If a parameter is not valid
459 * @throws UnexpectedValueException If a parameter contains an unexpected/unsupported value
461 public function getCriteriaElemnent (string $criteriaKey, string $criteriaType = Criteria::CRITERIA_TYPE_DEFAULT) {
463 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('%s-CRITERIA: criteriaKey=%s,criteriaType=%s - CALLED!', strtoupper($criteriaType), $criteriaKey, $criteriaType));
464 if (empty($criteriaKey)) {
466 throw new InvalidArgumentException('Parameter "criteriaKey" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
467 } elseif ((strpos($criteriaKey, 'my-') !== false) || (strpos($criteriaKey, 'my_') !== false)) {
469 throw new InvalidArgumentException(sprintf('criteriaKey=%s has illegal prefix "my"', $criteriaKey));
470 } elseif (empty($criteriaType)) {
472 throw new InvalidArgumentException('Parameter "criteriaType" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
473 } elseif (!in_array($criteriaType, self::$CRITERIA_TYPES)) {
475 throw new UnexpectedValueException(sprintf('criteriaType=%s is not supported', $criteriaType));
478 // Convert dashes to underscore
479 $criteriaKey = StringUtils::convertDashesToUnderscores($criteriaKey);
481 // Default is not found
484 // Is the criteria there?
485 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('%s-CRITERIA: criteriaKey=%s,criteria()=%d', strtoupper($criteriaType), $criteriaKey, $this->countGenericArrayGroup('criteria', $criteriaType)));
486 if ($this->isKeySet($criteriaType, $criteriaKey)) {
488 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('%s-CRITERIA: Invoking this->getGenericArrayElement(criteria,%s,entries,%s) ...', strtoupper($criteriaType), $criteriaType, $criteriaKey));
489 $value = $this->getGenericArrayElement('criteria', $criteriaType, 'entries', $criteriaKey);
493 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('%s-CRITERIA: value[]=%s - EXIT!', strtoupper($criteriaType), gettype($value)));
498 * Get criteria element or false if not found for 'choice' type
500 * @param $criteriaKey The requested criteria key
501 * @return $value Whether the value of the critera or false
502 * @throws InvalidArgumentException If a parameter is not valid
504 public function getCriteriaChoiceElemnent (string $criteriaKey) {
506 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-CRITERIA: criteriaKey=%s - CALLED!', $criteriaKey));
507 if (empty($criteriaKey)) {
509 throw new InvalidArgumentException('Parameter "criteriaKey" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
510 } elseif ((strpos($criteriaKey, 'my-') !== false) || (strpos($criteriaKey, 'my_') !== false)) {
512 throw new InvalidArgumentException(sprintf('criteriaKey=%s has illegal prefix "my"', $criteriaKey));
515 // Invoke inner method
516 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-CRITERIA: Invoking this->getCriteriaElemnent(%s,%s) ...', $criteriaKey, Criteria::CRITERIA_TYPE_CHOICE));
517 return $this->getCriteriaElemnent($criteriaKey, Criteria::CRITERIA_TYPE_CHOICE);
521 * Get criteria element or false if not found for 'exclude' type
523 * @param $criteriaKey The requested criteria key
524 * @return $value Whether the value of the critera or false
525 * @throws InvalidArgumentException If a parameter is not valid
527 public function getCriteriaExcludeElemnent (string $criteriaKey) {
529 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-CRITERIA: criteriaKey=%s - CALLED!', $criteriaKey));
530 if (empty($criteriaKey)) {
532 throw new InvalidArgumentException('Parameter "criteriaKey" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
533 } elseif ((strpos($criteriaKey, 'my-') !== false) || (strpos($criteriaKey, 'my_') !== false)) {
535 throw new InvalidArgumentException(sprintf('criteriaKey=%s has illegal prefix "my"', $criteriaKey));
538 // Invoke inner method
539 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-CRITERIA: Invoking this->getCriteriaElemnent(%s,%s) ...', $criteriaKey, Criteria::CRITERIA_TYPE_EXCLUDE));
540 return $this->getCriteriaElemnent($criteriaKey, Criteria::CRITERIA_TYPE_EXCLUDE);
544 * Checks whether given array entry matches
546 * @param $entryArray Array with the entries to find
547 * @param $criteriaType Type of this criteria, can be one of 'default' (default), 'choice' or 'exclude'
548 * @return $matches Whether the entry matches or not
549 * @throws InvalidArgumentException If a parameter is not valid
550 * @throws UnexpectedValueException If a parameter contains an unexpected/unsupported value
552 public function ifEntryMatches (array $entryArray, string $criteriaType = Criteria::CRITERIA_TYPE_DEFAULT) {
554 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('%s-CRITERIA: entryArray()=%d,criteriaType=%s - CALLED!', strtoupper($criteriaType), count($entryArray), $criteriaType));
555 if (count($entryArray) == 0) {
557 throw new InvalidArgumentException('entryArray cannot be an empty array');
558 } elseif (empty($criteriaType)) {
560 throw new InvalidArgumentException('Parameter "criteriaType" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
561 } elseif (!in_array($criteriaType, self::$CRITERIA_TYPES)) {
563 throw new UnexpectedValueException(sprintf('criteriaType=%s is not supported', $criteriaType));
566 // First nothing matches and nothing is counted
570 // Walk through all entries
571 foreach ($entryArray as $key => $entry) {
572 // Make sure no 'my-' or 'my_' passes this point
573 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('%s-CRITERIA: key=%s,entry[%s]=%s', strtoupper($criteriaType), $key, gettype($entry), $entry));
574 if ((strpos($key, 'my-') !== false) || (strpos($key, 'my_') !== false)) {
576 throw new InvalidArgumentException(sprintf('key=%s has illegal prefix "my"', $key));
579 // Convert dashes to underscore
580 $key = StringUtils::convertDashesToUnderscores($key);
582 // Then walk through all search criteria
583 foreach ($this->getGenericArrayKey('criteria', $criteriaType, 'entries') as $criteriaKey => $criteriaValue) {
584 // Make sure no 'my-' or 'my_' passes this point
585 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('%s-CRITERIA: criteriaKey=%s,criteriaValue[%s]=%s', strtoupper($criteriaType), $criteriaKey, gettype($criteriaValue), $criteriaValue));
586 if ((strpos($criteriaKey, 'my-') !== false) || (strpos($criteriaKey, 'my_') !== false)) {
588 throw new UnexpectedValueException(sprintf('criteriaKey=%s has illegal prefix "my"', $criteriaKey));
591 // Convert dashes to underscore
592 $criteriaKey = StringUtils::convertDashesToUnderscores($criteriaKey);
594 // Is the element found and does it match?
595 if (($key == $criteriaKey) && ($criteriaValue == $entry)) {
596 // Then count this one up
597 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('%s-CRITERIA: MATCHES!', strtoupper($criteriaType)));
603 // Now check if expected criteria counts match
604 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('%s-CRITERIA: counted=%d', strtoupper($criteriaType), $counted));
605 $matches = ($counted == $this->countGenericArrayGroup('criteria', $criteriaType));
608 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('%s-CRITERIA: matches=%d - EXIT!', strtoupper($criteriaType), intval($matches)));
613 * Checks whether given array 'choice' entry matches
615 * @param $entryArray Array with the entries to find
616 * @return $matches Whether the entry matches or not
617 * @throws InvalidArgumentException If a parameter is not valid
619 public function ifChoiceMatches (array $entryArray) {
621 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-CRITERIA: entryArray()=%d - CALLED!', count($entryArray)));
622 if (count($entryArray) == 0) {
624 throw new InvalidArgumentException('entryArray cannot be an empty array');
627 // Invoke inner method
628 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-CRITERIA: Invoking this->ifEntryMatches(%d,%s) ...', count($entryArray), Criteria::CRITERIA_TYPE_CHOICE));
629 return $this->ifEntryMatches($entryArray, Criteria::CRITERIA_TYPE_CHOICE);
633 * Checks whether given array 'exclude' entry matches
635 * @param $entryArray Array with the entries to find
636 * @return $matches Whether the entry matches or not
637 * @throws InvalidArgumentException If a parameter is not valid
639 public function ifExcludeMatches (array $entryArray) {
641 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-CRITERIA: entryArray()=%d - CALLED!', count($entryArray)));
642 if (count($entryArray) == 0) {
644 throw new InvalidArgumentException('entryArray cannot be an empty array');
647 // Invoke inner method
648 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-CRITERIA: Invoking this->ifEntryMatches(%d,%s) ...', count($entryArray), Criteria::CRITERIA_TYPE_EXCLUDE));
649 return $this->ifEntryMatches($entryArray, Criteria::CRITERIA_TYPE_EXCLUDE);
653 * "Getter" for a cache key
655 * @param $onlyKeys Only use these keys for a cache key
656 * @param $criteriaType Type of this criteria, can be one of 'default' (default), 'choice' or 'exclude'
657 * @return $cacheKey The key suitable for the cache system
658 * @throws InvalidArgumentException If a parameter is not valid
659 * @throws UnexpectedValueException If a parameter contains an unexpected/unsupported value
660 * @throws BadMethodCallException If this method is invoked before $criteriaType has been initialized
662 public function getCacheKey (array $onlyKeys = [], string $criteriaType = Criteria::CRITERIA_TYPE_DEFAULT) {
664 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('%s-CRITERIA: onlyKeys()=%d,criteriaType=%s - CALLED!', strtoupper($criteriaType), count($onlyKeys), $criteriaType));
665 if (empty($criteriaType)) {
667 throw new InvalidArgumentException('Parameter "criteriaType" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
668 } elseif (!in_array($criteriaType, self::$CRITERIA_TYPES)) {
670 throw new UnexpectedValueException(sprintf('criteriaType=%s is not supported', $criteriaType));
671 } elseif (!$this->isValidGenericArrayGroup('criteria', $criteriaType)) {
672 // Not intialized yet
673 throw new BadMethodCallException(sprintf('Method cannot be invoked before criteriaType=%s is initialized!', $criteriaType), FrameworkInterface::EXCEPTION_BAD_METHOD_CALL);
676 // Initialize the key
679 // Now walk through all criterias
680 foreach ($this->getGenericArrayKey('criteria', $criteriaType, 'entries') as $criteriaKey => $criteriaValue) {
681 // Make sure no 'my-' or 'my_' passes this point
682 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('%s-CRITERIA: criteriaKey=%s,criteriaValue[%s]=%s', strtoupper($criteriaType), $criteriaKey, gettype($criteriaValue), $criteriaValue));
683 if ((strpos($criteriaKey, 'my-') !== false) || (strpos($criteriaKey, 'my_') !== false)) {
685 throw new UnexpectedValueException(sprintf('criteriaKey=%s has illegal prefix "my"', $criteriaKey));
686 } elseif (is_array($criteriaValue) || is_bool($criteriaValue) || is_object($criteriaValue) || is_resource($criteriaValue)) {
688 throw new UnexpectedValueException(sprintf('criteriaValue[]=%s is not supported', gettype($criteriaValue)));
691 // Convert dashes to underscore
692 $criteriaKey = StringUtils::convertDashesToUnderscores($criteriaKey);
694 // Is the value in array or is $onlyKeys empty?
695 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('%s-CRITERIA: criteriaKey=%s', strtoupper($criteriaType), $criteriaKey));
696 if ((isset($onlyKeys[$criteriaKey])) || (count($onlyKeys) == 0)) {
697 // Add the value URL encoded to avoid any trouble with special characters
698 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('%s-CRITERIA: Adding criteriaKey=%s,criteriaValue[%s]=%s to cache key ...', strtoupper($criteriaType), $criteriaKey, gettype($criteriaValue), $criteriaValue));
699 $cacheKey .= sprintf('%s=%s;',
701 urlencode($criteriaValue)
706 // Remove last semicolon
707 $cacheKey = substr($cacheKey, 0, -1);
709 // Is the instance SearchCriteria?
710 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('%s-CRITERIA: cacheKey=%s,this=%s', strtoupper($criteriaType), $cacheKey, $this->__toString()));
711 if ($this instanceof SearchCriteria) {
712 // Check if 'limit' and 'skip' are in
713 if (((isset($onlyKeys['limit'])) && (isset($onlyKeys['skip']))) || (count($onlyKeys) == 0)) {
714 // Add limit and skip values
715 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('%s-CRITERIA: Adding this->limit=%d,this->skip=%d to cache key ...', strtoupper($criteriaType), $this->getLimit(), $this->getSkip()));
716 $cacheKey .= sprintf(';%%limit%%=%s;%%skip%%=%s',
723 // Return the cache key
724 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('%s-CRITERIA: cacheKey=%s - EXIT!', strtoupper($criteriaType), $cacheKey));
729 * "Getter" for a cache key ('choice' type)
731 * @param $onlyKeys Only use these keys for a cache key
732 * @return $cacheKey The key suitable for the cache system
734 public function getCacheKeyChoice (array $onlyKeys = []) {
736 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-CRITERIA: onlyKeys()=%d - CALLED!', count($onlyKeys)));
738 // Invoke inner method
739 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-CRITERIA: Invoking this->getCacheKey(onlyKeys()=%d,%s) ...', count($onlyKeys),Criteria::CRITERIA_TYPE_CHOICE));
740 return $this->getCacheKey($onlyKeys, Criteria::CRITERIA_TYPE_CHOICE);
744 * "Getter" for a cache key ('exclude' type)
746 * @param $onlyKeys Only use these keys for a cache key
747 * @return $cacheKey The key suitable for the cache system
749 public function getCacheKeyExclude (array $onlyKeys = []) {
751 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-CRITERIA: onlyKeys()=%d - CALLED!', count($onlyKeys)));
753 // Invoke inner method
754 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput(sprintf('BASE-CRITERIA: Invoking this->getCacheKey(onlyKeys()=%d,%s) ...', count($onlyKeys),Criteria::CRITERIA_TYPE_EXCLUDE));
755 return $this->getCacheKey($onlyKeys, Criteria::CRITERIA_TYPE_EXCLUDE);
759 * Count 'choice' criteria, e.g. useful to find out if a database query
760 * has no limitation (search criteria).
762 * @return $count Count of all criteria entries
764 public final function countChoice () {
766 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-CRITERIA: CALLED!');
767 return $this->count(Criteria::CRITERIA_TYPE_CHOICE);
771 * Count 'exclude' criteria, e.g. useful to find out if a database query
772 * has no limitation (search criteria).
774 * @return $count Count of all criteria entries
776 public final function countExclude () {
778 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('BASE-CRITERIA: CALLED!');
779 return $this->count(Criteria::CRITERIA_TYPE_EXCLUDE);