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 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('BASE-CRITERIA: className=%s - CONSTRUCTED!', $className));
59 parent::__construct($className);
61 // Initialize valid criteria types array
62 self::$CRITERIA_TYPES = [Criteria::CRITERIA_TYPE_DEFAULT, Criteria::CRITERIA_TYPE_CHOICE, Criteria::CRITERIA_TYPE_EXCLUDE];
64 // Initialize all criteria arrays
65 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugMessage(sprintf('BASE-CRITERIA: self::CRITERIA_TYPES()=%d', count(self::$CRITERIA_TYPES)));
66 foreach (self::$CRITERIA_TYPES as $criteriaType) {
68 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('BASE-CRITERIA: Invoking this->initGenericArrayKey(criteria,%s,entries) ...', $criteriaType));
69 $this->initGenericArrayKey('criteria', $criteriaType, 'entries');
73 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage('BASE-CRITERIA: EXIT!');
77 * Count the criteria, e.g. useful to find out if a database query has no
78 * limitation (search criteria).
80 * @param $criteriaType Type of this criteria, can be one of 'default' (default), 'choice' or 'exclude'
81 * @return $count Count of all criteria entries
82 * @throws InvalidArgumentException If a parameter is not valid
84 protected final function count (string $criteriaType = Criteria::CRITERIA_TYPE_DEFAULT) {
86 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('%s-CRITERIA: criteriaType=%s - CALLED!', strtoupper($criteriaType), $criteriaType));
87 if (empty($criteriaType)) {
89 throw new InvalidArgumentException('Parameter "criteriaType" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
90 } elseif (!in_array($criteriaType, self::$CRITERIA_TYPES)) {
92 throw new InvalidArgumentException(sprintf('criteriaType=%s is not supported', $criteriaType));
95 // Invoke inner method
96 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('%s-CRITERIA: Invoking this->countGenericArrayGroup(criteria, %s) ... - EXIT!', strtoupper($criteriaType), $criteriaType));
97 return $this->countGenericArrayGroup('criteria', $criteriaType);
101 * Checks whether given key is set
103 * @param $criteriaType Type of this criteria, can be one of 'default' (default), 'choice' or 'exclude'
104 * @param $criteriaKey Criteria key
105 * @return $isset Whether key is set
106 * @throws InvalidArgumentException If a parameter is not valid
107 * @throws UnexpectedValueException If a parameter contains an unexpected/unsupported value
109 public function isKeySet (string $criteriaType, string $criteriaKey) {
111 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('%s-CRITERIA: criteriaType=%s,criteriaKey=%s - CALLED!', strtoupper($criteriaType), $criteriaType, $criteriaKey));
112 if (empty($criteriaType)) {
114 throw new InvalidArgumentException('Parameter "criteriaType" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
115 } elseif (!in_array($criteriaType, self::$CRITERIA_TYPES)) {
117 throw new UnexpectedValueException(sprintf('criteriaType=%s is not supported', $criteriaType));
118 } elseif (empty($criteriaKey)) {
120 throw new InvalidArgumentException('Parameter "criteriaKey" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
121 } elseif ((strpos($criteriaKey, 'my-') !== false) || (strpos($criteriaKey, 'my_') !== false)) {
123 throw new InvalidArgumentException(sprintf('criteriaKey=%s has illegal prefix "my"', $criteriaKey));
127 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugMessage(sprintf('%s-CRITERIA: Invoking this->isGenericArrayElementSet(criteria,%s,entries,%s) ...', strtoupper($criteriaType), $criteriaType, $criteriaKey));
128 $isset = $this->isGenericArrayElementSet('criteria', $criteriaType, 'entries', $criteriaKey);
131 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('%s-CRITERIA: isset=%d - EXIT!', strtoupper($criteriaType), intval($isset)));
136 * Checks whether given key is set for 'choice' type
138 * @param $criteriaKey Criteria key
139 * @return $isset Whether key is set
140 * @throws InvalidArgumentException If a parameter is not valid
142 public function isChoiceKeySet (string $criteriaKey) {
143 // Validate parameter
144 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('BASE-CRITERIA: criteriaKey=%s - CALLED!', $criteriaKey));
145 if (empty($criteriaKey)) {
147 throw new InvalidArgumentException('Parameter "criteriaKey" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
150 // Invoke inner method
151 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('BASE-CRITERIA: Invoking this->isKeySet(%s,%s) ...', Criteria::CRITERIA_TYPE_CHOICE, $criteriaKey));
152 return $this->isKeySet(Criteria::CRITERIA_TYPE_CHOICE, $criteriaKey);
156 * Checks whether given key is set for 'exclude' type
158 * @param $criteriaKey Criteria key
159 * @return $isset Whether key is set
160 * @throws InvalidArgumentException If a parameter is not valid
162 public function isExcludeKeySet (string $criteriaKey) {
163 // Validate parameter
164 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('BASE-CRITERIA: criteriaKey=%s - CALLED!', $criteriaKey));
165 if (empty($criteriaKey)) {
167 throw new InvalidArgumentException('Parameter "criteriaKey" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
170 // Invoke inner method
171 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('BASE-CRITERIA: Invoking this->isKeySet(%s,%s) ... - EXIT!', Criteria::CRITERIA_TYPE_EXCLUDE, $criteriaKey));
172 return $this->isKeySet(Criteria::CRITERIA_TYPE_EXCLUDE, $criteriaKey);
176 * Setter for frontend class name
178 * @param $frontendConfigEntry Configuration entry which hold the frontend class' name
181 public final function setFrontendConfigEntry (string $frontendConfigEntry) {
182 $this->frontendConfigEntry = $frontendConfigEntry;
186 * Getter for frontend class name
188 * @return $frontendConfigEntry Configuration entry which hold the frontend class' name
190 public final function getFrontendConfigEntry () {
191 return $this->frontendConfigEntry;
195 * Getter for criteria array
197 * @param $criteriaType Type of this criteria, can be one of 'default' (default), 'choice' or 'exclude'
199 * @throws InvalidArgumentException If a parameter is not valid
200 * @throws UnexpectedValueException If a parameter contains an unexpected/unsupported value
202 public final function getCriteriaArray (string $criteriaType = Criteria::CRITERIA_TYPE_DEFAULT) {
204 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('%s-CRITERIA: criteriaType=%s - CALLED!', strtoupper($criteriaType), $criteriaType));
205 if (empty($criteriaType)) {
207 throw new InvalidArgumentException('Parameter "criteriaType" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
208 } elseif (!in_array($criteriaType, self::$CRITERIA_TYPES)) {
210 throw new UnexpectedValueException(sprintf('criteriaType=%s is not supported', $criteriaType));
213 // Invoke inner method
214 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('%s-CRITERIA: Invoking this->getGenericArrayKey(criteria,%s,entries) ... - EXIT!', strtoupper($criteriaType), $criteriaType));
215 return $this->getGenericArrayKey('criteria', $criteriaType, 'entries');
219 * Getter for criteria array 'choice' type
223 public final function getCriteriaChoiceArray () {
224 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('%s-CRITERIA: CALLED!', strtoupper($criteriaType)));
225 return $this->getCriteriaArray(Criteria::CRITERIA_TYPE_CHOICE);
229 * Getter for criteria array 'exclude' type
233 public final function getCriteriaExcludeArray () {
234 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage('BASE-CRITERIA: CALLED!');
235 return $this->getCriteriaArray(Criteria::CRITERIA_TYPE_EXCLUDE);
239 * Unsets a criteria key from all criteria types
241 * @param $criteriaKey Criteria key to unset
244 public final function unsetCriteria (string $criteriaKey) {
246 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('BASE-CRITERIA: criteriaKey=%s - CALLED!', $criteriaKey));
247 if (empty($criteriaKey)) {
249 throw new InvalidArgumentException('Parameter "criteriaKey" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
250 } elseif ((strpos($criteriaKey, 'my-') !== false) || (strpos($criteriaKey, 'my_') !== false)) {
252 throw new InvalidArgumentException(sprintf('criteriaKey=%s has illegal prefix "my"', $criteriaKey));
255 // Convert dashes to underscore
256 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('%s-CRITERIA: Invoking StringUtils::convertDashesToUnderscores(%s) ...', strtoupper($criteriaType), $criteriaKey));
257 $criteriaKey = StringUtils::convertDashesToUnderscores($criteriaKey);
259 // "Walk" through all criterias
260 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugMessage(sprintf('%s-CRITERIA: criteriaKey=%s', strtoupper($criteriaType), $criteriaKey));
261 foreach ($this->getGenericArray('criteria') as $criteriaType => $dummy) {
263 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('%s-CRITERIA: Removing criteriaType=%s,criteriaKey=%s ...', strtoupper($criteriaType), $criteriaType, $criteriaKey));
264 $this->unsetGenericArrayElement('criteria', $criteriaType, 'entries', $criteriaKey);
268 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage('BASE-CRITERIA: EXIT!');
272 * Add criteria, this method converts dashes to underscores because dashes
273 * are not valid for criteria keys.
275 * @param $criteriaKey Criteria key
276 * @param $criteriaValue Criteria value
277 * @param $criteriaType Type of this criteria, can be one of 'default' (default), 'choice' or 'exclude'
279 * @throws InvalidArgumentException If a parameter is not valid
280 * @throws UnexpectedValueException If a parameter contains an unexpected/unsupported value
282 public final function addCriteria (string $criteriaKey, $criteriaValue, string $criteriaType = Criteria::CRITERIA_TYPE_DEFAULT) {
284 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('%s-CRITERIA: criteriaKey=%s,criteriaValue[]=%s,criteriaType=%s - CALLED!', strtoupper($criteriaType), $criteriaKey, gettype($criteriaValue), $criteriaType));
285 if (empty($criteriaKey)) {
287 throw new InvalidArgumentException('Parameter "criteriaKey" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
288 } elseif ((strpos($criteriaKey, 'my-') !== false) || (strpos($criteriaKey, 'my_') !== false)) {
290 throw new InvalidArgumentException(sprintf('criteriaKey=%s has illegal prefix "my"', $criteriaKey));
291 } elseif (is_array($criteriaValue) || is_bool($criteriaValue) || is_object($criteriaValue) || is_resource($criteriaValue)) {
293 throw new InvalidArgumentException(sprintf('value[]=%s is not supported', gettype($criteriaValue)));
294 } elseif (empty($criteriaType)) {
296 throw new InvalidArgumentException('Parameter "criteriaType" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
297 } elseif (!in_array($criteriaType, self::$CRITERIA_TYPES)) {
299 throw new UnexpectedValueException(sprintf('criteriaType=%s is not supported', $criteriaType));
302 // Convert dashes to underscore
303 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('%s-CRITERIA: Invoking StringUtils::convertDashesToUnderscores(%s) ...', strtoupper($criteriaType), $criteriaKey));
304 $criteriaKey = StringUtils::convertDashesToUnderscores($criteriaKey);
307 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('%s-CRITERIA: Invoking this->setGenericArrayElement(criteria,%s,entries,%s,criteriaValue[]=%s) ...', strtoupper($criteriaType), $criteriaType, $criteriaKey, gettype($criteriaValue)));
308 $this->setGenericArrayElement('criteria', $criteriaType, 'entries', $criteriaKey, $criteriaValue);
311 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('%s-CRITERIA: EXIT!', strtoupper($criteriaType)));
315 * Set criteria, this method converts dashes to underscores because dashes
316 * are not valid for criteria keys.
318 * @param $criteriaKey Criteria key
319 * @param $criteriaValue Criteria value
320 * @param $criteriaType Type of this criteria, can be one of 'default' (default), 'choice' or 'exclude'
322 * @throws InvalidArgumentException If a parameter is not valid
323 * @throws UnexpectedValueException If a parameter contains an unexpected/unsupported value
325 public final function setCriteria (string $criteriaKey, $criteriaValue, string $criteriaType = Criteria::CRITERIA_TYPE_DEFAULT) {
327 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('%s-CRITERIA: criteriaKey=%s,criteriaValue[]=%s$criteriaValue,criteriaType=%s - CALLED!', strtoupper($criteriaType), $criteriaKey, gettype($criteriaValue), $criteriaType));
328 if (empty($criteriaKey)) {
330 throw new InvalidArgumentException('Parameter "criteriaKey" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
331 } elseif ((strpos($criteriaKey, 'my-') !== false) || (strpos($criteriaKey, 'my_') !== false)) {
333 throw new InvalidArgumentException(sprintf('criteriaKey=%s has illegal prefix "my"', $criteriaKey));
334 } elseif (is_array($criteriaValue) || is_bool($criteriaValue) || is_object($criteriaValue) || is_resource($criteriaValue)) {
336 throw new InvalidArgumentException(sprintf('value[]=%s is not supported', gettype($criteriaValue)));
337 } elseif (empty($criteriaType)) {
339 throw new InvalidArgumentException('Parameter "criteriaType" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
340 } elseif (!in_array($criteriaType, self::$CRITERIA_TYPES)) {
342 throw new UnexpectedValueException(sprintf('criteriaType=%s is not supported', $criteriaType));
345 // Convert dashes to underscore
346 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('%s-CRITERIA: Invoking StringUtils::convertDashesToUnderscores(%s) ...', strtoupper($criteriaType), $criteriaKey));
347 $criteriaKey = StringUtils::convertDashesToUnderscores($criteriaKey);
350 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('%s-CRITERIA: Invoking this->setGenericArrayElement(criteria,%s,entries,%s,criteriaValue[]=%s) ...', strtoupper($criteriaType), $criteriaKey, gettype($criteriaValue)));
351 $this->setGenericArrayElement('criteria', $criteriaType, 'entries', $criteriaKey, $criteriaValue);
354 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage('BASE-CRITERIA: EXIT!');
358 * Add "choice" criteria, this method converts dashes to underscores because
359 * dashes are not valid for criteria keys.
361 * @param $criteriaKey Criteria key
362 * @param $criteriaValue Criteria value
364 * @throws InvalidArgumentException If a parameter is not valid
365 * @throws UnexpectedValueException If $criteriaValue has an unexpected type
367 public final function addChoiceCriteria (string $criteriaKey, $criteriaValue) {
369 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('BASE-CRITERIA: criteriaKey=%s,criteriaValue[]=%s - CALLED!', $criteriaKey, gettype($criteriaValue)));
370 if (empty($criteriaKey)) {
372 throw new InvalidArgumentException('Parameter "criteriaKey" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
373 } elseif ((strpos($criteriaKey, 'my-') !== false) || (strpos($criteriaKey, 'my_') !== false)) {
375 throw new InvalidArgumentException(sprintf('criteriaKey=%s has illegal prefix "my"', $criteriaKey));
376 } elseif (is_array($criteriaValue) || is_bool($criteriaValue) || is_object($criteriaValue) || is_resource($criteriaValue)) {
378 throw new UnexpectedValueException(sprintf('criteriaValue[]=%s is not accepted', gettype($criteriaValue)));
381 // Convert dashes to underscore
382 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('BASE-CRITERIA: Invoking StringUtils::convertDashesToUnderscores(%s) ...', $criteriaKey));
383 $criteriaKey = StringUtils::convertDashesToUnderscores($criteriaKey);
386 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('BASE-CRITERIA: Invoking this->pushValueToGenericArrayElement(criteria,%s,entries,%s,criteriaValue[]=%s) ...', Criteria::CRITERIA_TYPE_CHOICE, $criteriaKey, gettype($criteriaValue)));
387 $this->pushValueToGenericArrayElement('criteria', Criteria::CRITERIA_TYPE_CHOICE, 'entries', $criteriaKey, $criteriaValue);
390 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage('BASE-CRITERIA: EXIT!');
394 * Add "exclude" criteria, this method converts dashes to underscores because
395 * dashes are not valid for criteria keys.
397 * @param $criteriaKey Criteria key
398 * @param $criteriaValue Criteria value
400 * @throws InvalidArgumentException If a parameter is not valid
401 * @throws UnexpectedValueException If $criteriaValue has an unexpected type
403 public final function addExcludeCriteria (string $criteriaKey, $criteriaValue) {
405 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('BASE-CRITERIA: criteriaKey=%s,criteriaValue[%s]=%s - CALLED!', $criteriaKey, gettype($criteriaValue), $criteriaValue));
406 if (empty($criteriaKey)) {
408 throw new InvalidArgumentException('Parameter "criteriaKey" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
409 } elseif ((strpos($criteriaKey, 'my-') !== false) || (strpos($criteriaKey, 'my_') !== false)) {
411 throw new InvalidArgumentException(sprintf('criteriaKey=%s has illegal prefix "my"', $criteriaKey));
412 } elseif (is_array($criteriaValue) || is_bool($criteriaValue) || is_object($criteriaValue) || is_resource($criteriaValue)) {
414 throw new UnexpectedValueException(sprintf('criteriaValue[]=%s is not accepted', gettype($criteriaValue)));
417 // Add it with generic method
418 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('BASE-CRITERIA: Invoking this->addCriteria(%s,criteriaValue[]=%s,%s) ...', $criteriaKey, gettype($criteriaValue), Criteria::CRITERIA_TYPE_EXCLUDE));
419 $this->addCriteria($criteriaKey, $criteriaValue, Criteria::CRITERIA_TYPE_EXCLUDE);
422 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage('BASE-CRITERIA: EXIT!');
426 * Add configured criteria
428 * @param $criteriaKey Criteria key
429 * @param $configEntry Configuration entry
430 * @param $criteriaType Type of this criteria, can be one of 'default' (default), 'choice' or 'exclude'
432 * @throws InvalidArgumentException If a parameter is not valid
433 * @throws UnexpectedValueException If a parameter contains an unexpected/unsupported value
435 public final function addConfiguredCriteria (string $criteriaKey, string $configEntry, string $criteriaType = Criteria::CRITERIA_TYPE_DEFAULT) {
437 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('%s-CRITERIA: criteriaKey=%s,configEntry=%s,criteriaType=%s - CALLED!', strtoupper($criteriaType), $criteriaKey, $configEntry, $criteriaType));
438 if (empty($criteriaKey)) {
440 throw new InvalidArgumentException('Parameter "criteriaKey" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
441 } elseif ((strpos($criteriaKey, 'my-') !== false) || (strpos($criteriaKey, 'my_') !== false)) {
443 throw new InvalidArgumentException(sprintf('criteriaKey=%s has illegal prefix "my"', $criteriaKey));
444 } elseif (empty($configEntry)) {
446 throw new InvalidArgumentException('Parameter "configEntry" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
447 } elseif (empty($criteriaType)) {
449 throw new InvalidArgumentException('Parameter "criteriaType" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
450 } elseif (!in_array($criteriaType, self::$CRITERIA_TYPES)) {
452 throw new UnexpectedValueException(sprintf('criteriaType=%s is not supported', $criteriaType));
455 // Add the configuration entry as a criteria
456 $value = FrameworkBootstrap::getConfigurationInstance()->getConfigEntry($configEntry);
458 // Invoke inner method
459 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('%s-CRITERIA: Invoking this->addCriteria(%s,value[%s]=%s,%s) ...', strtoupper($criteriaType), $criteriaKey, gettype($value), $value, $criteriaType));
460 $this->addCriteria($criteriaKey, $value, $criteriaType);
463 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('%s-CRITERIA: EXIT!', strtoupper($criteriaType)));
467 * Get criteria element or false if not found
469 * @param $criteriaKey The requested criteria key
470 * @param $criteriaType Type of this criteria, can be one of 'default' (default), 'choice' or 'exclude'
471 * @return $value Whether the value of the critera or false
472 * @throws InvalidArgumentException If a parameter is not valid
473 * @throws UnexpectedValueException If a parameter contains an unexpected/unsupported value
475 public function getCriteriaElemnent (string $criteriaKey, string $criteriaType = Criteria::CRITERIA_TYPE_DEFAULT) {
477 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('%s-CRITERIA: criteriaKey=%s,criteriaType=%s - CALLED!', strtoupper($criteriaType), $criteriaKey, $criteriaType));
478 if (empty($criteriaKey)) {
480 throw new InvalidArgumentException('Parameter "criteriaKey" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
481 } elseif ((strpos($criteriaKey, 'my-') !== false) || (strpos($criteriaKey, 'my_') !== false)) {
483 throw new InvalidArgumentException(sprintf('criteriaKey=%s has illegal prefix "my"', $criteriaKey));
484 } elseif (empty($criteriaType)) {
486 throw new InvalidArgumentException('Parameter "criteriaType" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
487 } elseif (!in_array($criteriaType, self::$CRITERIA_TYPES)) {
489 throw new UnexpectedValueException(sprintf('criteriaType=%s is not supported', $criteriaType));
492 // Convert dashes to underscore
493 $criteriaKey = StringUtils::convertDashesToUnderscores($criteriaKey);
495 // Default is not found
498 // Is the criteria there?
499 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugMessage(sprintf('%s-CRITERIA: criteriaKey=%s,criteria()=%d', strtoupper($criteriaType), $criteriaKey, $this->countGenericArrayGroup('criteria', $criteriaType)));
500 if ($this->isKeySet($criteriaType, $criteriaKey)) {
502 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('%s-CRITERIA: Invoking this->getGenericArrayElement(criteria,%s,entries,%s) ...', strtoupper($criteriaType), $criteriaType, $criteriaKey));
503 $value = $this->getGenericArrayElement('criteria', $criteriaType, 'entries', $criteriaKey);
507 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('%s-CRITERIA: value[]=%s - EXIT!', strtoupper($criteriaType), gettype($value)));
512 * Get criteria element or false if not found for 'choice' type
514 * @param $criteriaKey The requested criteria key
515 * @return $value Whether the value of the critera or false
516 * @throws InvalidArgumentException If a parameter is not valid
518 public function getCriteriaChoiceElemnent (string $criteriaKey) {
520 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('BASE-CRITERIA: criteriaKey=%s - CALLED!', $criteriaKey));
521 if (empty($criteriaKey)) {
523 throw new InvalidArgumentException('Parameter "criteriaKey" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
524 } elseif ((strpos($criteriaKey, 'my-') !== false) || (strpos($criteriaKey, 'my_') !== false)) {
526 throw new InvalidArgumentException(sprintf('criteriaKey=%s has illegal prefix "my"', $criteriaKey));
529 // Invoke inner method
530 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('BASE-CRITERIA: Invoking this->getCriteriaElemnent(%s,%s) ...', $criteriaKey, Criteria::CRITERIA_TYPE_CHOICE));
531 return $this->getCriteriaElemnent($criteriaKey, Criteria::CRITERIA_TYPE_CHOICE);
535 * Get criteria element or false if not found for 'exclude' type
537 * @param $criteriaKey The requested criteria key
538 * @return $value Whether the value of the critera or false
539 * @throws InvalidArgumentException If a parameter is not valid
541 public function getCriteriaExcludeElemnent (string $criteriaKey) {
543 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('BASE-CRITERIA: criteriaKey=%s - CALLED!', $criteriaKey));
544 if (empty($criteriaKey)) {
546 throw new InvalidArgumentException('Parameter "criteriaKey" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
547 } elseif ((strpos($criteriaKey, 'my-') !== false) || (strpos($criteriaKey, 'my_') !== false)) {
549 throw new InvalidArgumentException(sprintf('criteriaKey=%s has illegal prefix "my"', $criteriaKey));
552 // Invoke inner method
553 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('BASE-CRITERIA: Invoking this->getCriteriaElemnent(%s,%s) ...', $criteriaKey, Criteria::CRITERIA_TYPE_EXCLUDE));
554 return $this->getCriteriaElemnent($criteriaKey, Criteria::CRITERIA_TYPE_EXCLUDE);
558 * Checks whether given array entry matches
560 * @param $entryArray Array with the entries to find
561 * @param $criteriaType Type of this criteria, can be one of 'default' (default), 'choice' or 'exclude'
562 * @return $matches Whether the entry matches or not
563 * @throws InvalidArgumentException If a parameter is not valid
564 * @throws UnexpectedValueException If a parameter contains an unexpected/unsupported value
566 public function ifEntryMatches (array $entryArray, string $criteriaType = Criteria::CRITERIA_TYPE_DEFAULT) {
568 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('%s-CRITERIA: entryArray()=%d,criteriaType=%s - CALLED!', strtoupper($criteriaType), count($entryArray), $criteriaType));
569 if (count($entryArray) == 0) {
571 throw new InvalidArgumentException('entryArray cannot be an empty array');
572 } elseif (empty($criteriaType)) {
574 throw new InvalidArgumentException('Parameter "criteriaType" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
575 } elseif (!in_array($criteriaType, self::$CRITERIA_TYPES)) {
577 throw new UnexpectedValueException(sprintf('criteriaType=%s is not supported', $criteriaType));
580 // First nothing matches and nothing is counted
584 // Walk through all entries
585 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugMessage(sprintf('%s-CRITERIA: Walking over entryArray()=%d ...', strtoupper($criteriaType), count($entryArray)));
586 foreach ($entryArray as $key => $entry) {
587 // Make sure no 'my-' or 'my_' passes this point
588 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugMessage(sprintf('%s-CRITERIA: key=%s,entry[%s]=%s', strtoupper($criteriaType), $key, gettype($entry), $entry));
589 if ((strpos($key, 'my-') !== false) || (strpos($key, 'my_') !== false)) {
591 throw new InvalidArgumentException(sprintf('key=%s has illegal prefix "my"', $key));
594 // Convert dashes to underscore
595 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('%s-CRITERIA: Invoking StringUtils::convertDashesToUnderscores(%s) ...', strtoupper($criteriaType), $key));
596 $key = StringUtils::convertDashesToUnderscores($key);
598 // Then walk through all search criteria
599 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugMessage(sprintf('%s-CRITERIA: key=%s - AFTER!', strtoupper($criteriaType), $key));
600 foreach ($this->getGenericArrayKey('criteria', $criteriaType, 'entries') as $criteriaKey => $criteriaValue) {
601 // Make sure no 'my-' or 'my_' passes this point
602 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugMessage(sprintf('%s-CRITERIA: criteriaKey=%s,criteriaValue[%s]=%s', strtoupper($criteriaType), $criteriaKey, gettype($criteriaValue), $criteriaValue));
603 if ((strpos($criteriaKey, 'my-') !== false) || (strpos($criteriaKey, 'my_') !== false)) {
605 throw new UnexpectedValueException(sprintf('criteriaKey=%s has illegal prefix "my"', $criteriaKey));
608 // Convert dashes to underscore
609 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('%s-CRITERIA: Invoking StringUtils::convertDashesToUnderscores(%s) ...', strtoupper($criteriaType), $criteriaKey));
610 $criteriaKey = StringUtils::convertDashesToUnderscores($criteriaKey);
612 // Is the element found and does it match?
613 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugMessage(sprintf('%s-CRITERIA: key=%s,criteriaKey=%s', strtoupper($criteriaType), $key, $criteriaKey));
614 if (($key == $criteriaKey) && ($criteriaValue == $entry)) {
615 // Then count this one up
616 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugMessage(sprintf('%s-CRITERIA: MATCHES!', strtoupper($criteriaType)));
622 // Now check if expected criteria counts match
623 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugMessage(sprintf('%s-CRITERIA: counted=%d', strtoupper($criteriaType), $counted));
624 $matches = ($counted == $this->countGenericArrayGroup('criteria', $criteriaType));
627 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('%s-CRITERIA: matches=%d - EXIT!', strtoupper($criteriaType), intval($matches)));
632 * Checks whether given array 'choice' entry matches
634 * @param $entryArray Array with the entries to find
635 * @return $matches Whether the entry matches or not
636 * @throws InvalidArgumentException If a parameter is not valid
638 public function ifChoiceMatches (array $entryArray) {
640 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('BASE-CRITERIA: entryArray()=%d - CALLED!', count($entryArray)));
641 if (count($entryArray) == 0) {
643 throw new InvalidArgumentException('entryArray cannot be an empty array');
646 // Invoke inner method
647 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('BASE-CRITERIA: Invoking this->ifEntryMatches(%d,%s) ...', count($entryArray), Criteria::CRITERIA_TYPE_CHOICE));
648 return $this->ifEntryMatches($entryArray, Criteria::CRITERIA_TYPE_CHOICE);
652 * Checks whether given array 'exclude' entry matches
654 * @param $entryArray Array with the entries to find
655 * @return $matches Whether the entry matches or not
656 * @throws InvalidArgumentException If a parameter is not valid
658 public function ifExcludeMatches (array $entryArray) {
660 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('BASE-CRITERIA: entryArray()=%d - CALLED!', count($entryArray)));
661 if (count($entryArray) == 0) {
663 throw new InvalidArgumentException('entryArray cannot be an empty array');
666 // Invoke inner method
667 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('BASE-CRITERIA: Invoking this->ifEntryMatches(%d,%s) ...', count($entryArray), Criteria::CRITERIA_TYPE_EXCLUDE));
668 return $this->ifEntryMatches($entryArray, Criteria::CRITERIA_TYPE_EXCLUDE);
672 * "Getter" for a cache key
674 * @param $onlyKeys Only use these keys for a cache key
675 * @param $criteriaType Type of this criteria, can be one of 'default' (default), 'choice' or 'exclude'
676 * @return $cacheKey The key suitable for the cache system
677 * @throws InvalidArgumentException If a parameter is not valid
678 * @throws UnexpectedValueException If a parameter contains an unexpected/unsupported value
679 * @throws BadMethodCallException If this method is invoked before $criteriaType has been initialized
681 public function getCacheKey (array $onlyKeys = [], string $criteriaType = Criteria::CRITERIA_TYPE_DEFAULT) {
683 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('%s-CRITERIA: onlyKeys()=%d,criteriaType=%s - CALLED!', strtoupper($criteriaType), count($onlyKeys), $criteriaType));
684 if (empty($criteriaType)) {
686 throw new InvalidArgumentException('Parameter "criteriaType" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
687 } elseif (!in_array($criteriaType, self::$CRITERIA_TYPES)) {
689 throw new UnexpectedValueException(sprintf('criteriaType=%s is not supported', $criteriaType));
690 } elseif (!$this->isValidGenericArrayGroup('criteria', $criteriaType)) {
691 // Not intialized yet
692 throw new BadMethodCallException(sprintf('Method cannot be invoked before criteriaType=%s is initialized!', $criteriaType), FrameworkInterface::EXCEPTION_BAD_METHOD_CALL);
695 // Initialize the key
698 // Now walk through all criterias
699 foreach ($this->getGenericArrayKey('criteria', $criteriaType, 'entries') as $criteriaKey => $criteriaValue) {
700 // Make sure no 'my-' or 'my_' passes this point
701 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugMessage(sprintf('%s-CRITERIA: criteriaKey=%s,criteriaValue[%s]=%s', strtoupper($criteriaType), $criteriaKey, gettype($criteriaValue), $criteriaValue));
702 if ((strpos($criteriaKey, 'my-') !== false) || (strpos($criteriaKey, 'my_') !== false)) {
704 throw new UnexpectedValueException(sprintf('criteriaKey=%s has illegal prefix "my"', $criteriaKey));
705 } elseif (is_array($criteriaValue) || is_bool($criteriaValue) || is_object($criteriaValue) || is_resource($criteriaValue)) {
707 throw new UnexpectedValueException(sprintf('criteriaValue[]=%s is not supported', gettype($criteriaValue)));
710 // Convert dashes to underscore
711 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('%s-CRITERIA: Invoking StringUtils::convertDashesToUnderscores(%s) ...', strtoupper($criteriaType), $criteriaKey));
712 $criteriaKey = StringUtils::convertDashesToUnderscores($criteriaKey);
714 // Is the value in array or is $onlyKeys empty?
715 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugMessage(sprintf('%s-CRITERIA: criteriaKey=%s', strtoupper($criteriaType), $criteriaKey));
716 if ((isset($onlyKeys[$criteriaKey])) || (count($onlyKeys) == 0)) {
717 // Add the value URL encoded to avoid any trouble with special characters
718 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugMessage(sprintf('%s-CRITERIA: Adding criteriaKey=%s,criteriaValue[%s]=%s to cache key ...', strtoupper($criteriaType), $criteriaKey, gettype($criteriaValue), $criteriaValue));
719 $cacheKey .= sprintf('%s=%s;',
721 urlencode($criteriaValue)
726 // Remove last semicolon
727 $cacheKey = substr($cacheKey, 0, -1);
729 // Is the instance SearchCriteria?
730 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugMessage(sprintf('%s-CRITERIA: cacheKey=%s,this=%s', strtoupper($criteriaType), $cacheKey, $this->__toString()));
731 if ($this instanceof SearchCriteria) {
732 // Check if 'limit' and 'skip' are in
733 if (((isset($onlyKeys['limit'])) && (isset($onlyKeys['skip']))) || (count($onlyKeys) == 0)) {
734 // Add limit and skip values
735 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugMessage(sprintf('%s-CRITERIA: Adding this->limit=%d,this->skip=%d to cache key ...', strtoupper($criteriaType), $this->getLimit(), $this->getSkip()));
736 $cacheKey .= sprintf(';%%limit%%=%s;%%skip%%=%s',
743 // Return the cache key
744 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('%s-CRITERIA: cacheKey=%s - EXIT!', strtoupper($criteriaType), $cacheKey));
749 * "Getter" for a cache key ('choice' type)
751 * @param $onlyKeys Only use these keys for a cache key
752 * @return $cacheKey The key suitable for the cache system
754 public function getCacheKeyChoice (array $onlyKeys = []) {
756 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('BASE-CRITERIA: onlyKeys()=%d - CALLED!', count($onlyKeys)));
758 // Invoke inner method
759 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('BASE-CRITERIA: Invoking this->getCacheKey(onlyKeys()=%d,%s) ...', count($onlyKeys),Criteria::CRITERIA_TYPE_CHOICE));
760 return $this->getCacheKey($onlyKeys, Criteria::CRITERIA_TYPE_CHOICE);
764 * "Getter" for a cache key ('exclude' type)
766 * @param $onlyKeys Only use these keys for a cache key
767 * @return $cacheKey The key suitable for the cache system
769 public function getCacheKeyExclude (array $onlyKeys = []) {
771 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('BASE-CRITERIA: onlyKeys()=%d - CALLED!', count($onlyKeys)));
773 // Invoke inner method
774 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('BASE-CRITERIA: Invoking this->getCacheKey(onlyKeys()=%d,%s) ...', count($onlyKeys),Criteria::CRITERIA_TYPE_EXCLUDE));
775 return $this->getCacheKey($onlyKeys, Criteria::CRITERIA_TYPE_EXCLUDE);
779 * Count 'choice' criteria, e.g. useful to find out if a database query
780 * has no limitation (search criteria).
782 * @return $count Count of all criteria entries
784 public final function countChoice () {
786 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage('BASE-CRITERIA: CALLED!');
787 return $this->count(Criteria::CRITERIA_TYPE_CHOICE);
791 * Count 'exclude' criteria, e.g. useful to find out if a database query
792 * has no limitation (search criteria).
794 * @return $count Count of all criteria entries
796 public final function countExclude () {
798 //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage('BASE-CRITERIA: CALLED!');
799 return $this->count(Criteria::CRITERIA_TYPE_EXCLUDE);