* @version 0.0.0 * @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2023 Core Developer Team * @license GNU GPL 3.0 or any newer version * @link http://www.shipsimu.org * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ abstract class BaseCriteria extends BaseFrameworkSystem implements Criteria { /** * Frontend class name stored in config entry */ private $frontendConfigEntry = ''; /** * All supported criteria types */ private static $CRITERIA_TYPES = []; /** * Protected constructor * * @param $className Name of the class * @return void */ protected function __construct (string $className) { // Call parent constructor //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('BASE-CRITERIA: className=%s - CONSTRUCTED!', $className)); parent::__construct($className); // Initialize valid criteria types array self::$CRITERIA_TYPES = [Criteria::CRITERIA_TYPE_DEFAULT, Criteria::CRITERIA_TYPE_CHOICE, Criteria::CRITERIA_TYPE_EXCLUDE]; // Initialize all criteria arrays //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugMessage(sprintf('BASE-CRITERIA: self::CRITERIA_TYPES()=%d', count(self::$CRITERIA_TYPES))); foreach (self::$CRITERIA_TYPES as $criteriaType) { // Init it //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('BASE-CRITERIA: Invoking this->initGenericArrayKey(criteria,%s,entries) ...', $criteriaType)); $this->initGenericArrayKey('criteria', $criteriaType, 'entries'); } // Trace message //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage('BASE-CRITERIA: EXIT!'); } /** * Count the criteria, e.g. useful to find out if a database query has no * limitation (search criteria). * * @param $criteriaType Type of this criteria, can be one of 'default' (default), 'choice' or 'exclude' * @return $count Count of all criteria entries * @throws InvalidArgumentException If a parameter is not valid */ protected final function count (string $criteriaType = Criteria::CRITERIA_TYPE_DEFAULT) { // Check parameter //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('%s-CRITERIA: criteriaType=%s - CALLED!', strtoupper($criteriaType), $criteriaType)); if (empty($criteriaType)) { // Throw it again throw new InvalidArgumentException('Parameter "criteriaType" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT); } elseif (!in_array($criteriaType, self::$CRITERIA_TYPES)) { // Throw it again throw new InvalidArgumentException(sprintf('criteriaType=%s is not supported', $criteriaType)); } // Invoke inner method //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('%s-CRITERIA: Invoking this->countGenericArrayGroup(criteria, %s) ... - EXIT!', strtoupper($criteriaType), $criteriaType)); return $this->countGenericArrayGroup('criteria', $criteriaType); } /** * Checks whether given key is set * * @param $criteriaType Type of this criteria, can be one of 'default' (default), 'choice' or 'exclude' * @param $criteriaKey Criteria key * @return $isset Whether key is set * @throws InvalidArgumentException If a parameter is not valid * @throws UnexpectedValueException If a parameter contains an unexpected/unsupported value */ public function isKeySet (string $criteriaType, string $criteriaKey) { // Check parameters //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('%s-CRITERIA: criteriaType=%s,criteriaKey=%s - CALLED!', strtoupper($criteriaType), $criteriaType, $criteriaKey)); if (empty($criteriaType)) { // Throw it again throw new InvalidArgumentException('Parameter "criteriaType" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT); } elseif (!in_array($criteriaType, self::$CRITERIA_TYPES)) { // Throw it again throw new UnexpectedValueException(sprintf('criteriaType=%s is not supported', $criteriaType), FrameworkInterface::EXCEPTION_UNEXPECTED_VALUE); } elseif (empty($criteriaKey)) { // Throw it again throw new InvalidArgumentException('Parameter "criteriaKey" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT); } elseif ((strpos($criteriaKey, 'my-') !== false) || (strpos($criteriaKey, 'my_') !== false)) { // Throw it again throw new InvalidArgumentException(sprintf('criteriaKey=%s has illegal prefix "my"', $criteriaKey)); } // Determine it //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugMessage(sprintf('%s-CRITERIA: Invoking this->isGenericArrayElementSet(criteria,%s,entries,%s) ...', strtoupper($criteriaType), $criteriaType, $criteriaKey)); $isset = $this->isGenericArrayElementSet('criteria', $criteriaType, 'entries', $criteriaKey); // Return it //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('%s-CRITERIA: isset=%d - EXIT!', strtoupper($criteriaType), intval($isset))); return $isset; } /** * Checks whether given key is set for 'choice' type * * @param $criteriaKey Criteria key * @return $isset Whether key is set * @throws InvalidArgumentException If a parameter is not valid */ public function isChoiceKeySet (string $criteriaKey) { // Validate parameter //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('BASE-CRITERIA: criteriaKey=%s - CALLED!', $criteriaKey)); if (empty($criteriaKey)) { // Throw it again throw new InvalidArgumentException('Parameter "criteriaKey" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT); } // Invoke inner method //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('BASE-CRITERIA: Invoking this->isKeySet(%s,%s) ...', Criteria::CRITERIA_TYPE_CHOICE, $criteriaKey)); return $this->isKeySet(Criteria::CRITERIA_TYPE_CHOICE, $criteriaKey); } /** * Checks whether given key is set for 'exclude' type * * @param $criteriaKey Criteria key * @return $isset Whether key is set * @throws InvalidArgumentException If a parameter is not valid */ public function isExcludeKeySet (string $criteriaKey) { // Validate parameter //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('BASE-CRITERIA: criteriaKey=%s - CALLED!', $criteriaKey)); if (empty($criteriaKey)) { // Throw it again throw new InvalidArgumentException('Parameter "criteriaKey" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT); } // Invoke inner method //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('BASE-CRITERIA: Invoking this->isKeySet(%s,%s) ... - EXIT!', Criteria::CRITERIA_TYPE_EXCLUDE, $criteriaKey)); return $this->isKeySet(Criteria::CRITERIA_TYPE_EXCLUDE, $criteriaKey); } /** * Setter for frontend class name * * @param $frontendConfigEntry Configuration entry which hold the frontend class' name * @return void */ public final function setFrontendConfigEntry (string $frontendConfigEntry) { $this->frontendConfigEntry = $frontendConfigEntry; } /** * Getter for frontend class name * * @return $frontendConfigEntry Configuration entry which hold the frontend class' name */ public final function getFrontendConfigEntry () { return $this->frontendConfigEntry; } /** * Getter for criteria array * * @param $criteriaType Type of this criteria, can be one of 'default' (default), 'choice' or 'exclude' * @return $criteria * @throws InvalidArgumentException If a parameter is not valid * @throws UnexpectedValueException If a parameter contains an unexpected/unsupported value */ public final function getCriteriaArray (string $criteriaType = Criteria::CRITERIA_TYPE_DEFAULT) { // Check parameters //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('%s-CRITERIA: criteriaType=%s - CALLED!', strtoupper($criteriaType), $criteriaType)); if (empty($criteriaType)) { // Throw it again throw new InvalidArgumentException('Parameter "criteriaType" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT); } elseif (!in_array($criteriaType, self::$CRITERIA_TYPES)) { // Throw it again throw new UnexpectedValueException(sprintf('criteriaType=%s is not supported', $criteriaType), FrameworkInterface::EXCEPTION_UNEXPECTED_VALUE); } // Invoke inner method //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('%s-CRITERIA: Invoking this->getGenericArrayKey(criteria,%s,entries) ... - EXIT!', strtoupper($criteriaType), $criteriaType)); return $this->getGenericArrayKey('criteria', $criteriaType, 'entries'); } /** * Getter for criteria array 'choice' type * * @return $criteria */ public final function getCriteriaChoiceArray () { //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('%s-CRITERIA: CALLED!', strtoupper($criteriaType))); return $this->getCriteriaArray(Criteria::CRITERIA_TYPE_CHOICE); } /** * Getter for criteria array 'exclude' type * * @return $criteria */ public final function getCriteriaExcludeArray () { //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage('BASE-CRITERIA: CALLED!'); return $this->getCriteriaArray(Criteria::CRITERIA_TYPE_EXCLUDE); } /** * Unsets a criteria key from all criteria types * * @param $criteriaKey Criteria key to unset * @return void */ public final function unsetCriteria (string $criteriaKey) { // Check parameter //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('BASE-CRITERIA: criteriaKey=%s - CALLED!', $criteriaKey)); if (empty($criteriaKey)) { // Throw it again throw new InvalidArgumentException('Parameter "criteriaKey" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT); } elseif ((strpos($criteriaKey, 'my-') !== false) || (strpos($criteriaKey, 'my_') !== false)) { // Throw it again throw new InvalidArgumentException(sprintf('criteriaKey=%s has illegal prefix "my"', $criteriaKey)); } // Convert dashes to underscore //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('%s-CRITERIA: Invoking StringUtils::convertDashesToUnderscores(%s) ...', strtoupper($criteriaType), $criteriaKey)); $criteriaKey = StringUtils::convertDashesToUnderscores($criteriaKey); // "Walk" through all criterias //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugMessage(sprintf('%s-CRITERIA: criteriaKey=%s', strtoupper($criteriaType), $criteriaKey)); foreach ($this->getGenericArray('criteria') as $criteriaType => $dummy) { // Remove it //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('%s-CRITERIA: Removing criteriaType=%s,criteriaKey=%s ...', strtoupper($criteriaType), $criteriaType, $criteriaKey)); $this->unsetGenericArrayElement('criteria', $criteriaType, 'entries', $criteriaKey); } // Trace message //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage('BASE-CRITERIA: EXIT!'); } /** * Add criteria, this method converts dashes to underscores because dashes * are not valid for criteria keys. * * @param $criteriaKey Criteria key * @param $criteriaValue Criteria value * @param $criteriaType Type of this criteria, can be one of 'default' (default), 'choice' or 'exclude' * @return void * @throws InvalidArgumentException If a parameter is not valid * @throws UnexpectedValueException If a parameter contains an unexpected/unsupported value */ public final function addCriteria (string $criteriaKey, $criteriaValue, string $criteriaType = Criteria::CRITERIA_TYPE_DEFAULT) { // Check parameter //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('%s-CRITERIA: criteriaKey=%s,criteriaValue[]=%s,criteriaType=%s - CALLED!', strtoupper($criteriaType), $criteriaKey, gettype($criteriaValue), $criteriaType)); if (empty($criteriaKey)) { // Throw IAE throw new InvalidArgumentException('Parameter "criteriaKey" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT); } elseif ((strpos($criteriaKey, 'my-') !== false) || (strpos($criteriaKey, 'my_') !== false)) { // Throw it again throw new InvalidArgumentException(sprintf('criteriaKey=%s has illegal prefix "my"', $criteriaKey)); } elseif (is_array($criteriaValue) || is_bool($criteriaValue) || is_object($criteriaValue) || is_resource($criteriaValue)) { // Throw it again throw new InvalidArgumentException(sprintf('value[]=%s is not supported', gettype($criteriaValue))); } elseif (empty($criteriaType)) { // Throw it again throw new InvalidArgumentException('Parameter "criteriaType" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT); } elseif (!in_array($criteriaType, self::$CRITERIA_TYPES)) { // Throw it again throw new UnexpectedValueException(sprintf('criteriaType=%s is not supported', $criteriaType), FrameworkInterface::EXCEPTION_UNEXPECTED_VALUE); } // Convert dashes to underscore //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('%s-CRITERIA: Invoking StringUtils::convertDashesToUnderscores(%s) ...', strtoupper($criteriaType), $criteriaKey)); $criteriaKey = StringUtils::convertDashesToUnderscores($criteriaKey); // Set it //* 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))); $this->setGenericArrayElement('criteria', $criteriaType, 'entries', $criteriaKey, $criteriaValue); // Trace message //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('%s-CRITERIA: EXIT!', strtoupper($criteriaType))); } /** * Set criteria, this method converts dashes to underscores because dashes * are not valid for criteria keys. * * @param $criteriaKey Criteria key * @param $criteriaValue Criteria value * @param $criteriaType Type of this criteria, can be one of 'default' (default), 'choice' or 'exclude' * @return void * @throws InvalidArgumentException If a parameter is not valid * @throws UnexpectedValueException If a parameter contains an unexpected/unsupported value */ public final function setCriteria (string $criteriaKey, $criteriaValue, string $criteriaType = Criteria::CRITERIA_TYPE_DEFAULT) { // Check parameter //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('%s-CRITERIA: criteriaKey=%s,criteriaValue[]=%s$criteriaValue,criteriaType=%s - CALLED!', strtoupper($criteriaType), $criteriaKey, gettype($criteriaValue), $criteriaType)); if (empty($criteriaKey)) { // Throw IAE throw new InvalidArgumentException('Parameter "criteriaKey" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT); } elseif ((strpos($criteriaKey, 'my-') !== false) || (strpos($criteriaKey, 'my_') !== false)) { // Throw it again throw new InvalidArgumentException(sprintf('criteriaKey=%s has illegal prefix "my"', $criteriaKey)); } elseif (is_array($criteriaValue) || is_bool($criteriaValue) || is_object($criteriaValue) || is_resource($criteriaValue)) { // Throw it again throw new InvalidArgumentException(sprintf('value[]=%s is not supported', gettype($criteriaValue))); } elseif (empty($criteriaType)) { // Throw it again throw new InvalidArgumentException('Parameter "criteriaType" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT); } elseif (!in_array($criteriaType, self::$CRITERIA_TYPES)) { // Throw it again throw new UnexpectedValueException(sprintf('criteriaType=%s is not supported', $criteriaType), FrameworkInterface::EXCEPTION_UNEXPECTED_VALUE); } // Convert dashes to underscore //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('%s-CRITERIA: Invoking StringUtils::convertDashesToUnderscores(%s) ...', strtoupper($criteriaType), $criteriaKey)); $criteriaKey = StringUtils::convertDashesToUnderscores($criteriaKey); // Set it //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('%s-CRITERIA: Invoking this->setGenericArrayElement(criteria,%s,entries,%s,criteriaValue[]=%s) ...', strtoupper($criteriaType), $criteriaKey, gettype($criteriaValue))); $this->setGenericArrayElement('criteria', $criteriaType, 'entries', $criteriaKey, $criteriaValue); // Trace message //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage('BASE-CRITERIA: EXIT!'); } /** * Add "choice" criteria, this method converts dashes to underscores because * dashes are not valid for criteria keys. * * @param $criteriaKey Criteria key * @param $criteriaValue Criteria value * @return void * @throws InvalidArgumentException If a parameter is not valid * @throws UnexpectedValueException If $criteriaValue has an unexpected type */ public final function addChoiceCriteria (string $criteriaKey, $criteriaValue) { // Check parameter //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('BASE-CRITERIA: criteriaKey=%s,criteriaValue[]=%s - CALLED!', $criteriaKey, gettype($criteriaValue))); if (empty($criteriaKey)) { // Throw IAE throw new InvalidArgumentException('Parameter "criteriaKey" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT); } elseif ((strpos($criteriaKey, 'my-') !== false) || (strpos($criteriaKey, 'my_') !== false)) { // Throw it again throw new InvalidArgumentException(sprintf('criteriaKey=%s has illegal prefix "my"', $criteriaKey)); } elseif (is_array($criteriaValue) || is_bool($criteriaValue) || is_object($criteriaValue) || is_resource($criteriaValue)) { // Throw UAE throw new UnexpectedValueException(sprintf('criteriaValue[]=%s is not accepted', gettype($criteriaValue)), FrameworkInterface::EXCEPTION_UNEXPECTED_VALUE); } // Convert dashes to underscore //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('BASE-CRITERIA: Invoking StringUtils::convertDashesToUnderscores(%s) ...', $criteriaKey)); $criteriaKey = StringUtils::convertDashesToUnderscores($criteriaKey); // Add it //* 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))); $this->pushValueToGenericArrayElement('criteria', Criteria::CRITERIA_TYPE_CHOICE, 'entries', $criteriaKey, $criteriaValue); // Trace message //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage('BASE-CRITERIA: EXIT!'); } /** * Add "exclude" criteria, this method converts dashes to underscores because * dashes are not valid for criteria keys. * * @param $criteriaKey Criteria key * @param $criteriaValue Criteria value * @return void * @throws InvalidArgumentException If a parameter is not valid * @throws UnexpectedValueException If $criteriaValue has an unexpected type */ public final function addExcludeCriteria (string $criteriaKey, $criteriaValue) { // Check parameter //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('BASE-CRITERIA: criteriaKey=%s,criteriaValue[%s]=%s - CALLED!', $criteriaKey, gettype($criteriaValue), $criteriaValue)); if (empty($criteriaKey)) { // Throw IAE throw new InvalidArgumentException('Parameter "criteriaKey" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT); } elseif ((strpos($criteriaKey, 'my-') !== false) || (strpos($criteriaKey, 'my_') !== false)) { // Throw it again throw new InvalidArgumentException(sprintf('criteriaKey=%s has illegal prefix "my"', $criteriaKey)); } elseif (is_array($criteriaValue) || is_bool($criteriaValue) || is_object($criteriaValue) || is_resource($criteriaValue)) { // Throw UAE throw new UnexpectedValueException(sprintf('criteriaValue[]=%s is not accepted', gettype($criteriaValue)), FrameworkInterface::EXCEPTION_UNEXPECTED_VALUE); } // Add it with generic method //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('BASE-CRITERIA: Invoking this->addCriteria(%s,criteriaValue[]=%s,%s) ...', $criteriaKey, gettype($criteriaValue), Criteria::CRITERIA_TYPE_EXCLUDE)); $this->addCriteria($criteriaKey, $criteriaValue, Criteria::CRITERIA_TYPE_EXCLUDE); // Trace message //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage('BASE-CRITERIA: EXIT!'); } /** * Add configured criteria * * @param $criteriaKey Criteria key * @param $configEntry Configuration entry * @param $criteriaType Type of this criteria, can be one of 'default' (default), 'choice' or 'exclude' * @return void * @throws InvalidArgumentException If a parameter is not valid * @throws UnexpectedValueException If a parameter contains an unexpected/unsupported value */ public final function addConfiguredCriteria (string $criteriaKey, string $configEntry, string $criteriaType = Criteria::CRITERIA_TYPE_DEFAULT) { // Check parameter //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('%s-CRITERIA: criteriaKey=%s,configEntry=%s,criteriaType=%s - CALLED!', strtoupper($criteriaType), $criteriaKey, $configEntry, $criteriaType)); if (empty($criteriaKey)) { // Throw IAE throw new InvalidArgumentException('Parameter "criteriaKey" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT); } elseif ((strpos($criteriaKey, 'my-') !== false) || (strpos($criteriaKey, 'my_') !== false)) { // Throw it again throw new InvalidArgumentException(sprintf('criteriaKey=%s has illegal prefix "my"', $criteriaKey)); } elseif (empty($configEntry)) { // Throw it again throw new InvalidArgumentException('Parameter "configEntry" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT); } elseif (empty($criteriaType)) { // Throw it again throw new InvalidArgumentException('Parameter "criteriaType" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT); } elseif (!in_array($criteriaType, self::$CRITERIA_TYPES)) { // Throw it again throw new UnexpectedValueException(sprintf('criteriaType=%s is not supported', $criteriaType), FrameworkInterface::EXCEPTION_UNEXPECTED_VALUE); } // Add the configuration entry as a criteria $value = FrameworkBootstrap::getConfigurationInstance()->getConfigEntry($configEntry); // Invoke inner method //* 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)); $this->addCriteria($criteriaKey, $value, $criteriaType); // Trace message //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('%s-CRITERIA: EXIT!', strtoupper($criteriaType))); } /** * Get criteria element or false if not found * * @param $criteriaKey The requested criteria key * @param $criteriaType Type of this criteria, can be one of 'default' (default), 'choice' or 'exclude' * @return $value Whether the value of the critera or false * @throws InvalidArgumentException If a parameter is not valid * @throws UnexpectedValueException If a parameter contains an unexpected/unsupported value */ public function getCriteriaElemnent (string $criteriaKey, string $criteriaType = Criteria::CRITERIA_TYPE_DEFAULT) { // Check parameter //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('%s-CRITERIA: criteriaKey=%s,criteriaType=%s - CALLED!', strtoupper($criteriaType), $criteriaKey, $criteriaType)); if (empty($criteriaKey)) { // Throw IAE throw new InvalidArgumentException('Parameter "criteriaKey" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT); } elseif ((strpos($criteriaKey, 'my-') !== false) || (strpos($criteriaKey, 'my_') !== false)) { // Throw it again throw new InvalidArgumentException(sprintf('criteriaKey=%s has illegal prefix "my"', $criteriaKey)); } elseif (empty($criteriaType)) { // Throw it again throw new InvalidArgumentException('Parameter "criteriaType" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT); } elseif (!in_array($criteriaType, self::$CRITERIA_TYPES)) { // Throw it again throw new UnexpectedValueException(sprintf('criteriaType=%s is not supported', $criteriaType), FrameworkInterface::EXCEPTION_UNEXPECTED_VALUE); } // Convert dashes to underscore $criteriaKey = StringUtils::convertDashesToUnderscores($criteriaKey); // Default is not found $value = false; // Is the criteria there? //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugMessage(sprintf('%s-CRITERIA: criteriaKey=%s,criteria()=%d', strtoupper($criteriaType), $criteriaKey, $this->countGenericArrayGroup('criteria', $criteriaType))); if ($this->isKeySet($criteriaType, $criteriaKey)) { // Then use it //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('%s-CRITERIA: Invoking this->getGenericArrayElement(criteria,%s,entries,%s) ...', strtoupper($criteriaType), $criteriaType, $criteriaKey)); $value = $this->getGenericArrayElement('criteria', $criteriaType, 'entries', $criteriaKey); } // Return the value //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('%s-CRITERIA: value[]=%s - EXIT!', strtoupper($criteriaType), gettype($value))); return $value; } /** * Get criteria element or false if not found for 'choice' type * * @param $criteriaKey The requested criteria key * @return $value Whether the value of the critera or false * @throws InvalidArgumentException If a parameter is not valid */ public function getCriteriaChoiceElemnent (string $criteriaKey) { // Check parameter //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('BASE-CRITERIA: criteriaKey=%s - CALLED!', $criteriaKey)); if (empty($criteriaKey)) { // Throw IAE throw new InvalidArgumentException('Parameter "criteriaKey" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT); } elseif ((strpos($criteriaKey, 'my-') !== false) || (strpos($criteriaKey, 'my_') !== false)) { // Throw it again throw new InvalidArgumentException(sprintf('criteriaKey=%s has illegal prefix "my"', $criteriaKey)); } // Invoke inner method //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('BASE-CRITERIA: Invoking this->getCriteriaElemnent(%s,%s) ...', $criteriaKey, Criteria::CRITERIA_TYPE_CHOICE)); return $this->getCriteriaElemnent($criteriaKey, Criteria::CRITERIA_TYPE_CHOICE); } /** * Get criteria element or false if not found for 'exclude' type * * @param $criteriaKey The requested criteria key * @return $value Whether the value of the critera or false * @throws InvalidArgumentException If a parameter is not valid */ public function getCriteriaExcludeElemnent (string $criteriaKey) { // Check parameter //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('BASE-CRITERIA: criteriaKey=%s - CALLED!', $criteriaKey)); if (empty($criteriaKey)) { // Throw IAE throw new InvalidArgumentException('Parameter "criteriaKey" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT); } elseif ((strpos($criteriaKey, 'my-') !== false) || (strpos($criteriaKey, 'my_') !== false)) { // Throw it again throw new InvalidArgumentException(sprintf('criteriaKey=%s has illegal prefix "my"', $criteriaKey)); } // Invoke inner method //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('BASE-CRITERIA: Invoking this->getCriteriaElemnent(%s,%s) ...', $criteriaKey, Criteria::CRITERIA_TYPE_EXCLUDE)); return $this->getCriteriaElemnent($criteriaKey, Criteria::CRITERIA_TYPE_EXCLUDE); } /** * Checks whether given array entry matches * * @param $entryArray Array with the entries to find * @param $criteriaType Type of this criteria, can be one of 'default' (default), 'choice' or 'exclude' * @return $matches Whether the entry matches or not * @throws InvalidArgumentException If a parameter is not valid * @throws UnexpectedValueException If a parameter contains an unexpected/unsupported value */ public function ifEntryMatches (array $entryArray, string $criteriaType = Criteria::CRITERIA_TYPE_DEFAULT) { // Check parameters //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('%s-CRITERIA: entryArray()=%d,criteriaType=%s - CALLED!', strtoupper($criteriaType), count($entryArray), $criteriaType)); if (count($entryArray) == 0) { // Throw IAE throw new InvalidArgumentException('entryArray cannot be an empty array'); } elseif (empty($criteriaType)) { // Throw it again throw new InvalidArgumentException('Parameter "criteriaType" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT); } elseif (!in_array($criteriaType, self::$CRITERIA_TYPES)) { // Throw it again throw new UnexpectedValueException(sprintf('criteriaType=%s is not supported', $criteriaType), FrameworkInterface::EXCEPTION_UNEXPECTED_VALUE); } // First nothing matches and nothing is counted $matches = false; $counted = 0; // Walk through all entries //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugMessage(sprintf('%s-CRITERIA: Walking over entryArray()=%d ...', strtoupper($criteriaType), count($entryArray))); foreach ($entryArray as $key => $entry) { // Make sure no 'my-' or 'my_' passes this point //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugMessage(sprintf('%s-CRITERIA: key=%s,entry[%s]=%s', strtoupper($criteriaType), $key, gettype($entry), $entry)); if ((strpos($key, 'my-') !== false) || (strpos($key, 'my_') !== false)) { // Throw it again throw new InvalidArgumentException(sprintf('key=%s has illegal prefix "my"', $key)); } // Convert dashes to underscore //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('%s-CRITERIA: Invoking StringUtils::convertDashesToUnderscores(%s) ...', strtoupper($criteriaType), $key)); $key = StringUtils::convertDashesToUnderscores($key); // Then walk through all search criteria //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugMessage(sprintf('%s-CRITERIA: key=%s - AFTER!', strtoupper($criteriaType), $key)); foreach ($this->getGenericArrayKey('criteria', $criteriaType, 'entries') as $criteriaKey => $criteriaValue) { // Make sure no 'my-' or 'my_' passes this point //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugMessage(sprintf('%s-CRITERIA: criteriaKey=%s,criteriaValue[%s]=%s', strtoupper($criteriaType), $criteriaKey, gettype($criteriaValue), $criteriaValue)); if ((strpos($criteriaKey, 'my-') !== false) || (strpos($criteriaKey, 'my_') !== false)) { // Throw it again throw new UnexpectedValueException(sprintf('criteriaKey=%s has illegal prefix "my"', $criteriaKey), FrameworkInterface::EXCEPTION_UNEXPECTED_VALUE); } // Convert dashes to underscore //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('%s-CRITERIA: Invoking StringUtils::convertDashesToUnderscores(%s) ...', strtoupper($criteriaType), $criteriaKey)); $criteriaKey = StringUtils::convertDashesToUnderscores($criteriaKey); // Is the element found and does it match? //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugMessage(sprintf('%s-CRITERIA: key=%s,criteriaKey=%s', strtoupper($criteriaType), $key, $criteriaKey)); if (($key == $criteriaKey) && ($criteriaValue == $entry)) { // Then count this one up //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugMessage(sprintf('%s-CRITERIA: MATCHES!', strtoupper($criteriaType))); $counted++; } } } // Now check if expected criteria counts match //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugMessage(sprintf('%s-CRITERIA: counted=%d', strtoupper($criteriaType), $counted)); $matches = ($counted == $this->countGenericArrayGroup('criteria', $criteriaType)); // Return the result //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('%s-CRITERIA: matches=%d - EXIT!', strtoupper($criteriaType), intval($matches))); return $matches; } /** * Checks whether given array 'choice' entry matches * * @param $entryArray Array with the entries to find * @return $matches Whether the entry matches or not * @throws InvalidArgumentException If a parameter is not valid */ public function ifChoiceMatches (array $entryArray) { // Check parameter //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('BASE-CRITERIA: entryArray()=%d - CALLED!', count($entryArray))); if (count($entryArray) == 0) { // Throw IAE throw new InvalidArgumentException('entryArray cannot be an empty array'); } // Invoke inner method //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('BASE-CRITERIA: Invoking this->ifEntryMatches(%d,%s) ...', count($entryArray), Criteria::CRITERIA_TYPE_CHOICE)); return $this->ifEntryMatches($entryArray, Criteria::CRITERIA_TYPE_CHOICE); } /** * Checks whether given array 'exclude' entry matches * * @param $entryArray Array with the entries to find * @return $matches Whether the entry matches or not * @throws InvalidArgumentException If a parameter is not valid */ public function ifExcludeMatches (array $entryArray) { // Check parameter //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('BASE-CRITERIA: entryArray()=%d - CALLED!', count($entryArray))); if (count($entryArray) == 0) { // Throw IAE throw new InvalidArgumentException('entryArray cannot be an empty array'); } // Invoke inner method //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('BASE-CRITERIA: Invoking this->ifEntryMatches(%d,%s) ...', count($entryArray), Criteria::CRITERIA_TYPE_EXCLUDE)); return $this->ifEntryMatches($entryArray, Criteria::CRITERIA_TYPE_EXCLUDE); } /** * "Getter" for a cache key * * @param $onlyKeys Only use these keys for a cache key * @param $criteriaType Type of this criteria, can be one of 'default' (default), 'choice' or 'exclude' * @return $cacheKey The key suitable for the cache system * @throws InvalidArgumentException If a parameter is not valid * @throws UnexpectedValueException If a parameter contains an unexpected/unsupported value * @throws BadMethodCallException If this method is invoked before $criteriaType has been initialized */ public function getCacheKey (array $onlyKeys = [], string $criteriaType = Criteria::CRITERIA_TYPE_DEFAULT) { // Check parameters //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('%s-CRITERIA: onlyKeys()=%d,criteriaType=%s - CALLED!', strtoupper($criteriaType), count($onlyKeys), $criteriaType)); if (empty($criteriaType)) { // Throw it again throw new InvalidArgumentException('Parameter "criteriaType" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT); } elseif (!in_array($criteriaType, self::$CRITERIA_TYPES)) { // Throw it again throw new UnexpectedValueException(sprintf('criteriaType=%s is not supported', $criteriaType), FrameworkInterface::EXCEPTION_UNEXPECTED_VALUE); } elseif (!$this->isValidGenericArrayGroup('criteria', $criteriaType)) { // Not intialized yet throw new BadMethodCallException(sprintf('Method cannot be invoked before criteriaType=%s is initialized!', $criteriaType), FrameworkInterface::EXCEPTION_BAD_METHOD_CALL); } // Initialize the key $cacheKey = ''; // Now walk through all criterias foreach ($this->getGenericArrayKey('criteria', $criteriaType, 'entries') as $criteriaKey => $criteriaValue) { // Make sure no 'my-' or 'my_' passes this point //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugMessage(sprintf('%s-CRITERIA: criteriaKey=%s,criteriaValue[%s]=%s', strtoupper($criteriaType), $criteriaKey, gettype($criteriaValue), $criteriaValue)); if ((strpos($criteriaKey, 'my-') !== false) || (strpos($criteriaKey, 'my_') !== false)) { // Throw UAE throw new UnexpectedValueException(sprintf('criteriaKey=%s has illegal prefix "my"', $criteriaKey), FrameworkInterface::EXCEPTION_UNEXPECTED_VALUE); } elseif (is_array($criteriaValue) || is_bool($criteriaValue) || is_object($criteriaValue) || is_resource($criteriaValue)) { // Throw it again throw new UnexpectedValueException(sprintf('criteriaValue[]=%s is not supported', gettype($criteriaValue)), FrameworkInterface::EXCEPTION_UNEXPECTED_VALUE); } // Convert dashes to underscore //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('%s-CRITERIA: Invoking StringUtils::convertDashesToUnderscores(%s) ...', strtoupper($criteriaType), $criteriaKey)); $criteriaKey = StringUtils::convertDashesToUnderscores($criteriaKey); // Is the value in array or is $onlyKeys empty? //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugMessage(sprintf('%s-CRITERIA: criteriaKey=%s', strtoupper($criteriaType), $criteriaKey)); if ((isset($onlyKeys[$criteriaKey])) || (count($onlyKeys) == 0)) { // Add the value URL encoded to avoid any trouble with special characters //* 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)); $cacheKey .= sprintf('%s=%s;', $criteriaKey, urlencode($criteriaValue) ); } } // Remove last semicolon $cacheKey = substr($cacheKey, 0, -1); // Is the instance SearchCriteria? //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugMessage(sprintf('%s-CRITERIA: cacheKey=%s,this=%s', strtoupper($criteriaType), $cacheKey, $this->__toString())); if ($this instanceof SearchCriteria) { // Check if 'limit' and 'skip' are in if (((isset($onlyKeys['limit'])) && (isset($onlyKeys['skip']))) || (count($onlyKeys) == 0)) { // Add limit and skip values //* 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())); $cacheKey .= sprintf(';%%limit%%=%s;%%skip%%=%s', $this->getLimit(), $this->getSkip() ); } } // Return the cache key //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('%s-CRITERIA: cacheKey=%s - EXIT!', strtoupper($criteriaType), $cacheKey)); return $cacheKey; } /** * "Getter" for a cache key ('choice' type) * * @param $onlyKeys Only use these keys for a cache key * @return $cacheKey The key suitable for the cache system */ public function getCacheKeyChoice (array $onlyKeys = []) { // Trace message //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('BASE-CRITERIA: onlyKeys()=%d - CALLED!', count($onlyKeys))); // Invoke inner method //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('BASE-CRITERIA: Invoking this->getCacheKey(onlyKeys()=%d,%s) ...', count($onlyKeys),Criteria::CRITERIA_TYPE_CHOICE)); return $this->getCacheKey($onlyKeys, Criteria::CRITERIA_TYPE_CHOICE); } /** * "Getter" for a cache key ('exclude' type) * * @param $onlyKeys Only use these keys for a cache key * @return $cacheKey The key suitable for the cache system */ public function getCacheKeyExclude (array $onlyKeys = []) { // Trace message //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('BASE-CRITERIA: onlyKeys()=%d - CALLED!', count($onlyKeys))); // Invoke inner method //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage(sprintf('BASE-CRITERIA: Invoking this->getCacheKey(onlyKeys()=%d,%s) ...', count($onlyKeys),Criteria::CRITERIA_TYPE_EXCLUDE)); return $this->getCacheKey($onlyKeys, Criteria::CRITERIA_TYPE_EXCLUDE); } /** * Count 'choice' criteria, e.g. useful to find out if a database query * has no limitation (search criteria). * * @return $count Count of all criteria entries */ public final function countChoice () { // Trace message //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage('BASE-CRITERIA: CALLED!'); return $this->count(Criteria::CRITERIA_TYPE_CHOICE); } /** * Count 'exclude' criteria, e.g. useful to find out if a database query * has no limitation (search criteria). * * @return $count Count of all criteria entries */ public final function countExclude () { // Trace message //* NOISY-DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->traceMessage('BASE-CRITERIA: CALLED!'); return $this->count(Criteria::CRITERIA_TYPE_EXCLUDE); } }