Total Complexity | 46 |
Total Lines | 329 |
Duplicated Lines | 0 % |
Changes | 0 |
Complex classes like OrdersDetailForm_ItemRequest 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.
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 OrdersDetailForm_ItemRequest, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
24 | class OrdersDetailForm_ItemRequest extends GridFieldDetailForm_ItemRequest |
||
25 | { |
||
26 | |||
27 | private static $allowed_actions = [ |
||
28 | 'edit', |
||
29 | 'view', |
||
30 | 'ItemEditForm' |
||
31 | ]; |
||
32 | |||
33 | public function edit($request) |
||
34 | { |
||
35 | $controller = $this->getToplevelController(); |
||
36 | $form = $this->ItemEditForm(); |
||
37 | |||
38 | // If this is a new record, we need to save it first |
||
39 | if ($this->record->ID == 0) { |
||
40 | // ensure we populate any foreign keys first |
||
41 | $list = $this->gridField->getList(); |
||
42 | if ($list instanceof HasManyList && !$this->record->isInDB()) { |
||
43 | $key = $list->getForeignKey(); |
||
44 | $id = $list->getForeignID(); |
||
45 | $this->record->$key = $id; |
||
46 | } |
||
47 | |||
48 | $this->record->write(); |
||
49 | |||
50 | $controller |
||
51 | ->getRequest() |
||
52 | ->addHeader('X-Pjax', 'Content'); |
||
53 | |||
54 | return $controller->redirect($this->Link("edit")); |
||
55 | } |
||
56 | |||
57 | $return = $this->customise(array( |
||
58 | 'Backlink' => $controller->hasMethod('Backlink') ? $controller->Backlink() : $controller->Link(), |
||
59 | 'ItemEditForm' => $form, |
||
60 | ))->renderWith($this->getTemplates()); |
||
61 | |||
62 | if ($request->isAjax()) { |
||
63 | return $return; |
||
64 | } else { |
||
65 | // If not requested by ajax, we need to render it within the controller context+template |
||
66 | return $controller->customise(array( |
||
67 | // TODO CMS coupling |
||
68 | 'Content' => $return, |
||
69 | )); |
||
70 | } |
||
71 | } |
||
72 | |||
73 | public function ItemEditForm() |
||
74 | { |
||
75 | $form = parent::ItemEditForm(); |
||
76 | $fields = $form->Fields(); |
||
77 | $actions = $form->Actions(); |
||
78 | $record = $this->record; |
||
79 | $member = Member::currentUser(); |
||
80 | |||
81 | $can_view = $this->record->canView(); |
||
82 | $can_edit = $this->record->canEdit(); |
||
83 | $can_delete = $this->record->canDelete(); |
||
84 | $can_create = $this->record->canCreate(); |
||
85 | |||
86 | // First cache and remove the delete button |
||
87 | $delete_action = $actions->dataFieldByName("action_doDelete"); |
||
88 | $actions->removeByName("action_doDelete"); |
||
89 | |||
90 | // Deal with Estimate objects |
||
91 | if ($record->ClassName == Estimate::class) { |
||
92 | if ($record->ID && $can_edit) { |
||
93 | $actions->insertAfter( |
||
94 | FormAction::create( |
||
95 | 'doConvert', |
||
96 | _t('OrdersAdmin.ConvertToInvoice', 'Convert To Invoice') |
||
97 | )->setUseButtonTag(true) |
||
98 | ->addExtraClass('btn-outline-primary btn-hide-outline font-icon-sync'), |
||
99 | "action_doSave" |
||
100 | ); |
||
101 | } |
||
102 | } |
||
103 | |||
104 | // Deal with Order objects |
||
105 | if ($record->ClassName == Invoice::class) { |
||
106 | $can_change_status = $this->record->canChangeStatus(); |
||
107 | |||
108 | // Set our status field as a dropdown (has to be here to |
||
109 | // ignore canedit) |
||
110 | // Allow users to change status (as long as they have permission) |
||
111 | if ($can_edit || $can_change_status) { |
||
112 | $status_field = DropdownField::create( |
||
113 | 'Status', |
||
114 | null, |
||
115 | $record->config()->statuses |
||
116 | ); |
||
117 | |||
118 | // Set default status if we can |
||
119 | if (!$record->Status && !$record->config()->default_status) { |
||
120 | $status_field |
||
121 | ->setValue($record->config()->default_status); |
||
122 | } else { |
||
123 | $status_field |
||
124 | ->setValue($record->Status); |
||
125 | } |
||
126 | |||
127 | $fields->replaceField("Status", $status_field); |
||
128 | } |
||
129 | |||
130 | // Setup order history |
||
131 | if (Permission::check(array('ORDERS_EDIT_INVOICES', 'ADMIN'), 'any', $member)) { |
||
132 | $versions = $record->AllVersions(); |
||
133 | $first_version = $versions->First(); |
||
134 | $curr_version = ($first_version) ? $versions->First() : null; |
||
135 | $message = ""; |
||
136 | |||
137 | foreach ($versions as $version) { |
||
138 | $i = $version->Version; |
||
139 | $name = "History_{$i}"; |
||
140 | |||
141 | if ($i > 1) { |
||
142 | $frm = Versioned::get_version($record->ClassName, $record->ID, $i - 1); |
||
143 | $to = Versioned::get_version($record->ClassName, $record->ID, $i); |
||
144 | $diff = new DataDifferencer($frm, $to); |
||
145 | |||
146 | if ($version->Author()) { |
||
147 | $message = "<p>{$version->Author()->FirstName} ({$version->LastEdited})</p>"; |
||
148 | } else { |
||
149 | $message = "<p>Unknown ({$version->LastEdited})</p>"; |
||
150 | } |
||
151 | |||
152 | if ($diff->ChangedFields()->exists()) { |
||
153 | $message .= "<ul>"; |
||
154 | |||
155 | // Now loop through all changed fields and track as message |
||
156 | foreach ($diff->ChangedFields() as $change) { |
||
157 | if ($change->Name != "LastEdited") { |
||
158 | $message .= "<li>{$change->Title}: {$change->Diff}</li>"; |
||
159 | } |
||
160 | } |
||
161 | |||
162 | $message .= "</ul>"; |
||
163 | } |
||
164 | |||
165 | $fields->addFieldToTab("Root.History", LiteralField::create( |
||
166 | $name, |
||
167 | "<div class=\"field\">{$message}</div>" |
||
168 | )); |
||
169 | } |
||
170 | } |
||
171 | } |
||
172 | |||
173 | // Is user cannot edit, but can change status, add change |
||
174 | // status button |
||
175 | if ($record->ID && !$can_edit && $can_change_status) { |
||
176 | $actions->push( |
||
177 | FormAction::create('doChangeStatus', _t('OrdersAdmin.Save', 'Save')) |
||
178 | ->setUseButtonTag(true) |
||
179 | ->addExtraClass('btn-primary font-icon-save') |
||
180 | ); |
||
181 | } |
||
182 | } |
||
183 | |||
184 | // Add a duplicate button, either after the save button or |
||
185 | // the change status "save" button. |
||
186 | if ($record->ID) { |
||
187 | $duplicate_button = FormAction::create( |
||
188 | 'doDuplicate', |
||
189 | _t('OrdersAdmin.Duplicate', 'Duplicate') |
||
190 | )->setUseButtonTag(true) |
||
191 | ->addExtraClass('btn-outline-primary btn-hide-outline font-icon-switch'); |
||
192 | |||
193 | if ($actions->find("Name", "action_doSave")) { |
||
194 | $actions->insertAfter($duplicate_button, "action_doSave"); |
||
195 | } |
||
196 | |||
197 | if ($actions->find("Name", "action_doChangeStatus")) { |
||
198 | $actions->insertAfter($duplicate_button, "action_doChangeStatus"); |
||
199 | } |
||
200 | } |
||
201 | |||
202 | if ($record->ID) { |
||
203 | $html = '<a href="' . $record->DisplayLink() . '" '; |
||
204 | $html .= 'target="_blank" class="btn btn-outline-primary btn-hide-outline font-icon-eye"'; |
||
205 | $html .= '>' . _t('OrdersAdmin.View', 'View') . '</a>'; |
||
206 | |||
207 | $view_field = LiteralField::create('ViewButton', $html); |
||
208 | |||
209 | $html = '<a href="' . $record->PDFLink() . '" '; |
||
210 | $html .= 'target="_blank" class="btn btn-outline-primary btn-hide-outline font-icon-down-circled"'; |
||
211 | $html .= '>' . _t('OrdersAdmin.Download', 'Download') . '</a>'; |
||
212 | |||
213 | $download_field = LiteralField::create('DownloadButton', $html); |
||
214 | |||
215 | $actions->push($view_field, "action_doSave"); |
||
216 | $actions->push($download_field, "action_doSave"); |
||
217 | } |
||
218 | |||
219 | // Finally, if allowed, re-add the delete button (so it is last) |
||
220 | if ($record->ID && $can_delete) { |
||
221 | $actions->push($delete_action); |
||
222 | } |
||
223 | |||
224 | $this->extend("updateItemEditForm", $form); |
||
225 | |||
226 | return $form; |
||
227 | } |
||
228 | |||
229 | public function doDuplicate($data, $form) |
||
230 | { |
||
231 | $record = $this->record; |
||
232 | |||
233 | if ($record && !$record->canEdit()) { |
||
234 | return Security::permissionFailure($this); |
||
235 | } |
||
236 | |||
237 | $form->saveInto($record); |
||
238 | |||
239 | $record->write(); |
||
240 | |||
241 | $new_record = $record->duplicate(); |
||
242 | |||
243 | $this->gridField->getList()->add($new_record); |
||
244 | |||
245 | $message = sprintf( |
||
246 | _t('OrdersAdmin.Duplicated', 'Duplicated %s %s'), |
||
247 | $this->record->singular_name(), |
||
248 | '"'.Convert::raw2xml($this->record->Title).'"' |
||
249 | ); |
||
250 | |||
251 | $toplevelController = $this->getToplevelController(); |
||
252 | if ($toplevelController && $toplevelController instanceof LeftAndMain) { |
||
253 | $backForm = $toplevelController->getEditForm(); |
||
254 | $backForm->sessionMessage($message, 'good', ValidationResult::CAST_HTML); |
||
255 | } else { |
||
256 | $form->sessionMessage($message, 'good', ValidationResult::CAST_HTML); |
||
257 | } |
||
258 | |||
259 | $toplevelController = $this->getToplevelController(); |
||
260 | $toplevelController->getRequest()->addHeader('X-Pjax', 'Content'); |
||
261 | |||
262 | return $toplevelController->redirect($this->getBacklink(), 302); |
||
263 | } |
||
264 | |||
265 | public function doConvert($data, $form) |
||
298 | } |
||
299 | |||
300 | public function doChangeStatus($data, $form) |
||
353 | } |
||
354 | } |
||
355 | } |
||
356 |