Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.

Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401] [Versions 400 and 401] [Versions 401 and 402] [Versions 401 and 403]

   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  namespace core;
  18  
  19  defined('MOODLE_INTERNAL') || die();
  20  
  21  global $CFG;
  22  require_once($CFG->dirroot . '/lib/myprofilelib.php');
  23  
  24  /**
  25   * Tests for myprofilelib apis.
  26   *
  27   * @package    core
  28   * @copyright  2015 onwards Ankit agarwal <ankit.agrr@gmail.com>
  29   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later.
  30   */
  31  class myprofilelib_test extends \advanced_testcase {
  32  
  33      /**
  34       * @var stdClass The user.
  35       */
  36      private $user;
  37  
  38      /**
  39       * @var stdClass The course.
  40       */
  41      private $course;
  42  
  43      /**
  44       * @var \core_user\output\myprofile\tree The navigation tree.
  45       */
  46      private $tree;
  47  
  48      public function setUp(): void {
  49          // Set the $PAGE->url value so core_myprofile_navigation() doesn't complain.
  50          global $PAGE;
  51          $PAGE->set_url('/test');
  52  
  53          $this->user = $this->getDataGenerator()->create_user();
  54          $this->user2 = $this->getDataGenerator()->create_user();
  55          $this->course = $this->getDataGenerator()->create_course();
  56          $this->tree = new \core_user\output\myprofile\tree();
  57          $this->resetAfterTest();
  58      }
  59  
  60      /**
  61       * Tests the core_myprofile_navigation() function as an admin viewing a user's course profile.
  62       */
  63      public function test_core_myprofile_navigation_as_admin() {
  64          $this->setAdminUser();
  65          $iscurrentuser = false;
  66  
  67          // Test tree as admin user.
  68          core_myprofile_navigation($this->tree, $this->user, $iscurrentuser, $this->course);
  69          $reflector = new \ReflectionObject($this->tree);
  70          $categories = $reflector->getProperty('categories');
  71          $categories->setAccessible(true);
  72          $cats = $categories->getValue($this->tree);
  73          $this->assertArrayHasKey('contact', $cats);
  74          $this->assertArrayHasKey('coursedetails', $cats);
  75          $this->assertArrayHasKey('miscellaneous', $cats);
  76          $this->assertArrayHasKey('reports', $cats);
  77          $this->assertArrayHasKey('administration', $cats);
  78          $this->assertArrayHasKey('loginactivity', $cats);
  79  
  80          $nodes = $reflector->getProperty('nodes');
  81          $nodes->setAccessible(true);
  82          $this->assertArrayHasKey('fullprofile', $nodes->getValue($this->tree));
  83      }
  84  
  85      /**
  86       * Tests the core_myprofile_navigation() function as a user without permission to view the full
  87       * profile of another another user.
  88       */
  89      public function test_core_myprofile_navigation_course_without_permission() {
  90          $this->setUser($this->user2);
  91          $iscurrentuser = false;
  92  
  93          core_myprofile_navigation($this->tree, $this->user, $iscurrentuser, $this->course);
  94          $reflector = new \ReflectionObject($this->tree);
  95          $nodes = $reflector->getProperty('nodes');
  96          $nodes->setAccessible(true);
  97          $this->assertArrayNotHasKey('fullprofile', $nodes->getValue($this->tree));
  98      }
  99  
 100      /**
 101       * Tests the core_myprofile_navigation() function as the currently logged in user.
 102       */
 103      public function test_core_myprofile_navigation_profile_link_as_current_user() {
 104          $this->setUser($this->user);
 105          $iscurrentuser = true;
 106  
 107          core_myprofile_navigation($this->tree, $this->user, $iscurrentuser, $this->course);
 108          $reflector = new \ReflectionObject($this->tree);
 109          $nodes = $reflector->getProperty('nodes');
 110          $nodes->setAccessible(true);
 111          $this->assertArrayHasKey('editprofile', $nodes->getValue($this->tree));
 112      }
 113  
 114      /**
 115       * Tests the core_myprofile_navigation() function as the admin viewing another user.
 116       */
 117      public function test_core_myprofile_navigation_profile_link_as_admin() {
 118          $this->setAdminUser();
 119          $iscurrentuser = false;
 120  
 121          core_myprofile_navigation($this->tree, $this->user, $iscurrentuser, $this->course);
 122          $reflector = new \ReflectionObject($this->tree);
 123          $nodes = $reflector->getProperty('nodes');
 124          $nodes->setAccessible(true);
 125          $this->assertArrayHasKey('editprofile', $nodes->getValue($this->tree));
 126      }
 127  
 128      /**
 129       * Tests the core_myprofile_navigation() function when viewing the preference page as an admin.
 130       */
 131      public function test_core_myprofile_navigation_preference_as_admin() {
 132          $this->setAdminUser();
 133          $iscurrentuser = false;
 134  
 135          core_myprofile_navigation($this->tree, $this->user, $iscurrentuser, $this->course);
 136          $reflector = new \ReflectionObject($this->tree);
 137          $nodes = $reflector->getProperty('nodes');
 138          $nodes->setAccessible(true);
 139          $this->assertArrayHasKey('preferences', $nodes->getValue($this->tree));
 140          $this->assertArrayHasKey('loginas', $nodes->getValue($this->tree));
 141      }
 142  
 143      /**
 144       * Tests the core_myprofile_navigation() function when viewing the preference
 145       * page as another user without the ability to use the 'loginas' functionality.
 146       */
 147      public function test_core_myprofile_navigation_preference_without_permission() {
 148          // Login as link for a user who doesn't have the capability to login as.
 149          $this->setUser($this->user2);
 150          $iscurrentuser = false;
 151  
 152          core_myprofile_navigation($this->tree, $this->user, $iscurrentuser, $this->course);
 153          $reflector = new \ReflectionObject($this->tree);
 154          $nodes = $reflector->getProperty('nodes');
 155          $nodes->setAccessible(true);
 156          $this->assertArrayNotHasKey('loginas', $nodes->getValue($this->tree));
 157      }
 158  
 159      /**
 160       * Tests the core_myprofile_navigation() function as an admin viewing another user's contact details.
 161       */
 162      public function test_core_myprofile_navigation_contact_fields_as_admin() {
 163          global $CFG;
 164  
 165          // User contact fields.
 166          set_config("hiddenuserfields", "country,city");
 167          set_config("showuseridentity", "email,address,phone1,phone2,institution,department,idnumber");
 168          $hiddenfields = explode(',', $CFG->hiddenuserfields);
 169          $identityfields = explode(',', $CFG->showuseridentity);
 170          $this->setAdminUser();
 171          $iscurrentuser = false;
 172  
 173          // Make sure fields are not empty.
 174          $fields = array(
 175              'country' => 'AU',
 176              'city' => 'Silent hill',
 177              'email' => 'Rulelikeaboss@example.com',
 178              'address' => 'Didn\'t I mention silent hill already ?',
 179              'phone1' => '123',
 180              'phone2' => '234',
 181              'institution' => 'strange land',
 182              'department' => 'video game/movie',
 183              'idnumber' => 'SLHL'
 184          );
 185          foreach ($fields as $field => $value) {
 186              $this->user->$field = $value;
 187          }
 188  
 189          // User with proper permissions.
 190          core_myprofile_navigation($this->tree, $this->user, $iscurrentuser, null);
 191          $reflector = new \ReflectionObject($this->tree);
 192          $nodes = $reflector->getProperty('nodes');
 193          $nodes->setAccessible(true);
 194          foreach ($hiddenfields as $field) {
 195              $this->assertArrayHasKey($field, $nodes->getValue($this->tree));
 196          }
 197          foreach ($identityfields as $field) {
 198              $this->assertArrayHasKey($field, $nodes->getValue($this->tree));
 199          }
 200      }
 201  
 202      /**
 203       * Tests the core_myprofile_navigation() function as a user viewing another user's profile
 204       * ensuring that the contact details are not shown.
 205       */
 206      public function test_core_myprofile_navigation_contact_field_without_permission() {
 207          global $CFG;
 208  
 209          $iscurrentuser = false;
 210          $hiddenfields = explode(',', $CFG->hiddenuserfields);
 211          $identityfields = explode(',', $CFG->showuseridentity);
 212  
 213          // User without permission.
 214          $this->setUser($this->user2);
 215          core_myprofile_navigation($this->tree, $this->user, $iscurrentuser, null);
 216          $reflector = new \ReflectionObject($this->tree);
 217          $nodes = $reflector->getProperty('nodes');
 218          $nodes->setAccessible(true);
 219          foreach ($hiddenfields as $field) {
 220              $this->assertArrayNotHasKey($field, $nodes->getValue($this->tree));
 221          }
 222          foreach ($identityfields as $field) {
 223              $this->assertArrayNotHasKey($field, $nodes->getValue($this->tree));
 224          }
 225      }
 226  
 227      /**
 228       * Data provider for {@see test_core_myprofile_navigation_contact_timezone}
 229       *
 230       * @return array[]
 231       */
 232      public function core_myprofile_navigation_contact_timezone_provider(): array {
 233          return [
 234              'Hidden field' => ['timezone', '99', '99', null],
 235              'Forced timezone' => ['', 'Europe/London', 'Pacific/Tahiti', 'Europe/London'],
 236              'User timezone (default)' => ['', '99', '99', 'Australia/Perth'],
 237              'User timezone (selected)' => ['', '99', 'Pacific/Tahiti', 'Pacific/Tahiti'],
 238          ];
 239      }
 240  
 241      /**
 242       * Test timezone node added to user profile navigation
 243       *
 244       * @param string $hiddenuserfields
 245       * @param string $forcetimezone Timezone identifier or '99' (User can choose their own)
 246       * @param string $usertimezone Timezone identifier or '99' (Use server default)
 247       * @param string|null $expectresult
 248       * @return bool
 249       *
 250       * @dataProvider core_myprofile_navigation_contact_timezone_provider
 251       */
 252      public function test_core_myprofile_navigation_contact_timezone(string $hiddenuserfields, string $forcetimezone,
 253              string $usertimezone, ?string $expectresult = null): void {
 254  
 255          set_config('hiddenuserfields', $hiddenuserfields);
 256          set_config('forcetimezone', $forcetimezone);
 257  
 258          // Set the timezone of our test user, and load their navigation tree.
 259          $this->user->timezone = $usertimezone;
 260          $this->setUser($this->user);
 261  
 262          core_myprofile_navigation($this->tree, $this->user, true, null);
 263  
 264          $reflector = new \ReflectionObject($this->tree);
 265          $nodes = $reflector->getProperty('nodes');
 266          $nodes->setAccessible(true);
 267  
 268          /** @var \core_user\output\myprofile\node[] $tree */
 269          $tree = $nodes->getValue($this->tree);
 270          if ($expectresult !== null) {
 271              $this->assertArrayHasKey('timezone', $tree);
 272              $this->assertEquals($expectresult, $tree['timezone']->content);
 273          } else {
 274              $this->assertArrayNotHasKey('timezone', $tree);
 275          }
 276      }
 277  
 278      /**
 279       * Tests the core_myprofile_navigation() function as an admin viewing another user's
 280       * profile ensuring the login activity links are shown.
 281       */
 282      public function test_core_myprofile_navigation_login_activity() {
 283          // First access, last access, last ip.
 284          $this->setAdminUser();
 285          $iscurrentuser = false;
 286  
 287          core_myprofile_navigation($this->tree, $this->user, $iscurrentuser, null);
 288          $reflector = new \ReflectionObject($this->tree);
 289          $nodes = $reflector->getProperty('nodes');
 290          $nodes->setAccessible(true);
 291          $this->assertArrayHasKey('firstaccess', $nodes->getValue($this->tree));
 292          $this->assertArrayHasKey('lastaccess', $nodes->getValue($this->tree));
 293          $this->assertArrayHasKey('lastip', $nodes->getValue($this->tree));
 294      }
 295  
 296      /**
 297       * Tests the core_myprofile_navigation() function as a user viewing another user's profile
 298       * ensuring the login activity links are not shown.
 299       */
 300      public function test_core_myprofile_navigationn_login_activity_without_permission() {
 301          // User without permission.
 302          set_config("hiddenuserfields", "firstaccess,lastaccess,lastip");
 303          $this->setUser($this->user2);
 304          $iscurrentuser = false;
 305  
 306          core_myprofile_navigation($this->tree, $this->user, $iscurrentuser, null);
 307          $reflector = new \ReflectionObject($this->tree);
 308          $nodes = $reflector->getProperty('nodes');
 309          $nodes->setAccessible(true);
 310          $this->assertArrayNotHasKey('firstaccess', $nodes->getValue($this->tree));
 311          $this->assertArrayNotHasKey('lastaccess', $nodes->getValue($this->tree));
 312          $this->assertArrayNotHasKey('lastip', $nodes->getValue($this->tree));
 313      }
 314  }