Your IP : 127.0.0.1
<?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;
}
}