These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | /** |
||
4 | * @description: see OrderStep.md |
||
5 | * |
||
6 | * |
||
7 | * @authors: Nicolaas [at] Sunny Side Up .co.nz |
||
8 | * @package: ecommerce |
||
9 | * @sub-package: model |
||
10 | * @inspiration: Silverstripe Ltd, Jeremy |
||
11 | **/ |
||
12 | class OrderStep extends DataObject implements EditableEcommerceObject |
||
13 | { |
||
14 | |||
15 | |||
16 | /** |
||
17 | * standard SS variable. |
||
18 | * |
||
19 | * @return array |
||
20 | */ |
||
21 | private static $db = array( |
||
22 | 'Name' => 'Varchar(50)', |
||
23 | 'Code' => 'Varchar(50)', |
||
24 | 'Description' => 'Text', |
||
25 | 'EmailSubject' => 'Varchar(200)', |
||
26 | 'CustomerMessage' => 'HTMLText', |
||
27 | //customer privileges |
||
28 | 'CustomerCanEdit' => 'Boolean', |
||
29 | 'CustomerCanCancel' => 'Boolean', |
||
30 | 'CustomerCanPay' => 'Boolean', |
||
31 | //What to show the customer... |
||
32 | 'ShowAsUncompletedOrder' => 'Boolean', |
||
33 | 'ShowAsInProcessOrder' => 'Boolean', |
||
34 | 'ShowAsCompletedOrder' => 'Boolean', |
||
35 | 'HideStepFromCustomer' => 'Boolean', |
||
36 | //sorting index |
||
37 | 'Sort' => 'Int', |
||
38 | 'DeferTimeInSeconds' => 'Int', |
||
39 | 'DeferFromSubmitTime' => 'Boolean' |
||
40 | ); |
||
41 | |||
42 | |||
43 | |||
44 | /** |
||
45 | * standard SS variable. |
||
46 | * |
||
47 | * @return array |
||
48 | */ |
||
49 | private static $indexes = array( |
||
50 | 'Code' => true, |
||
51 | 'Sort' => true, |
||
52 | ); |
||
53 | |||
54 | /** |
||
55 | * standard SS variable. |
||
56 | * |
||
57 | * @return array |
||
58 | */ |
||
59 | private static $has_many = array( |
||
60 | 'Orders' => 'Order', |
||
61 | 'OrderEmailRecords' => 'OrderEmailRecord', |
||
62 | ); |
||
63 | |||
64 | /** |
||
65 | * standard SS variable. |
||
66 | * |
||
67 | * @return array |
||
68 | */ |
||
69 | private static $field_labels = array( |
||
70 | 'Sort' => 'Sorting Index', |
||
71 | 'CustomerCanEdit' => 'Customer can edit order', |
||
72 | 'CustomerCanPay' => 'Customer can pay order', |
||
73 | 'CustomerCanCancel' => 'Customer can cancel order', |
||
74 | ); |
||
75 | |||
76 | /** |
||
77 | * standard SS variable. |
||
78 | * |
||
79 | * @return array |
||
80 | */ |
||
81 | private static $summary_fields = array( |
||
82 | 'NameAndDescription' => 'Step', |
||
83 | 'ShowAsSummary' => 'Phase', |
||
84 | ); |
||
85 | |||
86 | /** |
||
87 | * standard SS variable. |
||
88 | * |
||
89 | * @return array |
||
90 | */ |
||
91 | private static $casting = array( |
||
92 | 'Title' => 'Varchar', |
||
93 | 'CustomerCanEditNice' => 'Varchar', |
||
94 | 'CustomerCanPayNice' => 'Varchar', |
||
95 | 'CustomerCanCancelNice' => 'Varchar', |
||
96 | 'ShowAsUncompletedOrderNice' => 'Varchar', |
||
97 | 'ShowAsInProcessOrderNice' => 'Varchar', |
||
98 | 'ShowAsCompletedOrderNice' => 'Varchar', |
||
99 | 'HideStepFromCustomerNice' => 'Varchar', |
||
100 | 'HasCustomerMessageNice' => 'Varchar', |
||
101 | 'ShowAsSummary' => 'HTMLText', |
||
102 | 'NameAndDescription' => 'HTMLText' |
||
103 | ); |
||
104 | |||
105 | /** |
||
106 | * standard SS variable. |
||
107 | * |
||
108 | * @return array |
||
109 | */ |
||
110 | private static $searchable_fields = array( |
||
111 | 'Name' => array( |
||
112 | 'title' => 'Name', |
||
113 | 'filter' => 'PartialMatchFilter', |
||
114 | ), |
||
115 | 'Code' => array( |
||
116 | 'title' => 'Code', |
||
117 | 'filter' => 'PartialMatchFilter', |
||
118 | ), |
||
119 | ); |
||
120 | |||
121 | |||
122 | /** |
||
123 | * casted variable. |
||
124 | * |
||
125 | * @return string |
||
126 | */ |
||
127 | public function Title() |
||
128 | { |
||
129 | return $this->getTitle(); |
||
130 | } |
||
131 | public function getTitle() |
||
132 | { |
||
133 | return $this->Name; |
||
134 | } |
||
135 | |||
136 | /** |
||
137 | * casted variable. |
||
138 | * |
||
139 | * @return string |
||
140 | */ |
||
141 | public function CustomerCanEditNice() |
||
142 | { |
||
143 | return $this->getCustomerCanEditNice(); |
||
144 | } |
||
145 | public function getCustomerCanEditNice() |
||
146 | { |
||
147 | if ($this->CustomerCanEdit) { |
||
148 | return _t('OrderStep.YES', 'Yes'); |
||
149 | } |
||
150 | |||
151 | return _t('OrderStep.NO', 'No'); |
||
152 | } |
||
153 | |||
154 | /** |
||
155 | * casted variable. |
||
156 | * |
||
157 | * @return string |
||
158 | */ |
||
159 | public function CustomerCanPayNice() |
||
160 | { |
||
161 | return $this->getCustomerCanPayNice(); |
||
162 | } |
||
163 | public function getCustomerCanPayNice() |
||
164 | { |
||
165 | if ($this->CustomerCanPay) { |
||
166 | return _t('OrderStep.YES', 'Yes'); |
||
167 | } |
||
168 | |||
169 | return _t('OrderStep.NO', 'No'); |
||
170 | } |
||
171 | |||
172 | /** |
||
173 | * casted variable. |
||
174 | * |
||
175 | * @return string |
||
176 | */ |
||
177 | public function CustomerCanCancelNice() |
||
178 | { |
||
179 | return $this->getCustomerCanCancelNice(); |
||
180 | } |
||
181 | public function getCustomerCanCancelNice() |
||
182 | { |
||
183 | if ($this->CustomerCanCancel) { |
||
184 | return _t('OrderStep.YES', 'Yes'); |
||
185 | } |
||
186 | |||
187 | return _t('OrderStep.NO', 'No'); |
||
188 | } |
||
189 | |||
190 | public function ShowAsUncompletedOrderNice() |
||
191 | { |
||
192 | return $this->getShowAsUncompletedOrderNice(); |
||
193 | } |
||
194 | public function getShowAsUncompletedOrderNice() |
||
195 | { |
||
196 | if ($this->ShowAsUncompletedOrder) { |
||
197 | return _t('OrderStep.YES', 'Yes'); |
||
198 | } |
||
199 | |||
200 | return _t('OrderStep.NO', 'No'); |
||
201 | } |
||
202 | |||
203 | /** |
||
204 | * casted variable. |
||
205 | * |
||
206 | * @return string |
||
207 | */ |
||
208 | public function ShowAsInProcessOrderNice() |
||
209 | { |
||
210 | return $this->getShowAsInProcessOrderNice(); |
||
211 | } |
||
212 | public function getShowAsInProcessOrderNice() |
||
213 | { |
||
214 | if ($this->ShowAsInProcessOrder) { |
||
215 | return _t('OrderStep.YES', 'Yes'); |
||
216 | } |
||
217 | |||
218 | return _t('OrderStep.NO', 'No'); |
||
219 | } |
||
220 | |||
221 | /** |
||
222 | * casted variable. |
||
223 | * |
||
224 | * @return string |
||
225 | */ |
||
226 | public function ShowAsCompletedOrderNice() |
||
227 | { |
||
228 | return $this->getShowAsCompletedOrderNice(); |
||
229 | } |
||
230 | public function getShowAsCompletedOrderNice() |
||
231 | { |
||
232 | if ($this->ShowAsCompletedOrder) { |
||
233 | return _t('OrderStep.YES', 'Yes'); |
||
234 | } |
||
235 | |||
236 | return _t('OrderStep.NO', 'No'); |
||
237 | } |
||
238 | |||
239 | /** |
||
240 | * do not show in steps at all. |
||
241 | * @return boolean |
||
242 | */ |
||
243 | public function HideFromEveryone() |
||
244 | { |
||
245 | return false; |
||
246 | } |
||
247 | |||
248 | /** |
||
249 | * casted variable. |
||
250 | * |
||
251 | * @return string |
||
252 | */ |
||
253 | public function HideStepFromCustomerNice() |
||
254 | { |
||
255 | return $this->getHideStepFromCustomerNice(); |
||
256 | } |
||
257 | |||
258 | public function getHideStepFromCustomerNice() |
||
259 | { |
||
260 | if ($this->HideStepFromCustomer) { |
||
261 | return _t('OrderStep.YES', 'Yes'); |
||
262 | } |
||
263 | |||
264 | return _t('OrderStep.NO', 'No'); |
||
265 | } |
||
266 | |||
267 | /** |
||
268 | * standard SS variable. |
||
269 | * |
||
270 | * @return string |
||
271 | */ |
||
272 | private static $singular_name = 'Order Step'; |
||
273 | public function i18n_singular_name() |
||
274 | { |
||
275 | return _t('OrderStep.ORDERSTEP', 'Order Step'); |
||
276 | } |
||
277 | |||
278 | /** |
||
279 | * standard SS variable. |
||
280 | * |
||
281 | * @return string |
||
282 | */ |
||
283 | private static $plural_name = 'Order Steps'; |
||
284 | public function i18n_plural_name() |
||
285 | { |
||
286 | return _t('OrderStep.ORDERSTEPS', 'Order Steps'); |
||
287 | } |
||
288 | |||
289 | /** |
||
290 | * Standard SS variable. |
||
291 | * |
||
292 | * @var string |
||
293 | */ |
||
294 | private static $description = 'A step that any order goes through.'; |
||
295 | |||
296 | /** |
||
297 | * SUPER IMPORTANT TO KEEP ORDER! |
||
298 | * standard SS variable. |
||
299 | * |
||
300 | * @return string |
||
301 | */ |
||
302 | private static $default_sort = '"Sort" ASC'; |
||
303 | |||
304 | /** |
||
305 | * returns all the order steps |
||
306 | * that the admin should / can edit.... |
||
307 | * |
||
308 | * @return DataList |
||
309 | */ |
||
310 | public static function admin_manageable_steps() |
||
311 | { |
||
312 | $lastStep = OrderStep::get()->Last(); |
||
313 | |||
314 | return OrderStep::get()->filter(array('ShowAsInProcessOrder' => 1))->exclude(array('ID' => $lastStep->ID)); |
||
315 | } |
||
316 | /** |
||
317 | * returns all the order steps |
||
318 | * that the admin should / can edit.... |
||
319 | * |
||
320 | * @return DataList |
||
321 | */ |
||
322 | public static function non_admin_manageable_steps() |
||
323 | { |
||
324 | $lastStep = OrderStep::get()->Last(); |
||
325 | |||
326 | return OrderStep::get()->filterAny(array('ShowAsInProcessOrder' => 0, 'ID' => $lastStep->ID)); |
||
327 | } |
||
328 | |||
329 | /** |
||
330 | * return StatusIDs (orderstep IDs) from orders that are bad.... |
||
331 | * (basically StatusID values that do not exist) |
||
332 | * |
||
333 | * @return array |
||
334 | */ |
||
335 | public static function bad_order_step_ids() |
||
336 | { |
||
337 | $badorderStatus = Order::get() |
||
338 | ->leftJoin('OrderStep', '"OrderStep"."ID" = "Order"."StatusID"') |
||
339 | ->where('"OrderStep"."ID" IS NULL AND "StatusID" > 0') |
||
340 | ->column('StatusID'); |
||
341 | if (is_array($badorderStatus)) { |
||
342 | return array_unique(array_values($badorderStatus)); |
||
343 | } else { |
||
344 | return array(-1); |
||
345 | } |
||
346 | } |
||
347 | |||
348 | /** |
||
349 | * turns code into ID. |
||
350 | * |
||
351 | * @param string $code |
||
352 | * @param int |
||
353 | */ |
||
354 | public static function get_status_id_from_code($code) |
||
355 | { |
||
356 | $otherStatus = OrderStep::get() |
||
357 | ->filter(array('Code' => $code)) |
||
358 | ->First(); |
||
359 | if ($otherStatus) { |
||
360 | return $otherStatus->ID; |
||
361 | } |
||
362 | |||
363 | return 0; |
||
364 | } |
||
365 | |||
366 | /** |
||
367 | *@return array |
||
368 | **/ |
||
369 | public static function get_codes_for_order_steps_to_include() |
||
370 | { |
||
371 | $newArray = array(); |
||
372 | $array = EcommerceConfig::get('OrderStep', 'order_steps_to_include'); |
||
373 | if (is_array($array) && count($array)) { |
||
374 | foreach ($array as $className) { |
||
375 | $code = singleton($className)->getMyCode(); |
||
376 | $newArray[$className] = strtoupper($code); |
||
377 | } |
||
378 | } |
||
379 | |||
380 | return $newArray; |
||
381 | } |
||
382 | |||
383 | /** |
||
384 | * returns a list of ordersteps that have not been created yet. |
||
385 | * |
||
386 | * @return array |
||
387 | **/ |
||
388 | public static function get_not_created_codes_for_order_steps_to_include() |
||
389 | { |
||
390 | $array = EcommerceConfig::get('OrderStep', 'order_steps_to_include'); |
||
391 | if (is_array($array) && count($array)) { |
||
392 | foreach ($array as $className) { |
||
393 | $obj = $className::get()->First(); |
||
394 | if ($obj) { |
||
395 | unset($array[$className]); |
||
396 | } |
||
397 | } |
||
398 | } |
||
399 | |||
400 | return $array; |
||
401 | } |
||
402 | |||
403 | /** |
||
404 | *@return string |
||
405 | **/ |
||
406 | public function getMyCode() |
||
407 | { |
||
408 | $array = Config::inst()->get($this->ClassName, 'defaults', Config::UNINHERITED); |
||
409 | if (!isset($array['Code'])) { |
||
410 | user_error($this->class.' does not have a default code specified'); |
||
411 | } |
||
412 | |||
413 | return $array['Code']; |
||
414 | } |
||
415 | |||
416 | /** |
||
417 | * IMPORTANT:: MUST HAVE Code must be defined!!! |
||
418 | * standard SS variable. |
||
419 | * |
||
420 | * @return array |
||
421 | */ |
||
422 | private static $defaults = array( |
||
423 | 'CustomerCanEdit' => 0, |
||
424 | 'CustomerCanCancel' => 0, |
||
425 | 'CustomerCanPay' => 1, |
||
426 | 'ShowAsUncompletedOrder' => 0, |
||
427 | 'ShowAsInProcessOrder' => 0, |
||
428 | 'ShowAsCompletedOrder' => 0, |
||
429 | 'Code' => 'ORDERSTEP', |
||
430 | ); |
||
431 | |||
432 | /** |
||
433 | * standard SS method. |
||
434 | */ |
||
435 | public function populateDefaults() |
||
436 | { |
||
437 | parent::populateDefaults(); |
||
438 | $this->Description = $this->myDescription(); |
||
439 | } |
||
440 | |||
441 | /** |
||
442 | *@return FieldList |
||
443 | **/ |
||
444 | public function getCMSFields() |
||
445 | { |
||
446 | $fields = parent::getCMSFields(); |
||
447 | //replacing |
||
448 | if ($this->canBeDefered()) { |
||
449 | if ($this->DeferTimeInSeconds) { |
||
450 | $fields->addFieldToTab( |
||
451 | 'Root.Queue', |
||
452 | HeaderField::create( |
||
453 | 'WhenWillThisRun', |
||
454 | $this->humanReadeableDeferTimeInSeconds() |
||
455 | ) |
||
456 | ); |
||
457 | } |
||
458 | $fields->addFieldToTab( |
||
459 | 'Root.Queue', |
||
460 | $deferTimeInSecondsField = TextField::create( |
||
461 | 'DeferTimeInSeconds', |
||
462 | _t('OrderStep.DeferTimeInSeconds', 'Seconds in queue') |
||
463 | ) |
||
464 | ->setRightTitle( |
||
465 | _t( |
||
466 | 'OrderStep.TIME_EXPLANATION', |
||
467 | '86,400 seconds is one day ... |
||
468 | <br />To make it easier, you can also enter things like <em>1 week</em>, <em>3 hours</em>, or <em>7 minutes</em>. |
||
469 | <br />Non-second entries will automatically be converted to seconds.' |
||
470 | ) |
||
471 | ) |
||
472 | ); |
||
473 | if ($this->DeferTimeInSeconds) { |
||
474 | $fields->addFieldToTab( |
||
475 | 'Root.Queue', |
||
476 | $deferTimeInSecondsField = CheckboxField::create( |
||
477 | 'DeferFromSubmitTime', |
||
478 | _t('OrderStep.DeferFromSubmitTime', 'Calculated from submit time?') |
||
479 | ) |
||
480 | ->setDescription( |
||
481 | _t( |
||
482 | 'OrderStep.DeferFromSubmitTime_HELP', |
||
483 | 'The time in the queue can be calculated from the moment the current orderstep starts or from the moment the order was submitted (in this case, check the box above) ' |
||
484 | ) |
||
485 | ) |
||
486 | ); |
||
487 | } |
||
488 | } |
||
489 | if ($this->hasCustomerMessage()) { |
||
490 | $rightTitle = _t( |
||
491 | 'OrderStep.EXPLAIN_ORDER_NUMBER_IN_SUBJECT', |
||
492 | 'You can use [OrderNumber] as a tag that will be replaced with the actual Order Number.' |
||
493 | ); |
||
494 | $fields->addFieldToTab( |
||
495 | 'Root.CustomerMessage', |
||
496 | TextField::create('EmailSubject', _t('OrderStep.EMAILSUBJECT', 'Email Subject')) |
||
497 | ->setRightTitle($rightTitle) |
||
498 | ); |
||
499 | if ($testEmailLink = $this->testEmailLink()) { |
||
500 | $fields->addFieldToTab( |
||
501 | 'Root.CustomerMessage', |
||
502 | new LiteralField( |
||
503 | 'testEmailLink', |
||
504 | '<h3> |
||
505 | <a href="'.$testEmailLink.'" data-popup="true" target"_blank" onclick="emailPrompt(this, event);"> |
||
506 | '._t('OrderStep.VIEW_EMAIL_EXAMPLE', 'View email example in browser').' |
||
507 | </a> |
||
508 | </h3> |
||
509 | <script language="javascript"> |
||
510 | function emailPrompt(caller, event) { |
||
511 | event.preventDefault(); |
||
512 | var href = jQuery(caller).attr("href"); |
||
513 | var email = prompt("Enter an email address to receive a copy of this example in your inbox, leave blank to view in the browser"); |
||
514 | if (email) { |
||
515 | href += "&send=" + email; |
||
516 | } |
||
517 | window.open(href); |
||
518 | }; |
||
519 | </script>' |
||
520 | ) |
||
521 | ); |
||
522 | } |
||
523 | |||
524 | $fields->addFieldToTab('Root.CustomerMessage', $htmlEditorField = new HTMLEditorField('CustomerMessage', _t('OrderStep.CUSTOMERMESSAGE', 'Customer Message (if any)'))); |
||
525 | $htmlEditorField->setRows(3); |
||
526 | |||
527 | } else { |
||
528 | $fields->removeFieldFromTab('Root', 'OrderEmailRecords'); |
||
529 | $fields->removeFieldFromTab('Root.Main', 'EmailSubject'); |
||
530 | $fields->removeFieldFromTab('Root.Main', 'CustomerMessage'); |
||
531 | } |
||
532 | //adding |
||
533 | if (!$this->exists() || !$this->isDefaultStatusOption()) { |
||
534 | $fields->removeFieldFromTab('Root.Main', 'Code'); |
||
535 | $fields->addFieldToTab('Root.Main', new DropdownField('ClassName', _t('OrderStep.TYPE', 'Type'), self::get_not_created_codes_for_order_steps_to_include()), 'Name'); |
||
536 | } |
||
537 | if ($this->isDefaultStatusOption()) { |
||
538 | $fields->replaceField('Code', $fields->dataFieldByName('Code')->performReadonlyTransformation()); |
||
539 | } |
||
540 | //headers |
||
541 | $fields->addFieldToTab('Root.Main', new HeaderField('WARNING1', _t('OrderStep.CAREFUL', 'CAREFUL! please edit details below with care'), 2), 'Description'); |
||
542 | $fields->addFieldToTab('Root.Main', new HeaderField('WARNING2', _t('OrderStep.CUSTOMERCANCHANGE', 'What can be changed during this step?'), 3), 'CustomerCanEdit'); |
||
543 | $fields->addFieldToTab('Root.Main', new HeaderField('WARNING5', _t('OrderStep.ORDERGROUPS', 'Order groups for customer?'), 3), 'ShowAsUncompletedOrder'); |
||
544 | $fields->addFieldToTab('Root.Main', new HeaderField('HideStepFromCustomerHeader', _t('OrderStep.HIDE_STEP_FROM_CUSTOMER_HEADER', 'Customer Interaction'), 3), 'HideStepFromCustomer'); |
||
545 | //final cleanup |
||
546 | $fields->removeFieldFromTab('Root.Main', 'Sort'); |
||
547 | $fields->addFieldToTab('Root.Main', new TextareaField('Description', _t('OrderStep.DESCRIPTION', 'Explanation for internal use only')), 'WARNING1'); |
||
548 | |||
549 | return $fields; |
||
550 | } |
||
551 | |||
552 | /** |
||
553 | * link to edit the record. |
||
554 | * |
||
555 | * @param string | Null $action - e.g. edit |
||
556 | * |
||
557 | * @return string |
||
558 | */ |
||
559 | public function CMSEditLink($action = null) |
||
560 | { |
||
561 | return Controller::join_links( |
||
562 | Director::baseURL(), |
||
563 | '/admin/shop/'.$this->ClassName.'/EditForm/field/'.$this->ClassName.'/item/'.$this->ID.'/', |
||
564 | $action |
||
565 | ); |
||
566 | } |
||
567 | |||
568 | /** |
||
569 | * tells the order to display itself with an alternative display page. |
||
570 | * in that way, orders can be displayed differently for certain steps |
||
571 | * for example, in a print step, the order can be displayed in a |
||
572 | * PRINT ONLY format. |
||
573 | * |
||
574 | * When the method return null, the order is displayed using the standard display page |
||
575 | * |
||
576 | * @see Order::DisplayPage |
||
577 | * |
||
578 | * @return null|object (Page) |
||
579 | **/ |
||
580 | public function AlternativeDisplayPage() |
||
581 | { |
||
582 | return; |
||
583 | } |
||
584 | |||
585 | /** |
||
586 | * Allows the opportunity for the Order Step to add any fields to Order::getCMSFields |
||
587 | * Usually this is added before ActionNextStepManually. |
||
588 | * |
||
589 | * @param FieldList $fields |
||
590 | * @param Order $order |
||
591 | * |
||
592 | * @return FieldList |
||
593 | **/ |
||
594 | public function addOrderStepFields(FieldList $fields, Order $order) |
||
595 | { |
||
596 | return $fields; |
||
597 | } |
||
598 | |||
599 | /** |
||
600 | *@return ValidationResult |
||
601 | **/ |
||
602 | public function validate() |
||
603 | { |
||
604 | $result = parent::validate(); |
||
605 | $anotherOrderStepWithSameNameOrCode = OrderStep::get() |
||
606 | ->filter( |
||
607 | array( |
||
608 | 'Name' => $this->Name, |
||
609 | 'Code' => strtoupper($this->Code), |
||
610 | ) |
||
611 | ) |
||
612 | ->exclude(array('ID' => intval($this->ID))) |
||
613 | ->First(); |
||
614 | if ($anotherOrderStepWithSameNameOrCode) { |
||
615 | $result->error(_t('OrderStep.ORDERSTEPALREADYEXISTS', 'An order status with this name already exists. Please change the name and try again.')); |
||
616 | } |
||
617 | |||
618 | return $result; |
||
619 | } |
||
620 | |||
621 | /************************************************** |
||
622 | * moving between statusses... |
||
623 | **************************************************/ |
||
624 | /** |
||
625 | *initStep: |
||
626 | * makes sure the step is ready to run.... (e.g. check if the order is ready to be emailed as receipt). |
||
627 | * should be able to run this function many times to check if the step is ready. |
||
628 | * |
||
629 | * @see Order::doNextStatus |
||
630 | * |
||
631 | * @param Order object |
||
632 | * |
||
633 | * @return bool - true if the current step is ready to be run... |
||
634 | **/ |
||
635 | public function initStep(Order $order) |
||
636 | { |
||
637 | user_error('Please implement the initStep method in a subclass ('.get_class().') of OrderStep', E_USER_WARNING); |
||
638 | |||
639 | return true; |
||
640 | } |
||
641 | |||
642 | /** |
||
643 | *doStep: |
||
644 | * should only be able to run this function once |
||
645 | * (init stops you from running it twice - in theory....) |
||
646 | * runs the actual step. |
||
647 | * |
||
648 | * @see Order::doNextStatus |
||
649 | * |
||
650 | * @param Order object |
||
651 | * |
||
652 | * @return bool - true if run correctly. |
||
653 | **/ |
||
654 | public function doStep(Order $order) |
||
655 | { |
||
656 | user_error('Please implement the initStep method in a subclass ('.get_class().') of OrderStep', E_USER_WARNING); |
||
657 | |||
658 | return true; |
||
659 | } |
||
660 | |||
661 | /** |
||
662 | * nextStep: |
||
663 | * returns the next step (after it checks if everything is in place for the next step to run...). |
||
664 | * |
||
665 | * @see Order::doNextStatus |
||
666 | * |
||
667 | * @param Order $order |
||
668 | * |
||
669 | * @return OrderStep | Null (next step OrderStep object) |
||
670 | **/ |
||
671 | public function nextStep(Order $order) |
||
672 | { |
||
673 | $nextOrderStepObject = OrderStep::get() |
||
674 | ->filter(array('Sort:GreaterThan' => $this->Sort)) |
||
675 | ->First(); |
||
676 | if ($nextOrderStepObject) { |
||
677 | return $nextOrderStepObject; |
||
678 | } |
||
679 | |||
680 | return; |
||
681 | } |
||
682 | |||
683 | /************************************************** |
||
684 | * Boolean checks |
||
685 | **************************************************/ |
||
686 | |||
687 | /** |
||
688 | * Checks if a step has passed (been completed) in comparison to the current step. |
||
689 | * |
||
690 | * @param string $code: the name of the step to check |
||
691 | * @param bool $orIsEqualTo if set to true, this method will return TRUE if the step being checked is the current one |
||
692 | * |
||
693 | * @return bool |
||
694 | **/ |
||
695 | public function hasPassed($code, $orIsEqualTo = false) |
||
696 | { |
||
697 | $otherStatus = OrderStep::get() |
||
698 | ->filter(array('Code' => $code)) |
||
699 | ->First(); |
||
700 | if ($otherStatus) { |
||
701 | if ($otherStatus->Sort < $this->Sort) { |
||
702 | return true; |
||
703 | } |
||
704 | if ($orIsEqualTo && $otherStatus->Code == $this->Code) { |
||
705 | return true; |
||
706 | } |
||
707 | } else { |
||
708 | user_error("could not find $code in OrderStep", E_USER_NOTICE); |
||
709 | } |
||
710 | |||
711 | return false; |
||
712 | } |
||
713 | |||
714 | /** |
||
715 | * @param string $code |
||
716 | * |
||
717 | * @return bool |
||
718 | **/ |
||
719 | public function hasPassedOrIsEqualTo($code) |
||
720 | { |
||
721 | return $this->hasPassed($code, true); |
||
722 | } |
||
723 | |||
724 | /** |
||
725 | * @param string $code |
||
726 | * |
||
727 | * @return bool |
||
728 | **/ |
||
729 | public function hasNotPassed($code) |
||
730 | { |
||
731 | return (bool) !$this->hasPassed($code, true); |
||
732 | } |
||
733 | |||
734 | /** |
||
735 | * Opposite of hasPassed. |
||
736 | * |
||
737 | * @param string $code |
||
738 | * |
||
739 | * @return bool |
||
740 | **/ |
||
741 | public function isBefore($code) |
||
742 | { |
||
743 | return (bool) $this->hasPassed($code, false) ? false : true; |
||
744 | } |
||
745 | |||
746 | /** |
||
747 | *@return bool |
||
748 | **/ |
||
749 | protected function isDefaultStatusOption() |
||
750 | { |
||
751 | return in_array($this->Code, self::get_codes_for_order_steps_to_include()); |
||
752 | } |
||
753 | |||
754 | /************************************************** |
||
755 | |||
756 | **************************************************/ |
||
757 | |||
758 | /** |
||
759 | * @var string |
||
760 | */ |
||
761 | protected $emailClassName = ''; |
||
762 | |||
763 | /** |
||
764 | * returns the email class used for emailing the |
||
765 | * customer during a specific step (IF ANY!). |
||
766 | * |
||
767 | * @return string |
||
768 | */ |
||
769 | public function getEmailClassName() |
||
770 | { |
||
771 | return $this->emailClassName; |
||
772 | } |
||
773 | |||
774 | /** |
||
775 | * return true if done already or mailed successfully now. |
||
776 | * |
||
777 | * @param order $order |
||
778 | * @param string $subject |
||
779 | * @param string $message |
||
780 | * @param bool $resend |
||
781 | * @param bool | string $adminOnlyOrToEmail you can set to false = send to customer, true: send to admin, or email = send to email |
||
782 | * @param string $emailClassName |
||
783 | * |
||
784 | * @return boolean; |
||
785 | */ |
||
786 | protected function sendEmailForStep( |
||
787 | $order, |
||
788 | $subject, |
||
789 | $message = '', |
||
790 | $resend = false, |
||
791 | $adminOnlyOrToEmail = false, |
||
792 | $emailClassName = '' |
||
793 | ) { |
||
794 | if (!$this->hasBeenSent($order) || $resend) { |
||
795 | if (!$subject) { |
||
796 | $subject = $this->EmailSubject; |
||
797 | } |
||
798 | if (!$emailClassName) { |
||
799 | $emailClassName = $this->getEmailClassName(); |
||
800 | } |
||
801 | $adminOnlyOrToEmailIsEmail = $adminOnlyOrToEmail && filter_var($adminOnlyOrToEmail, FILTER_VALIDATE_EMAIL); |
||
802 | if ($this->hasCustomerMessage() || $adminOnlyOrToEmailIsEmail) { |
||
803 | return $order->sendEmail( |
||
804 | $emailClassName, |
||
805 | $subject, |
||
806 | $message, |
||
807 | $resend, |
||
808 | $adminOnlyOrToEmail |
||
809 | ); |
||
810 | } else { |
||
811 | if (!$emailClassName) { |
||
812 | $emailClassName = 'Order_ErrorEmail'; |
||
813 | } |
||
814 | //looks like we are sending an error, but we are just using this for notification |
||
815 | $message = _t('OrderStep.THISMESSAGENOTSENTTOCUSTOMER', 'NOTE: This message was not sent to the customer.').'<br /><br /><br /><br />'.$message; |
||
816 | $outcome = $order->sendAdminNotification( |
||
817 | $emailClassName, |
||
818 | $subject, |
||
819 | $message, |
||
820 | $resend |
||
821 | ); |
||
822 | } |
||
823 | if ($outcome || Director::isDev()) { |
||
824 | return true; |
||
825 | } |
||
826 | |||
827 | return false; |
||
828 | } |
||
829 | |||
830 | return true; |
||
831 | } |
||
832 | |||
833 | /** |
||
834 | * sets the email class used for emailing the |
||
835 | * customer during a specific step (IF ANY!). |
||
836 | * |
||
837 | * @param string |
||
838 | */ |
||
839 | public function setEmailClassName($s) |
||
840 | { |
||
841 | $this->emailClassName = $s; |
||
842 | } |
||
843 | |||
844 | /** |
||
845 | * returns a link that can be used to test |
||
846 | * the email being sent during this step |
||
847 | * this method returns NULL if no email |
||
848 | * is being sent OR if there is no suitable Order |
||
849 | * to test with... |
||
850 | * |
||
851 | * @return string |
||
0 ignored issues
–
show
|
|||
852 | */ |
||
853 | protected function testEmailLink() |
||
854 | { |
||
855 | if ($this->getEmailClassName()) { |
||
856 | $order = Order::get()->filter(array('StatusID' => $this->ID)) |
||
857 | ->sort('RAND() ASC') |
||
858 | ->first(); |
||
859 | if(! $order) { |
||
860 | $order = Order::get() |
||
861 | ->where('"OrderStep"."Sort" >= '.$this->Sort) |
||
862 | ->sort('IF("OrderStep"."Sort" > '.$this->Sort.', 0, 1) ASC, "OrderStep"."Sort" ASC, RAND() ASC') |
||
863 | ->innerJoin('OrderStep', '"OrderStep"."ID" = "Order"."StatusID"') |
||
864 | ->first(); |
||
865 | } |
||
866 | if ($order) { |
||
867 | return OrderConfirmationPage::get_email_link( |
||
868 | $order->ID, |
||
869 | $this->getEmailClassName(), |
||
870 | $actuallySendEmail = false, |
||
871 | $alternativeOrderStepID = $this->ID |
||
872 | ); |
||
873 | } |
||
874 | } |
||
875 | } |
||
876 | |||
877 | /** |
||
878 | * Has an email been sent to the customer for this |
||
879 | * order step. |
||
880 | *"-10 days". |
||
881 | * |
||
882 | * @param Order $order |
||
883 | * @param bool $checkDateOfOrder |
||
884 | * |
||
885 | * @return bool |
||
886 | **/ |
||
887 | public function hasBeenSent(Order $order, $checkDateOfOrder = true) |
||
888 | { |
||
889 | //if it has been more than a XXX days since the order was last edited (submitted) then we do not send emails as |
||
890 | //this would be embarrasing. |
||
891 | if ($checkDateOfOrder) { |
||
892 | if ($log = $order->SubmissionLog()) { |
||
893 | $lastEditedValue = $log->LastEdited; |
||
894 | } else { |
||
895 | $lastEditedValue = $order->LastEdited; |
||
896 | } |
||
897 | if ((strtotime($lastEditedValue) < strtotime('-'.EcommerceConfig::get('OrderStep', 'number_of_days_to_send_update_email').' days'))) { |
||
898 | return true; |
||
899 | } |
||
900 | } |
||
901 | $count = OrderEmailRecord::get() |
||
902 | ->Filter(array( |
||
903 | 'OrderID' => $order->ID, |
||
904 | 'OrderStepID' => $this->ID, |
||
905 | 'Result' => 1, |
||
906 | )) |
||
907 | ->count(); |
||
908 | |||
909 | return $count ? true : false; |
||
910 | } |
||
911 | |||
912 | /** |
||
913 | * For some ordersteps this returns true... |
||
914 | * |
||
915 | * @return bool |
||
916 | **/ |
||
917 | protected function hasCustomerMessage() |
||
918 | { |
||
919 | return false; |
||
920 | } |
||
921 | |||
922 | |||
923 | /** |
||
924 | * Formatted answer for "hasCustomerMessage". |
||
925 | * |
||
926 | * @return string |
||
927 | */ |
||
928 | public function HasCustomerMessageNice() |
||
929 | { |
||
930 | return $this->getHasCustomerMessageNice(); |
||
931 | } |
||
932 | public function getHasCustomerMessageNice() |
||
933 | { |
||
934 | return $this->hasCustomerMessage() ? _t('OrderStep.YES', 'Yes') : _t('OrderStep.NO', 'No'); |
||
935 | } |
||
936 | |||
937 | /** |
||
938 | * Formatted answer for "hasCustomerMessage". |
||
939 | * |
||
940 | * @return string |
||
941 | */ |
||
942 | public function ShowAsSummary() |
||
943 | { |
||
944 | return $this->getShowAsSummary(); |
||
945 | } |
||
946 | |||
947 | /** |
||
948 | * |
||
949 | * |
||
950 | * @return string |
||
951 | */ |
||
952 | public function getShowAsSummary() |
||
953 | { |
||
954 | $v = '<strong>'; |
||
955 | if ($this->ShowAsUncompletedOrder) { |
||
956 | $v .= _t('OrderStep.UNCOMPLETED', 'Uncompleted'); |
||
957 | } elseif ($this->ShowAsInProcessOrder) { |
||
958 | $v .= _t('OrderStep.INPROCESS', 'In process'); |
||
959 | } elseif ($this->ShowAsCompletedOrder) { |
||
960 | $v .= _t('OrderStep.COMPLETED', 'Completed'); |
||
961 | } |
||
962 | $v .= '</strong>'; |
||
963 | $canArray = array(); |
||
964 | if ($this->CustomerCanEdit) { |
||
965 | $canArray[] = _t('OrderStep.EDITABLE', 'edit'); |
||
966 | } |
||
967 | if ($this->CustomerCanPay) { |
||
968 | $canArray[] = _t('OrderStep.PAY', 'pay'); |
||
969 | } |
||
970 | if ($this->CustomerCanCancel) { |
||
971 | $canArray[] = _t('OrderStep.CANCEL', 'cancel'); |
||
972 | } |
||
973 | if (count($canArray)) { |
||
974 | $v .= '<br />'._t('OrderStep.CUSTOMER_CAN', 'Customer Can').': '.implode(', ', $canArray).''; |
||
975 | } |
||
976 | if ($this->hasCustomerMessage()) { |
||
977 | $v .= '<br />'._t('OrderStep.CUSTOMER_MESSAGES', 'Includes message to customer'); |
||
978 | } |
||
979 | if ($this->DeferTimeInSeconds) { |
||
980 | $v .= '<br />'.$this->humanReadeableDeferTimeInSeconds(); |
||
981 | } |
||
982 | |||
983 | return DBField::create_field('HTMLText', $v); |
||
984 | } |
||
985 | |||
986 | /** |
||
987 | * @return string |
||
0 ignored issues
–
show
|
|||
988 | */ |
||
989 | protected function humanReadeableDeferTimeInSeconds() |
||
990 | { |
||
991 | if ($this->canBeDefered()) { |
||
992 | $field = DBField::create_field('SS_DateTime', strtotime('+ '.$this->DeferTimeInSeconds.' seconds')); |
||
993 | $descr0 = _t('OrderStep.THE', 'The').' '.'<span style="color: #338DC1">'.$this->getTitle().'</span>'; |
||
994 | $descr1 = _t('OrderStep.DELAY_VALUE', 'Order Step, for any order, will run'); |
||
995 | $descr2 = $field->ago(); |
||
996 | $descr3 = $this->DeferFromSubmitTime ? |
||
997 | _t('OrderStep.FROM_ORDER_SUBMIT_TIME', 'from the order being submitted') : |
||
998 | _t('OrderStep.FROM_START_OF_ORDSTEP', 'from the order arriving on this step'); |
||
999 | return $descr0. ' ' . $descr1.' <span style="color: #338DC1">'.$descr2.'</span> '.$descr3.'.'; |
||
1000 | } |
||
1001 | // $dtF = new \DateTime('@0'); |
||
1002 | // $dtT = new \DateTime("@".$this->DeferTimeInSeconds); |
||
1003 | // |
||
1004 | // return $dtF->diff($dtT)->format('%a days, %h hours, %i minutes and %s seconds'); |
||
1005 | } |
||
1006 | |||
1007 | /** |
||
1008 | * Formatted answer for "hasCustomerMessage". |
||
1009 | * |
||
1010 | * @return string |
||
1011 | */ |
||
1012 | public function NameAndDescription() |
||
1013 | { |
||
1014 | return $this->getNameAndDescription(); |
||
1015 | } |
||
1016 | |||
1017 | public function getNameAndDescription() |
||
1018 | { |
||
1019 | $v = '<strong>'.$this->Name.'</strong><br /><em>'.$this->Description.'</em>'; |
||
1020 | |||
1021 | return DBField::create_field('HTMLText', $v); |
||
1022 | } |
||
1023 | |||
1024 | /** |
||
1025 | * This allows you to set the time to something other than the standard DeferTimeInSeconds |
||
1026 | * value based on the order provided. |
||
1027 | * |
||
1028 | * @param Order |
||
1029 | * |
||
1030 | * @return int |
||
1031 | */ |
||
1032 | public function CalculatedDeferTimeInSeconds($order) |
||
1033 | { |
||
1034 | return $this->DeferTimeInSeconds; |
||
1035 | } |
||
1036 | |||
1037 | /** |
||
1038 | * can this order step be delayed? |
||
1039 | * in general, if there is a customer message |
||
1040 | * we should be able to delay it |
||
1041 | * |
||
1042 | * This method can be overridden in any orderstep |
||
1043 | * @return bool |
||
1044 | **/ |
||
1045 | protected function canBeDefered() |
||
1046 | { |
||
1047 | return $this->hasCustomerMessage(); |
||
1048 | } |
||
1049 | |||
1050 | |||
1051 | /************************************************** |
||
1052 | * Order Status Logs |
||
1053 | **************************************************/ |
||
1054 | |||
1055 | /** |
||
1056 | * The OrderStatusLog that is relevant to the particular step. |
||
1057 | * |
||
1058 | * @var string |
||
1059 | */ |
||
1060 | protected $relevantLogEntryClassName = ''; |
||
1061 | |||
1062 | /** |
||
1063 | * @return string |
||
1064 | */ |
||
1065 | public function getRelevantLogEntryClassName() |
||
1066 | { |
||
1067 | return $this->relevantLogEntryClassName; |
||
1068 | } |
||
1069 | |||
1070 | /** |
||
1071 | * @param string |
||
1072 | */ |
||
1073 | public function setRelevantLogEntryClassName($s) |
||
1074 | { |
||
1075 | $this->relevantLogEntryClassName = $s; |
||
1076 | } |
||
1077 | |||
1078 | /** |
||
1079 | * returns the OrderStatusLog that is relevant to this step. |
||
1080 | * |
||
1081 | * @param Order $order |
||
1082 | * |
||
1083 | * @return OrderStatusLog | null |
||
1084 | */ |
||
1085 | public function RelevantLogEntry(Order $order) |
||
1086 | { |
||
1087 | if ($className = $this->getRelevantLogEntryClassName()) { |
||
1088 | return $this->RelevantLogEntries($order)->Last(); |
||
1089 | } |
||
1090 | } |
||
1091 | |||
1092 | /** |
||
1093 | * returns the OrderStatusLogs that are relevant to this step. |
||
1094 | * It is important that getRelevantLogEntryClassName returns |
||
1095 | * a specific enough ClassName and not a base class name. |
||
1096 | * |
||
1097 | * @param Order $order |
||
1098 | * |
||
1099 | * @return DataObjectSet | null |
||
1100 | */ |
||
1101 | public function RelevantLogEntries(Order $order) |
||
1102 | { |
||
1103 | if ($className = $this->getRelevantLogEntryClassName()) { |
||
1104 | return $className::get()->filter( |
||
1105 | array( |
||
1106 | 'OrderID' => $order->ID |
||
1107 | ) |
||
1108 | ); |
||
1109 | } |
||
1110 | } |
||
1111 | |||
1112 | /************************************************** |
||
1113 | * Silverstripe Standard Data Object Methods |
||
1114 | **************************************************/ |
||
1115 | |||
1116 | /** |
||
1117 | * Standard SS method |
||
1118 | * These are only created programmatically. |
||
1119 | * |
||
1120 | * @param Member $member |
||
0 ignored issues
–
show
Should the type for parameter
$member not be Member|null ?
This check looks for It makes a suggestion as to what type it considers more descriptive. Most often this is a case of a parameter that can be null in addition to its declared types.
Loading history...
|
|||
1121 | * |
||
1122 | * @return bool |
||
1123 | */ |
||
1124 | public function canCreate($member = null) |
||
1125 | { |
||
1126 | return false; |
||
1127 | } |
||
1128 | |||
1129 | /** |
||
1130 | * Standard SS method. |
||
1131 | * |
||
1132 | * @param Member $member |
||
0 ignored issues
–
show
Should the type for parameter
$member not be Member|null ?
This check looks for It makes a suggestion as to what type it considers more descriptive. Most often this is a case of a parameter that can be null in addition to its declared types.
Loading history...
|
|||
1133 | * |
||
1134 | * @return bool |
||
0 ignored issues
–
show
|
|||
1135 | */ |
||
1136 | public function canView($member = null) |
||
1137 | { |
||
1138 | if (! $member) { |
||
1139 | $member = Member::currentUser(); |
||
1140 | } |
||
1141 | $extended = $this->extendedCan(__FUNCTION__, $member); |
||
0 ignored issues
–
show
$member is of type object<DataObject>|null , but the function expects a object<Member>|integer .
It seems like the type of the argument is not accepted by the function/method which you are calling. In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug. We suggest to add an explicit type cast like in the following example: function acceptsInteger($int) { }
$x = '123'; // string "123"
// Instead of
acceptsInteger($x);
// we recommend to use
acceptsInteger((integer) $x);
Loading history...
|
|||
1142 | if ($extended !== null) { |
||
1143 | return $extended; |
||
1144 | } |
||
1145 | if (Permission::checkMember($member, Config::inst()->get('EcommerceRole', 'admin_permission_code'))) { |
||
1146 | return true; |
||
1147 | } |
||
1148 | |||
1149 | return parent::canEdit($member); |
||
1150 | } |
||
1151 | |||
1152 | /** |
||
1153 | * the default for this is TRUE, but for completed order steps |
||
1154 | * |
||
1155 | * we do not allow this. |
||
1156 | * |
||
1157 | * @param Order $order |
||
1158 | * @param Member $member optional |
||
1159 | * @return bool |
||
1160 | */ |
||
1161 | public function canOverrideCanViewForOrder($order, $member = null) |
||
1162 | { |
||
1163 | //return true if the order can have customer input |
||
1164 | // orders recently saved can also be views |
||
1165 | return |
||
1166 | $this->CustomerCanEdit || |
||
1167 | $this->CustomerCanCancel || |
||
1168 | $this->CustomerCanPay; |
||
1169 | } |
||
1170 | |||
1171 | /** |
||
1172 | * standard SS method. |
||
1173 | * |
||
1174 | * @param Member | NULL |
||
1175 | * |
||
1176 | * @return bool |
||
0 ignored issues
–
show
|
|||
1177 | */ |
||
1178 | public function canEdit($member = null) |
||
1179 | { |
||
1180 | if (! $member) { |
||
1181 | $member = Member::currentUser(); |
||
1182 | } |
||
1183 | $extended = $this->extendedCan(__FUNCTION__, $member); |
||
1184 | if ($extended !== null) { |
||
1185 | return $extended; |
||
1186 | } |
||
1187 | if (Permission::checkMember($member, Config::inst()->get('EcommerceRole', 'admin_permission_code'))) { |
||
1188 | return true; |
||
1189 | } |
||
1190 | |||
1191 | return parent::canEdit($member); |
||
1192 | } |
||
1193 | |||
1194 | /** |
||
1195 | * Standard SS method. |
||
1196 | * |
||
1197 | * @param Member $member |
||
0 ignored issues
–
show
Should the type for parameter
$member not be Member|null ?
This check looks for It makes a suggestion as to what type it considers more descriptive. Most often this is a case of a parameter that can be null in addition to its declared types.
Loading history...
|
|||
1198 | * |
||
1199 | * @return bool |
||
0 ignored issues
–
show
|
|||
1200 | */ |
||
1201 | public function canDelete($member = null) |
||
1202 | { |
||
1203 | //cant delete last status if there are orders with this status |
||
1204 | $nextOrderStepObject = $this->NextOrderStep(); |
||
1205 | if ($nextOrderStepObject) { |
||
1206 | //do nothing |
||
1207 | } else { |
||
1208 | $orderCount = Order::get() |
||
1209 | ->filter(array('StatusID' => intval($this->ID) - 0)) |
||
1210 | ->count(); |
||
1211 | if ($orderCount) { |
||
1212 | return false; |
||
1213 | } |
||
1214 | } |
||
1215 | if ($this->isDefaultStatusOption()) { |
||
1216 | return false; |
||
1217 | } |
||
1218 | if (! $member) { |
||
1219 | $member = Member::currentUser(); |
||
1220 | } |
||
1221 | $extended = $this->extendedCan(__FUNCTION__, $member); |
||
0 ignored issues
–
show
$member is of type object<DataObject>|null , but the function expects a object<Member>|integer .
It seems like the type of the argument is not accepted by the function/method which you are calling. In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug. We suggest to add an explicit type cast like in the following example: function acceptsInteger($int) { }
$x = '123'; // string "123"
// Instead of
acceptsInteger($x);
// we recommend to use
acceptsInteger((integer) $x);
Loading history...
|
|||
1222 | if ($extended !== null) { |
||
1223 | return $extended; |
||
1224 | } |
||
1225 | if (Permission::checkMember($member, Config::inst()->get('EcommerceRole', 'admin_permission_code'))) { |
||
1226 | return true; |
||
1227 | } |
||
1228 | |||
1229 | return parent::canEdit($member); |
||
1230 | } |
||
1231 | |||
1232 | /** |
||
1233 | * standard SS method. |
||
1234 | */ |
||
1235 | public function onBeforeWrite() |
||
1236 | { |
||
1237 | parent::onBeforeWrite(); |
||
1238 | //make sure only one of three conditions applies ... |
||
1239 | if ($this->ShowAsUncompletedOrder) { |
||
1240 | $this->ShowAsInProcessOrder = false; |
||
1241 | $this->ShowAsCompletedOrder = false; |
||
1242 | } elseif ($this->ShowAsInProcessOrder) { |
||
1243 | $this->ShowAsUncompletedOrder = false; |
||
1244 | $this->ShowAsCompletedOrder = false; |
||
1245 | } elseif ($this->ShowAsCompletedOrder) { |
||
1246 | $this->ShowAsUncompletedOrder = false; |
||
1247 | $this->ShowAsInProcessOrder = false; |
||
1248 | } |
||
1249 | if (! $this->canBeDefered()) { |
||
1250 | $this->DeferTimeInSeconds = 0; |
||
1251 | $this->DeferFromSubmitTime = 0; |
||
1252 | } else { |
||
1253 | if (is_numeric($this->DeferTimeInSeconds)) { |
||
1254 | $this->DeferTimeInSeconds = intval($this->DeferTimeInSeconds); |
||
1255 | } else { |
||
1256 | $this->DeferTimeInSeconds = strtotime('+'.$this->DeferTimeInSeconds); |
||
1257 | if ($this->DeferTimeInSeconds > 0) { |
||
1258 | $this->DeferTimeInSeconds = $this->DeferTimeInSeconds - time(); |
||
1259 | } |
||
1260 | } |
||
1261 | } |
||
1262 | $this->Code = strtoupper($this->Code); |
||
1263 | } |
||
1264 | |||
1265 | /** |
||
1266 | * move linked orders to the next status |
||
1267 | * standard SS method. |
||
1268 | */ |
||
1269 | public function onBeforeDelete() |
||
1270 | { |
||
1271 | $ordersWithThisStatus = Order::get()->filter(array('StatusID' => $this->ID)); |
||
1272 | if ($ordersWithThisStatus->count()) { |
||
1273 | $previousOrderStepObject = null; |
||
1274 | $bestOrderStep = $this->NextOrderStep(); |
||
1275 | //backup |
||
1276 | if ($bestOrderStep && $bestOrderStep->exists()) { |
||
1277 | //do nothing |
||
1278 | } else { |
||
1279 | $bestOrderStep = $this->PreviousOrderStep(); |
||
1280 | } |
||
1281 | if ($bestOrderStep) { |
||
1282 | foreach ($ordersWithThisStatus as $orderWithThisStatus) { |
||
1283 | $orderWithThisStatus->StatusID = $bestOrderStep->ID; |
||
1284 | $orderWithThisStatus->write(); |
||
1285 | } |
||
1286 | } |
||
1287 | } |
||
1288 | parent::onBeforeDelete(); |
||
1289 | } |
||
1290 | |||
1291 | /** |
||
1292 | * standard SS method. |
||
1293 | */ |
||
1294 | public function onAfterDelete() |
||
1295 | { |
||
1296 | parent::onAfterDelete(); |
||
1297 | $this->requireDefaultRecords(); |
||
1298 | } |
||
1299 | |||
1300 | protected function NextOrderStep() |
||
1301 | { |
||
1302 | return OrderStep::get() |
||
1303 | ->filter(array('Sort:GreaterThan' => $this->Sort)) |
||
1304 | ->First(); |
||
1305 | } |
||
1306 | |||
1307 | protected function PreviousOrderStep() |
||
1308 | { |
||
1309 | return OrderStep::get() |
||
1310 | ->filter(array('Sort:LessThan' => $this->Sort)) |
||
1311 | ->First(); |
||
1312 | } |
||
1313 | |||
1314 | /** |
||
1315 | * standard SS method |
||
1316 | * USED TO BE: Unpaid,Query,Paid,Processing,Sent,Complete,AdminCancelled,MemberCancelled,Cart. |
||
1317 | */ |
||
1318 | public function requireDefaultRecords() |
||
1319 | { |
||
1320 | parent::requireDefaultRecords(); |
||
1321 | $orderStepsToInclude = EcommerceConfig::get('OrderStep', 'order_steps_to_include'); |
||
1322 | $codesToInclude = self::get_codes_for_order_steps_to_include(); |
||
1323 | $indexNumber = 0; |
||
1324 | if ($orderStepsToInclude && count($orderStepsToInclude)) { |
||
1325 | if ($codesToInclude && count($codesToInclude)) { |
||
1326 | foreach ($codesToInclude as $className => $code) { |
||
1327 | $code = strtoupper($code); |
||
1328 | $filter = array('ClassName' => $className); |
||
1329 | $indexNumber += 10; |
||
1330 | $itemCount = OrderStep::get()->filter($filter)->Count(); |
||
1331 | if ($itemCount) { |
||
1332 | //always reset code |
||
1333 | $obj = OrderStep::get()->filter($filter)->First(); |
||
1334 | if ($obj->Code != $code) { |
||
1335 | $obj->Code = $code; |
||
1336 | $obj->write(); |
||
1337 | } |
||
1338 | //replace default description |
||
1339 | $parentObj = singleton('OrderStep'); |
||
1340 | if ($obj->Description == $parentObj->myDescription()) { |
||
1341 | $obj->Description = $obj->myDescription(); |
||
1342 | $obj->write(); |
||
1343 | } |
||
1344 | //check sorting order |
||
1345 | if ($obj->Sort != $indexNumber) { |
||
1346 | $obj->Sort = $indexNumber; |
||
1347 | $obj->write(); |
||
1348 | } |
||
1349 | } else { |
||
1350 | $obj = $className::create($filter); |
||
1351 | $obj->Code = $code; |
||
1352 | $obj->Description = $obj->myDescription(); |
||
1353 | $obj->Sort = $indexNumber; |
||
1354 | $obj->write(); |
||
1355 | DB::alteration_message("Created \"$code\" as $className.", 'created'); |
||
1356 | } |
||
1357 | $obj = OrderStep::get() |
||
1358 | ->filter($filter) |
||
1359 | ->First(); |
||
1360 | if (! $obj) { |
||
1361 | user_error("There was an error in creating the $code OrderStep"); |
||
1362 | } |
||
1363 | } |
||
1364 | } |
||
1365 | } |
||
1366 | $steps = OrderStep::get(); |
||
1367 | foreach ($steps as $step) { |
||
1368 | if (!$step->Description) { |
||
1369 | $step->Description = $step->myDescription(); |
||
1370 | $step->write(); |
||
1371 | } |
||
1372 | } |
||
1373 | } |
||
1374 | |||
1375 | /** |
||
1376 | * returns the standard EcommerceDBConfig for use within OrderSteps. |
||
1377 | * |
||
1378 | * @return EcommerceDBConfig |
||
1379 | */ |
||
1380 | protected function EcomConfig() |
||
1381 | { |
||
1382 | return EcommerceDBConfig::current_ecommerce_db_config(); |
||
1383 | } |
||
1384 | |||
1385 | /** |
||
1386 | * Explains the current order step. |
||
1387 | * |
||
1388 | * @return string |
||
1389 | */ |
||
1390 | protected function myDescription() |
||
1391 | { |
||
1392 | return _t('OrderStep.DESCRIPTION', 'No description has been provided for this step.'); |
||
1393 | } |
||
1394 | } |
||
1395 |
This check compares the return type specified in the
@return
annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.