Membership::getFormFields()   A
last analyzed

Complexity

Conditions 5
Paths 3

Size

Total Lines 13
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 8
nc 3
nop 2
dl 0
loc 13
rs 9.6111
c 0
b 0
f 0
1
<?php
2
3
namespace SilverShop\Checkout\Component;
4
5
use SilverShop\Checkout\Checkout;
6
use SilverShop\Checkout\ShopMemberFactory;
7
use SilverShop\Extension\ShopConfigExtension;
8
use SilverShop\Extension\MemberExtension;
9
use SilverShop\Model\Order;
10
use SilverStripe\Core\Injector\Injector;
11
use SilverStripe\Forms\ConfirmedPasswordField;
12
use SilverStripe\Forms\FieldList;
13
use SilverStripe\Forms\Form;
14
use SilverStripe\Forms\PasswordField;
15
use SilverStripe\Forms\TextField;
16
use SilverStripe\ORM\ValidationException;
17
use SilverStripe\ORM\ValidationResult;
18
use SilverStripe\Security\IdentityStore;
19
use SilverStripe\Security\Member;
20
use SilverStripe\Security\PasswordValidator;
21
use SilverStripe\Security\Security;
22
23
/**
24
 * Provides:
25
 *    - member identifier, and password fields.
26
 *    - required membership fields
27
 *    - validating data
28
 */
29
class Membership extends CheckoutComponent
30
{
31
    protected $confirmed;
32
33
    protected $passwordvalidator;
34
35
    protected $dependson = [
36
        CustomerDetails::class,
37
    ];
38
39
    public function __construct($confirmed = true, $validator = null)
40
    {
41
        $this->confirmed = $confirmed;
42
        if (!$validator) {
43
            $this->passwordvalidator = Member::password_validator();
44
            if (!$this->passwordvalidator) {
45
                $this->passwordvalidator = PasswordValidator::create();
46
                $this->passwordvalidator->minLength(5);
47
                $this->passwordvalidator->characterStrength(
48
                    2,
49
                    ["lowercase", "uppercase", "digits", "punctuation"]
50
                );
51
            }
52
        }
53
    }
54
55
    public function getFormFields(Order $order, Form $form = null)
56
    {
57
        $fields = FieldList::create();
58
        if (Security::getCurrentUser()) {
59
            return $fields;
60
        }
61
        $idfield = Member::config()->unique_identifier_field;
62
        if (!$order->{$idfield} && ($form && !$form->Fields()->fieldByName($idfield))) {
0 ignored issues
show
Bug introduced by
Are you sure the usage of $form->Fields()->fieldByName($idfield) targeting SilverStripe\Forms\FieldList::fieldByName() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
63
            //TODO: scaffold the correct id field type
64
            $fields->push(TextField::create($idfield, $idfield));
65
        }
66
        $fields->push($this->getPasswordField());
67
        return $fields;
68
    }
69
70
    public function getRequiredFields(Order $order)
71
    {
72
        if (Security::getCurrentUser() || !Checkout::membership_required()) {
73
            return [];
74
        }
75
        return [
76
            Member::config()->unique_identifier_field,
77
            'Password',
78
        ];
79
    }
80
81
    public function getPasswordField()
82
    {
83
        if ($this->confirmed) {
84
            //relies on fix: https://github.com/silverstripe/silverstripe-framework/pull/2757
85
            return ConfirmedPasswordField::create('Password', _t('SilverShop\Checkout\CheckoutField.Password', 'Password'))
86
                ->setCanBeEmpty(!Checkout::membership_required());
87
        }
88
        return PasswordField::create('Password', _t('SilverShop\Checkout\CheckoutField.Password', 'Password'));
89
    }
90
91
    public function validateData(Order $order, array $data)
92
    {
93
        if (Security::getCurrentUser()) {
94
            return;
95
        }
96
        $result = ValidationResult::create();
97
        if (Checkout::membership_required() || !empty($data['Password'])) {
98
            $member = Member::create($data);
99
            $idfield = Member::config()->unique_identifier_field;
100
            $idval = $data[$idfield];
101
            if (MemberExtension::get_by_identifier($idval)) {
102
                // get localized field labels
103
                $fieldLabels = $member->fieldLabels(false);
104
                // if a localized value exists, use this for our error-message
105
                $fieldLabel = isset($fieldLabels[$idfield]) ? $fieldLabels[$idfield] : $idfield;
106
                $result->addError(
107
                    _t(
108
                        'SilverShop\Checkout\Checkout.MemberExists',
109
                        'A member already exists with the {Field} {Identifier}',
110
                        '',
111
                        ['Field' => $fieldLabel, 'Identifier' => $idval]
112
                    ),
113
                    $idfield
114
                );
115
            }
116
            $passwordresult = $this->passwordvalidator->validate($data['Password'], $member);
117
            if (!$passwordresult->isValid()) {
118
                foreach ($passwordresult->getMessages() as $message) {
119
                    $result->addError($message['message'], "Password");
120
                }
121
            }
122
        }
123
        if (!$result->isValid()) {
124
            throw new ValidationException($result);
125
        }
126
    }
127
128
    public function getData(Order $order)
129
    {
130
        $data = [];
131
132
        if ($member = Security::getCurrentUser()) {
133
            $idf = Member::config()->unique_identifier_field;
134
            $data[$idf] = $member->{$idf};
135
        }
136
        return $data;
137
    }
138
139
    /**
140
     * @throws ValidationException
141
     */
142
    public function setData(Order $order, array $data)
143
    {
144
        if (Security::getCurrentUser()) {
145
            return;
146
        }
147
        if (!Checkout::membership_required() && empty($data['Password'])) {
148
            return;
149
        }
150
151
        $factory = new ShopMemberFactory();
152
        $member = $factory->create($data);
153
        $member->write();
154
155
        $customer_group = ShopConfigExtension::current()->CustomerGroup();
156
        if ($customer_group->exists()) {
157
            $member->Groups()->add($customer_group);
158
        }
159
160
        // Log-in the current member
161
        Injector::inst()->get(IdentityStore::class)->logIn($member);
162
163
        if ($order->BillingAddressID) {
164
            $address = $order->getBillingAddress();
165
            $address->MemberID = $member->ID;
0 ignored issues
show
Bug Best Practice introduced by
The property MemberID does not exist on SilverShop\Model\Address. Since you implemented __set, consider adding a @property annotation.
Loading history...
166
            $address->write();
167
            $member->DefaultBillingAddressID = $order->BillingAddressID;
168
        }
169
        if ($order->ShippingAddressID) {
170
            $address = $order->getShippingAddress();
171
            $address->MemberID = $member->ID;
172
            $address->write();
173
            $member->DefaultShippingAddressID = $order->ShippingAddressID;
174
        }
175
        if ($member->isChanged()) {
176
            $member->write();
177
        }
178
    }
179
180
    public function setConfirmed($confirmed)
181
    {
182
        $this->confirmed = $confirmed;
183
184
        return $this;
185
    }
186
}
187