Completed
Push — master ( e418e8...0b16c6 )
by Nicolaas
01:47
created

OrderStepPaymentCheck::initStep()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 9
c 0
b 0
f 0
rs 9.6666
cc 2
eloc 4
nc 2
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 been pending then do not do the step
75
        elseif($order->PaymentIsPending()){
76
            return false;
77
        }
78
        //do we send at all?
79
        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...
80
            // too late to send
81
            if ($this->isExpiredPaymentCheckStep($order)) {
82
                //cancel order ....
83
                if ($this->Config()->get("verbose")) {
84
                    DB::alteration_message(" - Time to send payment reminder is expired ... archive email");
85
                }
86
                // cancel as the member placing the order
87
                $member = $order->CreateOrReturnExistingMember();
88
                if (! $member) {
89
                    $member = EcommerceRole::get_default_shop_admin_user();
90
                }
91
                $order->Cancel(
92
                    $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...
93
                    _t('OrderStep.CANCELLED_DUE_TO_NON_PAYMENT', 'Cancelled due to non-payment')
94
                );
95
96
                return true;
97
            }
98
            //is now the right time to send?
99
            elseif ($this->isReadyToGo($order)) {
100
                $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...
101
                $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...
102
                if ($this->hasBeenSent($order, false)) {
103
                    if ($this->Config()->get("verbose")) {
104
                        DB::alteration_message(" - already sent!");
105
                    }
106
107
                    return true; //do nothing
108
                } else {
109
                    if ($this->Config()->get("verbose")) {
110
                        DB::alteration_message(" - Sending it now!");
111
                    }
112
                    return $order->sendEmail(
113
                        $this->getEmailClassName(),
114
                        $subject,
115
                        $message,
116
                        $resend = false,
117
                        $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...
118
                    );
119
                }
120
            }
121
            //wait until later....
122
            else {
123
                if ($this->Config()->get("verbose")) {
124
                    DB::alteration_message(" - We need to wait until minimum number of days.");
125
                }
126
                return false;
127
            }
128
        } else {
129
            return true;
130
        }
131
    }
132
133
    /**
134
     * can continue if emails has been sent or if there is no need to send a receipt.
135
     * @param DataObject $order Order
136
     * @return DataObject | Null - DataObject = next OrderStep
0 ignored issues
show
Documentation introduced by
Should the return type not be DataObject|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 ($this->isExpiredPaymentCheckStep($order)) {
141
            //archive order as we have cancelled...
142
143
            return $lastOrderStep = OrderStep::get()->last();
0 ignored issues
show
Unused Code introduced by
$lastOrderStep is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

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