123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354 |
- <?php
- /**
- * Magento Validator Builder
- *
- * Copyright © Magento, Inc. All rights reserved.
- * See COPYING.txt for license details.
- */
- namespace Magento\Framework\Validator;
- use Magento\Framework\Validator\Constraint\OptionInterface;
- class Builder
- {
- /**
- * @var array
- */
- protected $_constraints;
- /**
- * @var \Magento\Framework\Validator\ConstraintFactory
- */
- protected $_constraintFactory;
- /**
- * @var \Magento\Framework\ValidatorFactory
- */
- protected $_validatorFactory;
- /**
- * @var \Magento\Framework\Validator\UniversalFactory
- */
- protected $_oneValidatorFactory;
- /**
- * @param \Magento\Framework\Validator\ConstraintFactory $constraintFactory
- * @param \Magento\Framework\ValidatorFactory $validatorFactory
- * @param \Magento\Framework\Validator\UniversalFactory $oneValidatorFactory
- * @param array $constraints
- */
- public function __construct(
- \Magento\Framework\Validator\ConstraintFactory $constraintFactory,
- \Magento\Framework\ValidatorFactory $validatorFactory,
- \Magento\Framework\Validator\UniversalFactory $oneValidatorFactory,
- array $constraints
- ) {
- foreach ($constraints as $constraint) {
- if (isset($constraint['options']) && is_array($constraint['options'])) {
- $this->_checkConfigurationArguments($constraint['options'], true);
- $this->_checkConfigurationCallback($constraint['options'], true);
- }
- }
- $this->_constraints = $constraints;
- $this->_constraintFactory = $constraintFactory;
- $this->_validatorFactory = $validatorFactory;
- $this->_oneValidatorFactory = $oneValidatorFactory;
- }
- /**
- * Check configuration arguments
- *
- * @param array $configuration
- * @param bool $argumentsIsArray
- * @return void
- * @throws \InvalidArgumentException
- */
- protected function _checkConfigurationArguments(array $configuration, $argumentsIsArray)
- {
- // https://jira.corp.x.com/browse/MAGETWO-10439
- $allowedKeys = ['arguments', 'callback', 'method', 'methods', 'breakChainOnFailure'];
- if (!array_intersect($allowedKeys, array_keys($configuration))) {
- throw new \InvalidArgumentException('Configuration has incorrect format');
- }
- // Check method arguments
- if ($argumentsIsArray) {
- if (array_key_exists('methods', $configuration)) {
- foreach ($configuration['methods'] as $method) {
- $this->_checkMethodArguments($method);
- }
- }
- } elseif (array_key_exists('method', $configuration)) {
- $this->_checkMethodArguments($configuration);
- }
- // Check constructor arguments
- if (array_key_exists('arguments', $configuration) && !is_array($configuration['arguments'])) {
- throw new \InvalidArgumentException('Arguments must be an array');
- }
- }
- /**
- * Check configuration method arguments
- *
- * @param array $configuration
- * @return void
- * @throws \InvalidArgumentException
- */
- protected function _checkMethodArguments(array $configuration)
- {
- if (!is_string($configuration['method'])) {
- throw new \InvalidArgumentException('Method has to be passed as string');
- }
- if (array_key_exists('arguments', $configuration) && !is_array($configuration['arguments'])) {
- throw new \InvalidArgumentException('Method arguments must be an array');
- }
- }
- /**
- * Check configuration callbacks
- *
- * @param array $configuration
- * @param bool $callbackIsArray
- * @return void
- * @throws \InvalidArgumentException
- */
- protected function _checkConfigurationCallback(array $configuration, $callbackIsArray)
- {
- if (array_key_exists('callback', $configuration)) {
- if ($callbackIsArray) {
- $callbacks = $configuration['callback'];
- } else {
- $callbacks = [$configuration['callback']];
- }
- foreach ($callbacks as $callback) {
- if (!$callback instanceof \Magento\Framework\Validator\Constraint\Option\Callback) {
- throw new \InvalidArgumentException(
- 'Callback must be instance of \Magento\Framework\Validator\Constraint\Option\Callback'
- );
- }
- }
- }
- }
- /**
- * Create validator instance and configure it
- *
- * @return \Magento\Framework\Validator
- */
- public function createValidator()
- {
- return $this->_createValidatorInstance();
- }
- /**
- * Get validator instance
- *
- * @return \Magento\Framework\Validator
- */
- protected function _createValidatorInstance()
- {
- $validator = $this->_validatorFactory->create();
- foreach ($this->_constraints as $constraintData) {
- // https://jira.corp.x.com/browse/MAGETWO-10439
- $breakChainOnFailure = !empty($constraintData['options']['breakChainOnFailure']);
- $validator->addValidator($this->_createConstraint($constraintData), $breakChainOnFailure);
- }
- return $validator;
- }
- /**
- * Add constraint configuration
- *
- * @param string $alias
- * @param array $configuration
- * @return $this
- * @throws \InvalidArgumentException
- */
- public function addConfiguration($alias, array $configuration)
- {
- $this->_checkConfigurationArguments($configuration, false);
- $this->_checkConfigurationCallback($configuration, false);
- foreach ($this->_constraints as &$constraint) {
- if ($constraint['alias'] != $alias) {
- continue;
- }
- if (!array_key_exists('options', $constraint) || !is_array($constraint['options'])) {
- $constraint['options'] = [];
- }
- if (!array_key_exists('method', $configuration)) {
- if (array_key_exists('arguments', $configuration)) {
- $constraint['options']['arguments'] = $configuration['arguments'];
- } elseif (array_key_exists('callback', $configuration)) {
- $constraint = $this->_addConstraintCallback($constraint, $configuration['callback']);
- }
- } else {
- $constraint = $this->_addConstraintMethod($constraint, $configuration);
- }
- }
- return $this;
- }
- /**
- * Add callback to constraint configuration
- *
- * @param array $constraint
- * @param \Magento\Framework\Validator\Constraint\Option\Callback $callback
- * @return array
- */
- protected function _addConstraintCallback(
- array $constraint,
- \Magento\Framework\Validator\Constraint\Option\Callback $callback
- ) {
- if (!array_key_exists('callback', $constraint['options'])) {
- $constraint['options']['callback'] = [];
- }
- $constraint['options']['callback'][] = $callback;
- return $constraint;
- }
- /**
- * Add method to constraint configuration
- *
- * @param array $constraint
- * @param array $configuration
- * @return array
- */
- protected function _addConstraintMethod(array $constraint, array $configuration)
- {
- if (!array_key_exists('methods', $constraint['options'])) {
- $constraint['options']['methods'] = [];
- }
- $constraint['options']['methods'][] = $configuration;
- return $constraint;
- }
- /**
- * Add constraints configuration
- *
- * @param array $configurations
- * @return $this
- */
- public function addConfigurations(array $configurations)
- {
- foreach ($configurations as $alias => $concreteConfigs) {
- foreach ($concreteConfigs as $configuration) {
- $this->addConfiguration($alias, $configuration);
- }
- }
- return $this;
- }
- /**
- * Create constraint from data
- *
- * @param array $data
- * @return \Magento\Framework\Validator\Constraint
- */
- protected function _createConstraint(array $data)
- {
- // Create validator instance
- $validator = $this->_createConstraintValidator($data);
- if (isset($data['options']) && is_array($data['options'])) {
- $this->_configureConstraintValidator($validator, $data['options']);
- }
- if (\Magento\Framework\Validator\Config::CONSTRAINT_TYPE_PROPERTY == $data['type']) {
- $result = new \Magento\Framework\Validator\Constraint\Property(
- $validator,
- $data['property'],
- $data['alias']
- );
- } else {
- $result = $this->_constraintFactory->create(['validator' => $validator, 'alias' => $data['alias']]);
- }
- return $result;
- }
- /**
- * Create constraint validator instance
- *
- * @param array $data
- * @return \Magento\Framework\Validator\ValidatorInterface
- * @throws \InvalidArgumentException
- */
- protected function _createConstraintValidator(array $data)
- {
- $validator = $this->_oneValidatorFactory->create(
- $data['class'],
- isset(
- $data['options']['arguments']
- ) ? $this->_applyArgumentsCallback(
- $data['options']['arguments']
- ) : []
- );
- // Check validator type
- if (!$validator instanceof \Magento\Framework\Validator\ValidatorInterface) {
- throw new \InvalidArgumentException(
- sprintf(
- 'Constraint class "%s" must implement \Magento\Framework\Validator\ValidatorInterface',
- $data['class']
- )
- );
- }
- return $validator;
- }
- /**
- * Configure validator
- *
- * @param \Magento\Framework\Validator\ValidatorInterface $validator
- * @param array $options
- * @return void
- */
- protected function _configureConstraintValidator(
- \Magento\Framework\Validator\ValidatorInterface $validator,
- array $options
- ) {
- // Call all validator methods according to configuration
- if (isset($options['methods'])) {
- foreach ($options['methods'] as $methodData) {
- $methodName = $methodData['method'];
- if (method_exists($validator, $methodName)) {
- if (array_key_exists('arguments', $methodData)) {
- $arguments = $this->_applyArgumentsCallback($methodData['arguments']);
- call_user_func_array([$validator, $methodName], $arguments);
- } else {
- call_user_func([$validator, $methodName]);
- }
- }
- }
- }
- // Call validator configurators if any
- if (isset($options['callback'])) {
- /** @var $callback \Magento\Framework\Validator\Constraint\Option\Callback */
- foreach ($options['callback'] as $callback) {
- $callback->setArguments($validator);
- $callback->getValue();
- }
- }
- }
- /**
- * Apply all argument callback
- *
- * @param OptionInterface[] $arguments
- * @return OptionInterface[]
- */
- protected function _applyArgumentsCallback(array $arguments)
- {
- foreach ($arguments as &$argument) {
- if (is_array($argument)) {
- $argument = $this->_applyArgumentsCallback($argument);
- } elseif ($argument instanceof OptionInterface) {
- $argument = $argument->getValue();
- }
- }
- return $arguments;
- }
- }
|