Complex classes like OrderItem 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 OrderItem, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
13 | class OrderItem extends OrderAttribute |
||
14 | { |
||
15 | /** |
||
16 | * what variables are accessible through http://mysite.com/api/ecommerce/v1/OrderItem/. |
||
17 | * |
||
18 | * @var array |
||
19 | */ |
||
20 | private static $api_access = array( |
||
|
|||
21 | 'view' => array( |
||
22 | 'InternalItemID', |
||
23 | 'CalculatedTotal', |
||
24 | 'TableTitle', |
||
25 | 'TableSubTitleNOHTML', |
||
26 | 'Name', |
||
27 | 'TableValue', |
||
28 | 'Quantity', |
||
29 | 'BuyableID', |
||
30 | 'BuyableClassName', |
||
31 | 'Version', |
||
32 | 'UnitPrice', |
||
33 | 'Total', |
||
34 | 'Order', |
||
35 | ), |
||
36 | ); |
||
37 | |||
38 | /** |
||
39 | * stardard SS variable. |
||
40 | * |
||
41 | * @var array |
||
42 | */ |
||
43 | private static $db = array( |
||
44 | 'Quantity' => 'Double', |
||
45 | 'BuyableID' => 'Int', |
||
46 | 'BuyableClassName' => 'Varchar(60)', |
||
47 | 'Version' => 'Int', |
||
48 | ); |
||
49 | |||
50 | /** |
||
51 | * @var array |
||
52 | * stardard SS definition |
||
53 | */ |
||
54 | private static $indexes = array( |
||
55 | 'Quantity' => true, |
||
56 | 'BuyableID' => true, |
||
57 | 'BuyableClassName' => true, |
||
58 | ); |
||
59 | |||
60 | /** |
||
61 | * @var array |
||
62 | * stardard SS definition |
||
63 | */ |
||
64 | private static $casting = array( |
||
65 | 'UnitPrice' => 'Currency', |
||
66 | 'UnitPriceAsMoney' => 'Money', |
||
67 | 'Total' => 'Currency', |
||
68 | 'TotalAsMoney' => 'Money', |
||
69 | 'InternalItemID' => 'Varchar', |
||
70 | 'Link' => 'Varchar', |
||
71 | 'AbsoluteLink' => 'Varchar', |
||
72 | 'BuyableLink' => 'Varchar', |
||
73 | 'BuyableExists' => 'Boolean', |
||
74 | 'BuyableFullName' => 'Varchar', |
||
75 | 'BuyableMoreDetails' => 'Varchar' |
||
76 | ); |
||
77 | |||
78 | ###################### |
||
79 | ## CMS CONFIG ## |
||
80 | ###################### |
||
81 | |||
82 | /** |
||
83 | * @var array |
||
84 | * stardard SS definition |
||
85 | */ |
||
86 | private static $searchable_fields = array( |
||
87 | 'OrderID' => array( |
||
88 | 'field' => 'NumericField', |
||
89 | 'title' => 'Order Number', |
||
90 | ), |
||
91 | //"TableTitle" => "PartialMatchFilter", |
||
92 | //"UnitPrice", |
||
93 | 'Quantity', |
||
94 | //"Total" |
||
95 | ); |
||
96 | |||
97 | /** |
||
98 | * @var array |
||
99 | * stardard SS definition |
||
100 | */ |
||
101 | private static $field_labels = array( |
||
102 | //@todo - complete |
||
103 | ); |
||
104 | |||
105 | /** |
||
106 | * @var array |
||
107 | * stardard SS definition |
||
108 | */ |
||
109 | private static $summary_fields = array( |
||
110 | 'OrderID' => 'Order ID', |
||
111 | 'BuyableFullName' => 'Item', |
||
112 | 'BuyableMoreDetails' => 'Details ... ', |
||
113 | 'UnitPrice' => 'Unit Price', |
||
114 | 'Quantity' => 'Quantity', |
||
115 | 'Total' => 'Total Price', |
||
116 | ); |
||
117 | |||
118 | /** |
||
119 | * singular name of the object. it is recommended to override this |
||
120 | * in any extensions of this class. |
||
121 | * |
||
122 | * @var string |
||
123 | */ |
||
124 | private static $singular_name = 'Order Item'; |
||
125 | public function i18n_singular_name() |
||
129 | |||
130 | /** |
||
131 | * plural name of the object. it is recommended to override this |
||
132 | * in any extensions of this class. |
||
133 | * |
||
134 | * @var string |
||
135 | */ |
||
136 | private static $plural_name = 'Order Items'; |
||
137 | public function i18n_plural_name() |
||
141 | |||
142 | /** |
||
143 | * Standard SS variable. |
||
144 | * |
||
145 | * @var string |
||
146 | */ |
||
147 | private static $description = 'Any item that is added to an order and sits before the sub-total. '; |
||
148 | |||
149 | /** |
||
150 | * HACK: Versioned is BROKEN this method helps in fixing it. |
||
151 | * Basically, in Versioned, you get a hard-coded error |
||
152 | * when you retrieve an older version of a DataObject. |
||
153 | * This method returns null if it does not exist. |
||
154 | * |
||
155 | * Idea is from Jeremy: https://github.com/burnbright/silverstripe-shop/blob/master/code/products/FixVersioned.php |
||
156 | * |
||
157 | * @param string $class |
||
158 | * @param int $id |
||
159 | * @param int $version |
||
160 | * |
||
161 | * @return DataObject | Null |
||
162 | */ |
||
163 | public static function get_version($class, $id, $version) |
||
172 | |||
173 | /** |
||
174 | * Standard SS method. |
||
175 | * |
||
176 | * @var string |
||
177 | */ |
||
178 | public function getCMSFields() |
||
262 | |||
263 | /** |
||
264 | * standard SS method. |
||
265 | * |
||
266 | * @param Member $member |
||
267 | * |
||
268 | * @return bool |
||
269 | **/ |
||
270 | public function canDelete($member = null) |
||
274 | |||
275 | /** |
||
276 | * Determine which properties on the DataObject are |
||
277 | * searchable, and map them to their default {@link FormField} |
||
278 | * representations. Used for scaffolding a searchform for {@link ModelAdmin}. |
||
279 | * |
||
280 | * Some additional logic is included for switching field labels, based on |
||
281 | * how generic or specific the field type is. |
||
282 | * |
||
283 | * Used by {@link SearchContext}. |
||
284 | * |
||
285 | * @param array $_params |
||
286 | * 'fieldClasses': Associative array of field names as keys and FormField classes as values |
||
287 | * 'restrictFields': Numeric array of a field name whitelist |
||
288 | * |
||
289 | * @return FieldList |
||
290 | */ |
||
291 | public function scaffoldSearchFields($_params = null) |
||
298 | |||
299 | /** |
||
300 | * standard SS method. |
||
301 | * |
||
302 | * @param BuyableModel $buyable |
||
303 | * @param float $quantity |
||
304 | * |
||
305 | * @return FieldList |
||
306 | **/ |
||
307 | public function addBuyableToOrderItem(BuyableModel $buyable, $quantity = 1) |
||
314 | |||
315 | /** |
||
316 | * used to return data for ajax. |
||
317 | * |
||
318 | * @param array |
||
319 | * |
||
320 | * @return array used to create JSON for AJAX |
||
321 | **/ |
||
322 | public function updateForAjax(array $js) |
||
387 | |||
388 | /** |
||
389 | * saves details about the Order Item before the order is submittted. |
||
390 | * |
||
391 | * @param bool $recalculate - run it, even if it has run already |
||
392 | **/ |
||
393 | public function runUpdate($recalculate = false) |
||
417 | |||
418 | |||
419 | /** |
||
420 | * Standard SS method. |
||
421 | * If the quantity is zero then we set it to 1. |
||
422 | * TODO: evaluate this rule. |
||
423 | */ |
||
424 | public function onBeforeWrite() |
||
446 | |||
447 | /** |
||
448 | * Standard SS method |
||
449 | * the method below is very important... |
||
450 | * We initialise the order once it has an OrderItem. |
||
451 | */ |
||
452 | public function onAfterWrite() |
||
463 | |||
464 | /** |
||
465 | * Check if two Order Items are the same. |
||
466 | * Useful when adding two items to cart. |
||
467 | * |
||
468 | * @param OrderItem $orderItem |
||
469 | * |
||
470 | * @return bool |
||
471 | **/ |
||
472 | public function hasSameContent(OrderItem $orderItem) |
||
480 | |||
481 | ###################### |
||
482 | ## TEMPLATE METHODS ## |
||
483 | ###################### |
||
484 | |||
485 | protected static $calculated_buyable_price = array(); |
||
486 | public static function reset_calculated_buyable_price() |
||
490 | |||
491 | public function UnitPrice($recalculate = false) |
||
518 | |||
519 | public function UnitPriceAsMoney($recalculate = false) |
||
527 | |||
528 | /** |
||
529 | * @param bool $recalculate - forces recalculation of price |
||
530 | * |
||
531 | * @return float |
||
532 | */ |
||
533 | public function Total($recalculate = false) |
||
552 | |||
553 | /** |
||
554 | * @param bool $recalculate - forces recalculation of price |
||
555 | * |
||
556 | * @return Money |
||
557 | */ |
||
558 | public function TotalAsMoney($recalculate = false) |
||
566 | |||
567 | /** |
||
568 | * Casted variable |
||
569 | * returns InternalItemID from Buyable. |
||
570 | */ |
||
571 | public function InternalItemID() |
||
581 | |||
582 | /** |
||
583 | * @return Field (EcomQuantityField) |
||
584 | **/ |
||
585 | public function QuantityField() |
||
589 | |||
590 | /** |
||
591 | * @return Currency (DB Object) |
||
592 | **/ |
||
593 | public function TotalAsCurrencyObject() |
||
597 | |||
598 | ########################## |
||
599 | ## OTHER LOOKUP METHODS ## |
||
600 | ########################## |
||
601 | |||
602 | /** |
||
603 | * @param int $orderID |
||
604 | * |
||
605 | */ |
||
606 | public static function reset_price_has_been_fixed($orderID = 0) |
||
610 | |||
611 | |||
612 | |||
613 | /** |
||
614 | * Store for buyables. |
||
615 | * We store this here to speed up things a little |
||
616 | * Format is like this |
||
617 | * Array( |
||
618 | * 0 => Buyable (versioned) |
||
619 | * 1 => Buyable (current) |
||
620 | * );. |
||
621 | * |
||
622 | * @var array |
||
623 | */ |
||
624 | protected $tempBuyableStore = array(); |
||
625 | |||
626 | /** |
||
627 | * @param bool $current - is this a current one, or an older VERSION ? |
||
628 | * |
||
629 | * @return DataObject (Any type of Data Object that is buyable) |
||
630 | **/ |
||
631 | public function Buyable($current = false) |
||
635 | |||
636 | /** |
||
637 | * @param string $current - is this a current one, or an older VERSION ? |
||
638 | * |
||
639 | * @return DataObject (Any type of Data Object that is buyable) |
||
640 | **/ |
||
641 | public function getBuyable($current = '') |
||
706 | |||
707 | /** |
||
708 | * @alias for getBuyableTitle |
||
709 | * @return string |
||
710 | **/ |
||
711 | public function BuyableTitle() |
||
715 | |||
716 | /** |
||
717 | * @return string |
||
718 | **/ |
||
719 | public function getBuyableTitle() |
||
731 | |||
732 | /** |
||
733 | * @alias for getBuyableLink |
||
734 | * @return string |
||
735 | */ |
||
736 | public function BuyableLink() |
||
740 | |||
741 | /** |
||
742 | * |
||
743 | * @return string |
||
744 | */ |
||
745 | public function getBuyableLink() |
||
758 | |||
759 | /** |
||
760 | * @alias for getBuyableExists |
||
761 | * @return bool |
||
762 | */ |
||
763 | public function BuyableExists() |
||
767 | |||
768 | /** |
||
769 | * |
||
770 | * @return bool |
||
771 | */ |
||
772 | public function getBuyableExists() |
||
782 | |||
783 | |||
784 | /** |
||
785 | * @alias for getBuyableFullName |
||
786 | * @return String |
||
787 | */ |
||
788 | public function BuyableFullName() |
||
792 | |||
793 | /** |
||
794 | * @return String |
||
795 | */ |
||
796 | public function getBuyableFullName() |
||
805 | |||
806 | /** |
||
807 | * @alias for getBuyableMoreDetails |
||
808 | * @return String |
||
809 | */ |
||
810 | public function BuyableMoreDetails() |
||
814 | |||
815 | /** |
||
816 | * @return String |
||
817 | */ |
||
818 | public function getBuyableMoreDetails() |
||
832 | |||
833 | ########################## |
||
834 | ## LINKS ## |
||
835 | ########################## |
||
836 | |||
837 | /** |
||
838 | * @return string (URLSegment) |
||
839 | **/ |
||
840 | public function Link() |
||
844 | |||
845 | /** |
||
846 | * @return string (URLSegment) |
||
847 | **/ |
||
848 | public function getLink() |
||
857 | |||
858 | /** |
||
859 | * alias |
||
860 | * @return string |
||
861 | */ |
||
862 | public function AbsoluteLink() |
||
866 | |||
867 | /** |
||
868 | * @return string |
||
869 | */ |
||
870 | public function getAbsoluteLink() |
||
874 | |||
875 | /** |
||
876 | * @return string (URLSegment) |
||
877 | **/ |
||
878 | public function CheckoutLink() |
||
882 | |||
883 | ## Often Overloaded functions ## |
||
884 | |||
885 | /** |
||
886 | * @return string (URLSegment) |
||
887 | **/ |
||
888 | public function AddLink() |
||
892 | |||
893 | /** |
||
894 | * @return string (URLSegment) |
||
895 | **/ |
||
896 | public function IncrementLink() |
||
900 | |||
901 | /** |
||
902 | * @return string (URLSegment) |
||
903 | **/ |
||
904 | public function DecrementLink() |
||
908 | |||
909 | /** |
||
910 | * @return string (URLSegment) |
||
911 | **/ |
||
912 | public function RemoveLink() |
||
916 | |||
917 | /** |
||
918 | * @return string (URLSegment) |
||
919 | **/ |
||
920 | public function RemoveAllLink() |
||
924 | |||
925 | /** |
||
926 | * @return string (URLSegment) |
||
927 | **/ |
||
928 | public function RemoveAllAndEditLink() |
||
932 | |||
933 | /** |
||
934 | * @return string (URLSegment) |
||
935 | **/ |
||
936 | public function SetSpecificQuantityItemLink($quantity) |
||
940 | |||
941 | /** |
||
942 | * @Todo: do we still need this? |
||
943 | * |
||
944 | * @return array for use as get variables in link |
||
945 | **/ |
||
946 | protected function linkParameters() |
||
958 | |||
959 | public function debug() |
||
969 | } |
||
970 |