Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.2.x will end 22 April 2024 (12 months).
  • Bug fixes for security issues in 4.2.x will end 7 October 2024 (18 months).
  • PHP version: minimum PHP 8.0.0 Note: minimum PHP version has increased since Moodle 4.1. PHP 8.1.x is supported too.

Differences Between: [Versions 311 and 402] [Versions 400 and 402] [Versions 401 and 402]

   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  use core_external\external_api;
  20  use externallib_advanced_testcase;
  21  
  22  defined('MOODLE_INTERNAL') || die();
  23  
  24  global $CFG;
  25  require_once($CFG->dirroot . '/lib/external/externallib.php');
  26  require_once($CFG->dirroot . '/webservice/tests/helpers.php');
  27  
  28  /**
  29   * External library functions unit tests
  30   *
  31   * @package    core
  32   * @category   phpunit
  33   * @copyright  2012 Jerome Mouneyrac
  34   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  35   */
  36  class external_externallib_test extends externallib_advanced_testcase {
  37  
  38      /**
  39       * Test get_string
  40       */
  41      public function test_get_string() {
  42          $this->resetAfterTest(true);
  43  
  44          $service = new \stdClass();
  45          $service->name = 'Dummy Service';
  46          $service->id = 12;
  47  
  48          // String with two parameters.
  49          $returnedstring = \core_external::get_string('addservice', 'webservice', null,
  50                  array(array('name' => 'name', 'value' => $service->name),
  51                        array('name' => 'id', 'value' => $service->id)));
  52  
  53          // We need to execute the return values cleaning process to simulate the web service server.
  54          $returnedstring = external_api::clean_returnvalue(\core_external::get_string_returns(), $returnedstring);
  55  
  56          $corestring = get_string('addservice', 'webservice', $service);
  57          $this->assertSame($corestring, $returnedstring);
  58  
  59          // String with one parameter.
  60          $acapname = 'A capability name';
  61          $returnedstring = \core_external::get_string('missingrequiredcapability', 'webservice', null,
  62                  array(array('value' => $acapname)));
  63  
  64          // We need to execute the return values cleaning process to simulate the web service server.
  65          $returnedstring = external_api::clean_returnvalue(\core_external::get_string_returns(), $returnedstring);
  66  
  67          $corestring = get_string('missingrequiredcapability', 'webservice', $acapname);
  68          $this->assertSame($corestring, $returnedstring);
  69  
  70          // String without parameters.
  71          $returnedstring = \core_external::get_string('missingpassword', 'webservice');
  72  
  73          // We need to execute the return values cleaning process to simulate the web service server.
  74          $returnedstring = external_api::clean_returnvalue(\core_external::get_string_returns(), $returnedstring);
  75  
  76          $corestring = get_string('missingpassword', 'webservice');
  77          $this->assertSame($corestring, $returnedstring);
  78  
  79          // String with two parameter but one is invalid (not named).
  80          $this->expectException('moodle_exception');
  81          $returnedstring = \core_external::get_string('addservice', 'webservice', null,
  82                  array(array('value' => $service->name),
  83                        array('name' => 'id', 'value' => $service->id)));
  84      }
  85  
  86      /**
  87       * Test get_string with HTML.
  88       */
  89      public function test_get_string_containing_html() {
  90          $result = \core_external::get_string('registrationinfo');
  91          $actual = external_api::clean_returnvalue(\core_external::get_string_returns(), $result);
  92          $expected = get_string('registrationinfo', 'moodle');
  93          $this->assertSame($expected, $actual);
  94      }
  95  
  96      /**
  97       * Test get_string with arguments containing HTML.
  98       */
  99      public function test_get_string_with_args_containing_html() {
 100          $result = \core_external::get_string('added', 'moodle', null, [['value' => '<strong>Test</strong>']]);
 101          $actual = external_api::clean_returnvalue(\core_external::get_string_returns(), $result);
 102          $expected = get_string('added', 'moodle', '<strong>Test</strong>');
 103          $this->assertSame($expected, $actual);
 104      }
 105  
 106      /**
 107       * Test get_strings
 108       */
 109      public function test_get_strings() {
 110          $this->resetAfterTest(true);
 111  
 112          $stringmanager = get_string_manager();
 113  
 114          $service = new \stdClass();
 115          $service->name = 'Dummy Service';
 116          $service->id = 12;
 117  
 118          $returnedstrings = \core_external::get_strings(
 119                  array(
 120                      array(
 121                          'stringid' => 'addservice', 'component' => 'webservice',
 122                          'stringparams' => array(array('name' => 'name', 'value' => $service->name),
 123                                array('name' => 'id', 'value' => $service->id)
 124                          ),
 125                          'lang' => 'en'
 126                      ),
 127                      array('stringid' =>  'addaservice', 'component' => 'webservice', 'lang' => 'en')
 128                  ));
 129  
 130          // We need to execute the return values cleaning process to simulate the web service server.
 131          $returnedstrings = external_api::clean_returnvalue(\core_external::get_strings_returns(), $returnedstrings);
 132  
 133          foreach($returnedstrings as $returnedstring) {
 134              $corestring = $stringmanager->get_string($returnedstring['stringid'],
 135                                                       $returnedstring['component'],
 136                                                       $service,
 137                                                       'en');
 138              $this->assertSame($corestring, $returnedstring['string']);
 139          }
 140      }
 141  
 142      /**
 143       * Test get_strings with HTML.
 144       */
 145      public function test_get_strings_containing_html() {
 146          $result = \core_external::get_strings([['stringid' => 'registrationinfo'], ['stringid' => 'loginaspasswordexplain']]);
 147          $actual = external_api::clean_returnvalue(\core_external::get_strings_returns(), $result);
 148          $this->assertSame(get_string('registrationinfo', 'moodle'), $actual[0]['string']);
 149          $this->assertSame(get_string('loginaspasswordexplain', 'moodle'), $actual[1]['string']);
 150      }
 151  
 152      /**
 153       * Test get_strings with arguments containing HTML.
 154       */
 155      public function test_get_strings_with_args_containing_html() {
 156          $result = \core_external::get_strings([
 157              ['stringid' => 'added', 'stringparams' => [['value' => '<strong>Test</strong>']]],
 158              ['stringid' => 'loggedinas', 'stringparams' => [['value' => '<strong>Test</strong>']]]]
 159          );
 160          $actual = external_api::clean_returnvalue(\core_external::get_strings_returns(), $result);
 161          $this->assertSame(get_string('added', 'moodle', '<strong>Test</strong>'), $actual[0]['string']);
 162          $this->assertSame(get_string('loggedinas', 'moodle', '<strong>Test</strong>'), $actual[1]['string']);
 163      }
 164  
 165      /**
 166       * Test get_component_strings
 167       */
 168      public function test_get_component_strings() {
 169          global $USER;
 170          $this->resetAfterTest(true);
 171  
 172          $stringmanager = get_string_manager();
 173  
 174          $wsstrings = $stringmanager->load_component_strings('webservice', current_language());
 175  
 176          $componentstrings = \core_external::get_component_strings('webservice');
 177  
 178          // We need to execute the return values cleaning process to simulate the web service server.
 179          $componentstrings = external_api::clean_returnvalue(\core_external::get_component_strings_returns(), $componentstrings);
 180  
 181          $this->assertEquals(count($componentstrings), count($wsstrings));
 182          foreach($componentstrings as $string) {
 183              $this->assertSame($string['string'], $wsstrings[$string['stringid']]);
 184          }
 185      }
 186  
 187      /**
 188       * Test update_inplace_editable()
 189       */
 190      public function test_update_inplace_editable() {
 191          $this->resetAfterTest(true);
 192  
 193          // Call service for component that does not have inplace_editable callback.
 194          try {
 195              \core_external::update_inplace_editable('tool_log', 'itemtype', 1, 'newvalue');
 196              $this->fail('Exception expected');
 197          } catch (\moodle_exception $e) {
 198              $this->assertEquals('Error calling update processor', $e->getMessage());
 199          }
 200  
 201          // This is a very basic test for the return value of the external function.
 202          // More detailed test for tag updating can be found in core_tag component.
 203          $this->setAdminUser();
 204          $tag = $this->getDataGenerator()->create_tag();
 205          $res = \core_external::update_inplace_editable('core_tag', 'tagname', $tag->id, 'new tag name');
 206          $res = external_api::clean_returnvalue(\core_external::update_inplace_editable_returns(), $res);
 207  
 208          $this->assertEquals('new tag name', $res['value']);
 209      }
 210  
 211      /**
 212       * Test update_inplace_editable with mathjax.
 213       */
 214      public function test_update_inplace_editable_with_mathjax() {
 215          $this->resetAfterTest(true);
 216          $this->setAdminUser();
 217  
 218          // Enable MathJax filter in content and headings.
 219          $this->configure_filters([
 220              ['name' => 'mathjaxloader', 'state' => TEXTFILTER_ON, 'move' => -1, 'applytostrings' => true],
 221          ]);
 222  
 223          // Create a forum.
 224          $course = $this->getDataGenerator()->create_course();
 225          $forum = self::getDataGenerator()->create_module('forum', array('course' => $course->id, 'name' => 'forum name'));
 226  
 227          // Change the forum name.
 228          $newname = 'New forum name $$(a+b)=2$$';
 229          $res = \core_external::update_inplace_editable('core_course', 'activityname', $forum->cmid, $newname);
 230          $res = external_api::clean_returnvalue(\core_external::update_inplace_editable_returns(), $res);
 231  
 232          // Format original data.
 233          $context = \context_module::instance($forum->cmid);
 234          $newname = \core_external\util::format_string($newname, $context);
 235          $editlabel = get_string('newactivityname', '', $newname);
 236  
 237          // Check editlabel is the same and has mathjax.
 238          $this->assertStringContainsString('<span class="filter_mathjaxloader_equation">', $res['editlabel']);
 239          $this->assertEquals($editlabel, $res['editlabel']);
 240      }
 241  
 242      public function test_get_user_dates() {
 243          $this->resetAfterTest();
 244  
 245          $this->setAdminUser();
 246  
 247          // Set default timezone to Australia/Perth, else time calculated
 248          // will not match expected values.
 249          $this->setTimezone(99, 'Australia/Perth');
 250  
 251          $context = \context_system::instance();
 252          $request = [
 253              [
 254                  'timestamp' => 1293876000,
 255                  'format' => '%A, %d %B %Y, %I:%M'
 256              ],
 257              [
 258                  'timestamp' => 1293876000,
 259                  'format' => '%d %m %Y'
 260              ],
 261              [
 262                  'timestamp' => 1293876000,
 263                  'format' => '%d %m %Y',
 264                  'type' => 'gregorian'
 265              ],
 266              [
 267                  'timestamp' => 1293876000,
 268                  'format' => 'some invalid format'
 269              ],
 270          ];
 271  
 272          $result = \core_external::get_user_dates($context->id, null, null, $request);
 273          $result = external_api::clean_returnvalue(\core_external::get_user_dates_returns(), $result);
 274  
 275          $this->assertEquals('Saturday, 1 January 2011, 6:00', $result['dates'][0]);
 276          $this->assertEquals('1 01 2011', $result['dates'][1]);
 277          $this->assertEquals('1 01 2011', $result['dates'][2]);
 278          $this->assertEquals('some invalid format', $result['dates'][3]);
 279      }
 280  }