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 | 162 | public function __construct($model) |
|
126 | |||
127 | /** |
||
128 | * This is called after initialization to |
||
129 | * finalize any changes to the meta object. |
||
130 | * |
||
131 | * @param string $model |
||
132 | */ |
||
133 | 7 | public function finalize($model) |
|
134 | { |
||
135 | 7 | if ($this->_initialized) |
|
136 | 7 | return; |
|
137 | |||
138 | // Set the name of a possible behavior class |
||
139 | 7 | $behavior_class = Jam::behavior_prefix().Jam::capitalize_class_name($model); |
|
140 | |||
141 | // See if we have a special behavior class to use |
||
142 | 7 | if (class_exists($behavior_class)) |
|
143 | 7 | { |
|
144 | // Load behavior |
||
145 | $behavior = new $behavior_class; |
||
146 | |||
147 | if ( ! in_array($behavior, $this->_behaviors)) |
||
148 | { |
||
149 | // Add to behaviors |
||
150 | $this->_behaviors[] = $behavior; |
||
151 | } |
||
152 | } |
||
153 | |||
154 | 7 | foreach ($this->_behaviors as $name => $behavior) |
|
155 | { |
||
156 | 6 | if ( ! $behavior instanceof Jam_Behavior) |
|
157 | 6 | throw new Kohana_Exception('Behavior at index [ :key ] is not an instance of Jam_Behavior, :type found.', array( |
|
158 | ':type' => is_object($behavior) ? ('instance of '.get_class($behavior)) : gettype($behavior), |
||
159 | ':key' => $name, |
||
160 | )); |
||
161 | |||
162 | // Initialize behavior |
||
163 | 6 | $behavior->initialize($this, $name); |
|
|
|||
164 | 7 | } |
|
165 | |||
166 | // Allow modification of this meta object by the behaviors |
||
167 | 7 | $this->_events->trigger('meta.before_finalize', $this); |
|
168 | |||
169 | // Ensure certain fields are not overridden |
||
170 | 7 | $this->_model = $model; |
|
171 | 7 | $this->_defaults = array(); |
|
172 | |||
173 | 7 | if ( ! $this->_errors_filename) |
|
174 | 7 | { |
|
175 | // Default errors filename to the model's name |
||
176 | 7 | $this->_errors_filename = 'validators/'.$this->_model; |
|
177 | 7 | } |
|
178 | |||
179 | // Table should be a sensible default |
||
180 | 7 | if (empty($this->_table)) |
|
181 | 7 | { |
|
182 | 6 | $this->_table = Inflector::plural($model); |
|
183 | 6 | } |
|
184 | |||
185 | // Can we set a sensible foreign key? |
||
186 | 7 | if (empty($this->_foreign_key)) |
|
187 | 7 | { |
|
188 | 6 | $this->_foreign_key = $model.'_id'; |
|
189 | 6 | } |
|
190 | |||
191 | 7 | if (empty($this->_unique_key) AND method_exists(Jam::class_name($this->_model), 'unique_key')) |
|
192 | 7 | { |
|
193 | $this->_unique_key = Jam::class_name($this->_model).'::unique_key'; |
||
194 | } |
||
195 | |||
196 | 7 | foreach ($this->_fields as $column => $field) |
|
197 | { |
||
198 | // Ensure a default primary key is set |
||
199 | 7 | if ($field instanceof Jam_Field AND $field->primary AND empty($this->_primary_key)) |
|
200 | 7 | { |
|
201 | 6 | $this->_primary_key = $column; |
|
202 | 6 | } |
|
203 | |||
204 | // Ensure a default plymorphic key is set |
||
205 | 7 | if ($field instanceof Jam_Field_Polymorphic AND empty($this->_polymorphic_key)) |
|
206 | 7 | { |
|
207 | 5 | $this->_polymorphic_key = $column; |
|
208 | 5 | } |
|
209 | 7 | } |
|
210 | |||
211 | 7 | foreach ($this->_associations as $column => & $association) |
|
212 | { |
||
213 | 6 | $association->initialize($this, $column); |
|
214 | 7 | } |
|
215 | |||
216 | 7 | foreach ($this->_fields as $column => & $field) |
|
217 | { |
||
218 | 7 | $field->initialize($this, $column); |
|
219 | 7 | $this->_defaults[$column] = $field->default; |
|
220 | 7 | } |
|
221 | |||
222 | 7 | if ( ! $this->_collection AND ($class = Jam::collection_prefix().Jam::capitalize_class_name($this->_model)) AND class_exists($class)) |
|
223 | 7 | { |
|
224 | 5 | $this->_collection = $class; |
|
225 | 5 | } |
|
226 | |||
227 | // Meta object is initialized and no longer writable |
||
228 | 7 | $this->_initialized = TRUE; |
|
229 | |||
230 | // Final meta callback |
||
231 | 7 | $this->_events->trigger('meta.after_finalize', $this); |
|
232 | 7 | } |
|
233 | |||
234 | /** |
||
235 | * Returns a string representation of the meta object. |
||
236 | * |
||
237 | * @return string |
||
238 | */ |
||
239 | public function __toString() |
||
243 | |||
244 | /** |
||
245 | * Returns whether or not the meta object has finished initialization |
||
246 | * |
||
247 | * @return boolean |
||
248 | */ |
||
249 | 3 | public function initialized() |
|
253 | |||
254 | 81 | public function collection($value = NULL) |
|
262 | |||
263 | 6 | public function validator($field, $options) |
|
277 | |||
278 | 1 | public function with_options($options) |
|
283 | |||
284 | public function end() |
||
289 | |||
290 | 11 | public function validators() |
|
294 | |||
295 | 21 | public function execute_validators(Jam_Validated $model, $force = FALSE) |
|
306 | |||
307 | /** |
||
308 | * Allows setting a variable only when not initialized. |
||
309 | * |
||
310 | * @param string $key |
||
311 | * @param mixed $value |
||
312 | * @return $this |
||
313 | */ |
||
314 | 7 | protected function set($key, $value) |
|
330 | |||
331 | /** |
||
332 | * Allows appending an array to a variable only when not initialized. |
||
333 | * |
||
334 | * @param string $key |
||
335 | * @param mixed $value |
||
336 | * @return $this |
||
337 | */ |
||
338 | 6 | protected function set_append($key, $value) |
|
357 | |||
358 | /** |
||
359 | * Gets or sets the db group |
||
360 | * |
||
361 | * @param string $value |
||
362 | * @return $this|string |
||
363 | */ |
||
364 | 163 | public function db($value = NULL) |
|
373 | |||
374 | /** |
||
375 | * Returns the model name this object is attached to |
||
376 | * |
||
377 | * @return string |
||
378 | */ |
||
379 | 269 | public function model() |
|
383 | |||
384 | /** |
||
385 | * Gets or sets the table |
||
386 | * |
||
387 | * @param string $value |
||
388 | * @return $this|string |
||
389 | */ |
||
390 | 169 | public function table($value = NULL) |
|
399 | |||
400 | /** |
||
401 | * Getter / setter for individual fields. |
||
402 | * |
||
403 | * @param string $name name of the field |
||
404 | * @param mixed $field the field alias or object |
||
405 | * @return Jam_Field|$this|null |
||
406 | */ |
||
407 | 262 | public function field($name, $field = NULL, $prepend = FALSE) |
|
437 | |||
438 | /** |
||
439 | * The same as field method, but throws an exception if association does not exist |
||
440 | * |
||
441 | * @param string $name name of the field |
||
442 | * @param mixed $field the field alias or object |
||
443 | * @return Jam_Field|$this|null |
||
444 | */ |
||
445 | public function field_insist($name, $field = NULL) |
||
452 | |||
453 | 1 | public function attribute($name) |
|
457 | |||
458 | public function attribute_insist($name) |
||
467 | |||
468 | |||
469 | /** |
||
470 | * Gets and sets the fields for this object. |
||
471 | * |
||
472 | * Calling this multiple times will overwrite fields. |
||
473 | * |
||
474 | * @param array|null $fields |
||
475 | * @return Jam_Field[]|$this |
||
476 | */ |
||
477 | 206 | public function fields(array $fields = NULL) |
|
494 | |||
495 | /** |
||
496 | * Getter / setter for individual associations. |
||
497 | * |
||
498 | * @param string $name name of the association |
||
499 | * @param mixed $association the association alias or object |
||
500 | * @return Jam_Association|$this|null |
||
501 | */ |
||
502 | 752 | public function association($name, $association = NULL, $prepend = FALSE) |
|
532 | |||
533 | /** |
||
534 | * The same as assocation method, but throws an exception if association does not exist |
||
535 | * @param string $name name of the association |
||
536 | * @param mixed $association the association alias or object |
||
537 | * @return Jam_Association|$this|null |
||
538 | * @see association |
||
539 | */ |
||
540 | public function association_insist($name, $association = NULL) |
||
547 | |||
548 | |||
549 | /** |
||
550 | * Gets and sets the associations for this object. |
||
551 | * |
||
552 | * Calling this multiple times will overwrite associations. |
||
553 | * |
||
554 | * @param array|null $associations |
||
555 | * @return Jam_Association[]|$this |
||
556 | */ |
||
557 | 6 | public function associations(array $associations = NULL) |
|
574 | |||
575 | /** |
||
576 | * Returns the defaults for the object. |
||
577 | * |
||
578 | * If $name is specified, then the defaults |
||
579 | * for that field are returned. |
||
580 | * |
||
581 | * @param string|null $name |
||
582 | * @return array|mixed|null |
||
583 | */ |
||
584 | 752 | public function defaults($name = NULL) |
|
593 | |||
594 | /** |
||
595 | * Returns or sets the name of the file used for errors. |
||
596 | * |
||
597 | * @return $this|string |
||
598 | */ |
||
599 | 201 | public function errors_filename($value = NULL) |
|
608 | |||
609 | /** |
||
610 | * Gets or sets the behaviors attached to the object. |
||
611 | * |
||
612 | * @param array|null $behaviors |
||
613 | * @return Jam_Behavior[]|$this |
||
614 | */ |
||
615 | 6 | public function behaviors(array $behaviors = NULL) |
|
625 | |||
626 | |||
627 | /** |
||
628 | * Get / Set individual behaviors. |
||
629 | * |
||
630 | * @param string $name name of the association |
||
631 | * @param mixed $association the association alias or object |
||
632 | * @return Jam_Behavior|$this|null |
||
633 | */ |
||
634 | public function behavior($name, $behavior = NULL, $prepend = FALSE) |
||
664 | |||
665 | /** |
||
666 | * Gets the events attached to the object. |
||
667 | * |
||
668 | * @return Jam_Event |
||
669 | */ |
||
670 | 575 | public function events() |
|
674 | |||
675 | /** |
||
676 | * Gets or sets the model's primary key. |
||
677 | * |
||
678 | * @param string $value |
||
679 | * @return mixed |
||
680 | */ |
||
681 | 218 | public function primary_key($value = NULL) |
|
690 | |||
691 | /** |
||
692 | * Gets or sets the model's name key |
||
693 | * |
||
694 | * @param string $value |
||
695 | * @return string|$this |
||
696 | */ |
||
697 | 35 | public function name_key($value = NULL) |
|
706 | |||
707 | /** |
||
708 | * Gets or sets the model's foreign key |
||
709 | * |
||
710 | * @param string $value |
||
711 | * @return string|$this |
||
712 | */ |
||
713 | 1 | public function foreign_key($value = NULL) |
|
722 | |||
723 | /** |
||
724 | * Gets the unique key basend on a model method |
||
725 | * |
||
726 | * @param string $value |
||
727 | * @return string |
||
728 | */ |
||
729 | 32 | public function unique_key($value = NULL) |
|
745 | |||
746 | /** |
||
747 | * Gets the model's polymorphic key. |
||
748 | * |
||
749 | * @param string $value |
||
750 | * @return string |
||
751 | */ |
||
752 | 440 | public function polymorphic_key($value = NULL) |
|
756 | |||
757 | /** |
||
758 | * Gets the model's child models |
||
759 | * |
||
760 | * @param array $children |
||
761 | * @return array |
||
762 | */ |
||
763 | public function children(array $children = NULL) |
||
773 | |||
774 | /** |
||
775 | * Gets or sets the object's sorting properties |
||
776 | * |
||
777 | * @param array|null $value |
||
778 | * @return array |
||
779 | */ |
||
780 | 1 | public function sorting($value = NULL) |
|
789 | |||
790 | } // End Kohana_Jam_Meta |
||
791 |
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.