1: <?php
2: /**
3: * Wei Framework
4: *
5: * @copyright Copyright (c) 2008-2015 Twin Huang
6: * @license http://opensource.org/licenses/mit-license.php MIT License
7: */
8:
9: namespace Wei\Validator;
10:
11: /**
12: * Check if the input is valid by specified number of the rules
13: *
14: * @author Twin Huang <twinhuang@qq.com>
15: */
16: class SomeOf extends BaseValidator
17: {
18: protected $atLeastMessage = '%name% must be passed by at least %left% of %count% rules';
19:
20: /**
21: * The validator rules
22: *
23: * Format:
24: * array(
25: * 'email' => true,
26: * 'endsWith' => array(
27: * 'findMe' => '@google.com'
28: * )
29: * );
30: * @var array
31: */
32: protected $rules = array();
33:
34: /**
35: * How many rules should pass at least
36: *
37: * @var int
38: */
39: protected $atLeast;
40:
41: /**
42: * Whether combine messages into single one or not
43: *
44: * @var bool
45: */
46: protected $combineMessages = true;
47:
48: /**
49: * The passed rules number, using for message only
50: *
51: * @var string
52: */
53: protected $count;
54:
55: /**
56: * The not passed rules number, using for message only
57: *
58: * @var string
59: */
60: protected $left;
61:
62: /**
63: * The invalid validators
64: *
65: * @var BaseValidator[]
66: */
67: protected $validators = array();
68:
69: /**
70: * {@inheritdoc}
71: */
72: public function __invoke($input, array $rules = array(), $atLeast = null)
73: {
74: $atLeast && $this->storeOption('atLeast', $atLeast);
75: $rules && $this->storeOption('rules', $rules);
76:
77: return $this->isValid($input);
78: }
79:
80: /**
81: * {@inheritdoc}
82: */
83: protected function doValidate($input)
84: {
85: // Adds "atLeast" error at first, make sure this error at the top of
86: // stack, if any rule is passed, the error will be removed
87: $this->addError('atLeast');
88:
89: $passed = 0;
90: $validator = null;
91: $props = array('name' => $this->name);
92: foreach ($this->rules as $rule => $options) {
93: if ($this->validate->validateOne($rule, $input, $options, $validator, $props)) {
94: $passed++;
95: if ($passed >= $this->atLeast) {
96: // Removes all error messages
97: $this->errors = array();
98: return true;
99: }
100: } else {
101: $this->validators[$rule] = $validator;
102: }
103: }
104:
105: $this->count = count($this->rules) - $passed;
106: $this->left = $this->atLeast - $passed;
107:
108: return false;
109: }
110:
111: /**
112: * {@inheritdoc}
113: */
114: protected function reset()
115: {
116: $this->validators = array();
117: parent::reset();
118: }
119:
120: /**
121: * {@inheritdoc}
122: */
123: public function getMessages($name = null)
124: {
125: /**
126: * Combines messages into single one
127: *
128: * FROM
129: * array(
130: * 'atLeast' => 'atLeast message',
131: * 'validator.rule' => 'first message',
132: * 'validator.rul2' => 'second message',
133: * 'validator2.rule' => 'third message'
134: * )
135: * TO
136: * array(
137: * 'atLeast' => "atLeast message\n"
138: * . "first message;second message\n"
139: * . "third message"
140: * )
141: */
142: if ($this->combineMessages) {
143: $messages = parent::getMessages();
144: $key = key($messages);
145:
146: foreach ($this->validators as $rule => $validator) {
147: $messages[$rule] = implode(';', $validator->getMessages($name));
148: }
149:
150: return array(
151: $key => implode("\n", $messages)
152: );
153: } else {
154: $messages = array();
155: foreach ($this->validators as $rule => $validator) {
156: foreach ($validator->getMessages($name) as $option => $message) {
157: $messages[$rule . '.' . $option] = $message;
158: }
159: }
160: return $messages;
161: }
162: }
163: }
164: