Proyectos de Subversion Moodle

Rev

Rev 11 | Mostrar el archivo completo | | | Autoría | Ultima modificación | Ver Log |

Rev 11 Rev 1441
Línea 20... Línea 20...
20
 * @package   core_user
20
 * @package   core_user
21
 * @copyright 2009 Moodle Pty Ltd (http://moodle.com)
21
 * @copyright 2009 Moodle Pty Ltd (http://moodle.com)
22
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
22
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23
 */
23
 */
Línea -... Línea 24...
-
 
24
 
-
 
25
use core\di;
-
 
26
use core\hook;
-
 
27
use core_user\hook\extend_user_menu;
24
 
28
 
25
define('USER_FILTER_ENROLMENT', 1);
29
define('USER_FILTER_ENROLMENT', 1);
26
define('USER_FILTER_GROUP', 2);
30
define('USER_FILTER_GROUP', 2);
27
define('USER_FILTER_LAST_ACCESS', 3);
31
define('USER_FILTER_LAST_ACCESS', 3);
28
define('USER_FILTER_ROLE', 4);
32
define('USER_FILTER_ROLE', 4);
Línea 327... Línea 331...
327
 
331
 
328
    if (!in_array('fullname', $userfields)) {
332
    if (!in_array('fullname', $userfields)) {
329
        $userfields[] = 'fullname';
333
        $userfields[] = 'fullname';
Línea -... Línea 334...
-
 
334
    }
-
 
335
 
-
 
336
    // Callback check for plugins to allow or prevent access.
-
 
337
    $forceallow = true;
-
 
338
    $currentuser = ($user->id == $USER->id);
-
 
339
    $isadmin = is_siteadmin($USER);
-
 
340
    if (!$currentuser) {
-
 
341
        $forceallow = false;
-
 
342
        $callbackresult = user_process_profile_callbacks($user, $course);
-
 
343
        if ($callbackresult === core_user::VIEWPROFILE_PREVENT) {
-
 
344
            return null; // Access denied.
-
 
345
        } else if ($callbackresult === core_user::VIEWPROFILE_FORCE_ALLOW) {
-
 
346
            $forceallow = true;
-
 
347
        }
330
    }
348
    }
331
 
349
 
332
    if (!empty($course)) {
350
    if (!empty($course)) {
333
        $context = context_course::instance($course->id);
-
 
334
        $usercontext = context_user::instance($user->id);
351
        $context = context_course::instance($course->id);
335
        $canviewdetailscap = (has_capability('moodle/user:viewdetails', $context) || has_capability('moodle/user:viewdetails', $usercontext));
352
        $usercontext = context_user::instance($user->id);
336
    } else {
353
    } else {
337
        $context = context_user::instance($user->id);
-
 
338
        $usercontext = $context;
354
        $context = context_user::instance($user->id);
Línea -... Línea 355...
-
 
355
        $usercontext = $context;
-
 
356
    }
-
 
357
 
-
 
358
    if (!$forceallow) {
-
 
359
        // Existing capability checks.
-
 
360
        if (!empty($course)) {
-
 
361
            $canviewdetailscap = (has_capability('moodle/user:viewdetails', $context) || has_capability('moodle/user:viewdetails', $usercontext));
-
 
362
        } else {
-
 
363
            $canviewdetailscap = has_capability('moodle/user:viewdetails', $usercontext);
339
        $canviewdetailscap = has_capability('moodle/user:viewdetails', $usercontext);
364
        }
340
    }
365
 
-
 
366
        if (!$currentuser && !$canviewdetailscap && !has_coursecontact_role($user->id)) {
-
 
367
            // Skip this user details.
Línea 341... Línea 368...
341
 
368
            return null;
342
    $currentuser = ($user->id == $USER->id);
369
        }
343
    $isadmin = is_siteadmin($USER);
370
    }
Línea 362... Línea 389...
362
        $canaccessallgroups = has_capability('moodle/site:accessallgroups', $context);
389
        $canaccessallgroups = has_capability('moodle/site:accessallgroups', $context);
363
    } else {
390
    } else {
364
        $canaccessallgroups = false;
391
        $canaccessallgroups = false;
365
    }
392
    }
Línea 366... Línea 393...
366
 
393
 
367
    if (!$currentuser && !$canviewdetailscap && !has_coursecontact_role($user->id)) {
394
    // User ID and fullname are always included.
368
        // Skip this user details.
395
    $userdetails = [
-
 
396
        'id' => $user->id,
-
 
397
        'fullname' => fullname($user, $canviewfullnames),
-
 
398
    ];
-
 
399
 
-
 
400
    // User first/lastname included if capability check passes, or the same is present in fullname.
-
 
401
    $dummyusername = core_user::get_dummy_fullname($context, ['override' => $canviewfullnames]);
-
 
402
    if (in_array('firstname', $userfields) &&
-
 
403
            ($canviewfullnames || core_text::strrpos($dummyusername, 'firstname') !== false)) {
-
 
404
        $userdetails['firstname'] = $user->firstname;
-
 
405
    }
-
 
406
    if (in_array('lastname', $userfields) &&
-
 
407
            ($canviewfullnames || core_text::strrpos($dummyusername, 'lastname') !== false)) {
369
        return null;
408
        $userdetails['lastname'] = $user->lastname;
Línea 370... Línea -...
370
    }
-
 
371
 
-
 
372
    $userdetails = array();
-
 
373
    $userdetails['id'] = $user->id;
409
    }
374
 
410
 
375
    if (in_array('username', $userfields)) {
411
    if (in_array('username', $userfields)) {
376
        if ($currentuser or has_capability('moodle/user:viewalldetails', $context)) {
412
        if ($currentuser or has_capability('moodle/user:viewalldetails', $context)) {
377
            $userdetails['username'] = $user->username;
413
            $userdetails['username'] = $user->username;
378
        }
-
 
379
    }
-
 
380
    if ($isadmin or $canviewfullnames) {
-
 
381
        if (in_array('firstname', $userfields)) {
-
 
382
            $userdetails['firstname'] = $user->firstname;
-
 
383
        }
-
 
384
        if (in_array('lastname', $userfields)) {
-
 
385
            $userdetails['lastname'] = $user->lastname;
-
 
386
        }
-
 
Línea 387... Línea 414...
387
    }
414
        }
388
    $userdetails['fullname'] = fullname($user, $canviewfullnames);
415
    }
389
 
416
 
390
    if (in_array('customfields', $userfields)) {
417
    if (in_array('customfields', $userfields)) {
Línea 556... Línea 583...
556
                    if (!groups_is_member($group->id, $USER->id)) {
583
                    if (!groups_is_member($group->id, $USER->id)) {
557
                        continue;
584
                        continue;
558
                    }
585
                    }
559
                }
586
                }
Línea -... Línea 587...
-
 
587
 
-
 
588
                $groupdescription = file_rewrite_pluginfile_urls($group->description, 'pluginfile.php', $context->id, 'group',
-
 
589
                    'description', $group->id);
560
 
590
 
561
                $userdetails['groups'][] = [
591
                $userdetails['groups'][] = [
562
                    'id' => $group->id,
592
                    'id' => $group->id,
563
                    'name' => format_string($group->name),
593
                    'name' => format_string($group->name, true, ['context' => $context]),
564
                    'description' => format_text($group->description, $group->descriptionformat, ['context' => $context]),
594
                    'description' => format_text($groupdescription, $group->descriptionformat, ['context' => $context]),
565
                    'descriptionformat' => $group->descriptionformat
595
                    'descriptionformat' => $group->descriptionformat
566
                ];
596
                ];
567
            }
597
            }
568
        }
598
        }
Línea 886... Línea 916...
886
            // Don't reset the count either, as login_info() still needs it too.
916
            // Don't reset the count either, as login_info() still needs it too.
887
            if ($count = user_count_login_failures($user, false)) {
917
            if ($count = user_count_login_failures($user, false)) {
Línea 888... Línea 918...
888
 
918
 
889
                // Get login failures string.
919
                // Get login failures string.
890
                $a = new stdClass();
920
                $a = new stdClass();
891
                $a->attempts = html_writer::tag('span', $count, array('class' => 'value mr-1 font-weight-bold'));
921
                $a->attempts = html_writer::tag('span', $count, array('class' => 'value me-1 fw-bold'));
892
                $returnobject->metadata['userloginfail'] =
922
                $returnobject->metadata['userloginfail'] =
Línea 893... Línea 923...
893
                    get_string('failedloginattempts', '', $a);
923
                    get_string('failedloginattempts', '', $a);
894
 
924
 
Línea 907... Línea 937...
907
        if ($item->itemtype !== 'divider' && $item->itemtype !== 'invalid') {
937
        if ($item->itemtype !== 'divider' && $item->itemtype !== 'invalid') {
908
            $custommenucount++;
938
            $custommenucount++;
909
        }
939
        }
910
    }
940
    }
Línea -... Línea 941...
-
 
941
 
-
 
942
    // Call to hook to add menu items.
-
 
943
    $hook = new extend_user_menu();
-
 
944
    di::get(core\hook\manager::class)->dispatch($hook);
-
 
945
    $hookitems = $hook->get_navitems();
-
 
946
    foreach ($hookitems as $menuitem) {
-
 
947
        $returnobject->navitems[] = $menuitem;
-
 
948
    }
911
 
949
 
912
    if ($custommenucount > 0) {
950
    if ($custommenucount > 0) {
913
        // Only add a divider if we have customusermenuitems.
951
        // Only add a divider if we have customusermenuitems.
914
        $divider = new stdClass();
952
        $divider = new stdClass();
915
        $divider->itemtype = 'divider';
953
        $divider->itemtype = 'divider';
Línea 1185... Línea 1223...
1185
    if ($USER->id == $user->id) {
1223
    if ($USER->id == $user->id) {
1186
        return true;
1224
        return true;
1187
    }
1225
    }
Línea 1188... Línea 1226...
1188
 
1226
 
1189
    // Use callbacks so that (primarily) local plugins can prevent or allow profile access.
-
 
1190
    $forceallow = false;
-
 
1191
    $plugintypes = get_plugins_with_function('control_view_profile');
-
 
1192
    foreach ($plugintypes as $plugins) {
-
 
1193
        foreach ($plugins as $pluginfunction) {
1227
    // Use callbacks so that (primarily) local plugins can prevent or allow profile access.
1194
            $result = $pluginfunction($user, $course, $usercontext);
-
 
1195
            switch ($result) {
1228
    $callbackresult = user_process_profile_callbacks($user, $course, $usercontext);
1196
                case core_user::VIEWPROFILE_DO_NOT_PREVENT:
-
 
1197
                    // If the plugin doesn't stop access, just continue to next plugin or use
1229
    if ($callbackresult === core_user::VIEWPROFILE_PREVENT) {
1198
                    // default behaviour.
-
 
1199
                    break;
1230
        return false; // Access denied.
1200
                case core_user::VIEWPROFILE_FORCE_ALLOW:
-
 
1201
                    // Record that we are definitely going to allow it (unless another plugin
-
 
1202
                    // returns _PREVENT).
-
 
1203
                    $forceallow = true;
-
 
1204
                    break;
-
 
1205
                case core_user::VIEWPROFILE_PREVENT:
-
 
1206
                    // If any plugin returns PREVENT then we return false, regardless of what
-
 
1207
                    // other plugins said.
-
 
1208
                    return false;
-
 
1209
            }
-
 
1210
        }
-
 
1211
    }
-
 
1212
    if ($forceallow) {
1231
    } else if ($callbackresult === core_user::VIEWPROFILE_FORCE_ALLOW) {
1213
        return true;
1232
        return true;
Línea 1214... Línea 1233...
1214
    }
1233
    }
1215
 
1234
 
Línea 1254... Línea 1273...
1254
    }
1273
    }
