*/ protected $_rules = []; /** * The list of rules to check during create operations * * @var array<\Cake\Datasource\RuleInvoker> */ protected $_createRules = []; /** * The list of rules to check during update operations * * @var array<\Cake\Datasource\RuleInvoker> */ protected $_updateRules = []; /** * The list of rules to check during delete operations * * @var array<\Cake\Datasource\RuleInvoker> */ protected $_deleteRules = []; /** * List of options to pass to every callable rule * * @var array */ protected $_options = []; /** * Whether to use I18n functions for translating default error messages * * @var bool */ protected $_useI18n = false; /** * Constructor. Takes the options to be passed to all rules. * * @param array $options The options to pass to every rule */ public function __construct(array $options = []) { $this->_options = $options; $this->_useI18n = function_exists('\Cake\I18n\__d'); } /** * Adds a rule that will be applied to the entity both on create and update * operations. * * ### Options * * The options array accept the following special keys: * * - `errorField`: The name of the entity field that will be marked as invalid * if the rule does not pass. * - `message`: The error message to set to `errorField` if the rule does not pass. * * @param callable $rule A callable function or object that will return whether * the entity is valid or not. * @param array|string|null $name The alias for a rule, or an array of options. * @param array $options List of extra options to pass to the rule callable as * second argument. * @return $this */ public function add(callable $rule, $name = null, array $options = []) { $this->_rules[] = $this->_addError($rule, $name, $options); return $this; } /** * Adds a rule that will be applied to the entity on create operations. * * ### Options * * The options array accept the following special keys: * * - `errorField`: The name of the entity field that will be marked as invalid * if the rule does not pass. * - `message`: The error message to set to `errorField` if the rule does not pass. * * @param callable $rule A callable function or object that will return whether * the entity is valid or not. * @param array|string|null $name The alias for a rule or an array of options. * @param array $options List of extra options to pass to the rule callable as * second argument. * @return $this */ public function addCreate(callable $rule, $name = null, array $options = []) { $this->_createRules[] = $this->_addError($rule, $name, $options); return $this; } /** * Adds a rule that will be applied to the entity on update operations. * * ### Options * * The options array accept the following special keys: * * - `errorField`: The name of the entity field that will be marked as invalid * if the rule does not pass. * - `message`: The error message to set to `errorField` if the rule does not pass. * * @param callable $rule A callable function or object that will return whether * the entity is valid or not. * @param array|string|null $name The alias for a rule, or an array of options. * @param array $options List of extra options to pass to the rule callable as * second argument. * @return $this */ public function addUpdate(callable $rule, $name = null, array $options = []) { $this->_updateRules[] = $this->_addError($rule, $name, $options); return $this; } /** * Adds a rule that will be applied to the entity on delete operations. * * ### Options * * The options array accept the following special keys: * * - `errorField`: The name of the entity field that will be marked as invalid * if the rule does not pass. * - `message`: The error message to set to `errorField` if the rule does not pass. * * @param callable $rule A callable function or object that will return whether * the entity is valid or not. * @param array|string|null $name The alias for a rule, or an array of options. * @param array $options List of extra options to pass to the rule callable as * second argument. * @return $this */ public function addDelete(callable $rule, $name = null, array $options = []) { $this->_deleteRules[] = $this->_addError($rule, $name, $options); return $this; } /** * Runs each of the rules by passing the provided entity and returns true if all * of them pass. The rules to be applied are depended on the $mode parameter which * can only be RulesChecker::CREATE, RulesChecker::UPDATE or RulesChecker::DELETE * * @param \Cake\Datasource\EntityInterface $entity The entity to check for validity. * @param string $mode Either 'create, 'update' or 'delete'. * @param array $options Extra options to pass to checker functions. * @return bool * @throws \InvalidArgumentException if an invalid mode is passed. */ public function check(EntityInterface $entity, string $mode, array $options = []): bool { if ($mode === self::CREATE) { return $this->checkCreate($entity, $options); } if ($mode === self::UPDATE) { return $this->checkUpdate($entity, $options); } if ($mode === self::DELETE) { return $this->checkDelete($entity, $options); } throw new InvalidArgumentException('Wrong checking mode: ' . $mode); } /** * Runs each of the rules by passing the provided entity and returns true if all * of them pass. The rules selected will be only those specified to be run on 'create' * * @param \Cake\Datasource\EntityInterface $entity The entity to check for validity. * @param array $options Extra options to pass to checker functions. * @return bool */ public function checkCreate(EntityInterface $entity, array $options = []): bool { return $this->_checkRules($entity, $options, array_merge($this->_rules, $this->_createRules)); } /** * Runs each of the rules by passing the provided entity and returns true if all * of them pass. The rules selected will be only those specified to be run on 'update' * * @param \Cake\Datasource\EntityInterface $entity The entity to check for validity. * @param array $options Extra options to pass to checker functions. * @return bool */ public function checkUpdate(EntityInterface $entity, array $options = []): bool { return $this->_checkRules($entity, $options, array_merge($this->_rules, $this->_updateRules)); } /** * Runs each of the rules by passing the provided entity and returns true if all * of them pass. The rules selected will be only those specified to be run on 'delete' * * @param \Cake\Datasource\EntityInterface $entity The entity to check for validity. * @param array $options Extra options to pass to checker functions. * @return bool */ public function checkDelete(EntityInterface $entity, array $options = []): bool { return $this->_checkRules($entity, $options, $this->_deleteRules); } /** * Used by top level functions checkDelete, checkCreate and checkUpdate, this function * iterates an array containing the rules to be checked and checks them all. * * @param \Cake\Datasource\EntityInterface $entity The entity to check for validity. * @param array $options Extra options to pass to checker functions. * @param array<\Cake\Datasource\RuleInvoker> $rules The list of rules that must be checked. * @return bool */ protected function _checkRules(EntityInterface $entity, array $options = [], array $rules = []): bool { $success = true; $options += $this->_options; foreach ($rules as $rule) { $success = $rule($entity, $options) && $success; } return $success; } /** * Utility method for decorating any callable so that if it returns false, the correct * property in the entity is marked as invalid. * * @param callable|\Cake\Datasource\RuleInvoker $rule The rule to decorate * @param array|string|null $name The alias for a rule or an array of options * @param array $options The options containing the error message and field. * @return \Cake\Datasource\RuleInvoker */ protected function _addError(callable $rule, $name = null, array $options = []): RuleInvoker { if (is_array($name)) { $options = $name; $name = null; } if (!($rule instanceof RuleInvoker)) { $rule = new RuleInvoker($rule, $name, $options); } else { $rule->setOptions($options)->setName($name); } return $rule; } }