Completed
Push — 1 ( 13c7dd...13037b )
by Morven
01:38
created

code/control/Users_Register_Controller.php (3 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) {
46
            $subject = _t("Users.PleaseVerify", "Please verify your account");
47
            if (Users::config()->send_email_from) {
48
                $from = Users::config()->send_email_from;
49
            } else {
50
                $from = Email::config()->admin_email;
51
            }
52
53
            $body = $this->renderWith(
54
                'UsersAccountVerification',
55
                array(
56
                    "Link" => Controller::join_links(
57
                        Director::absoluteBaseURL(),
58
                        $this->config()->url_segment,
59
                        "verify",
60
                        $member->ID,
61
                        $member->VerificationCode
62
                    )
63
                )
64
            );
65
66
            $email = new Email($from, $member->Email, $subject, $body);
67
            $email->sendPlain();
68
69
            return true;
70
        }
71
72
        return false;
73
    }
74
75
    /**
76
     * Get the link to this controller
77
     * 
78
     * @param string $action
79
     * @return string|null
80
     */
81
    public function Link($action = null)
82
    {
83
        return Controller::join_links(
84
            $this->config()->url_segment,
85
            $action
86
        );
87
    }
88
89
    /**
90
     * Get an absolute link to this controller
91
     *
92
     * @param string $action
93
     * @return string|null
94
     */
95
    public function AbsoluteLink($action = null)
96
    {
97
        return Director::absoluteURL($this->Link($action));
98
    }
99
100
    /**
101
     * Get a relative (to the root url of the site) link to this
102
     * controller
103
     *
104
     * @param string $action
105
     * @return string|null
106
     */
107
    public function RelativeLink($action = null)
108
    {
109
        return Controller::join_links(
110
            $this->Link($action)
111
        );
112
    }
113
114
    /**
115
     * Default action this controller will deal with
116
     *
117
     * @param SS_HTTPRequest $request
118
     * @return string
0 ignored issues
show
Should the return type not be HTMLText?

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...
119
     */
120
    public function index(SS_HTTPRequest $request)
121
    {
122
        $this->customise(array(
123
            'Title'     => "Register",
124
            'ClassName' => 'RegisterPage',
125
            'Content'   => '',
126
            'Form'      => $this->RegisterForm(),
127
        ));
128
129
        $this->extend("updateIndexAction");
130
131
        return $this->renderWith(array(
132
            "Users_Register",
133
            "Users",
134
            "Page"
135
        ));
136
    }
137
138
139
    /**
140
     * Send a verification email to the user provided (if verification
141
     * emails are enabled and account is not already verified)
142
     *
143
     * @param SS_HTTPRequest $request
144
     * @return string
0 ignored issues
show
Should the return type not be HTMLText?

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...
145
     */
146
    public function sendverification(SS_HTTPRequest $request)
147
    {
148
        $sent = false;
149
150
        if (Member::currentUserID()) {
151
            $member = Member::currentUser();
152
        } else {
153
            $member = Member::get()->byID($this->request->param("ID"));
154
        }
155
156
        if ($member && !$member->isVerified() && Users::config()->send_verification_email) {
157
            $sent = $this->send_verification_email($member);
158
        } else {
159
            $sent = false;
160
        }
161
162
        $this->customise(array(
163
            "ClassName" => "RegisterPage",
164
            "Sent" => $sent
165
        ));
166
167
        return $this->renderWith(array(
168
            "Users_Register_sendverification",
169
            "Users",
170
            "Page"
171
        ));
172
    }
173
174
175
    /**
176
     * Verify the provided user (ID) using the verification code (Other
177
     * ID) provided
178
     *
179
     * @param SS_HTTPRequest $request
180
     * @return string
0 ignored issues
show
Should the return type not be HTMLText?

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...
181
     */
182
    public function verify(SS_HTTPRequest $request)
183
    {
184
        $member = Member::get()->byID($this->request->param("ID"));
185
        $code = $this->request->param("OtherID");
186
        $verify = false;
187
188
        // Check verification group exists, if not, make it
189
        // Add a verified users group (only used if we turn on
190
        // verification)
191
        $verify_groups = Group::get()
192
            ->filter("Code", Users::config()->verification_groups);
193
194
        $this->extend("onBeforeVerify", $member);
195
196
        if (($member && $code) && $code == $member->VerificationCode) {
197
            foreach ($verify_groups as $group) {
198
                $group->Members()->add($member);
199
                $verify = true;
200
            }
201
        }
202
203
        $this->customise(array(
204
            "ClassName" => "RegisterPage",
205
            "Verify" => $verify
206
        ));
207
208
        $this->extend("onAfterVerify", $member);
209
210
        return $this->renderWith(array(
211
            "Users_Register_verify",
212
            "Users",
213
            "Page"
214
        ));
215
    }