1255
    return false;
1274
    return false;
1256
}
1275
}
Línea 1257... Línea 1276...
1257
 
1276
 
-
 
1277
/**
-
 
1278
 * Process plugin callbacks for profile visibility.
-
 
1279
 *
-
 
1280
 * @param stdClass $user The user whose profile is being checked.
-
 
1281
 * @param stdClass|null $course The course context, if applicable.
-
 
1282
 * @param context|null $usercontext The user context, if applicable.
-
 
1283
 * @return int One of the core_user::VIEWPROFILE_* constants.
-
 
1284
 */
-
 
1285
function user_process_profile_callbacks(stdClass $user, ?stdClass $course = null, ?stdClass $usercontext = null): int {
-
 
1286
    $plugintypes = get_plugins_with_function('control_view_profile');
-
 
1287
    $forceallow = false;
-
 
1288
 
-
 
1289
    foreach ($plugintypes as $plugins) {
-
 
1290
        foreach ($plugins as $pluginfunction) {
-
 
1291
            $result = $pluginfunction($user, $course, $usercontext);
-
 
1292
            switch ($result) {
-
 
1293
                case core_user::VIEWPROFILE_FORCE_ALLOW:
-
 
1294
                    $forceallow = true;
-
 
1295
                    break;
-
 
1296
                case core_user::VIEWPROFILE_PREVENT:
-
 
1297
                    return core_user::VIEWPROFILE_PREVENT;
-
 
1298
            }
-
 
1299
        }
-
 
1300
    }
-
 
1301
 
-
 
1302
    return $forceallow ? core_user::VIEWPROFILE_FORCE_ALLOW : core_user::VIEWPROFILE_DO_NOT_PREVENT;
-
 
1303
}
-
 
1304
 
1258
/**
1305
/**
1259
 * Returns users tagged with a specified tag.
1306
 * Returns users tagged with a specified tag.
1260
 *
1307
 *
1261
 * @param core_tag_tag $tag
1308
 * @param core_tag_tag $tag
1262
 * @param bool $exclusivemode if set to true it means that no other entities tagged with this tag
1309
 * @param bool $exclusivemode if set to true it means that no other entities tagged with this tag
Línea 1269... Línea 1316...
1269
 * @return \core_tag\output\tagindex
1316
 * @return \core_tag\output\tagindex
1270
 */
1317
 */
