Differences Between: [Versions 310 and 311] [Versions 311 and 400] [Versions 311 and 401] [Versions 311 and 402] [Versions 311 and 403] [Versions 39 and 311]
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 * Persistent class tests. 19 * 20 * @package core 21 * @copyright 2015 Frédéric Massart - FMCorz.net 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24 25 defined('MOODLE_INTERNAL') || die(); 26 global $CFG; 27 28 /** 29 * Persistent testcase. 30 * 31 * @package core 32 * @copyright 2015 Frédéric Massart - FMCorz.net 33 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 34 */ 35 class core_persistent_testcase extends advanced_testcase { 36 37 public function setUp(): void { 38 $this->make_persistent_table(); 39 $this->resetAfterTest(); 40 } 41 42 /** 43 * Make the table for the persistent. 44 */ 45 protected function make_persistent_table() { 46 global $DB; 47 $dbman = $DB->get_manager(); 48 49 $table = new xmldb_table(core_testable_persistent::TABLE); 50 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 51 $table->add_field('shortname', XMLDB_TYPE_CHAR, '100', null, null, null, null); 52 $table->add_field('idnumber', XMLDB_TYPE_CHAR, '100', null, null, null, null); 53 $table->add_field('description', XMLDB_TYPE_TEXT, null, null, null, null, null); 54 $table->add_field('descriptionformat', XMLDB_TYPE_INTEGER, '4', null, XMLDB_NOTNULL, null, '0'); 55 $table->add_field('parentid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 56 $table->add_field('path', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null); 57 $table->add_field('sortorder', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 58 $table->add_field('scaleid', XMLDB_TYPE_INTEGER, '10', null, null, null, null); 59 $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 60 $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 61 $table->add_field('usermodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 62 63 $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id')); 64 65 if ($dbman->table_exists($table)) { 66 $dbman->drop_table($table); 67 } 68 69 $dbman->create_table($table); 70 } 71 72 public function test_properties_definition() { 73 $expected = array( 74 'shortname' => array( 75 'type' => PARAM_TEXT, 76 'default' => '', 77 'null' => NULL_NOT_ALLOWED 78 ), 79 'idnumber' => array( 80 'type' => PARAM_TEXT, 81 'null' => NULL_NOT_ALLOWED 82 ), 83 'description' => array( 84 'type' => PARAM_TEXT, 85 'default' => '', 86 'null' => NULL_NOT_ALLOWED 87 ), 88 'descriptionformat' => array( 89 'choices' => array(FORMAT_HTML, FORMAT_MOODLE, FORMAT_PLAIN, FORMAT_MARKDOWN), 90 'type' => PARAM_INT, 91 'default' => FORMAT_HTML, 92 'null' => NULL_NOT_ALLOWED 93 ), 94 'parentid' => array( 95 'type' => PARAM_INT, 96 'default' => 0, 97 'null' => NULL_NOT_ALLOWED 98 ), 99 'path' => array( 100 'type' => PARAM_RAW, 101 'default' => '', 102 'null' => NULL_NOT_ALLOWED 103 ), 104 'sortorder' => array( 105 'type' => PARAM_INT, 106 'message' => new lang_string('invalidrequest', 'error'), 107 'null' => NULL_NOT_ALLOWED 108 ), 109 'scaleid' => array( 110 'default' => null, 111 'type' => PARAM_INT, 112 'null' => NULL_ALLOWED 113 ), 114 'id' => array( 115 'default' => 0, 116 'type' => PARAM_INT, 117 'null' => NULL_NOT_ALLOWED 118 ), 119 'timecreated' => array( 120 'default' => 0, 121 'type' => PARAM_INT, 122 'null' => NULL_NOT_ALLOWED 123 ), 124 'timemodified' => array( 125 'default' => 0, 126 'type' => PARAM_INT, 127 'null' => NULL_NOT_ALLOWED 128 ), 129 'usermodified' => array( 130 'default' => 0, 131 'type' => PARAM_INT, 132 'null' => NULL_NOT_ALLOWED 133 ), 134 ); 135 $this->assertEquals($expected, core_testable_persistent::properties_definition()); 136 } 137 138 public function test_to_record() { 139 $p = new core_testable_persistent(); 140 $expected = (object) array( 141 'shortname' => '', 142 'idnumber' => null, 143 'description' => '', 144 'descriptionformat' => FORMAT_HTML, 145 'parentid' => 0, 146 'path' => '', 147 'sortorder' => null, 148 'id' => 0, 149 'timecreated' => 0, 150 'timemodified' => 0, 151 'usermodified' => 0, 152 'scaleid' => null, 153 ); 154 $this->assertEquals($expected, $p->to_record()); 155 } 156 157 public function test_from_record() { 158 $p = new core_testable_persistent(); 159 $data = (object) array( 160 'shortname' => 'ddd', 161 'idnumber' => 'abc', 162 'description' => 'xyz', 163 'descriptionformat' => FORMAT_PLAIN, 164 'parentid' => 999, 165 'path' => '/a/b/c', 166 'sortorder' => 12, 167 'id' => 1, 168 'timecreated' => 2, 169 'timemodified' => 3, 170 'usermodified' => 4, 171 'scaleid' => null, 172 ); 173 $p->from_record($data); 174 $this->assertEquals($data, $p->to_record()); 175 } 176 177 public function test_from_record_invalid_param() { 178 $p = new core_testable_persistent(); 179 $data = (object) array( 180 'shortname' => 'ddd', 181 'idnumber' => 'abc', 182 'description' => 'xyz', 183 'descriptionformat' => FORMAT_PLAIN, 184 'parentid' => 999, 185 'path' => '/a/b/c', 186 'sortorder' => 12, 187 'id' => 1, 188 'timecreated' => 2, 189 'timemodified' => 3, 190 'usermodified' => 4, 191 'scaleid' => null, 192 'invalidparam' => 'abc' 193 ); 194 195 $p->from_record($data); 196 197 // Previous call should succeed, assert we get back all data except invalid param. 198 unset($data->invalidparam); 199 $this->assertEquals($data, $p->to_record()); 200 } 201 202 public function test_validate() { 203 $data = (object) array( 204 'idnumber' => 'abc', 205 'sortorder' => 0 206 ); 207 $p = new core_testable_persistent(0, $data); 208 $this->assertFalse(isset($p->beforevalidate)); 209 $this->assertTrue($p->validate()); 210 $this->assertTrue(isset($p->beforevalidate)); 211 $this->assertTrue($p->is_valid()); 212 $this->assertEquals(array(), $p->get_errors()); 213 $p->set('descriptionformat', -100); 214 215 $expected = array( 216 'descriptionformat' => new lang_string('invaliddata', 'error'), 217 ); 218 $this->assertEquals($expected, $p->validate()); 219 $this->assertFalse($p->is_valid()); 220 $this->assertEquals($expected, $p->get_errors()); 221 } 222 223 public function test_validation_required() { 224 $data = (object) array( 225 'idnumber' => 'abc' 226 ); 227 $p = new core_testable_persistent(0, $data); 228 $expected = array( 229 'sortorder' => new lang_string('requiredelement', 'form'), 230 ); 231 $this->assertFalse($p->is_valid()); 232 $this->assertEquals($expected, $p->get_errors()); 233 } 234 235 public function test_validation_custom() { 236 $data = (object) array( 237 'idnumber' => 'abc', 238 'sortorder' => 10, 239 ); 240 $p = new core_testable_persistent(0, $data); 241 $expected = array( 242 'sortorder' => new lang_string('invalidkey', 'error'), 243 ); 244 $this->assertFalse($p->is_valid()); 245 $this->assertEquals($expected, $p->get_errors()); 246 } 247 248 public function test_validation_custom_message() { 249 $data = (object) array( 250 'idnumber' => 'abc', 251 'sortorder' => 'abc', 252 ); 253 $p = new core_testable_persistent(0, $data); 254 $expected = array( 255 'sortorder' => new lang_string('invalidrequest', 'error'), 256 ); 257 $this->assertFalse($p->is_valid()); 258 $this->assertEquals($expected, $p->get_errors()); 259 } 260 261 public function test_validation_choices() { 262 $data = (object) array( 263 'idnumber' => 'abc', 264 'sortorder' => 0, 265 'descriptionformat' => -100 266 ); 267 $p = new core_testable_persistent(0, $data); 268 $expected = array( 269 'descriptionformat' => new lang_string('invaliddata', 'error'), 270 ); 271 $this->assertFalse($p->is_valid()); 272 $this->assertEquals($expected, $p->get_errors()); 273 } 274 275 public function test_validation_type() { 276 $data = (object) array( 277 'idnumber' => 'abc', 278 'sortorder' => 'NaN' 279 ); 280 $p = new core_testable_persistent(0, $data); 281 $this->assertFalse($p->is_valid()); 282 $this->assertArrayHasKey('sortorder', $p->get_errors()); 283 } 284 285 public function test_validation_null() { 286 $data = (object) array( 287 'idnumber' => null, 288 'sortorder' => 0, 289 'scaleid' => 'bad!' 290 ); 291 $p = new core_testable_persistent(0, $data); 292 $this->assertFalse($p->is_valid()); 293 $this->assertArrayHasKey('idnumber', $p->get_errors()); 294 $this->assertArrayHasKey('scaleid', $p->get_errors()); 295 $p->set('idnumber', 'abc'); 296 $this->assertFalse($p->is_valid()); 297 $this->assertArrayNotHasKey('idnumber', $p->get_errors()); 298 $this->assertArrayHasKey('scaleid', $p->get_errors()); 299 $p->set('scaleid', null); 300 $this->assertTrue($p->is_valid()); 301 $this->assertArrayNotHasKey('scaleid', $p->get_errors()); 302 } 303 304 public function test_create() { 305 global $DB; 306 $p = new core_testable_persistent(0, (object) array('sortorder' => 123, 'idnumber' => 'abc')); 307 $this->assertFalse(isset($p->beforecreate)); 308 $this->assertFalse(isset($p->aftercreate)); 309 $p->create(); 310 $record = $DB->get_record(core_testable_persistent::TABLE, array('id' => $p->get('id')), '*', MUST_EXIST); 311 $expected = $p->to_record(); 312 $this->assertTrue(isset($p->beforecreate)); 313 $this->assertTrue(isset($p->aftercreate)); 314 $this->assertEquals($expected->sortorder, $record->sortorder); 315 $this->assertEquals($expected->idnumber, $record->idnumber); 316 $this->assertEquals($expected->id, $record->id); 317 $this->assertTrue($p->is_valid()); // Should always be valid after a create. 318 } 319 320 public function test_update() { 321 global $DB; 322 $p = new core_testable_persistent(0, (object) array('sortorder' => 123, 'idnumber' => 'abc')); 323 $p->create(); 324 $id = $p->get('id'); 325 $p->set('sortorder', 456); 326 $p->from_record((object) array('idnumber' => 'def')); 327 $this->assertFalse(isset($p->beforeupdate)); 328 $this->assertFalse(isset($p->afterupdate)); 329 $p->update(); 330 331 $expected = $p->to_record(); 332 $record = $DB->get_record(core_testable_persistent::TABLE, array('id' => $p->get('id')), '*', MUST_EXIST); 333 $this->assertTrue(isset($p->beforeupdate)); 334 $this->assertTrue(isset($p->afterupdate)); 335 $this->assertEquals($id, $record->id); 336 $this->assertEquals(456, $record->sortorder); 337 $this->assertEquals('def', $record->idnumber); 338 $this->assertTrue($p->is_valid()); // Should always be valid after an update. 339 } 340 341 public function test_save() { 342 global $DB; 343 $p = new core_testable_persistent(0, (object) array('sortorder' => 123, 'idnumber' => 'abc')); 344 $this->assertFalse(isset($p->beforecreate)); 345 $this->assertFalse(isset($p->aftercreate)); 346 $this->assertFalse(isset($p->beforeupdate)); 347 $this->assertFalse(isset($p->beforeupdate)); 348 $p->save(); 349 $record = $DB->get_record(core_testable_persistent::TABLE, array('id' => $p->get('id')), '*', MUST_EXIST); 350 $expected = $p->to_record(); 351 $this->assertTrue(isset($p->beforecreate)); 352 $this->assertTrue(isset($p->aftercreate)); 353 $this->assertFalse(isset($p->beforeupdate)); 354 $this->assertFalse(isset($p->beforeupdate)); 355 $this->assertEquals($expected->sortorder, $record->sortorder); 356 $this->assertEquals($expected->idnumber, $record->idnumber); 357 $this->assertEquals($expected->id, $record->id); 358 $this->assertTrue($p->is_valid()); // Should always be valid after a save/create. 359 360 $p->set('idnumber', 'abcd'); 361 $p->save(); 362 $record = $DB->get_record(core_testable_persistent::TABLE, array('id' => $p->get('id')), '*', MUST_EXIST); 363 $expected = $p->to_record(); 364 $this->assertTrue(isset($p->beforeupdate)); 365 $this->assertTrue(isset($p->beforeupdate)); 366 $this->assertEquals($expected->sortorder, $record->sortorder); 367 $this->assertEquals($expected->idnumber, $record->idnumber); 368 $this->assertEquals($expected->id, $record->id); 369 $this->assertTrue($p->is_valid()); // Should always be valid after a save/update. 370 } 371 372 public function test_read() { 373 $p = new core_testable_persistent(0, (object) array('sortorder' => 123, 'idnumber' => 'abc')); 374 $p->create(); 375 unset($p->beforevalidate); 376 unset($p->beforecreate); 377 unset($p->aftercreate); 378 379 $p2 = new core_testable_persistent($p->get('id')); 380 $this->assertEquals($p, $p2); 381 382 $p3 = new core_testable_persistent(); 383 $p3->set('id', $p->get('id')); 384 $p3->read(); 385 $this->assertEquals($p, $p3); 386 } 387 388 public function test_delete() { 389 global $DB; 390 391 $p = new core_testable_persistent(0, (object) array('sortorder' => 123, 'idnumber' => 'abc')); 392 $p->create(); 393 $this->assertNotEquals(0, $p->get('id')); 394 $this->assertTrue($DB->record_exists_select(core_testable_persistent::TABLE, 'id = ?', array($p->get('id')))); 395 $this->assertFalse(isset($p->beforedelete)); 396 $this->assertFalse(isset($p->afterdelete)); 397 398 $p->delete(); 399 $this->assertFalse($DB->record_exists_select(core_testable_persistent::TABLE, 'id = ?', array($p->get('id')))); 400 $this->assertEquals(0, $p->get('id')); 401 $this->assertEquals(true, $p->beforedelete); 402 $this->assertEquals(true, $p->afterdelete); 403 } 404 405 public function test_has_property() { 406 $this->assertFalse(core_testable_persistent::has_property('unknown')); 407 $this->assertTrue(core_testable_persistent::has_property('idnumber')); 408 } 409 410 public function test_custom_setter_getter() { 411 global $DB; 412 413 $path = array(1, 2, 3); 414 $json = json_encode($path); 415 416 $p = new core_testable_persistent(0, (object) array('sortorder' => 0, 'idnumber' => 'abc')); 417 $p->set('path', $path); 418 $this->assertEquals($path, $p->get('path')); 419 $this->assertEquals($json, $p->to_record()->path); 420 421 $p->create(); 422 $record = $DB->get_record(core_testable_persistent::TABLE, array('id' => $p->get('id')), 'id, path', MUST_EXIST); 423 $this->assertEquals($json, $record->path); 424 } 425 426 public function test_record_exists() { 427 global $DB; 428 $this->assertFalse($DB->record_exists(core_testable_persistent::TABLE, array('idnumber' => 'abc'))); 429 $p = new core_testable_persistent(0, (object) array('sortorder' => 123, 'idnumber' => 'abc')); 430 $p->create(); 431 $id = $p->get('id'); 432 $this->assertTrue(core_testable_persistent::record_exists($id)); 433 $this->assertTrue($DB->record_exists(core_testable_persistent::TABLE, array('idnumber' => 'abc'))); 434 $p->delete(); 435 $this->assertFalse(core_testable_persistent::record_exists($id)); 436 } 437 438 public function test_get_sql_fields() { 439 $expected = '' . 440 'c.id AS prefix_id, ' . 441 'c.shortname AS prefix_shortname, ' . 442 'c.idnumber AS prefix_idnumber, ' . 443 'c.description AS prefix_description, ' . 444 'c.descriptionformat AS prefix_descriptionformat, ' . 445 'c.parentid AS prefix_parentid, ' . 446 'c.path AS prefix_path, ' . 447 'c.sortorder AS prefix_sortorder, ' . 448 'c.scaleid AS prefix_scaleid, ' . 449 'c.timecreated AS prefix_timecreated, ' . 450 'c.timemodified AS prefix_timemodified, ' . 451 'c.usermodified AS prefix_usermodified'; 452 $this->assertEquals($expected, core_testable_persistent::get_sql_fields('c', 'prefix_')); 453 } 454 455 public function test_get_sql_fields_too_long() { 456 $this->expectException(coding_exception::class); 457 $this->expectExceptionMessageMatches('/The alias .+ exceeds 30 characters/'); 458 core_testable_persistent::get_sql_fields('c'); 459 } 460 } 461 462 /** 463 * Example persistent class. 464 * 465 * @package core 466 * @copyright 2015 Frédéric Massart - FMCorz.net 467 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 468 */ 469 class core_testable_persistent extends \core\persistent { 470 471 const TABLE = 'phpunit_persistent'; 472 473 protected static function define_properties() { 474 return array( 475 'shortname' => array( 476 'type' => PARAM_TEXT, 477 'default' => '' 478 ), 479 'idnumber' => array( 480 'type' => PARAM_TEXT, 481 ), 482 'description' => array( 483 'type' => PARAM_TEXT, 484 'default' => '' 485 ), 486 'descriptionformat' => array( 487 'choices' => array(FORMAT_HTML, FORMAT_MOODLE, FORMAT_PLAIN, FORMAT_MARKDOWN), 488 'type' => PARAM_INT, 489 'default' => FORMAT_HTML 490 ), 491 'parentid' => array( 492 'type' => PARAM_INT, 493 'default' => 0 494 ), 495 'path' => array( 496 'type' => PARAM_RAW, 497 'default' => '' 498 ), 499 'sortorder' => array( 500 'type' => PARAM_INT, 501 'message' => new lang_string('invalidrequest', 'error') 502 ), 503 'scaleid' => array( 504 'type' => PARAM_INT, 505 'default' => null, 506 'null' => NULL_ALLOWED 507 ) 508 ); 509 } 510 511 protected function before_validate() { 512 $this->beforevalidate = true; 513 } 514 515 protected function before_create() { 516 $this->beforecreate = true; 517 } 518 519 protected function before_update() { 520 $this->beforeupdate = true; 521 } 522 523 protected function before_delete() { 524 $this->beforedelete = true; 525 } 526 527 protected function after_create() { 528 $this->aftercreate = true; 529 } 530 531 protected function after_update($result) { 532 $this->afterupdate = true; 533 } 534 535 protected function after_delete($result) { 536 $this->afterdelete = true; 537 } 538 539 protected function get_path() { 540 $value = $this->raw_get('path'); 541 if (!empty($value)) { 542 $value = json_decode($value); 543 } 544 return $value; 545 } 546 547 protected function set_path($value) { 548 if (!empty($value)) { 549 $value = json_encode($value); 550 } 551 $this->raw_set('path', $value); 552 } 553 554 protected function validate_sortorder($value) { 555 if ($value == 10) { 556 return new lang_string('invalidkey', 'error'); 557 } 558 return true; 559 } 560 561 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body