Completed
Push — 1 ( fdc87b...27ddc3 )
by Morven
01:40
created

code/control/Users_Register_Controller.php (4 issues)

Upgrade to new PHP Analysis Engine

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
 * Base controller class for users to register. Provides extension hooks to
5
 * allow third party overwriting of both index and register form actions
6
 *
7
 * This controller is also used to allow registered accounts to "verify"
8
 * their details via email.
9
 *
10
 * This is done by adding verified users to the groups stipulated by the
11
 * $verification_groups config variable
12
 *
13
 */
14
class Users_Register_Controller extends Controller
15
{
16
17
    /**
18
     * URL That you can access this from
19
     *
20
     * @config
21
     */
22
    private static $url_segment = "users/register";
23
24
    /**
25
     * Current actions available to this controller
26
     *
27
     * @var array
28
     */
29
    private static $allowed_actions = array(
30
        "index",
31
        "sendverification",
32
        "verify",
33
        "RegisterForm"
34
    );
35
36
    /**
37
     * Internal function designed to allow us to send a verification
38
     * email from multiple locations
39
     *
40
     * @param $member Member object to send email to
41
     * @return boolean
42
     */
43
    protected function send_verification_email(Member $member)
44
    {
45
        if ($member->exists()) {
46
            return $member->sendVerificationEmail();            
47
        }
48
49
        return false;
50
    }
51
52
    /**
53
     * Get the link to this controller
54
     * 
55
     * @param string $action
0 ignored issues
show
Should the type for parameter $action not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

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...
56
     * @return string
57
     */
58
    public function Link($action = null)
59
    {
60
        return Controller::join_links(
61
            $this->config()->url_segment,
62
            $action
63
        );
64
    }
65
66
    /**
67
     * Get an absolute link to this controller
68
     *
69
     * @param string $action
0 ignored issues
show
Should the type for parameter $action not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

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...
70
     * @return false|string
71
     */
72
    public function AbsoluteLink($action = null)
73
    {
74
        return Director::absoluteURL($this->Link($action));
75
    }
76
77
    /**
78
     * Get a relative (to the root url of the site) link to this
79
     * controller
80
     *
81
     * @param string $action
0 ignored issues
show
Should the type for parameter $action not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

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...
82
     * @return string
83
     */
84
    public function RelativeLink($action = null)
85
    {
86
        return Controller::join_links(
87
            $this->Link($action)
88
        );
89
    }
90
91
    /**
92
     * If content controller exists, return it's menu function
93
     * @param int $level Menu level to return.
94
     * @return ArrayList
95
     */
96 View Code Duplication
    public function getMenu($level = 1)
97
    {
98
        if (class_exists(ContentController::class)) {
99
            $controller = Injector::inst()->get(ContentController::class);
100
            return $controller->getMenu($level);
101
        }
102
    }
103
104
    public function Menu($level)
0 ignored issues
show
The parameter $level is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
105
    {
106
        return $this->getMenu();
107
    }
108
109
    /**
110
     * Default action this controller will deal with
111
     *
112
     * @param SS_HTTPRequest $request
113
     * @return HTMLText
114
     */
115
    public function index(SS_HTTPRequest $request)
116
    {
117
        $this->customise(array(
118
            'Title'     => _t('Users.Register', 'Register'),
119
            'MetaTitle' => _t('Users.Register', 'Register'),
120
            'Form'      => $this->RegisterForm(),
121
        ));
122
123
        $this->extend("updateIndexAction");
124
125
        return $this->renderWith(array(
126
            "Users_Register",
127
            "Users",
128
            "Page"
129
        ));
130
    }
131
132
133
    /**
134
     * Send a verification email to the user provided (if verification
135
     * emails are enabled and account is not already verified)
136
     *
137
     * @param SS_HTTPRequest $request
138
     * @return HTMLText
139
     */
140
    public function sendverification(SS_HTTPRequest $request)
141
    {
142
        // If we don't allow verification emails, return an error
143
        if (!Users::config()->send_verification_email) {
144
            return $this->httpError(400);
145
        }
146
147
        $sent = false;
148
149
        if (Member::currentUserID()) {
150
            $member = Member::currentUser();
151
        } else {
152
            $member = Member::get()->byID($this->getRequest()->param("ID"));
153
        }
154
155
        if ($member && !$member->isVerified()) {
156
            $sent = $this->send_verification_email($member);
157
        }
158
159
        $this->customise(array(
160
            "Title" => _t('Users.AccountVerification','Account Verification'),
161
            "MetaTitle" => _t('Users.AccountVerification','Account Verification'),
162
            "Content" => $this->renderWith(
163
                "UsersSendVerificationContent",
164
                array("Sent" => $sent)
165
            ),
166
            "Sent" => $sent
167
        ));
168
169
        $this->extend("updateSendVerificationAction");
170
171
        return $this->renderWith(array(
172
            "Users_Register_sendverification",
173
            "Users",
174
            "Page"
175
        ));
176
    }
177
178
179
    /**
180
     * Verify the provided user (ID) using the verification code (Other
181
     * ID) provided
182
     *
183
     * @param SS_HTTPRequest $request
184
     * @return HTMLText
185
     */
186
    public function verify(SS_HTTPRequest $request)
187
    {   
188
        $member = Member::get()->byID($this->getRequest()->param("ID"));
189
        $code = $this->getRequest()->param("OtherID");
190
        $verify = false;
191
192
        // Check verification group exists, if not, make it
193
        // Add a verified users group (only used if we turn on
194
        // verification)
195
        $verify_groups = Group::get()
196
            ->filter("Code", Users::config()->verification_groups);
197
198
        $this->extend("onBeforeVerify", $member);
199
200
        if (($member && $code) && $code == $member->VerificationCode) {
201
            foreach ($verify_groups as $group) {
202
                $group->Members()->add($member);
203
                $verify = true;
204
            }
205
        }
206
207
        $this->customise(array(
208
            "Title" => _t('Users.AccountVerification','Account Verification'),
209
            "MetaTitle" => _t('Users.AccountVerification','Account Verification'),
210
            "Content" => $this->renderWith(
211
                "UsersVerifyContent",
212
                array("Verify" => $verify)
213
            ),
214
            "Verify" => $verify
215
        ));
216
217
        $this->extend("onAfterVerify", $member);
218
219
        return $this->renderWith(array(
220
            "Users_Register_verify",
221
            "Users",
222
            "Page"
223
        ));
224
    }
225
226
    /**
227
     * Registration form
228
     *
229
     * @return Form
230
     */
231
    public function RegisterForm()
232
    {
233
234
        // If back URL set, push to session
235
        if (isset($_REQUEST['BackURL'])) {
236
            Session::set('BackURL', $_REQUEST['BackURL']);
237
        }
238
239
        $config = Users::config();
240
241
        // Setup form fields
242
        $fields = FieldList::create(
243
            TextField::create("FirstName"),
244
            TextField::create("Surname"),
245
            EmailField::create("Email"),
246
            $password_field = ConfirmedPasswordField::create("Password")
247
        );
248
249
        $password_field->minLength = $config->get("password_min_length");
250
        $password_field->maxLength = $config->get("password_max_length");
251
        $password_field->requireStrongPassword = $config->get("password_require_strong");
252
253
        // Setup form actions
254
        $actions = new FieldList(
255
            FormAction::create("doRegister", "Register")
256
                ->addExtraClass("btn")
257
                ->addExtraClass("btn-green")
258
        );
259
260
        // Setup required fields
261
        $required = new RequiredFields(array(
262
            "FirstName",
263
            "Surname",
264
            "Email",
265
            "Password"
266
        ));
267
268
        $form = Form::create(
269
            $this,
270
            "RegisterForm",
271
            $fields,
272
            $actions,
273
            $required
274
        )->addExtraClass("forms")
275
        ->addExtraClass("forms-columnar");
276
277
        $this->extend("updateRegisterForm", $form);
278
279
        $session_data = Session::get("Form.{$form->FormName()}.data");
280
281
        if ($session_data && is_array($session_data)) {
282
            $form->loadDataFrom($session_data);
283
            Session::clear("Form.{$form->FormName()}.data");
284
        }
285
286
        return $form;
287
    }
288
289
    /**
290
     * Register a new member. This action is deigned to be intercepted at 2
291
     * points:
292
     *
293
     *  - Modify the initial member filter (so that you can perfom bespoke
294
     *    member filtering
295
     *
296
     *  - Modify the member user before saving (so we can add extra permissions
297
     *    etc)
298
     *
299
     * @param array $data User submitted data
300
     * @param Form $form Registration form
301
     */
302
    public function doRegister($data, $form)
303
    {
304
        $filter = array();
305
306
        if (isset($data['Email'])) {
307
            $filter['Email'] = $data['Email'];
308
        }
309
310
        $this->extend("updateMemberFilter", $filter);
311
312
        // Check if a user already exists
313
        if ($member = Member::get()->filter($filter)->first()) {
314
            if ($member) {
315
                $form->addErrorMessage(
316
                    "Blurb",
317
                    "Sorry, an account already exists with those details.",
318
                    "bad"
319
                );
320
321
                // Load errors into session and post back
322
                unset($data["Password"]);
323
                Session::set("Form.{$form->FormName()}.data", $data);
324
325
                return $this->redirectBack();
326
            }
327
        }
328
329
        $member = Member::create();
330
        $member->Register($data);
331
332
        $this->extend("updateNewMember", $member, $data);
333
334
        $session_url = Session::get("BackURL");
335
        $request_url = $this->getRequest()->requestVar("BackURL");
336
337
        // If a back URL is used in session.
338
        if (!empty($session_url)) {
339
            $redirect_url = $session_url;
340
        } elseif (!empty($request_url)) {
341
            $redirect_url = $request_url;
342
        } else {
343
            $controller = Injector::inst()->get("Users_Account_Controller");
344
            $redirect_url = $controller->Link();
345
        }
346
347
        return $this->redirect($redirect_url);
348
    }
349
}
350