Search moodle.org's
Developer Documentation

See Release Notes

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