Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
// This file is part of Moodle - http://moodle.org/
3
//
4
// Moodle is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8
//
9
// Moodle is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13
//
14
// You should have received a copy of the GNU General Public License
15
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
16
 
17
/**
18
 * Class registration
19
 *
20
 * @package    core
21
 * @copyright  2017 Marina Glancy
22
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23
 */
24
 
25
namespace core\hub;
26
defined('MOODLE_INTERNAL') || die();
27
 
28
use moodle_exception;
29
use moodle_url;
30
use context_system;
31
use stdClass;
32
use html_writer;
33
 
34
/**
35
 * Methods to use when registering the site at the moodle sites directory.
36
 *
37
 * @package    core
38
 * @copyright  2017 Marina Glancy
39
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
40
 */
41
class registration {
42
 
43
    /** @var array Fields used in a site registration form.
44
     * IMPORTANT: any new fields with non-empty defaults have to be added to CONFIRM_NEW_FIELDS */
45
    const FORM_FIELDS = ['policyagreed', 'language', 'countrycode', 'privacy',
46
        'contactemail', 'contactable', 'emailalert', 'emailalertemail', 'commnews', 'commnewsemail',
47
        'contactname', 'name', 'description', 'imageurl', 'contactphone', 'regioncode', 'geolocation', 'street'];
48
 
49
    /** @var array List of new FORM_FIELDS or siteinfo fields added indexed by the version when they were added.
50
     * If site was already registered, admin will be promted to confirm new registration data manually. Until registration is manually confirmed,
51
     * the scheduled task updating registration will be paused.
52
     * Keys of this array are not important as long as they increment, use current date to avoid confusions.
53
     */
54
    const CONFIRM_NEW_FIELDS = [
55
        2017092200 => [
56
            'commnews', // Receive communication news. This was added in 3.4 and is "On" by default. Admin must confirm or opt-out.
57
            'mobileservicesenabled', 'mobilenotificationsenabled', 'registereduserdevices', 'registeredactiveuserdevices' // Mobile stats added in 3.4.
58
        ],
59
        // Analytics stats added in Moodle 3.7.
60
        2019022200 => ['analyticsenabledmodels', 'analyticspredictions', 'analyticsactions', 'analyticsactionsnotuseful'],
61
        // Active users stats added in Moodle 3.9.
62
        2020022600 => ['activeusers', 'activeparticipantnumberaverage'],
63
        // Database type, course date info, site theme, primary auth type added in Moodle 4.2.
64
        2023021700 => ['dbtype', 'coursesnodates', 'sitetheme', 'primaryauthtype'],
65
    ];
66
 
67
    /** @var string Site privacy: not displayed */
68
    const HUB_SITENOTPUBLISHED = 'notdisplayed';
69
 
70
    /** @var string Site privacy: public */
71
    const HUB_SITENAMEPUBLISHED = 'named';
72
 
73
    /** @var string Site privacy: public and global */
74
    const HUB_SITELINKPUBLISHED = 'linked';
75
 
76
    /** @var stdClass cached site registration information */
77
    protected static $registration = null;
78
 
79
    /**
80
     * Get site registration
81
     *
82
     * @param bool $confirmed
83
     * @return stdClass|null
84
     */
85
    protected static function get_registration($confirmed = true) {
86
        global $DB;
87
 
88
        if (self::$registration === null) {
89
            self::$registration = $DB->get_record('registration_hubs', ['huburl' => HUB_MOODLEORGHUBURL]) ?: null;
90
        }
91
 
92
        if (self::$registration && (bool)self::$registration->confirmed == (bool)$confirmed) {
93
            return self::$registration;
94
        }
95
 
96
        return null;
97
    }
98
 
99
    /**
100
     * Same as get_registration except it throws exception if site not registered
101
     *
102
     * @return stdClass
103
     * @throws \moodle_exception
104
     */
105
    public static function require_registration() {
106
        if ($registration = self::get_registration()) {
107
            return $registration;
108
        }
109
        if (has_capability('moodle/site:config', context_system::instance())) {
110
            throw new moodle_exception('registrationwarning', 'admin', new moodle_url('/admin/registration/index.php'));
111
        } else {
112
            throw new moodle_exception('registrationwarningcontactadmin', 'admin');
113
        }
114
    }
115
 
116
    /**
117
     * Checks if site is registered
118
     *
119
     * @return bool
120
     */
121
    public static function is_registered() {
122
        return self::get_registration() ? true : false;
123
    }
124
 
125
    /**
126
     * Returns registration token
127
     *
128
     * @param int $strictness if set to MUST_EXIST and site is not registered will throw an exception
129
     * @return null
130
     * @throws moodle_exception
131
     */
132
    public static function get_token($strictness = IGNORE_MISSING) {
133
        if ($strictness == MUST_EXIST) {
134
            $registration = self::require_registration();
135
        } else if (!$registration = self::get_registration()) {
136
            return null;
137
        }
138
        return $registration->token;
139
    }
140
 
141
    /**
142
     * When was the registration last updated
143
     *
144
     * @return int|null timestamp or null if site is not registered
145
     */
146
    public static function get_last_updated() {
147
        if ($registration = self::get_registration()) {
148
            return $registration->timemodified;
149
        }
150
        return null;
151
    }
152
 
153
    /**
154
     * Calculates and prepares site information to send to the sites directory as a part of registration.
155
     *
156
     * @param array $defaults default values for inputs in the registration form (if site was never registered before)
157
     * @return array site info
158
     */
159
    public static function get_site_info($defaults = []) {
160
        global $CFG, $DB;
161
        require_once($CFG->libdir . '/badgeslib.php');
162
        require_once($CFG->dirroot . "/course/lib.php");
163
 
164
        $siteinfo = array();
165
        foreach (self::FORM_FIELDS as $field) {
166
            $siteinfo[$field] = get_config('hub', 'site_'.$field);
167
            if ($siteinfo[$field] === false) {
168
                $siteinfo[$field] = array_key_exists($field, $defaults) ? $defaults[$field] : null;
169
            }
170
        }
171
 
172
        // Statistical data.
173
        $siteinfo['courses'] = $DB->count_records('course') - 1;
174
        $siteinfo['users'] = $DB->count_records('user', array('deleted' => 0));
175
        $siteinfo['activeusers'] = $DB->count_records_select('user', 'deleted = ? AND lastlogin > ?', [0, time() - DAYSECS * 30]);
176
        $siteinfo['enrolments'] = $DB->count_records('role_assignments');
177
        $siteinfo['posts'] = $DB->count_records('forum_posts');
178
        $siteinfo['questions'] = $DB->count_records('question');
179
        $siteinfo['resources'] = $DB->count_records('resource');
180
        $siteinfo['badges'] = $DB->count_records_select('badge', 'status <> ' . BADGE_STATUS_ARCHIVED);
181
        $siteinfo['issuedbadges'] = $DB->count_records('badge_issued');
182
        $siteinfo['participantnumberaverage'] = average_number_of_participants();
183
        $siteinfo['activeparticipantnumberaverage'] = average_number_of_participants(true, time() - DAYSECS * 30);
184
        $siteinfo['modulenumberaverage'] = average_number_of_courses_modules();
185
        $siteinfo['dbtype'] = $CFG->dbtype;
186
        $siteinfo['coursesnodates'] = $DB->count_records_select('course', 'enddate = ?', [0]) - 1;
187
        $siteinfo['sitetheme'] = get_config('core', 'theme');
188
 
189
        // Primary auth type.
190
        $primaryauthsql = 'SELECT auth, count(auth) as tc FROM {user} GROUP BY auth ORDER BY tc DESC';
191
        $siteinfo['primaryauthtype'] = $DB->get_field_sql($primaryauthsql, null, IGNORE_MULTIPLE);
192
 
193
        // Version and url.
194
        $siteinfo['moodlerelease'] = $CFG->release;
195
        $siteinfo['url'] = $CFG->wwwroot;
196
 
197
        // Mobile related information.
198
        $siteinfo['mobileservicesenabled'] = 0;
199
        $siteinfo['mobilenotificationsenabled'] = 0;
200
        $siteinfo['registereduserdevices'] = 0;
201
        $siteinfo['registeredactiveuserdevices'] = 0;
202
        if (!empty($CFG->enablewebservices) && !empty($CFG->enablemobilewebservice)) {
203
            $siteinfo['mobileservicesenabled'] = 1;
204
            $siteinfo['registereduserdevices'] = $DB->count_records('user_devices');
205
            $airnotifierextpath = $CFG->dirroot . '/message/output/airnotifier/externallib.php';
206
            if (file_exists($airnotifierextpath)) { // Maybe some one uninstalled the plugin.
207
                require_once($airnotifierextpath);
208
                $siteinfo['mobilenotificationsenabled'] = \message_airnotifier_external::is_system_configured();
209
                $siteinfo['registeredactiveuserdevices'] = $DB->count_records('message_airnotifier_devices', array('enable' => 1));
210
            }
211
        }
212
 
213
        // Analytics related data follow.
214
        $siteinfo['analyticsenabledmodels'] = \core_analytics\stats::enabled_models();
215
        $siteinfo['analyticspredictions'] = \core_analytics\stats::predictions();
216
        $siteinfo['analyticsactions'] = \core_analytics\stats::actions();
217
        $siteinfo['analyticsactionsnotuseful'] = \core_analytics\stats::actions_not_useful();
218
 
219
        // IMPORTANT: any new fields in siteinfo have to be added to the constant CONFIRM_NEW_FIELDS.
220
 
221
        return $siteinfo;
222
    }
223
 
224
    /**
225
     * Human-readable summary of data that will be sent to the sites directory.
226
     *
227
     * @param array $siteinfo result of get_site_info()
228
     * @return string
229
     */
230
    public static function get_stats_summary($siteinfo) {
231
        $fieldsneedconfirm = self::get_new_registration_fields();
232
        $summary = html_writer::tag('p', get_string('sendfollowinginfo_help', 'hub')) .
233
            html_writer::start_tag('ul');
234
 
235
        $mobileservicesenabled = $siteinfo['mobileservicesenabled'] ? get_string('yes') : get_string('no');
236
        $mobilenotificationsenabled = $siteinfo['mobilenotificationsenabled'] ? get_string('yes') : get_string('no');
237
        $moodlerelease = $siteinfo['moodlerelease'];
238
        if (preg_match('/^(\d+\.\d.*?)[\. ]/', $moodlerelease, $matches)) {
239
            $moodlerelease = $matches[1];
240
        }
241
        $senddata = [
242
            'moodlerelease' => get_string('sitereleasenum', 'hub', $moodlerelease),
243
            'courses' => get_string('coursesnumber', 'hub', $siteinfo['courses']),
244
            'users' => get_string('usersnumber', 'hub', $siteinfo['users']),
245
            'activeusers' => get_string('activeusersnumber', 'hub', $siteinfo['activeusers']),
246
            'enrolments' => get_string('roleassignmentsnumber', 'hub', $siteinfo['enrolments']),
247
            'posts' => get_string('postsnumber', 'hub', $siteinfo['posts']),
248
            'questions' => get_string('questionsnumber', 'hub', $siteinfo['questions']),
249
            'resources' => get_string('resourcesnumber', 'hub', $siteinfo['resources']),
250
            'badges' => get_string('badgesnumber', 'hub', $siteinfo['badges']),
251
            'issuedbadges' => get_string('issuedbadgesnumber', 'hub', $siteinfo['issuedbadges']),
252
            'participantnumberaverage' => get_string('participantnumberaverage', 'hub',
253
                format_float($siteinfo['participantnumberaverage'], 2)),
254
            'activeparticipantnumberaverage' => get_string('activeparticipantnumberaverage', 'hub',
255
                format_float($siteinfo['activeparticipantnumberaverage'], 2)),
256
            'modulenumberaverage' => get_string('modulenumberaverage', 'hub',
257
                format_float($siteinfo['modulenumberaverage'], 2)),
258
            'mobileservicesenabled' => get_string('mobileservicesenabled', 'hub', $mobileservicesenabled),
259
            'mobilenotificationsenabled' => get_string('mobilenotificationsenabled', 'hub', $mobilenotificationsenabled),
260
            'registereduserdevices' => get_string('registereduserdevices', 'hub', $siteinfo['registereduserdevices']),
261
            'registeredactiveuserdevices' => get_string('registeredactiveuserdevices', 'hub', $siteinfo['registeredactiveuserdevices']),
262
            'analyticsenabledmodels' => get_string('analyticsenabledmodels', 'hub', $siteinfo['analyticsenabledmodels']),
263
            'analyticspredictions' => get_string('analyticspredictions', 'hub', $siteinfo['analyticspredictions']),
264
            'analyticsactions' => get_string('analyticsactions', 'hub', $siteinfo['analyticsactions']),
265
            'analyticsactionsnotuseful' => get_string('analyticsactionsnotuseful', 'hub', $siteinfo['analyticsactionsnotuseful']),
266
            'dbtype' => get_string('dbtype', 'hub', $siteinfo['dbtype']),
267
            'coursesnodates' => get_string('coursesnodates', 'hub', $siteinfo['coursesnodates']),
268
            'sitetheme' => get_string('sitetheme', 'hub', $siteinfo['sitetheme']),
269
            'primaryauthtype' => get_string('primaryauthtype', 'hub', $siteinfo['primaryauthtype']),
270
        ];
271
 
272
        foreach ($senddata as $key => $str) {
273
            $class = in_array($key, $fieldsneedconfirm) ? ' needsconfirmation mark' : '';
274
            $summary .= html_writer::tag('li', $str, ['class' => 'site' . $key . $class]);
275
        }
276
        $summary .= html_writer::end_tag('ul');
277
        return $summary;
278
    }
279
 
280
    /**
281
     * Save registration info locally so it can be retrieved when registration needs to be updated
282
     *
283
     * @param stdClass $formdata data from {@link site_registration_form}
284
     */
285
    public static function save_site_info($formdata) {
286
        foreach (self::FORM_FIELDS as $field) {
287
            set_config('site_' . $field, $formdata->$field, 'hub');
288
        }
289
        // Even if the connection with the sites directory fails, admin has manually submitted the form which means they don't need
290
        // to be redirected to the site registration page any more.
291
        set_config('site_regupdateversion', max(array_keys(self::CONFIRM_NEW_FIELDS)), 'hub');
292
    }
293
 
294
    /**
295
     * Updates site registration when "Update reigstration" button is clicked by admin
296
     */
297
    public static function update_manual() {
298
        global $DB;
299
 
300
        if (!$registration = self::get_registration()) {
301
            return false;
302
        }
303
 
304
        $siteinfo = self::get_site_info();
305
        try {
306
            api::update_registration($siteinfo);
307
        } catch (moodle_exception $e) {
308
            if (!self::is_registered()) {
309
                // Token was rejected during registration update and site and locally stored token was reset,
310
                // proceed to site registration. This method will redirect away.
311
                self::register('');
312
            }
313
            \core\notification::add(get_string('errorregistrationupdate', 'hub', $e->getMessage()),
314
                \core\output\notification::NOTIFY_ERROR);
315
            return false;
316
        }
317
        $DB->update_record('registration_hubs', ['id' => $registration->id, 'timemodified' => time()]);
318
        \core\notification::add(get_string('siteregistrationupdated', 'hub'),
319
            \core\output\notification::NOTIFY_SUCCESS);
320
        self::$registration = null;
321
        return true;
322
    }
323
 
324
    /**
325
     * Updates site registration via cron
326
     *
327
     * @throws moodle_exception
328
     */
329
    public static function update_cron() {
330
        global $DB;
331
 
332
        if (!$registration = self::get_registration()) {
333
            mtrace(get_string('registrationwarning', 'admin'));
334
            return;
335
        }
336
 
337
        if (self::get_new_registration_fields()) {
338
            mtrace(get_string('pleaserefreshregistrationnewdata', 'admin'));
339
            return;
340
        }
341
 
342
        $siteinfo = self::get_site_info();
343
        api::update_registration($siteinfo);
344
        $DB->update_record('registration_hubs', ['id' => $registration->id, 'timemodified' => time()]);
345
        mtrace(get_string('siteregistrationupdated', 'hub'));
346
        self::$registration = null;
347
    }
348
 
349
    /**
350
     * Confirms registration by the sites directory.
351
     *
352
     * @param string $token
353
     * @param string $newtoken
354
     * @param string $hubname
355
     * @throws moodle_exception
356
     */
357
    public static function confirm_registration($token, $newtoken, $hubname) {
358
        global $DB;
359
 
360
        $registration = self::get_registration(false);
361
        if (!$registration || $registration->token !== $token) {
362
            throw new moodle_exception('wrongtoken', 'hub', new moodle_url('/admin/registration/index.php'));
363
        }
364
        $record = ['id' => $registration->id];
365
        $record['token'] = $newtoken;
366
        $record['confirmed'] = 1;
367
        $record['hubname'] = $hubname;
368
        $record['timemodified'] = time();
369
        $DB->update_record('registration_hubs', $record);
370
        self::$registration = null;
371
 
372
        $siteinfo = self::get_site_info();
373
        if (strlen(http_build_query($siteinfo)) > 1800) {
374
            // Update registration again because the initial request was too long and could have been truncated.
375
            api::update_registration($siteinfo);
376
            self::$registration = null;
377
        }
378
 
379
        // Finally, allow other plugins to perform actions once a site is registered for first time.
380
        $pluginsfunction = get_plugins_with_function('post_site_registration_confirmed');
381
        foreach ($pluginsfunction as $plugins) {
382
            foreach ($plugins as $pluginfunction) {
383
                $pluginfunction($registration->id);
384
            }
385
        }
386
    }
387
 
388
    /**
389
     * Retrieve the options for site privacy form element to use in registration form
390
     * @return array
391
     */
392
    public static function site_privacy_options() {
393
        return [
394
            self::HUB_SITENOTPUBLISHED => get_string('siteprivacynotpublished', 'hub'),
395
            self::HUB_SITENAMEPUBLISHED => get_string('siteprivacypublished', 'hub'),
396
            self::HUB_SITELINKPUBLISHED => get_string('siteprivacylinked', 'hub')
397
        ];
398
    }
399
 
400
    /**
401
     * Registers a site
402
     *
403
     * This method will make sure that unconfirmed registration record is created and then redirect to
404
     * registration script on the sites directory.
405
     * The sites directory will check that the site is accessible, register it and redirect back
406
     * to /admin/registration/confirmregistration.php
407
     *
408
     * @param string $returnurl
409
     * @throws \coding_exception
410
     */
411
    public static function register($returnurl) {
412
        global $DB, $SESSION;
413
 
414
        if (self::is_registered()) {
415
            // Caller of this method must make sure that site is not registered.
416
            throw new \coding_exception('Site already registered');
417
        }
418
 
419
        $hub = self::get_registration(false);
420
        if (empty($hub)) {
421
            // Create a new record in 'registration_hubs'.
422
            $hub = new stdClass();
423
            $hub->token = get_site_identifier();
424
            $hub->secret = $hub->token;
425
            $hub->huburl = HUB_MOODLEORGHUBURL;
426
            $hub->hubname = 'moodle';
427
            $hub->confirmed = 0;
428
            $hub->timemodified = time();
429
            $hub->id = $DB->insert_record('registration_hubs', $hub);
430
            self::$registration = null;
431
        }
432
 
433
        $params = self::get_site_info();
434
 
435
        // The most conservative limit for the redirect URL length is 2000 characters. Only pass parameters before
436
        // we reach this limit. The next registration update will update all fields.
437
        // We will also update registration after we receive confirmation from moodle.net.
438
        $url = new moodle_url(HUB_MOODLEORGHUBURL . '/local/hub/siteregistration.php',
439
            ['token' => $hub->token, 'url' => $params['url']]);
440
        foreach ($params as $key => $value) {
441
            if (strlen($url->out(false, [$key => $value])) > 2000) {
442
                break;
443
            }
444
            $url->param($key, $value);
445
        }
446
 
447
        $SESSION->registrationredirect = $returnurl;
448
        redirect($url);
449
    }
450
 
451
    /**
452
     * Unregister site
453
     *
454
     * @param bool $unpublishalladvertisedcourses
455
     * @param bool $unpublishalluploadedcourses
456
     * @return bool
457
     */
458
    public static function unregister($unpublishalladvertisedcourses, $unpublishalluploadedcourses) {
459
        global $DB;
460
 
461
        if (!$hub = self::get_registration()) {
462
            return true;
463
        }
464
 
465
        // Course unpublish went ok, unregister the site now.
466
        try {
467
            api::unregister_site();
468
        } catch (moodle_exception $e) {
469
            \core\notification::add(get_string('unregistrationerror', 'hub', $e->getMessage()),
470
                \core\output\notification::NOTIFY_ERROR);
471
            return false;
472
        }
473
 
474
        $DB->delete_records('registration_hubs', array('id' => $hub->id));
475
        self::$registration = null;
476
        return true;
477
    }
478
 
479
    /**
480
     * Resets the registration token without changing site identifier so site can be re-registered
481
     *
482
     * @return bool
483
     */
484
    public static function reset_token() {
485
        global $DB;
486
        if (!$hub = self::get_registration()) {
487
            return true;
488
        }
489
        $DB->delete_records('registration_hubs', array('id' => $hub->id));
490
        self::$registration = null;
491
    }
492
 
493
    /**
494
     * Generate a new token for the site that is not registered
495
     *
496
     * @param string $token
497
     * @throws moodle_exception
498
     */
499
    public static function reset_site_identifier($token) {
500
        global $DB, $CFG;
501
 
502
        $registration = self::get_registration(false);
503
        if (!$registration || $registration->token != $token) {
504
            throw new moodle_exception('wrongtoken', 'hub',
505
               new moodle_url('/admin/registration/index.php'));
506
        }
507
 
508
        $DB->delete_records('registration_hubs', array('id' => $registration->id));
509
        self::$registration = null;
510
 
511
        $CFG->siteidentifier = null;
512
        get_site_identifier();
513
    }
514
 
515
    /**
516
     * Returns information about the sites directory.
517
     *
518
     * Example of the return array:
519
     * {
520
     *     "courses": 384,
521
     *     "description": "Official moodle sites directory",
522
     *     "downloadablecourses": 0,
523
     *     "enrollablecourses": 0,
524
     *     "hublogo": 1,
525
     *     "language": "en",
526
     *     "name": "moodle",
527
     *     "sites": 274175,
528
     *     "url": "https://stats.moodle.org",
529
     *     "imgurl": "https://stats.moodle.org/local/hub/webservice/download.php?filetype=hubscreenshot"
530
     * }
531
     *
532
     * @return array|null
533
     */
534
    public static function get_moodlenet_info() {
535
        try {
536
            return api::get_hub_info();
537
        } catch (moodle_exception $e) {
538
            // Ignore error, we only need it for displaying information about the sites directory.
539
            // If this request fails, it's not a big deal.
540
            return null;
541
        }
542
    }
543
 
544
    /**
545
     * Does admin need to be redirected to the registration page after install?
546
     *
547
     * @param bool|null $markasviewed if set to true will mark the registration form as viewed and admin will not be redirected
548
     *     to the registration form again (regardless of whether the site was registered or not).
549
     * @return bool
550
     */
551
    public static function show_after_install($markasviewed = null) {
552
        global $CFG;
553
        if (self::is_registered()) {
554
            $showregistration = false;
555
            $markasviewed = true;
556
        } else {
557
            $showregistration = !empty($CFG->registrationpending);
558
            if ($showregistration && !site_is_public()) {
559
                // If it's not a public site, don't redirect to registration, it won't work anyway.
560
                $showregistration = false;
561
                $markasviewed = true;
562
            }
563
        }
564
        if ($markasviewed !== null) {
565
            set_config('registrationpending', !$markasviewed);
566
        }
567
        return $showregistration;
568
    }
569
 
570
    /**
571
     * Returns the list of the fields in the registration form that were added since registration or last manual update
572
     *
573
     * If this list is not empty the scheduled task will be paused and admin will be reminded to update registration manually.
574
     *
575
     * @return array
576
     */
577
    public static function get_new_registration_fields() {
578
        $fieldsneedconfirm = [];
579
        if (!self::is_registered()) {
580
            // Nothing to update if site is not registered.
581
            return $fieldsneedconfirm;
582
        }
583
 
584
        $lastupdated = (int)get_config('hub', 'site_regupdateversion');
585
        foreach (self::CONFIRM_NEW_FIELDS as $version => $fields) {
586
            if ($version > $lastupdated) {
587
                $fieldsneedconfirm = array_merge($fieldsneedconfirm, $fields);
588
            }
589
        }
590
        return $fieldsneedconfirm;
591
    }
592
 
593
    /**
594
     * Redirect to the site registration form if it's a new install, upgrade or registration needs updating.
595
     *
596
     * @param string|moodle_url $url
597
     */
598
    public static function registration_reminder($url) {
599
        if (defined('BEHAT_SITE_RUNNING') && BEHAT_SITE_RUNNING) {
600
            // No redirection during behat runs.
601
            return;
602
        }
603
        if (!has_capability('moodle/site:config', context_system::instance())) {
604
            return;
605
        }
606
        if (self::show_after_install() || self::get_new_registration_fields()) {
607
            $returnurl = new moodle_url($url);
608
            redirect(new moodle_url('/admin/registration/index.php', ['returnurl' => $returnurl->out_as_local_url(false)]));
609
        }
610
    }
611
}