Complex classes like Kohana_Jam_Association_Belongsto 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_Association_Belongsto, and based on these observations, apply Extract Interface, too.
1 | <?php defined('SYSPATH') OR die('No direct script access.'); |
||
11 | abstract class Kohana_Jam_Association_Belongsto extends Jam_Association { |
||
12 | |||
13 | /** |
||
14 | * Indicates whether this is a polymorphic association. Will add the polymorphic field, |
||
15 | * named <name>_model, if you set this as a string you can change the name of the field to it. |
||
16 | * @var boolean|string |
||
17 | */ |
||
18 | public $polymorphic = FALSE; |
||
19 | |||
20 | /** |
||
21 | * This will be set to the polymorphic model column automatically if nothing is set there |
||
22 | * @var model |
||
23 | */ |
||
24 | public $polymorphic_default_model = NULL; |
||
25 | |||
26 | /** |
||
27 | * The name of the actual field holding the id of the associated model. Defaults to |
||
28 | * <name>_id |
||
29 | * @var string |
||
30 | */ |
||
31 | public $foreign_key = NULL; |
||
32 | |||
33 | public $inverse_of = NULL; |
||
34 | |||
35 | public $count_cache = NULL; |
||
36 | |||
37 | public $field_options = array(); |
||
38 | |||
39 | protected $_default_field_options = array( |
||
40 | 'default' => NULL, |
||
41 | 'allow_null' => TRUE, |
||
42 | 'convert_empty' => TRUE, |
||
43 | ); |
||
44 | |||
45 | /** |
||
46 | * Automatically sets foreign to sensible defaults. |
||
47 | * |
||
48 | * @param string $model |
||
|
|||
49 | * @param string $name |
||
50 | * @return void |
||
51 | */ |
||
52 | 48 | public function initialize(Jam_Meta $meta, $name) |
|
94 | |||
95 | /** |
||
96 | * Load associated model (from database or after deserialization) |
||
97 | * @param Jam_Validated $model |
||
98 | * @param mixed $value |
||
99 | * @return Jam_Model |
||
100 | */ |
||
101 | 9 | public function load_fields(Jam_Validated $model, $value) |
|
110 | |||
111 | /** |
||
112 | * Return a Jam_Query_Builder_Join object to allow a query to join with this association |
||
113 | * You can join polymorphic association only when you pass an alias, wich will be used as the |
||
114 | * name of the model to match to the polymorphic_key |
||
115 | * |
||
116 | * @param string $alias table name alias |
||
117 | * @param string $type join type (LEFT, NATURAL) |
||
118 | * @return Jam_Query_Builder_Join |
||
119 | */ |
||
120 | 18 | public function join($alias, $type = NULL) |
|
141 | |||
142 | /** |
||
143 | * Get the belonging model for this association using the foreign key, |
||
144 | * if the data was changed, use the key from the changed data. |
||
145 | * Assign inverse_of |
||
146 | * |
||
147 | * @param Jam_Validated $model |
||
148 | * @param mixed $value changed data |
||
149 | * @param boolean $is_changed |
||
150 | * @return Jam_Model |
||
151 | */ |
||
152 | 21 | public function get(Jam_Validated $model, $value, $is_changed) |
|
153 | { |
||
154 | 21 | if ($is_changed) |
|
155 | { |
||
156 | 16 | if ($value instanceof Jam_Validated OR ! $value) |
|
157 | 9 | return $value; |
|
158 | |||
159 | 7 | $key = Jam_Association::primary_key($this->foreign_model($model), $value); |
|
160 | } |
||
161 | else |
||
162 | { |
||
163 | 5 | $key = $model->{$this->foreign_key}; |
|
164 | } |
||
165 | |||
166 | 12 | if ($key) |
|
167 | { |
||
168 | 11 | $item = $this->_find_item($this->foreign_model($model), $key); |
|
169 | } |
||
170 | 1 | elseif (is_array($value)) |
|
171 | { |
||
172 | $item = Jam::build($this->foreign_model($model), $value); |
||
173 | } |
||
174 | else |
||
175 | { |
||
176 | 1 | $item = NULL; |
|
177 | } |
||
178 | |||
179 | |||
180 | 12 | if ($item) |
|
181 | { |
||
182 | 11 | if (is_array($value) AND Jam_Association::is_changed($value)) |
|
183 | { |
||
184 | 3 | $item->set($value); |
|
185 | } |
||
186 | |||
187 | 11 | if ($item instanceof Jam_Model AND $this->inverse_of AND $item->meta()->association($this->inverse_of) instanceof Jam_Association_Hasone) |
|
188 | { |
||
189 | 1 | $item->retrieved($this->inverse_of, $model); |
|
190 | } |
||
191 | } |
||
192 | |||
193 | 12 | return $item; |
|
194 | } |
||
195 | |||
196 | /** |
||
197 | * Set releated model, by assigning foreign key for this model |
||
198 | * @param Jam_Validated $model |
||
199 | * @param mixed $value |
||
200 | * @param boolean $is_changed |
||
201 | */ |
||
202 | 28 | public function set(Jam_Validated $model, $value, $is_changed) |
|
233 | |||
234 | 2 | public function build(Jam_Validated $model, array $attributes = NULL) |
|
250 | |||
251 | /** |
||
252 | * Perform validation on the belonging model, if it was changed. |
||
253 | * @param Jam_Model $model |
||
254 | * @param Jam_Event_Data $data |
||
255 | * @param array $changed |
||
256 | */ |
||
257 | 27 | public function model_after_check(Jam_Model $model, Jam_Event_Data $data, $changed) |
|
267 | |||
268 | /** |
||
269 | * Save the related model before the main model, because we'll need the id to assign to the foreign key |
||
270 | * Only save related model if it has been changed, and is not in a process of saving itself |
||
271 | * @param Jam_Model $model |
||
272 | * @param Jam_Event_Data $data |
||
273 | * @param boolean $changed |
||
274 | */ |
||
275 | 22 | public function model_before_save(Jam_Model $model, Jam_Event_Data $data, $changed) |
|
293 | |||
294 | |||
295 | /** |
||
296 | * If we're using count_cache, increment the count_cache field on the foreign model |
||
297 | * @param Jam_Model $model |
||
298 | */ |
||
299 | 16 | public function model_after_create(Jam_Model $model) |
|
306 | |||
307 | /** |
||
308 | * Delete related model if it has been assigned as dependent |
||
309 | * If dependent is Jam_Association::DELETE - execute the delete method (and all events) |
||
310 | * IF dependent is Jam_Association::ERASE - simply remove from database without executing any events (faster) |
||
311 | * @param Jam_Model $model |
||
312 | */ |
||
313 | 9 | public function model_before_delete(Jam_Model $model) |
|
324 | |||
325 | /** |
||
326 | * If we're using count_cache, decrement the count_cache field on the foreign model |
||
327 | * @param Jam_Model $model |
||
328 | */ |
||
329 | 9 | public function model_after_delete(Jam_Model $model) |
|
336 | |||
337 | /** |
||
338 | * Check if association is polymophic |
||
339 | * @return boolean |
||
340 | */ |
||
341 | 77 | public function is_polymorphic() |
|
345 | |||
346 | /** |
||
347 | * Get the foreign model, if its a polymorphic, use the polymorphic field (e.g. item_model is the polymorphic field, then it's contents will be used) |
||
348 | * @param Jam_Model $model |
||
349 | * @return string |
||
350 | */ |
||
351 | 40 | public function foreign_model(Jam_Model $model) |
|
355 | |||
356 | /** |
||
357 | * Get an item based on a unique key from the database |
||
358 | * @param string $foreign_model |
||
359 | * @param string $key |
||
360 | * @return Jam_Model |
||
361 | */ |
||
362 | 2 | protected function _find_item($foreign_model, $key) |
|
369 | |||
370 | /** |
||
371 | * Delete an item with a specific key from the database |
||
372 | * @param string $foreign_model |
||
373 | * @param string $key |
||
374 | * @return Database_Result |
||
375 | */ |
||
376 | protected function _delete_item($foreign_model, $key) |
||
383 | |||
384 | } |
||
385 |
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.