See Release Notes
Long Term Support Release
Differences Between: [Versions 310 and 401] [Versions 39 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 /** 18 * Exporter testcase. 19 * 20 * @package core 21 * @copyright 2015 Damyon Wiese 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24 25 namespace core; 26 27 defined('MOODLE_INTERNAL') || die(); 28 global $CFG; 29 30 /** 31 * Exporter testcase. 32 * 33 * @package core 34 * @copyright 2015 Damyon Wiese 35 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 36 */ 37 class exporter_test extends \advanced_testcase { 38 39 protected $validrelated = null; 40 protected $invalidrelated = null; 41 protected $validdata = null; 42 protected $invaliddata = null; 43 44 public function setUp(): void { 45 $s = new \stdClass(); 46 $this->validrelated = array( 47 'simplestdClass' => $s, 48 'arrayofstdClass' => array($s, $s), 49 'context' => null, 50 'aint' => 5, 51 'astring' => 'valid string', 52 'abool' => false, 53 'ints' => [] 54 ); 55 $this->invalidrelated = array( 56 'simplestdClass' => 'a string', 57 'arrayofstdClass' => 5, 58 'context' => null, 59 'aint' => false, 60 'astring' => 4, 61 'abool' => 'not a boolean', 62 'ints' => null 63 ); 64 65 $this->validdata = array('stringA' => 'A string', 'stringAformat' => FORMAT_HTML, 'intB' => 4); 66 67 $this->invaliddata = array('stringA' => 'A string'); 68 } 69 70 public function test_get_read_structure() { 71 $structure = core_testable_exporter::get_read_structure(); 72 73 $this->assertInstanceOf('external_single_structure', $structure); 74 $this->assertInstanceOf('external_value', $structure->keys['stringA']); 75 $this->assertInstanceOf('external_format_value', $structure->keys['stringAformat']); 76 $this->assertInstanceOf('external_value', $structure->keys['intB']); 77 $this->assertInstanceOf('external_value', $structure->keys['otherstring']); 78 $this->assertInstanceOf('external_multiple_structure', $structure->keys['otherstrings']); 79 } 80 81 public function test_get_create_structure() { 82 $structure = core_testable_exporter::get_create_structure(); 83 84 $this->assertInstanceOf('external_single_structure', $structure); 85 $this->assertInstanceOf('external_value', $structure->keys['stringA']); 86 $this->assertInstanceOf('external_format_value', $structure->keys['stringAformat']); 87 $this->assertInstanceOf('external_value', $structure->keys['intB']); 88 $this->assertArrayNotHasKey('otherstring', $structure->keys); 89 $this->assertArrayNotHasKey('otherstrings', $structure->keys); 90 } 91 92 public function test_get_update_structure() { 93 $structure = core_testable_exporter::get_update_structure(); 94 95 $this->assertInstanceOf('external_single_structure', $structure); 96 $this->assertInstanceOf('external_value', $structure->keys['stringA']); 97 $this->assertInstanceOf('external_format_value', $structure->keys['stringAformat']); 98 $this->assertInstanceOf('external_value', $structure->keys['intB']); 99 $this->assertArrayNotHasKey('otherstring', $structure->keys); 100 $this->assertArrayNotHasKey('otherstrings', $structure->keys); 101 } 102 103 public function test_invalid_data() { 104 global $PAGE; 105 $exporter = new core_testable_exporter($this->invaliddata, $this->validrelated); 106 $output = $PAGE->get_renderer('core'); 107 108 // The exception message is a bit misleading, it actually indicates an expected property wasn't found. 109 $this->expectException(\coding_exception::class); 110 $this->expectExceptionMessage('Unexpected property stringAformat'); 111 $result = $exporter->export($output); 112 } 113 114 public function test_invalid_related() { 115 $this->expectException(\coding_exception::class); 116 $this->expectExceptionMessage('Exporter class is missing required related data: (core\core_testable_exporter) ' . 117 'simplestdClass => stdClass'); 118 $exporter = new core_testable_exporter($this->validdata, $this->invalidrelated); 119 } 120 121 public function test_invalid_related_all_cases() { 122 global $PAGE; 123 124 foreach ($this->invalidrelated as $key => $value) { 125 $data = $this->validrelated; 126 $data[$key] = $value; 127 128 try { 129 $exporter = new core_testable_exporter($this->validdata, $data); 130 $output = $PAGE->get_renderer('core'); 131 $result = $exporter->export($output); 132 } catch (\coding_exception $e) { 133 $this->assertNotFalse(strpos($e->getMessage(), $key)); 134 } 135 } 136 } 137 138 public function test_valid_data_and_related() { 139 global $PAGE; 140 $output = $PAGE->get_renderer('core'); 141 $exporter = new core_testable_exporter($this->validdata, $this->validrelated); 142 $result = $exporter->export($output); 143 $this->assertSame('>Another string', $result->otherstring); 144 $this->assertSame(array('String >a', 'String b'), $result->otherstrings); 145 } 146 147 public function test_format_text() { 148 global $PAGE; 149 150 $this->resetAfterTest(); 151 $course = $this->getDataGenerator()->create_course(); 152 $syscontext = \context_system::instance(); 153 $coursecontext = \context_course::instance($course->id); 154 155 \external_settings::get_instance()->set_filter(true); 156 filter_set_global_state('urltolink', TEXTFILTER_OFF); 157 filter_set_local_state('urltolink', $coursecontext->id, TEXTFILTER_ON); 158 set_config('formats', FORMAT_MARKDOWN, 'filter_urltolink'); 159 \filter_manager::reset_caches(); 160 161 $data = [ 162 'stringA' => '__Watch out:__ https://moodle.org @@PLUGINFILE@@/test.pdf', 163 'stringAformat' => FORMAT_MARKDOWN, 164 'intB' => 1 165 ]; 166 167 // Export simulated in the system context. 168 $output = $PAGE->get_renderer('core'); 169 $exporter = new core_testable_exporter($data, ['context' => $syscontext] + $this->validrelated); 170 $result = $exporter->export($output); 171 172 $youtube = 'https://moodle.org'; 173 $fileurl = (new \moodle_url('/webservice/pluginfile.php/' . $syscontext->id . '/test/area/9/test.pdf'))->out(false); 174 $expected = "<p><strong>Watch out:</strong> $youtube $fileurl</p>\n"; 175 $this->assertEquals($expected, $result->stringA); 176 $this->assertEquals(FORMAT_HTML, $result->stringAformat); 177 178 // Export simulated in the course context where the filter is enabled. 179 $exporter = new core_testable_exporter($data, ['context' => $coursecontext] + $this->validrelated); 180 $result = $exporter->export($output); 181 $youtube = '<a href="https://moodle.org" class="_blanktarget">https://moodle.org</a>'; 182 $fileurl = (new \moodle_url('/webservice/pluginfile.php/' . $coursecontext->id . '/test/area/9/test.pdf'))->out(false); 183 $expected = "<p><strong>Watch out:</strong> $youtube <a href=\"$fileurl\" class=\"_blanktarget\">$fileurl</a></p>\n"; 184 $this->assertEquals($expected, $result->stringA); 185 $this->assertEquals(FORMAT_HTML, $result->stringAformat); 186 } 187 188 public function test_properties_description() { 189 $properties = core_testable_exporter::read_properties_definition(); 190 // Properties default description. 191 $this->assertEquals('stringA', $properties['stringA']['description']); 192 $this->assertEquals('stringAformat', $properties['stringAformat']['description']); 193 // Properties custom description. 194 $this->assertEquals('intB description', $properties['intB']['description']); 195 // Other properties custom description. 196 $this->assertEquals('otherstring description', $properties['otherstring']['description']); 197 // Other properties default description. 198 $this->assertEquals('otherstrings', $properties['otherstrings']['description']); 199 // Assert nested elements are formatted correctly. 200 $this->assertEquals('id', $properties['nestedarray']['type']['id']['description']); 201 } 202 } 203 204 /** 205 * Example persistent class. 206 * 207 * @package core 208 * @copyright 2015 Frédéric Massart - FMCorz.net 209 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 210 */ 211 class core_testable_exporter extends \core\external\exporter { 212 213 protected static function define_related() { 214 // We cache the context so it does not need to be retrieved from the course. 215 return array('simplestdClass' => 'stdClass', 'arrayofstdClass' => 'stdClass[]', 'context' => 'context?', 216 'astring' => 'string', 'abool' => 'bool', 'aint' => 'int', 'ints' => 'int[]'); 217 } 218 219 protected function get_other_values(\renderer_base $output) { 220 return array( 221 'otherstring' => '>Another <strong>string</strong>', 222 'otherstrings' => array('String >a', 'String <strong>b</strong>') 223 ); 224 } 225 226 public static function define_properties() { 227 return array( 228 'stringA' => array( 229 'type' => PARAM_RAW, 230 ), 231 'stringAformat' => array( 232 'type' => PARAM_INT, 233 ), 234 'intB' => array( 235 'type' => PARAM_INT, 236 'description' => 'intB description', 237 ) 238 ); 239 } 240 241 public static function define_other_properties() { 242 return array( 243 'otherstring' => array( 244 'type' => PARAM_TEXT, 245 'description' => 'otherstring description', 246 ), 247 'otherstrings' => array( 248 'type' => PARAM_TEXT, 249 'multiple' => true 250 ), 251 'nestedarray' => array( 252 'multiple' => true, 253 'optional' => true, 254 'type' => [ 255 'id' => ['type' => PARAM_INT] 256 ] 257 ) 258 ); 259 } 260 261 protected function get_format_parameters_for_stringA() { 262 return [ 263 // For testing use the passed context if any. 264 'context' => isset($this->related['context']) ? $this->related['context'] : \context_system::instance(), 265 'component' => 'test', 266 'filearea' => 'area', 267 'itemid' => 9, 268 ]; 269 } 270 271 protected function get_format_parameters_for_otherstring() { 272 return [ 273 'context' => \context_system::instance(), 274 'options' => ['escape' => false] 275 ]; 276 } 277 278 protected function get_format_parameters_for_otherstrings() { 279 return [ 280 'context' => \context_system::instance(), 281 ]; 282 } 283 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body