1<?php
2/**
3 * Zend Framework (http://framework.zend.com/)
4 *
5 * @link      http://github.com/zendframework/zf2 for the canonical source repository
6 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
7 * @license   http://framework.zend.com/license/new-bsd New BSD License
8 */
9
10namespace Zend\Validator;
11
12use Traversable;
13use Zend\Stdlib\ArrayUtils;
14
15class Explode extends AbstractValidator implements ValidatorPluginManagerAwareInterface
16{
17    const INVALID = 'explodeInvalid';
18
19    protected $pluginManager;
20
21    /**
22     * @var array
23     */
24    protected $messageTemplates = array(
25        self::INVALID => "Invalid type given",
26    );
27
28    /**
29     * @var array
30     */
31    protected $messageVariables = array();
32
33    /**
34     * @var string
35     */
36    protected $valueDelimiter = ',';
37
38    /**
39     * @var ValidatorInterface
40     */
41    protected $validator;
42
43    /**
44     * @var bool
45     */
46    protected $breakOnFirstFailure = false;
47
48    /**
49     * Sets the delimiter string that the values will be split upon
50     *
51     * @param string $delimiter
52     * @return Explode
53     */
54    public function setValueDelimiter($delimiter)
55    {
56        $this->valueDelimiter = $delimiter;
57        return $this;
58    }
59
60    /**
61     * Returns the delimiter string that the values will be split upon
62     *
63     * @return string
64     */
65    public function getValueDelimiter()
66    {
67        return $this->valueDelimiter;
68    }
69
70    /**
71     * Set validator plugin manager
72     *
73     * @param ValidatorPluginManager $pluginManager
74     */
75    public function setValidatorPluginManager(ValidatorPluginManager $pluginManager)
76    {
77        $this->pluginManager = $pluginManager;
78    }
79
80    /**
81     * Get validator plugin manager
82     *
83     * @return ValidatorPluginManager
84     */
85    public function getValidatorPluginManager()
86    {
87        if (!$this->pluginManager) {
88            $this->setValidatorPluginManager(new ValidatorPluginManager());
89        }
90
91        return $this->pluginManager;
92    }
93
94    /**
95     * Sets the Validator for validating each value
96     *
97     * @param ValidatorInterface|array $validator
98     * @throws Exception\RuntimeException
99     * @return Explode
100     */
101    public function setValidator($validator)
102    {
103        if (is_array($validator)) {
104            if (!isset($validator['name'])) {
105                throw new Exception\RuntimeException(
106                    'Invalid validator specification provided; does not include "name" key'
107                );
108            }
109            $name = $validator['name'];
110            $options = isset($validator['options']) ? $validator['options'] : array();
111            $validator = $this->getValidatorPluginManager()->get($name, $options);
112        }
113
114        if (!$validator instanceof ValidatorInterface) {
115            throw new Exception\RuntimeException(
116                'Invalid validator given'
117            );
118        }
119
120        $this->validator = $validator;
121        return $this;
122    }
123
124    /**
125     * Gets the Validator for validating each value
126     *
127     * @return ValidatorInterface
128     */
129    public function getValidator()
130    {
131        return $this->validator;
132    }
133
134    /**
135     * Set break on first failure setting
136     *
137     * @param  bool $break
138     * @return Explode
139     */
140    public function setBreakOnFirstFailure($break)
141    {
142        $this->breakOnFirstFailure = (bool) $break;
143        return $this;
144    }
145
146    /**
147     * Get break on first failure setting
148     *
149     * @return bool
150     */
151    public function isBreakOnFirstFailure()
152    {
153        return $this->breakOnFirstFailure;
154    }
155
156    /**
157     * Defined by Zend\Validator\ValidatorInterface
158     *
159     * Returns true if all values validate true
160     *
161     * @param  mixed $value
162     * @param  mixed $context Extra "context" to provide the composed validator
163     * @return bool
164     * @throws Exception\RuntimeException
165     */
166    public function isValid($value, $context = null)
167    {
168        $this->setValue($value);
169
170        if ($value instanceof Traversable) {
171            $value = ArrayUtils::iteratorToArray($value);
172        }
173
174        if (is_array($value)) {
175            $values = $value;
176        } elseif (is_string($value)) {
177            $delimiter = $this->getValueDelimiter();
178            // Skip explode if delimiter is null,
179            // used when value is expected to be either an
180            // array when multiple values and a string for
181            // single values (ie. MultiCheckbox form behavior)
182            $values = (null !== $delimiter)
183                      ? explode($this->valueDelimiter, $value)
184                      : array($value);
185        } else {
186            $values = array($value);
187        }
188
189        $validator = $this->getValidator();
190
191        if (!$validator) {
192            throw new Exception\RuntimeException(sprintf(
193                '%s expects a validator to be set; none given',
194                __METHOD__
195            ));
196        }
197
198        foreach ($values as $value) {
199            if (!$validator->isValid($value, $context)) {
200                $this->abstractOptions['messages'][] = $validator->getMessages();
201
202                if ($this->isBreakOnFirstFailure()) {
203                    return false;
204                }
205            }
206        }
207
208        return count($this->abstractOptions['messages']) == 0;
209    }
210}
211