Completed
Push — count-subquery-clone ( d5815f...6cc328 )
by Haralan
03:48
created

Kohana_Jam_Errors::offsetSet()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 4
c 0
b 0
f 0
rs 10
ccs 0
cts 2
cp 0
cc 1
eloc 2
nc 1
nop 2
crap 2
1
<?php defined('SYSPATH') OR die('No direct script access.');
2
/**
3
 * Jam Errors
4
 *
5
 * @package    Jam
6
 * @category   Model
7
 * @author     Ivan Kerin
8
 * @copyright  (c) 2011-2012 Despark Ltd.
9
 * @license    http://www.opensource.org/licenses/isc-license.txt
10
 */
11
abstract class Kohana_Jam_Errors implements Countable, SeekableIterator, ArrayAccess {
12
13 1
	public static function message($error_filename, $attribute, $error, $params)
14
	{
15 1
		if ($message = Kohana::message($error_filename, "{$attribute}.{$error}"))
16 1
		{
17
18
		}
19 1
		elseif ($message = Kohana::message('validators', $error))
20
		{
21
22 1
		}
23
		else
24
		{
25
			return $error_filename.":{$attribute}.{$error}";
26
		}
27
28 1
		return __($message, $params);
29
	}
30
31 1
	public static function attribute_label(Jam_Meta $meta, $attribute_name)
32
	{
33 1
		if ($attribute = $meta->attribute($attribute_name))
34 1
		{
35 1
			$label = $attribute->label;
36 1
		}
37
		else
38
		{
39
			$label = Inflector::humanize($attribute_name);
40
		}
41
42 1
		return UTF8::ucfirst($label);
43
	}
44
45
	/**
46
	 * @var  Jam_Meta  The current meta object, based on the model we're returning
47
	 */
48
	protected $_meta = NULL;
49
50
	/**
51
	 * @var  Jam_Validated  The current class we're placing results into
52
	 */
53
	protected $_model = NULL;
54
55
	/**
56
	 * @var  string
57
	 */
58
	protected $_error_filename = NULL;
59
60
	private $_container = array();
61
	private $_current;
62
63
	/**
64
	 * Tracks a database result
65
	 *
66
	 * @param  mixed  $result
0 ignored issues
show
Bug introduced by
There is no parameter named $result. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
67
	 * @param  mixed  $model
68
	 */
69 194
	public function __construct(Jam_Validated $model, $error_filename)
70
	{
71 194
		$this->_model = $model;
72 194
		$this->_meta = $model->meta();
73 194
		$this->_error_filename = $error_filename;
74 194
	}
75
76 182
	public function as_array()
77
	{
78 182
		return $this->_container;
79
	}
80
81 110
	public function add($attribute, $error, array $params = array())
82
	{
83 110
		if ( ! isset($this->_container[$attribute]))
84 110
		{
85 110
			$this->_container[$attribute] = array();
86 110
		}
87
88 110
		$this->_container[$attribute][$error] = $params;
89
90 110
		return $this;
91
	}
92
93 3
	public function messages($attribute = NULL)
94
	{
95 3
		$messages = array();
96
97 3
		if ($attribute !== NULL)
98 3
		{
99 3
			foreach (array_filter(Arr::extract($this->_container, (array) $attribute)) as $attribute_name => $errors)
100
			{
101
				foreach ($errors as $error => $params)
102
				{
103
					$messages[] = Jam_Errors::message($this->_error_filename, $attribute_name, $error, Arr::merge($params, array(
104
						':model' => $this->_meta->model(),
105
						':attribute' => Jam_Errors::attribute_label($this->_meta, $attribute_name),
106
					)));
107
				}
108 3
			}
109
110 3
			return $messages;
111
		}
112
113
		foreach ($this->_container as $attribute => $errors)
114
		{
115
			$messages[$attribute] = $this->messages($attribute);
116
		}
117
118
		return $messages;
119
	}
120
121 1
	public function messages_all()
122
	{
123 1
		$messages = array();
124 1
		return $this->_add_messages_all($this->_model, $messages);
125
	}
126
127 1
	private function _add_messages_all(Jam_Validated $model, array & $messages)
128
	{
129 1
		foreach ($model->errors() as $attribute_name => $errors)
0 ignored issues
show
Bug introduced by
The expression $model->errors() of type array|null is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
130
		{
131 1
			if ($model->meta()->association($attribute_name) instanceof Jam_Association_Collection)
132 1
			{
133
				foreach ($model->$attribute_name as $i => $item)
134
				{
135
					if ( ! $item->is_valid())
136
					{
137
						$this->_add_messages_all($item, $messages);
138
					}
139
				}
140
			}
141 1
			elseif ($model->meta()->association($attribute_name) AND $model->$attribute_name)
142
			{
143
				$this->_add_messages_all($model->$attribute_name, $messages);
144
			}
145
			else
146
			{
147 1
				foreach ($errors as $error => $params)
148
				{
149 1
					$model_name = UTF8::ucfirst(Inflector::humanize($model->meta()->model()));
150
151 1
					$messages[] = $model_name.': '.Jam_Errors::message($model->meta()->errors_filename(), $attribute_name, $error, Arr::merge($params, array(
152 1
						':model' => $model->meta()->model(),
153 1
						':attribute' => Jam_Errors::attribute_label($model->meta(), $attribute_name),
154 1
					)));
155 1
				}
156
			}
157 1
		}
158
159 1
		return $messages;
160
	}
161
162
	public function messages_dump()
163
	{
164
		return $this->_model_messages_dump($this->_model);
0 ignored issues
show
Compatibility introduced by
$this->_model of type object<Jam_Validated> is not a sub-type of object<Jam_Model>. It seems like you assume a child class of the class Jam_Validated to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
165
	}
166
167
	private function _model_messages_dump(Jam_Model $model)
168
	{
169
		$messages = array();
170
		foreach ($model->errors() as $attribute_name => $errors)
0 ignored issues
show
Bug introduced by
The expression $model->errors() of type array|null is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
171
		{
172
			if ($model->meta()->association($attribute_name) instanceof Jam_Association_Collection)
173
			{
174
				foreach ($model->$attribute_name as $i => $item)
175
				{
176
					if ( ! $item->is_valid())
177
					{
178
						$messages[] = UTF8::ucfirst(Inflector::humanize($attribute_name)).' ('.$i.'): '.join(', ', $this->_model_messages_dump($item));
179
					}
180
				}
181
			}
182
			elseif ($model->meta()->association($attribute_name) AND $model->$attribute_name)
183
			{
184
				$messages[] = UTF8::ucfirst(Inflector::humanize($attribute_name)).': '.join(', ', $this->_model_messages_dump($model->$attribute_name));
185
			}
186
			else
187
			{
188
				foreach ($errors as $error => $params)
189
				{
190
					$messages[] = Jam_Errors::message($model->meta()->errors_filename(), $attribute_name, $error, Arr::merge($params, array(
191
						':model' => $model->meta()->model(),
192
						':attribute' => Jam_Errors::attribute_label($model->meta(), $attribute_name),
193
					)));
194
				}
195
			}
196
		}
197
198
		return $messages;
199
	}
200
201
	public function __toString()
202
	{
203
		return $this->render();
204
	}
205
206
	public function render()
207
	{
208
		$all_messages = array();
209
		foreach ($this->messages() as $field => $messages)
210
		{
211
			$all_messages[] = join(', ', $messages);
212
		}
213
214
		return join(', ', $all_messages);
215
	}
216
217
	public function first()
218
	{
219
		$messages = $this->current();
220
221
		if (is_array($messages))
222
			return reset($messages);
223
224
		return NULL;
225
	}
226
227
	public function seek($offset)
228
	{
229
		if ($this->offsetExists($offset))
230
		{
231
			$this->_current = $offset;
232
233
			return TRUE;
234
		}
235
		else
236
		{
237
			return FALSE;
238
		}
239
	}
240
241
	public function offsetSet($offset, $value)
242
	{
243
		throw new Kohana_Exception('Cannot set the errors directly, must use add() method');
244
	}
245
246
	public function offsetExists($offset)
247
	{
248
	 return isset($this->_container[$offset]);
249
	}
250
251
	public function offsetUnset($offset)
252
	{
253
		unset($this->_container[$offset]);
254
		if ($this->_current == $offset)
255
		{
256
			$this->rewind();
257
		}
258
	}
259
260 1
	public function offsetGet($offset)
261
	{
262 1
		return isset($this->_container[$offset]) ? $this->_container[$offset] : NULL;
263
	}
264
265 1
	public function rewind()
266
	{
267 1
		reset($this->_container);
268 1
		$this->_current = key($this->_container);
269 1
	}
270
271 1
	public function current()
272
	{
273 1
		return $this->offsetGet($this->_current);
274
	}
275
276 1
	public function key()
277
	{
278 1
		return $this->_current;
279
	}
280
281 1
	public function next()
282
	{
283 1
		next($this->_container);
284 1
		$this->_current = key($this->_container);
285 1
		return $this->current();
286
	}
287
288
	public function prev()
289
	{
290
		prev($this->_container);
291
		$this->_current = key($this->_container);
292
		return $this->current();
293
	}
294
295 1
	public function valid()
296
	{
297 1
		return isset($this->_container[$this->_current]);
298
	}
299
300 11
	public function count()
301
	{
302 11
		return count($this->_container);
303
	}
304
}
305