Complex classes like Kohana_Jam_Meta 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_Meta, and based on these observations, apply Extract Interface, too.
1 | <?php defined('SYSPATH') OR die('No direct script access.'); |
||
13 | abstract class Kohana_Jam_Meta { |
||
14 | |||
15 | /** |
||
16 | * @var boolean If this is FALSE, properties can still be set on the meta object |
||
17 | */ |
||
18 | protected $_initialized = FALSE; |
||
19 | |||
20 | /** |
||
21 | * @var string The model this meta object belongs to |
||
22 | */ |
||
23 | protected $_model = NULL; |
||
24 | |||
25 | /** |
||
26 | * @var string The database key to use for connection |
||
27 | */ |
||
28 | protected $_db; |
||
29 | |||
30 | /** |
||
31 | * @var string The table this model represents, defaults to the model name pluralized |
||
32 | */ |
||
33 | protected $_table = ''; |
||
34 | |||
35 | /** |
||
36 | * @var string The primary key, defaults to the first Field_Primary found. |
||
37 | * This can be referenced in query building as :primary_key |
||
38 | */ |
||
39 | protected $_primary_key = ''; |
||
40 | |||
41 | /** |
||
42 | * @var string The title key. This can be referenced in query building as :name_key |
||
43 | */ |
||
44 | protected $_name_key = 'name'; |
||
45 | |||
46 | /** |
||
47 | * @var string The foreign key for use in other tables. This can be referenced in query building as :foreign_key |
||
48 | */ |
||
49 | protected $_foreign_key = ''; |
||
50 | |||
51 | /** |
||
52 | * @var string The method needed to get the item |
||
53 | */ |
||
54 | protected $_unique_key = ''; |
||
55 | |||
56 | /** |
||
57 | * @var string The polymorphic key for the model tree. |
||
58 | */ |
||
59 | protected $_polymorphic_key = NULL; |
||
60 | |||
61 | /** |
||
62 | * @var array An array of this model's children |
||
63 | */ |
||
64 | protected $_children = array(); |
||
65 | |||
66 | /** |
||
67 | * @var array An array of ordering options for SELECTs |
||
68 | */ |
||
69 | protected $_sorting = array(); |
||
70 | |||
71 | /** |
||
72 | * @var array A map to the models's fields and how to process each column. |
||
73 | */ |
||
74 | protected $_fields = array(); |
||
75 | |||
76 | /** |
||
77 | * @var array A map to the models's associations and how to process each column. |
||
78 | */ |
||
79 | protected $_associations = array(); |
||
80 | |||
81 | |||
82 | /** |
||
83 | * The message filename used for validation errors. |
||
84 | * Defaults to Jam_Meta::$_model |
||
85 | * @var string |
||
86 | */ |
||
87 | protected $_errors_filename = NULL; |
||
88 | |||
89 | /** |
||
90 | * @var array Default data for each field |
||
91 | */ |
||
92 | protected $_defaults = array(); |
||
93 | |||
94 | /** |
||
95 | * @var Jam_Event Events attached to this model |
||
96 | */ |
||
97 | protected $_events = array(); |
||
98 | |||
99 | /** |
||
100 | * @var array Behaviors attached to this model |
||
101 | */ |
||
102 | protected $_behaviors = array(); |
||
103 | |||
104 | /** |
||
105 | * @var string The parent model of this model |
||
106 | */ |
||
107 | protected $_parent = NULL; |
||
108 | |||
109 | protected $_validators = array(); |
||
110 | |||
111 | protected $_with_options; |
||
112 | |||
113 | protected $_collection = NULL; |
||
114 | |||
115 | /** |
||
116 | * The most basic initialization possible |
||
117 | * @param string $model Model name |
||
118 | */ |
||
119 | 153 | public function __construct($model) |
|
120 | { |
||
121 | 153 | $this->_model = $model; |
|
122 | |||
123 | // Set up event system |
||
124 | 153 | $this->_events = new Jam_Event($model); |
|
125 | 153 | } |
|
126 | |||
127 | /** |
||
128 | * This is called after initialization to |
||
129 | * finalize any changes to the meta object. |
||
130 | * |
||
131 | * @param string $model |
||
132 | * @return |
||
133 | */ |
||
134 | 2 | public function finalize($model) |
|
135 | { |
||
136 | 2 | if ($this->_initialized) |
|
137 | 2 | return; |
|
138 | |||
139 | // Set the name of a possible behavior class |
||
140 | 2 | $behavior_class = Jam::behavior_prefix().Jam::capitalize_class_name($model); |
|
141 | |||
142 | // See if we have a special behavior class to use |
||
143 | 2 | if (class_exists($behavior_class)) |
|
144 | 2 | { |
|
145 | // Load behavior |
||
146 | $behavior = new $behavior_class; |
||
147 | |||
148 | if ( ! in_array($behavior, $this->_behaviors)) |
||
149 | { |
||
150 | // Add to behaviors |
||
151 | $this->_behaviors[] = $behavior; |
||
152 | } |
||
153 | } |
||
154 | |||
155 | 2 | foreach ($this->_behaviors as $name => $behavior) |
|
156 | { |
||
157 | 1 | if ( ! $behavior instanceof Jam_Behavior) |
|
158 | 1 | throw new Kohana_Exception('Behavior at index [ :key ] is not an instance of Jam_Behavior, :type found.', array( |
|
159 | ':type' => is_object($behavior) ? ('instance of '.get_class($behavior)) : gettype($behavior), |
||
160 | ':key' => $name, |
||
161 | )); |
||
162 | |||
163 | // Initialize behavior |
||
164 | 1 | $behavior->initialize($this, $name); |
|
|
|||
165 | 2 | } |
|
166 | |||
167 | // Allow modification of this meta object by the behaviors |
||
168 | 2 | $this->_events->trigger('meta.before_finalize', $this); |
|
169 | |||
170 | // Ensure certain fields are not overridden |
||
171 | 2 | $this->_model = $model; |
|
172 | 2 | $this->_defaults = array(); |
|
173 | |||
174 | 2 | if ( ! $this->_errors_filename) |
|
175 | 2 | { |
|
176 | // Default errors filename to the model's name |
||
177 | 2 | $this->_errors_filename = 'validators/'.$this->_model; |
|
178 | 2 | } |
|
179 | |||
180 | // Table should be a sensible default |
||
181 | 2 | if (empty($this->_table)) |
|
182 | 2 | { |
|
183 | 1 | $this->_table = Inflector::plural($model); |
|
184 | 1 | } |
|
185 | |||
186 | // Can we set a sensible foreign key? |
||
187 | 2 | if (empty($this->_foreign_key)) |
|
188 | 2 | { |
|
189 | 1 | $this->_foreign_key = $model.'_id'; |
|
190 | 1 | } |
|
191 | |||
192 | 2 | if (empty($this->_unique_key) AND method_exists(Jam::class_name($this->_model), 'unique_key')) |
|
193 | 2 | { |
|
194 | $this->_unique_key = Jam::class_name($this->_model).'::unique_key'; |
||
195 | } |
||
196 | |||
197 | 2 | foreach ($this->_fields as $column => $field) |
|
198 | { |
||
199 | // Ensure a default primary key is set |
||
200 | 2 | if ($field instanceof Jam_Field AND $field->primary AND empty($this->_primary_key)) |
|
201 | 2 | { |
|
202 | 1 | $this->_primary_key = $column; |
|
203 | 1 | } |
|
204 | |||
205 | // Ensure a default plymorphic key is set |
||
206 | 2 | if ($field instanceof Jam_Field_Polymorphic AND empty($this->_polymorphic_key)) |
|
207 | 2 | { |
|
208 | $this->_polymorphic_key = $column; |
||
209 | } |
||
210 | 2 | } |
|
211 | |||
212 | 2 | foreach ($this->_associations as $column => & $association) |
|
213 | { |
||
214 | 1 | $association->initialize($this, $column); |
|
215 | 2 | } |
|
216 | |||
217 | 2 | foreach ($this->_fields as $column => & $field) |
|
218 | { |
||
219 | 2 | $field->initialize($this, $column); |
|
220 | 2 | $this->_defaults[$column] = $field->default; |
|
221 | 2 | } |
|
222 | |||
223 | 2 | if ( ! $this->_collection AND ($class = Jam::collection_prefix().Jam::capitalize_class_name($this->_model)) AND class_exists($class)) |
|
224 | 2 | { |
|
225 | $this->_collection = $class; |
||
226 | } |
||
227 | |||
228 | // Meta object is initialized and no longer writable |
||
229 | 2 | $this->_initialized = TRUE; |
|
230 | |||
231 | // Final meta callback |
||
232 | 2 | $this->_events->trigger('meta.after_finalize', $this); |
|
233 | 2 | } |
|
234 | |||
235 | /** |
||
236 | * Returns a string representation of the meta object. |
||
237 | * |
||
238 | * @return string |
||
239 | */ |
||
240 | public function __toString() |
||
241 | { |
||
242 | return (string) get_class($this).': '.$this->_model; |
||
243 | } |
||
244 | |||
245 | /** |
||
246 | * Returns whether or not the meta object has finished initialization |
||
247 | * |
||
248 | * @return boolean |
||
249 | */ |
||
250 | 3 | public function initialized() |
|
251 | { |
||
252 | 3 | return $this->_initialized; |
|
253 | } |
||
254 | |||
255 | 47 | public function collection($value = NULL) |
|
256 | { |
||
257 | 47 | if (func_num_args() !== 0) |
|
258 | 47 | { |
|
259 | return $this->set('collection', $value); |
||
260 | } |
||
261 | 47 | return $this->_collection; |
|
262 | } |
||
263 | |||
264 | 1 | public function validator($field, $options) |
|
265 | { |
||
266 | 1 | $fields = func_get_args(); |
|
267 | 1 | $options = (array) array_pop($fields); |
|
268 | |||
269 | 1 | if ($this->_with_options) |
|
270 | 1 | { |
|
271 | 1 | $options = Arr::merge($options, $this->_with_options); |
|
272 | 1 | } |
|
273 | |||
274 | 1 | $this->_validators[] = new Jam_Validator($fields, $options); |
|
275 | |||
276 | 1 | return $this; |
|
277 | } |
||
278 | |||
279 | 1 | public function with_options($options) |
|
280 | { |
||
281 | 1 | $this->_with_options = $options; |
|
282 | 1 | return $this; |
|
283 | } |
||
284 | |||
285 | public function end() |
||
286 | { |
||
287 | $this->_with_options = NULL; |
||
288 | return $this; |
||
289 | } |
||
290 | |||
291 | 11 | public function validators() |
|
292 | { |
||
293 | 11 | return $this->_validators; |
|
294 | } |
||
295 | |||
296 | 11 | public function execute_validators(Jam_Validated $model, $force = FALSE) |
|
307 | |||
308 | /** |
||
309 | * Allows setting a variable only when not initialized. |
||
310 | * |
||
311 | * @param string $key |
||
312 | * @param mixed $value |
||
313 | * @return Jam_Meta |
||
314 | */ |
||
315 | 2 | protected function set($key, $value) |
|
316 | { |
||
317 | 2 | if ($this->_initialized) |
|
318 | 2 | { |
|
319 | throw new Kohana_Exception(':class already initialized, cannot set :key to :value', array( |
||
320 | ':class' => Jam::class_name($this->_model), |
||
321 | ':key' => $key, |
||
322 | ':value' => $value, |
||
323 | )); |
||
324 | } |
||
325 | |||
326 | // Set key's value |
||
327 | 2 | $this->{'_'.$key} = $value; |
|
328 | |||
329 | 2 | return $this; |
|
330 | } |
||
331 | |||
332 | /** |
||
333 | * Allows appending an array to a variable only when not initialized. |
||
334 | * |
||
335 | * @param string $key |
||
336 | * @param mixed $value |
||
337 | * @return Jam_Meta |
||
338 | */ |
||
339 | 1 | protected function set_append($key, $value) |
|
340 | { |
||
341 | 1 | if ($this->_initialized) |
|
342 | 1 | { |
|
343 | // Throw exception |
||
344 | throw new Kohana_Exception(':class already initialized, cannot append to :key', array( |
||
345 | ':class' => Jam::class_name($this->_model), |
||
346 | ':key' => $key, |
||
347 | )); |
||
348 | } |
||
349 | |||
350 | 1 | if (is_array($value)) |
|
351 | 1 | { |
|
352 | // Set key's value |
||
353 | 1 | $this->{'_'.$key} = array_merge($this->{'_'.$key}, $value); |
|
354 | 1 | } |
|
355 | |||
356 | 1 | return $this; |
|
357 | } |
||
358 | |||
359 | /** |
||
360 | * Gets or sets the db group |
||
361 | * |
||
362 | * @param string $value |
||
363 | * @return Jam_Meta|string |
||
364 | */ |
||
365 | 133 | public function db($value = NULL) |
|
366 | { |
||
367 | 133 | if (func_num_args() !== 0) |
|
368 | 133 | { |
|
369 | 2 | return $this->set('db', $value); |
|
370 | } |
||
371 | |||
372 | 132 | return $this->_db ? $this->_db : Database::$default; |
|
373 | } |
||
374 | |||
375 | /** |
||
376 | * Returns the model name this object is attached to |
||
377 | * |
||
378 | * @return string |
||
379 | */ |
||
380 | 229 | public function model() |
|
381 | { |
||
382 | 229 | return $this->_model; |
|
383 | } |
||
384 | |||
385 | /** |
||
386 | * Gets or sets the table |
||
387 | * |
||
388 | * @param string $value |
||
389 | * @return Jam_Meta|string |
||
390 | */ |
||
391 | 139 | public function table($value = NULL) |
|
392 | { |
||
393 | 139 | if (func_num_args() !== 0) |
|
394 | 139 | { |
|
395 | 1 | return $this->set('table', $value); |
|
396 | } |
||
397 | |||
398 | 139 | return $this->_table; |
|
399 | } |
||
400 | |||
401 | /** |
||
402 | * Getter / setter for individual fields. |
||
403 | * |
||
404 | * @param string $name name of the field |
||
405 | * @param mixed $field the field alias or object |
||
406 | * @return Jam_Field|Jam_Meta|null |
||
407 | */ |
||
408 | 196 | public function field($name, $field = NULL, $prepend = FALSE) |
|
409 | { |
||
410 | 196 | if ($field === NULL) |
|
411 | 196 | { |
|
412 | // Get the association |
||
413 | 195 | return Arr::get($this->_fields, $name); |
|
414 | } |
||
415 | |||
416 | 2 | if ($this->_initialized) |
|
417 | 2 | { |
|
418 | // Cannot set after initialization |
||
419 | throw new Kohana_Exception(':class already initialized, cannot set :field', array( |
||
420 | ':class' => Jam::class_name($this->_model), |
||
421 | ':field' => $name, |
||
422 | )); |
||
423 | } |
||
424 | |||
425 | // Set the field |
||
426 | if ($prepend) |
||
427 | 2 | { |
|
428 | $this->_fields = array($name => $field) + $this->_fields; |
||
429 | } |
||
430 | else |
||
431 | { |
||
432 | 2 | $this->_fields[$name] = $field; |
|
433 | } |
||
434 | |||
435 | // Return Jam_Meta |
||
436 | 2 | return $this; |
|
437 | } |
||
438 | |||
439 | /** |
||
440 | * The same as field method, but throws an exception if association does not exist |
||
441 | * |
||
442 | * @param string $name name of the field |
||
443 | * @param mixed $field the field alias or object |
||
444 | * @return Jam_Field|Jam_Meta|null |
||
445 | */ |
||
446 | public function field_insist($name, $field = NULL) |
||
447 | { |
||
448 | if ( ! isset($this->_fields[$name])) |
||
449 | throw new Kohana_Exception('The field :name for this model :model does not exist', array(':name' => $name, ':model' => $this->_model)); |
||
450 | |||
451 | return $this->field($name, $field); |
||
452 | } |
||
453 | |||
454 | 1 | public function attribute($name) |
|
455 | { |
||
456 | 1 | return Arr::get($this->_fields, $name, Arr::get($this->_associations, $name)); |
|
457 | } |
||
458 | |||
459 | public function attribute_insist($name) |
||
460 | { |
||
461 | $attribute = $this->attribute($name); |
||
462 | |||
463 | if ( ! $attribute) |
||
464 | throw new Kohana_Exception('The attrubute :name for this model :model does not exist', array(':name' => $name, ':model' => $this->_model)); |
||
465 | |||
466 | return $attribute; |
||
467 | } |
||
468 | |||
469 | |||
470 | /** |
||
471 | * Gets and sets the fields for this object. |
||
472 | * |
||
473 | * Calling this multiple times will overwrite fields. |
||
474 | * |
||
475 | * @param array|null $fields |
||
476 | * @return array|Jam_Meta |
||
477 | */ |
||
478 | 159 | public function fields(array $fields = NULL) |
|
479 | { |
||
480 | 159 | if ($fields === NULL) |
|
481 | 159 | { |
|
482 | // Return the fields |
||
483 | 158 | return $this->_fields; |
|
484 | } |
||
485 | |||
486 | 2 | foreach ($fields as $name => $field) |
|
487 | { |
||
488 | // Set the field |
||
489 | 2 | $this->field($name, $field); |
|
490 | 2 | } |
|
491 | |||
492 | // Return Jam_Meta |
||
493 | 2 | return $this; |
|
494 | } |
||
495 | |||
496 | /** |
||
497 | * Getter / setter for individual associations. |
||
498 | * |
||
499 | * @param string $name name of the association |
||
500 | * @param mixed $association the association alias or object |
||
501 | * @return Jam_Association|Jam_Meta|null |
||
502 | */ |
||
503 | 644 | public function association($name, $association = NULL, $prepend = FALSE) |
|
504 | { |
||
505 | 644 | if ($association === NULL) |
|
506 | 644 | { |
|
507 | // Get the association |
||
508 | 644 | return Arr::get($this->_associations, $name); |
|
509 | } |
||
510 | |||
511 | 1 | if ($this->_initialized) |
|
512 | 1 | { |
|
513 | // Cannot set after initialization |
||
514 | throw new Kohana_Exception(':class already initialized, cannot set :association', array( |
||
515 | ':class' => Jam::class_name($this->_model), |
||
516 | ':association' => $name, |
||
517 | )); |
||
518 | } |
||
519 | |||
520 | // Set the association |
||
521 | if ($prepend) |
||
522 | 1 | { |
|
523 | $this->_associations = array($name => $association) + $this->_associations; |
||
524 | } |
||
525 | else |
||
526 | { |
||
527 | 1 | $this->_associations[$name] = $association; |
|
528 | } |
||
529 | |||
530 | // Return Jam_Meta |
||
531 | 1 | return $this; |
|
532 | } |
||
533 | |||
534 | /** |
||
535 | * The same as assocation method, but throws an exception if association does not exist |
||
536 | * @param string $name name of the association |
||
537 | * @param mixed $association the association alias or object |
||
538 | * @return Jam_Association|Jam_Meta|null |
||
539 | * @see association |
||
540 | */ |
||
541 | public function association_insist($name, $association = NULL) |
||
542 | { |
||
543 | if ( ! isset($this->_associations[$name])) |
||
544 | throw new Kohana_Exception('The association :name for this model :model does not exist', array(':name' => $name, ':model' => $this->_model)); |
||
545 | |||
546 | return $this->association($name, $association); |
||
547 | } |
||
548 | |||
549 | |||
550 | /** |
||
551 | * Gets and sets the associations for this object. |
||
552 | * |
||
553 | * Calling this multiple times will overwrite associations. |
||
554 | * |
||
555 | * @param array|null $associations |
||
556 | * @return array|Jam_Meta |
||
557 | */ |
||
558 | 1 | public function associations(array $associations = NULL) |
|
559 | { |
||
560 | 1 | if ($associations === NULL) |
|
561 | 1 | { |
|
562 | // Return the associations |
||
563 | return $this->_associations; |
||
564 | } |
||
565 | |||
566 | 1 | foreach ($associations as $name => $association) |
|
567 | { |
||
568 | // Set the associations |
||
569 | 1 | $this->association($name, $association); |
|
570 | 1 | } |
|
571 | |||
572 | // Return Jam_Meta |
||
573 | 1 | return $this; |
|
574 | } |
||
575 | |||
576 | /** |
||
577 | * Returns the defaults for the object. |
||
578 | * |
||
579 | * If $name is specified, then the defaults |
||
580 | * for that field are returned. |
||
581 | * |
||
582 | * @param string|null $name |
||
583 | * @return array|mixed|null |
||
584 | */ |
||
585 | 644 | public function defaults($name = NULL) |
|
586 | { |
||
587 | 644 | if ($name === NULL) |
|
588 | 644 | { |
|
589 | 644 | return $this->_defaults; |
|
590 | } |
||
591 | |||
592 | 1 | return $this->field($name)->default; |
|
593 | } |
||
594 | |||
595 | /** |
||
596 | * Returns or sets the name of the file used for errors. |
||
597 | * |
||
598 | * @return string |
||
599 | */ |
||
600 | 194 | public function errors_filename($value = NULL) |
|
601 | { |
||
602 | 194 | if (func_num_args() !== 0) |
|
603 | 194 | { |
|
604 | return $this->set('errors_filename', $value); |
||
605 | } |
||
606 | |||
607 | 194 | return $this->_errors_filename; |
|
608 | } |
||
609 | |||
610 | /** |
||
611 | * Gets or sets the behaviors attached to the object. |
||
612 | * |
||
613 | * @param array|null $behaviors |
||
614 | * @return array|Kohana_Jam_Meta |
||
615 | */ |
||
616 | 1 | public function behaviors(array $behaviors = NULL) |
|
617 | { |
||
618 | 1 | if (func_num_args() == 0) |
|
619 | 1 | { |
|
620 | 1 | return $this->_behaviors; |
|
621 | } |
||
622 | |||
623 | // Try to append |
||
624 | 1 | return $this->set_append('behaviors', $behaviors); |
|
625 | } |
||
626 | |||
627 | |||
628 | /** |
||
629 | * Get / Set individual behaviors. |
||
630 | * |
||
631 | * @param string $name name of the association |
||
632 | * @param mixed $association the association alias or object |
||
633 | * @return Jam_Association|Jam_Meta|null |
||
634 | */ |
||
635 | public function behavior($name, $behavior = NULL, $prepend = FALSE) |
||
665 | |||
666 | /** |
||
667 | * Gets the events attached to the object. |
||
668 | * |
||
669 | * @return array|Jam_Event |
||
670 | */ |
||
671 | 501 | public function events() |
|
672 | { |
||
673 | 501 | return $this->_events; |
|
674 | } |
||
675 | |||
676 | /** |
||
677 | * Gets or sets the model's primary key. |
||
678 | * |
||
679 | * @param string $value |
||
680 | * @return mixed |
||
681 | */ |
||
682 | 194 | public function primary_key($value = NULL) |
|
683 | { |
||
684 | 194 | if (func_num_args() !== 0) |
|
685 | 194 | { |
|
686 | 1 | return $this->set('primary_key', $value); |
|
691 | |||
692 | /** |
||
693 | * Gets or sets the model's name key |
||
694 | * |
||
695 | * @param string $value |
||
696 | * @return string |
||
697 | */ |
||
698 | 19 | public function name_key($value = NULL) |
|
707 | |||
708 | /** |
||
709 | * Gets or sets the model's foreign key |
||
710 | * |
||
711 | * @param string $value |
||
712 | * @return string |
||
713 | */ |
||
714 | 1 | public function foreign_key($value = NULL) |
|
723 | |||
724 | /** |
||
725 | * Gets the unique key basend on a model method |
||
726 | * |
||
727 | * @param string $value |
||
728 | * @return string |
||
729 | */ |
||
730 | 24 | public function unique_key($value = NULL) |
|
746 | |||
747 | /** |
||
748 | * Gets the model's polymorphic key. |
||
749 | * |
||
750 | * @param string $value |
||
751 | * @return string |
||
752 | */ |
||
753 | 385 | public function polymorphic_key($value = NULL) |
|
757 | |||
758 | /** |
||
759 | * Gets the model's child models |
||
760 | * |
||
761 | * @param array $children |
||
762 | * @return array |
||
763 | */ |
||
764 | public function children(array $children = NULL) |
||
774 | |||
775 | /** |
||
776 | * Gets or sets the object's sorting properties |
||
777 | * |
||
778 | * @param array|null $value |
||
779 | * @return array |
||
780 | */ |
||
781 | 1 | public function sorting($value = NULL) |
|
790 | |||
791 | } // End Kohana_Jam_Meta |
||
792 |
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.