OrderStepPaymentCheck   A
last analyzed

Complexity

Total Complexity 31

Size/Duplication

Total Lines 237
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 11

Importance

Changes 0
Metric Value
wmc 31
lcom 1
cbo 11
dl 0
loc 237
rs 9.92
c 0
b 0
f 0

9 Methods

Rating   Name   Duplication   Size   Complexity  
A getCMSFields() 0 25 1
A initStep() 0 9 2
C doStep() 0 62 11
A nextStep() 0 16 4
A hasCustomerMessage() 0 4 1
A myDescription() 0 4 1
A isReadyToGo() 0 25 5
A isExpiredPaymentCheckStep() 0 18 4
A hasBeenSent() 0 10 2
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
Documentation introduced by
$member is of type object<DataObject>, but the function expects a object<Member>|null.

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...
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
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
            return true;
128
        }
129
    }
130
131
    /**
132
     * can only continue if order has been paid ...
133
     *
134
     * @param DataObject $order Order
135
     *
136
     * @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...
137
     **/
138
    public function nextStep(Order $order)
139
    {
140
        if (
141
             $order->IsPaid()
142
        ) {
143
            if ($this->Config()->get("verbose")) {
144
                DB::alteration_message(" - Moving to next step");
145
            }
146
            return parent::nextStep($order);
147
        } else {
148
            if ($this->Config()->get("verbose")) {
149
                DB::alteration_message(" - no next step: has not been sent");
150
            }
151
            return null;
152
        }
153
    }
154
155
    /**
156
     * For some ordersteps this returns true...
157
     * @return Boolean
158
     **/
159
    protected function hasCustomerMessage()
160
    {
161
        return true;
162
    }
163
164
    /**
165
     * Explains the current order step.
166
     * @return String
167
     */
168
    protected function myDescription()
169
    {
170
        return "The customer is sent a payment reminder email.";
171
    }
172
173
    /**
174
     * returns true if the Minimum number of days is met....
175
     * @param Order
176
     * @return Boolean
177
     */
178
    protected function isReadyToGo(Order $order)
179
    {
180
        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...
181
            $log = $order->SubmissionLog();
182
            if ($log) {
183
                $createdTS = strtotime($log->Created);
184
                $nowTS = strtotime('now');
185
                $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...
186
                //current TS = 10
187
                //order TS = 8
188
                //add 4 days: 12
189
                //thus if 12 <= now then go for it (start point in time has passed)
190
                if ($this->Config()->get("verbose")) {
191
                    DB::alteration_message("Time comparison: Start Sending TS: ".$startSendingTS." current TS: ".$nowTS.". If SSTS > NowTS then Go for it.");
192
                }
193
                return ($startSendingTS <= $nowTS) ? true : false;
194
            } else {
195
                user_error("can not find order log for ".$order->ID);
196
                return false;
197
            }
198
        } else {
199
            //send immediately
200
            return true;
201
        }
202
    }
203
204
    /**
205
     * returns true if it is too late to send the  payment reminder step
206
     * @param Order
207
     * @return Boolean
208
     */
209
    protected function isExpiredPaymentCheckStep(Order $order)
210
    {
211
        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...
212
            $log = $order->SubmissionLog();
213
            if ($log) {
214
                $createdTS = strtotime($log->Created);
215
                $nowTS = strtotime('now');
216
                $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...
217
218
                return ($stopSendingTS < $nowTS) ? true : false;
219
            } else {
220
                user_error("can not find order log for ".$order->ID);
221
                return false;
222
            }
223
        } else {
224
            return true;
225
        }
226
    }
227
228
    public function hasBeenSent(Order $order, $checkDateOfOrder = true)
229
    {
230
        return OrderEmailRecord::get()->filter(
231
            array(
232
                "OrderEmailRecord.OrderID" => $order->ID,
233
                "OrderEmailRecord.OrderStepID" => $this->ID,
234
                "OrderEmailRecord.Result" => 1
235
            )
236
        )->count() ? true : parent::hasBeenSent($order, $checkDateOfOrder);
237
    }
238
}
239