216
217
    /**
218
     * Registration form
219
     *
220
     * @return Form
221
     */
222
    public function RegisterForm()
223
    {
224
225
        // If back URL set, push to session
226
        if (isset($_REQUEST['BackURL'])) {
227
            Session::set('BackURL', $_REQUEST['BackURL']);
228
        }
229
230
        // Setup form fields
231
        $fields = FieldList::create(
232
            TextField::create("FirstName"),
233
            TextField::create("Surname"),
234
            EmailField::create("Email"),
235
            ConfirmedPasswordField::create("Password")
236
        );
237
238
        // Setup form actions
239
        $actions = new FieldList(
240
            FormAction::create("doRegister", "Register")
241
                ->addExtraClass("btn")
242
                ->addExtraClass("btn-green")
243
        );
244
245
        // Setup required fields
246
        $required = new RequiredFields(array(
247
            "FirstName",
248
            "Surname",
249
            "Email",
250
            "Password"
251
        ));
252
253
        $form = Form::create($this, "RegisterForm", $fields, $actions, $required)
254
            ->addExtraClass("forms")
255
            ->addExtraClass("forms-columnar");
256
257
        $this->extend("updateRegisterForm", $form);
258
259
        $session_data = Session::get("Form.{$form->FormName()}.data");
260
261
        if ($session_data && is_array($session_data)) {
262
            $form->loadDataFrom($session_data);
263
            Session::clear("Form.{$form->FormName()}.data");
264
        }
265
266
        return $form;
267
    }
268
269
    /**
270
     * Register a new member. This action is deigned to be intercepted at 2
271
     * points:
272
     *
273
     *  - Modify the initial member filter (so that you can perfom bespoke
274
     *    member filtering
275
     *
276
     *  - Modify the member user before saving (so we can add extra permissions
277
     *    etc)
278
     *
279
     * @param array $data User submitted data
280
     * @param Form $form Registration form
281
     */
282
    public function doRegister($data, $form)
283
    {
284
        $filter = array();
285
286
        if (isset($data['Email'])) {
287
            $filter['Email'] = $data['Email'];
288
        }
289
290
        $this->extend("updateMemberFilter", $filter);
291
292
        // Check if a user already exists
293
        if ($member = Member::get()->filter($filter)->first()) {
294
            if ($member) {
295
                $form->addErrorMessage(
296
                    "Blurb",
297
                    "Sorry, an account already exists with those details.",
298
                    "bad"
299
                );
300
301
                // Load errors into session and post back
302
                unset($data["Password"]);
303
                Session::set("Form.{$form->FormName()}.data", $data);
304
305
                return $this->redirectBack();
306
            }
307
        }
308
309
        $member = Member::create();
310
        $form->saveInto($member);
311
312
        // Set verification code for this user
313
        $member->VerificationCode = sha1(mt_rand() . mt_rand());
314
        $member->write();
315
316
        // Add member to any groups that have been specified
317
        if (count(Users::config()->new_user_groups)) {
318
            $groups = Group::get()->filter(array(
319
                "Code" => Users::config()->new_user_groups
320
            ));
321
322
            foreach ($groups as $group) {
323
                $group->Members()->add($member);
324
                $group->write();
325
            }
326
        }
327
328
        $this->extend("updateNewMember", $member, $data);
329
330
        // Send a verification email, if needed
331
        if (Users::config()->send_verification_email) {
332
            $this->send_verification_email($member);
333
        }
334
335
        // Login (if enabled)
336
        if (Users::config()->login_after_register) {
337
            $member->LogIn(isset($data['Remember']));
338
        }
339
340
        $session_url = Session::get("BackURL");
341
        $request_url = $this->getRequest()->requestVar("BackURL");
342
343
        // If a back URL is used in session.
344
        if (!empty($session_url)) {
345
            $redirect_url = $session_url;
346
        } elseif (!empty($request_url)) {
347
            $redirect_url = $request_url;
348
        } else {
349
            $controller = Injector::inst()->get("Users_Account_Controller");
350
            $redirect_url = $controller->Link();
351
        }
352
353
        return $this->redirect($redirect_url);
354
    }
355
}
356