1271
function user_get_tagged_users($tag, $exclusivemode = false, $fromctx = 0, $ctx = 0, $rec = 1, $page = 0) {
1318
function user_get_tagged_users($tag, $exclusivemode = false, $fromctx = 0, $ctx = 0, $rec = 1, $page = 0) {
1272
    global $PAGE;
1319
    global $PAGE;
Línea 1273... Línea -...
1273
 
-
 
1274
    if ($ctx && $ctx != context_system::instance()->id) {
-
 
1275
        $usercount = 0;
-
 
1276
    } else {
-
 
1277
        // Users can only be displayed in system context.
-
 
1278
        $usercount = $tag->count_tagged_items('core', 'user',
-
 
1279
                'it.deleted=:notdeleted', array('notdeleted' => 0));
-
 
1280
    }
1320
 
-
 
1321
    $perpage = $exclusivemode ? 24 : 5;
-
 
1322
    $filteredusers = []; // Initialize an array to hold users that pass filtering.
-
 
1323
 
-
 
1324
    $totalusers = $tag->count_tagged_items('core', 'user', 'it.deleted=:notdeleted', ['notdeleted' => 0]);
-
 
1325
    $withinuserlimit = ($page * $perpage < $totalusers);
-
 
1326
    // Check if the requested page is within the user limit and if the context is valid or matches the system context.
-
 
1327
    if ($withinuserlimit && (!$ctx || $ctx == context_system::instance()->id)) {
-
 
1328
        // The output from get_tagged_items() will be filtered to check if users are visible to the current user.
-
 
1329
        // It’s possible that the count of users meeting the filtering criteria may fall short of the per-page limit,
-
 
1330
        // necessitating additional data beyond this limit.
-
 
1331
        // Implementing a batch approach addressed this issue by minimizing database queries.
-
 
1332
        $batch = 0;
-
 
1333
        // Increase the per-page limit to create a batch size for chunked querying.
-
 
1334
        // If the first chunk $perpagebatch doesn't return enough users, fetch the next chunk without re-querying the database.
-
 
1335
        $perpagebatch = $perpage * 2;
-
 
1336
 
-
 
1337
        do {
-
 
1338
            $userlist = $tag->get_tagged_items(
-
 
1339
                component: 'core',
-
 
1340
                itemtype: 'user',
-
 
1341
                limitfrom: $perpagebatch * $batch,
-
 
1342
                limitnum: $perpagebatch,
-
 
1343
                subquery: 'it.deleted=:notdeleted',
-
 
1344
                params: ['notdeleted' => 0],
-
 
1345
            );
-
 
1346
 
-
 
1347
            foreach ($userlist as $user) {
-
 
1348
                // Check if the user profile can be viewed.
-
 
1349
                if (user_can_view_profile($user)) {
-
 
1350
                    $filteredusers[] = $user;
-
 
1351
                    // If enough users have been collected for the requested page, exit both loops.
-
 
1352
                    if (count($filteredusers) > $perpage * ($page + 1)) {
-
 
1353
                        break 2;
-
 
1354
                    }
-
 
1355
                }
-
 
1356
            }
-
 
1357
 
-
 
1358
            $batch++;
-
 
1359
 
-
 
1360
        } while (count($userlist) > 0); // If all the data is still insufficient, run another batch.
-
 
1361
 
-
 
1362
    }
-
 
1363
 
-
 
1364
    $usercount = count($filteredusers);
-
 
1365
 
1281
    $perpage = $exclusivemode ? 24 : 5;
1366
    // Initialize the content to display tagged users.
1282
    $content = '';
1367
    $content = '';
-
 
1368
    if ($usercount > 0) {
-
 
1369
        // Prepare the paginated list of users, limiting it to the number of users per page.
Línea 1283... Línea -...
1283
    $totalpages = ceil($usercount / $perpage);
-
 
1284
 
-
 
1285
    if ($usercount) {
1370
        $paginatedusers = array_slice($filteredusers, $page * $perpage, $perpage);
1286
        $userlist = $tag->get_tagged_items('core', 'user', $page * $perpage, $perpage,
1371
 
1287
                'it.deleted=:notdeleted', array('notdeleted' => 0));
1372
        // Get the renderer for the user module to create the user list content.
1288
        $renderer = $PAGE->get_renderer('core', 'user');
1373
        $renderer = $PAGE->get_renderer('core', 'user');
Línea -... Línea 1374...
-
 
1374
        $content = $renderer->user_list($paginatedusers, $exclusivemode);
-
 
1375
    }
-
 
1376
 
1289
        $content .= $renderer->user_list($userlist, $exclusivemode);
1377
    // Calculate the total number of pages.
1290
    }
1378
    $totalpages = ceil($usercount / $perpage);
1291
 
1379
 
Línea 1292... Línea 1380...
1292
    return new core_tag\output\tagindex($tag, 'core', 'user', $content,
1380
    return new core_tag\output\tagindex($tag, 'core', 'user', $content,