Complex classes like Kohana_Jam_Errors often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use Kohana_Jam_Errors, and based on these observations, apply Extract Interface, too.
1 | <?php defined('SYSPATH') OR die('No direct script access.'); |
||
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 |
||
|
|||
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() |
|
126 | |||
127 | 1 | private function _add_messages_all(Jam_Validated $model, array & $messages) |
|
161 | |||
162 | public function messages_dump() |
||
166 | |||
167 | private function _model_messages_dump(Jam_Model $model) |
||
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() |
||
226 | |||
227 | public function seek($offset) |
||
228 | { |
||
229 | if ($this->offsetExists($offset)) |
||
230 | { |
||
231 | $this->_current = $offset; |
||
232 | |||
233 | return TRUE; |
||
234 | } |
||
240 | |||
241 | public function offsetSet($offset, $value) |
||
245 | |||
246 | public function offsetExists($offset) |
||
250 | |||
251 | public function offsetUnset($offset) |
||
259 | |||
260 | 1 | public function offsetGet($offset) |
|
264 | |||
265 | 1 | public function rewind() |
|
270 | |||
271 | 1 | public function current() |
|
275 | |||
276 | 1 | public function key() |
|
280 | |||
281 | 1 | public function next() |
|
287 | |||
288 | public function prev() |
||
294 | |||
295 | 1 | public function valid() |
|
299 | |||
300 | 11 | public function count() |
|
304 | } |
||
305 |
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 methodfinale(...)
.The most likely cause is that the parameter was removed, but the annotation was not.