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.

Differences Between: [Versions 310 and 311] [Versions 310 and 400] [Versions 310 and 401] [Versions 310 and 402] [Versions 310 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  /**
  18   * Unit tests for localization support in lib/moodlelib.php
  19   *
  20   * @package     core
  21   * @category    phpunit
  22   * @copyright   2013 David Mudrak <david@moodle.com>
  23   * @license     http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  24   */
  25  
  26  defined('MOODLE_INTERNAL') || die();
  27  
  28  global $CFG;
  29  require_once($CFG->libdir.'/moodlelib.php');
  30  
  31  /**
  32   * Tests for the API of the string_manager.
  33   *
  34   * @copyright 2013 David Mudrak <david@moodle.com>
  35   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  36   */
  37  class core_string_manager_standard_testcase extends advanced_testcase {
  38  
  39      public function test_string_manager_instance() {
  40          $this->resetAfterTest();
  41  
  42          $otherroot = __DIR__.'/fixtures/langtest';
  43          $stringman = testable_core_string_manager::instance($otherroot);
  44          $this->assertInstanceOf('core_string_manager', $stringman);
  45      }
  46  
  47      public function test_get_language_dependencies() {
  48          $this->resetAfterTest();
  49  
  50          $otherroot = __DIR__.'/fixtures/langtest';
  51          $stringman = testable_core_string_manager::instance($otherroot);
  52  
  53          // There is no parent language for 'en'.
  54          $this->assertSame(array(), $stringman->get_language_dependencies('en'));
  55          // Language with no parent language declared.
  56          $this->assertSame(array('aa'), $stringman->get_language_dependencies('aa'));
  57          // Language with parent language explicitly set to English (en < de).
  58          $this->assertSame(array('de'), $stringman->get_language_dependencies('de'));
  59          // Language dependency hierarchy (de < de_du < de_kids).
  60          $this->assertSame(array('de', 'de_du', 'de_kids'), $stringman->get_language_dependencies('de_kids'));
  61          // Language with the parent language misconfigured to itself (sd < sd).
  62          $this->assertSame(array('sd'), $stringman->get_language_dependencies('sd'));
  63          // Language with circular dependency (cda < cdb < cdc < cda).
  64          $this->assertSame(array('cda', 'cdb', 'cdc'), $stringman->get_language_dependencies('cdc'));
  65          // Orphaned language (N/A < bb).
  66          $this->assertSame(array('bb'), $stringman->get_language_dependencies('bb'));
  67          // Descendant of an orphaned language (N/A < bb < bc).
  68          $this->assertSame(array('bb', 'bc'), $stringman->get_language_dependencies('bc'));
  69      }
  70  
  71      public function test_deprecated_strings() {
  72          $stringman = get_string_manager();
  73  
  74          // Check non-deprecated string.
  75          $this->assertFalse($stringman->string_deprecated('hidden', 'grades'));
  76  
  77          // Check deprecated string.
  78          $this->assertTrue($stringman->string_deprecated('purgedefinitionsuccess', 'core_cache'));
  79          $this->assertTrue($stringman->string_exists('purgedefinitionsuccess', 'core_cache'));
  80          $this->assertDebuggingNotCalled();
  81          $this->assertEquals('Successfully purged the requested definition.', get_string('purgedefinitionsuccess', 'core_cache'));
  82          $this->assertDebuggingCalled('String [purgedefinitionsuccess,core_cache] is deprecated. '.
  83              'Either you should no longer be using that string, or the string has been incorrectly deprecated, in which case you should report this as a bug. '.
  84              'Please refer to https://docs.moodle.org/dev/String_deprecation');
  85      }
  86  
  87      /**
  88       * Return all deprecated strings.
  89       *
  90       * @return array
  91       */
  92      public function get_deprecated_strings_provider() {
  93          global $CFG;
  94  
  95          $teststringman = testable_core_string_manager::instance($CFG->langotherroot, $CFG->langlocalroot, array());
  96          $allstrings = $teststringman->get_all_deprecated_strings();
  97          return array_map(function($string) {
  98              return [$string];
  99          }, $allstrings);
 100      }
 101  
 102      /**
 103       * This test is a built-in validation of deprecated.txt files in lang locations.
 104       *
 105       * It will fail if the string in the wrong format or non-existing (mistyped) string was deprecated.
 106       *
 107       * @dataProvider get_deprecated_strings_provider
 108       * @param   string      $string     The string to be tested
 109       */
 110      public function test_validate_deprecated_strings_files($string) {
 111          $stringman = get_string_manager();
 112  
 113          $result = preg_match('/^(.*),(.*)$/', $string, $matches);
 114          $this->assertEquals(1, $result);
 115          $this->assertCount(3, $matches);
 116          $this->assertEquals($matches[2], clean_param($matches[2], PARAM_COMPONENT),
 117              "Component name {$string} appearing in one of the lang/en/deprecated.txt files does not have correct syntax");
 118  
 119          list($pluginttype, $pluginname) = core_component::normalize_component($matches[2]);
 120          $normcomponent = $pluginname ? ($pluginttype . '_' . $pluginname) : $pluginttype;
 121          $this->assertEquals($normcomponent, $matches[2],
 122              'String "'.$string.'" appearing in one of the lang/en/deprecated.txt files does not have normalised component name');
 123  
 124          $this->assertTrue($stringman->string_exists($matches[1], $matches[2]),
 125              "String {$string} appearing in one of the lang/en/deprecated.txt files does not exist");
 126      }
 127  
 128      /**
 129       * Test for $CFG->langlist (without installation of additional languages)
 130       */
 131      public function test_get_list_of_translations() {
 132          $this->resetAfterTest();
 133          $stringman = get_string_manager();
 134  
 135          $this->assertEquals(['en' => 'English ‎(en)‎'], $stringman->get_list_of_translations());
 136  
 137          set_config('langlist', 'en|En');
 138          get_string_manager(true);
 139          $stringman = get_string_manager();
 140  
 141          $this->assertEquals(['en' => 'En'], $stringman->get_list_of_translations());
 142  
 143          // Set invalid config, ensure original list is returned.
 144          set_config('langlist', 'xx');
 145          $this->assertEquals(['en' => 'English ‎(en)‎'], get_string_manager(true)->get_list_of_translations());
 146  
 147          set_config('langlist', 'xx,en|En');
 148          $this->assertEquals(['en' => 'En'], get_string_manager(true)->get_list_of_translations());
 149  
 150          set_config('langlist', '');
 151          get_string_manager(true);
 152      }
 153  
 154      /**
 155       * Test {@see core_string_manager_standard::get_list_of_countries()} under different conditions.
 156       */
 157      public function test_get_list_of_countries() {
 158  
 159          $this->resetAfterTest();
 160          $stringman = get_string_manager();
 161  
 162          $countries = $stringman->get_list_of_countries(true);
 163          $this->assertIsArray($countries);
 164          $this->assertArrayHasKey('AU', $countries);
 165          $this->assertArrayHasKey('BE', $countries);
 166          $this->assertArrayHasKey('CZ', $countries);
 167          $this->assertArrayHasKey('ES', $countries);
 168          $this->assertGreaterThan(4, count($countries));
 169  
 170          set_config('allcountrycodes', '');
 171          $countries = $stringman->get_list_of_countries(false);
 172          $this->assertArrayHasKey('AU', $countries);
 173          $this->assertArrayHasKey('BE', $countries);
 174          $this->assertArrayHasKey('CZ', $countries);
 175          $this->assertArrayHasKey('ES', $countries);
 176          $this->assertGreaterThan(4, count($countries));
 177  
 178          set_config('allcountrycodes', 'CZ,BE');
 179          $countries = $stringman->get_list_of_countries(true);
 180          $this->assertArrayHasKey('AU', $countries);
 181          $this->assertArrayHasKey('BE', $countries);
 182          $this->assertArrayHasKey('CZ', $countries);
 183          $this->assertArrayHasKey('ES', $countries);
 184          $this->assertGreaterThan(4, count($countries));
 185  
 186          $countries = $stringman->get_list_of_countries(false);
 187          $this->assertEquals(2, count($countries));
 188          $this->assertArrayHasKey('BE', $countries);
 189          $this->assertArrayHasKey('CZ', $countries);
 190  
 191          set_config('allcountrycodes', 'CZ,UVWXYZ');
 192          $countries = $stringman->get_list_of_countries();
 193          $this->assertArrayHasKey('CZ', $countries);
 194          $this->assertEquals(1, count($countries));
 195  
 196          set_config('allcountrycodes', 'UVWXYZ');
 197          $countries = $stringman->get_list_of_countries();
 198          $this->assertArrayHasKey('AU', $countries);
 199          $this->assertArrayHasKey('BE', $countries);
 200          $this->assertArrayHasKey('CZ', $countries);
 201          $this->assertArrayHasKey('ES', $countries);
 202          $this->assertGreaterThan(4, count($countries));
 203      }
 204  }
 205  
 206  /**
 207   * Helper class providing testable string_manager
 208   *
 209   * @copyright 2013 David Mudrak <david@moodle.com>
 210   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 211   */
 212  class testable_core_string_manager extends core_string_manager_standard {
 213  
 214      /**
 215       * Factory method
 216       *
 217       * @param string $otherroot full path to the location of installed upstream language packs
 218       * @param string $localroot full path to the location of locally customized language packs, defaults to $otherroot
 219       * @param bool $usecache use application permanent cache
 220       * @param array $translist explicit list of visible translations
 221       * @param string $menucache the location of a file that caches the list of available translations
 222       * @return testable_core_string_manager
 223       */
 224      public static function instance($otherroot, $localroot = null, $usecache = false, array $translist = array(), $menucache = null) {
 225          global $CFG;
 226  
 227          if (is_null($localroot)) {
 228              $localroot = $otherroot;
 229          }
 230  
 231          if (is_null($menucache)) {
 232              $menucache = $CFG->cachedir.'/languages';
 233          }
 234  
 235          return new testable_core_string_manager($otherroot, $localroot, $usecache, $translist, $menucache);
 236      }
 237  
 238      public function get_all_deprecated_strings() {
 239          return array_flip($this->load_deprecated_strings());
 240      }
 241  }