RuleInvoker.php 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. <?php
  2. /**
  3. * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
  4. * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
  5. *
  6. * Licensed under The MIT License
  7. * For full copyright and license information, please see the LICENSE.txt
  8. * Redistributions of files must retain the above copyright notice.
  9. *
  10. * @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
  11. * @link https://cakephp.org CakePHP(tm) Project
  12. * @since 3.2.12
  13. * @license https://opensource.org/licenses/mit-license.php MIT License
  14. */
  15. namespace Cake\Datasource;
  16. /**
  17. * Contains logic for invoking an application rule.
  18. *
  19. * Combined with Cake\Datasource\RuleChecker as an implementation
  20. * detail to de-duplicate rule decoration and provide cleaner separation
  21. * of duties.
  22. *
  23. * @internal
  24. */
  25. class RuleInvoker
  26. {
  27. /**
  28. * The rule name
  29. *
  30. * @var string
  31. */
  32. protected $name;
  33. /**
  34. * Rule options
  35. *
  36. * @var array
  37. */
  38. protected $options = [];
  39. /**
  40. * Rule callable
  41. *
  42. * @var callable
  43. */
  44. protected $rule;
  45. /**
  46. * Constructor
  47. *
  48. * ### Options
  49. *
  50. * - `errorField` The field errors should be set onto.
  51. * - `message` The error message.
  52. *
  53. * Individual rules may have additional options that can be
  54. * set here. Any options will be passed into the rule as part of the
  55. * rule $scope.
  56. *
  57. * @param callable $rule The rule to be invoked.
  58. * @param string $name The name of the rule. Used in error messsages.
  59. * @param array $options The options for the rule. See above.
  60. */
  61. public function __construct(callable $rule, $name, array $options = [])
  62. {
  63. $this->rule = $rule;
  64. $this->name = $name;
  65. $this->options = $options;
  66. }
  67. /**
  68. * Set options for the rule invocation.
  69. *
  70. * Old options will be merged with the new ones.
  71. *
  72. * @param array $options The options to set.
  73. * @return $this
  74. */
  75. public function setOptions(array $options)
  76. {
  77. $this->options = $options + $this->options;
  78. return $this;
  79. }
  80. /**
  81. * Set the rule name.
  82. *
  83. * Only truthy names will be set.
  84. *
  85. * @param string $name The name to set.
  86. * @return $this
  87. */
  88. public function setName($name)
  89. {
  90. if ($name) {
  91. $this->name = $name;
  92. }
  93. return $this;
  94. }
  95. /**
  96. * Invoke the rule.
  97. *
  98. * @param \Cake\Datasource\EntityInterface $entity The entity the rule
  99. * should apply to.
  100. * @param array $scope The rule's scope/options.
  101. * @return bool Whether or not the rule passed.
  102. */
  103. public function __invoke($entity, $scope)
  104. {
  105. $rule = $this->rule;
  106. $pass = $rule($entity, $this->options + $scope);
  107. if ($pass === true || empty($this->options['errorField'])) {
  108. return $pass === true;
  109. }
  110. $message = 'invalid';
  111. if (isset($this->options['message'])) {
  112. $message = $this->options['message'];
  113. }
  114. if (is_string($pass)) {
  115. $message = $pass;
  116. }
  117. if ($this->name) {
  118. $message = [$this->name => $message];
  119. } else {
  120. $message = [$message];
  121. }
  122. $errorField = $this->options['errorField'];
  123. $entity->setError($errorField, $message);
  124. if ($entity instanceof InvalidPropertyInterface && isset($entity->{$errorField})) {
  125. $invalidValue = $entity->{$errorField};
  126. $entity->setInvalidField($errorField, $invalidValue);
  127. }
  128. return $pass === true;
  129. }
  130. }