| 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 |