Completed
Push — master ( 0b16c6...5f4180 )
by Nicolaas
02:07
created

OrderStepPaymentCheck::nextStep()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 16
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 16
rs 9.2
c 0
b 0
f 0
cc 4
eloc 10
nc 4
nop 1
1
<?php
2
class OrderStepPaymentCheck extends OrderStep implements OrderStepInterface
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
3
{
4
    private static $verbose = false;
0 ignored issues
show
Unused Code introduced by
The property $verbose is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
5
6
    /**
7
     * @var String
8
     */
9
    protected $emailClassName = "OrderStepPaymentCheck_Email";
10
11
    private static $db = array(
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
Unused Code introduced by
The property $db is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
12
        'SendPaymentCheckEmail' => 'Boolean',
13
        'MinDays' => 'Int',
14
        'MaxDays' => 'Int',
15
        'LinkText' => 'Varchar'
16
    );
17
18
    private static $defaults = array(
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
Unused Code introduced by
The property $defaults is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
19
        'CustomerCanEdit' => 0,
20
        'CustomerCanCancel' => 0,
21
        'CustomerCanPay' => 0,
22
        'Name' => 'Send Payment Reminder',
23
        'Code' => 'PAYMENTCHECK',
24
        "ShowAsInProcessOrder" => true,
25
        "HideStepFromCustomer" => true,
26
        'SendPaymentCheckEmail' => true,
27
        'MinDays' => 10,
28
        'MaxDays' => 20
29
    );
30
31
32
    public function getCMSFields()
33
    {
34
        $fields = parent::getCMSFields();
35
        $fields->addFieldsToTab(
36
            'Root.CustomerMessage',
37
            array(
38
                CheckboxField::create('SendPaymentCheckEmail', 'Send payment reminder email to customer?'),
39
                $minDaysField = NumericField::create('MinDays', "<strong>Min Days</strong> before sending e-mail"),
40
                $maxDaysField = NumericField::create('MaxDays', "<strong>Max Days</strong> before cancelling order")
41
            ),
42
            "EmailSubject"
43
        );
44
        $minDaysField->setRightTitle('What is the <strong>mininum number of days to wait after the order has been placed</strong> before this email should be sent?');
45
        $maxDaysField->setRightTitle('What is the <strong>maxinum number of days to wait after the order has been placed </strong> before the order should be cancelled.');
46
        $fields->addFieldsToTab(
47
            'Root.CustomerMessage',
48
            array(
49
                TextField::create(
50
                    'LinkText',
51
                    _t('OrderStepPaymentCheck.BUTTONTEXT', 'Link Text')
52
                )->setRightTitle('This is the text displayed on the "complete your order" link/button')
53
            )
54
        );
55
        return $fields;
56
    }
57
58
    public function initStep(Order $order)
59
    {
60
        //make sure we can send emails at all.
61
        if ($this->SendPaymentCheckEmail) {
0 ignored issues
show
Documentation introduced by
The property SendPaymentCheckEmail does not exist on object<OrderStepPaymentCheck>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
62
            Config::inst()->update("OrderStep", "number_of_days_to_send_update_email", $this->MaxDays);
0 ignored issues
show
Documentation introduced by
The property MaxDays does not exist on object<OrderStepPaymentCheck>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
63
        }
64
65
        return true;
66
    }
67
68
    public function doStep(Order $order)
69
    {
70
        //if the order has been paid then do not worry about it at all!
71
        if ($order->IsPaid()) {
72
            return true;
73
        }
74
        //if the order has expired then cancel it ...
75
        if ($this->isExpiredPaymentCheckStep($order)) {
76
            //cancel order ....
77
            if ($this->Config()->get("verbose")) {
78
                DB::alteration_message(" - Time to send payment reminder is expired ... archive email");
79
            }
80
            // cancel as admin ...
81
            $member = EcommerceRole::get_default_shop_admin_user();
82
            $order->Cancel(
83
                $member,
0 ignored issues
show
Compatibility introduced by
$member of type object<DataObject> is not a sub-type of object<Member>. It seems like you assume a child class of the class DataObject to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
84
                _t('OrderStep.CANCELLED_DUE_TO_NON_PAYMENT', 'Cancelled due to non-payment')
85
            );
86
87
            return true;
88
        }
89
        //do we send at all?
90
        elseif ($this->SendPaymentCheckEmail) {
0 ignored issues
show
Documentation introduced by
The property SendPaymentCheckEmail does not exist on object<OrderStepPaymentCheck>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
91
            //we can not send emails for pending payments, because pending payments can not be paid for ...
92
            if($order->PaymentIsPending()) {
93
                return false;
94
            }
95
            //is now the right time to send?
96
            if ($this->isReadyToGo($order)) {
97
                $subject = $this->EmailSubject;
0 ignored issues
show
Documentation introduced by
The property EmailSubject does not exist on object<OrderStepPaymentCheck>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
98
                $message = $this->CustomerMessage;
0 ignored issues
show
Documentation introduced by
The property CustomerMessage does not exist on object<OrderStepPaymentCheck>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
99
                if ($this->hasBeenSent($order, false)) {
100
                    if ($this->Config()->get("verbose")) {
101
                        DB::alteration_message(" - already sent!");
102
                    }
103
104
                    return true; //do nothing
105
                } else {
106
                    if ($this->Config()->get("verbose")) {
107
                        DB::alteration_message(" - Sending it now!");
108
                    }
109
                    return $order->sendEmail(
110
                        $this->getEmailClassName(),
111
                        $subject,
112
                        $message,
113
                        $resend = false,
114
                        $adminOnlyOrToEmail = false
0 ignored issues
show
Documentation introduced by
$adminOnlyOrToEmail = false is of type boolean, but the function expects a string.

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...
115
                    );
116
                }
117
            }
118
            //wait until later....
119
            else {
120
                if ($this->Config()->get("verbose")) {
121
                    DB::alteration_message(" - We need to wait until minimum number of days.");
122
                }
123
124
                return false;
125
            }
126
        } else {
127
128
            return true;
129
        }
130
    }
131
132
    /**
133
     * can only continue if order has been paid ...
134
     *
135
     * @param DataObject $order Order
136
     *
137
     * @return DataObject | Null - DataObject = next OrderStep
0 ignored issues
show
Documentation introduced by
Should the return type not be OrderStep|null?

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.

Loading history...
138
     **/
139
    public function nextStep(Order $order)
140
    {
141
        if (
142
             $order->IsPaid()
143
        ) {
144
            if ($this->Config()->get("verbose")) {
145
                DB::alteration_message(" - Moving to next step");
146
            }
147
            return parent::nextStep($order);
148
        } else {
149
            if ($this->Config()->get("verbose")) {
150
                DB::alteration_message(" - no next step: has not been sent");
151
            }
152
            return null;
153
        }
154
    }
155
156
    /**
157
     * For some ordersteps this returns true...
158
     * @return Boolean
159
     **/
160
    protected function hasCustomerMessage()
161
    {
162
        return true;
163
    }
164
165
    /**
166
     * Explains the current order step.
167
     * @return String
168
     */
169
    protected function myDescription()
170
    {
171
        return "The customer is sent a payment reminder email.";
172
    }
173
174
    /**
175
     * returns true if the Minimum number of days is met....
176
     * @param Order
177
     * @return Boolean
178
     */
179
    protected function isReadyToGo(Order $order)
180
    {
181
        if ($this->MinDays) {
0 ignored issues
show
Documentation introduced by
The property MinDays does not exist on object<OrderStepPaymentCheck>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
182
            $log = $order->SubmissionLog();
183
            if ($log) {
184
                $createdTS = strtotime($log->Created);
185
                $nowTS = strtotime('now');
186
                $startSendingTS = strtotime("+{$this->MinDays} days", $createdTS);
0 ignored issues
show
Documentation introduced by
The property MinDays does not exist on object<OrderStepPaymentCheck>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
187
                //current TS = 10
188
                //order TS = 8
189
                //add 4 days: 12
190
                //thus if 12 <= now then go for it (start point in time has passed)
191
                if ($this->Config()->get("verbose")) {
192
                    DB::alteration_message("Time comparison: Start Sending TS: ".$startSendingTS." current TS: ".$nowTS.". If SSTS > NowTS then Go for it.");
193
                }
194
                return ($startSendingTS <= $nowTS) ? true : false;
195
            } else {
196
                user_error("can not find order log for ".$order->ID);
197
                return false;
198
            }
199
        } else {
200
            //send immediately
201
            return true;
202
        }
203
    }
204
205
    /**
206
     * returns true if it is too late to send the  payment reminder step
207
     * @param Order
208
     * @return Boolean
209
     */
210
    protected function isExpiredPaymentCheckStep(Order $order)
211
    {
212
        if ($this->MaxDays) {
0 ignored issues
show
Documentation introduced by
The property MaxDays does not exist on object<OrderStepPaymentCheck>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
213
            $log = $order->SubmissionLog();
214
            if ($log) {
215
                $createdTS = strtotime($log->Created);
216
                $nowTS = strtotime('now');
217
                $stopSendingTS = strtotime('+'.$this->MaxDays.' days', $createdTS);
0 ignored issues
show
Documentation introduced by
The property MaxDays does not exist on object<OrderStepPaymentCheck>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
218
219
                return ($stopSendingTS < $nowTS) ? true : false;
220
            } else {
221
                user_error("can not find order log for ".$order->ID);
222
                return false;
223
            }
224
        } else {
225
            return true;
226
        }
227
    }
228
229
    public function hasBeenSent(Order $order, $checkDateOfOrder = true)
230
    {
231
        return OrderEmailRecord::get()->filter(
232
            array(
233
                "OrderEmailRecord.OrderID" => $order->ID,
234
                "OrderEmailRecord.OrderStepID" => $this->ID,
235
                "OrderEmailRecord.Result" => 1
236
            )
237
        )->count() ? true : parent::hasBeenSent($order, $checkDateOfOrder);
238
    }
239
}
240