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) |
|
30 | |||
31 | 1 | public static function attribute_label(Jam_Meta $meta, $attribute_name) |
|
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 | 191 | public function __construct(Jam_Validated $model, $error_filename) |
|
75 | |||
76 | 179 | public function as_array() |
|
80 | |||
81 | 106 | public function add($attribute, $error, array $params = array()) |
|
92 | |||
93 | 3 | public function messages($attribute = NULL) |
|
121 | |||
122 | 1 | public function messages_all() |
|
127 | |||
128 | 1 | private function _add_messages_all(Jam_Validated $model, array & $messages) |
|
129 | { |
||
130 | 1 | foreach ($model->errors() as $attribute_name => $errors) |
|
131 | { |
||
132 | 1 | if ($model->meta()->association($attribute_name) instanceof Jam_Association_Collection) |
|
133 | 1 | { |
|
134 | foreach ($model->$attribute_name as $i => $item) |
||
135 | { |
||
136 | if ( ! $item->is_valid()) |
||
137 | { |
||
138 | $this->_add_messages_all($item, $messages); |
||
139 | } |
||
140 | } |
||
141 | } |
||
142 | 1 | elseif ($model->meta()->association($attribute_name) AND $model->$attribute_name) |
|
143 | { |
||
144 | $this->_add_messages_all($model->$attribute_name, $messages); |
||
145 | } |
||
146 | else |
||
147 | { |
||
148 | 1 | foreach ($errors as $error => $params) |
|
149 | { |
||
150 | 1 | $model_name = UTF8::ucfirst(Inflector::humanize($model->meta()->model())); |
|
151 | |||
152 | 1 | $messages[] = $model_name.': '.Jam_Errors::message($model->meta()->errors_filename(), $attribute_name, $error, Arr::merge($params, array( |
|
153 | 1 | ':model' => $model->meta()->model(), |
|
154 | 1 | ':name' => $model->name(), |
|
155 | 1 | ':attribute' => Jam_Errors::attribute_label($model->meta(), $attribute_name), |
|
156 | 1 | ))); |
|
157 | 1 | } |
|
158 | } |
||
159 | 1 | } |
|
160 | |||
161 | 1 | return $messages; |
|
162 | } |
||
163 | |||
164 | public function messages_dump() |
||
168 | |||
169 | private function _model_messages_dump(Jam_Model $model) |
||
170 | { |
||
171 | $messages = array(); |
||
172 | foreach ($model->errors() as $attribute_name => $errors) |
||
173 | { |
||
174 | if ($model->meta()->association($attribute_name) instanceof Jam_Association_Collection) |
||
175 | { |
||
176 | foreach ($model->$attribute_name as $i => $item) |
||
177 | { |
||
178 | if ( ! $item->is_valid()) |
||
179 | { |
||
180 | $messages[] = UTF8::ucfirst(Inflector::humanize($attribute_name)).' ('.$i.'): '.join(', ', $this->_model_messages_dump($item)); |
||
181 | } |
||
182 | } |
||
183 | } |
||
184 | elseif ($model->meta()->association($attribute_name) AND $model->$attribute_name) |
||
185 | { |
||
186 | $messages[] = UTF8::ucfirst(Inflector::humanize($attribute_name)).': '.join(', ', $this->_model_messages_dump($model->$attribute_name)); |
||
187 | } |
||
188 | else |
||
189 | { |
||
190 | foreach ($errors as $error => $params) |
||
191 | { |
||
192 | $messages[] = Jam_Errors::message($model->meta()->errors_filename(), $attribute_name, $error, Arr::merge($params, array( |
||
193 | ':model' => $model->meta()->model(), |
||
194 | ':attribute' => Jam_Errors::attribute_label($model->meta(), $attribute_name), |
||
195 | ))); |
||
196 | } |
||
197 | } |
||
198 | } |
||
199 | |||
200 | return $messages; |
||
201 | } |
||
202 | |||
203 | public function __toString() |
||
207 | |||
208 | public function render() |
||
209 | { |
||
210 | $all_messages = array(); |
||
211 | foreach ($this->messages() as $field => $messages) |
||
212 | { |
||
213 | $all_messages[] = join(', ', $messages); |
||
214 | } |
||
215 | |||
216 | return join(', ', $all_messages); |
||
217 | } |
||
218 | |||
219 | public function first() |
||
228 | |||
229 | public function seek($offset) |
||
230 | { |
||
231 | if ($this->offsetExists($offset)) |
||
232 | { |
||
233 | $this->_current = $offset; |
||
234 | |||
235 | return TRUE; |
||
236 | } |
||
237 | else |
||
238 | { |
||
239 | return FALSE; |
||
240 | } |
||
241 | } |
||
242 | |||
243 | public function offsetSet($offset, $value) |
||
247 | |||
248 | public function offsetExists($offset) |
||
252 | |||
253 | public function offsetUnset($offset) |
||
254 | { |
||
255 | unset($this->_container[$offset]); |
||
256 | if ($this->_current == $offset) |
||
257 | { |
||
258 | $this->rewind(); |
||
259 | } |
||
260 | } |
||
261 | |||
262 | 1 | public function offsetGet($offset) |
|
266 | |||
267 | 1 | public function rewind() |
|
272 | |||
273 | 1 | public function current() |
|
277 | |||
278 | 1 | public function key() |
|
282 | |||
283 | 1 | public function next() |
|
289 | |||
290 | public function prev() |
||
296 | |||
297 | 1 | public function valid() |
|
301 | |||
302 | 11 | public function count() |
|
306 | } |
||
307 |
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.