How to use isArray method of for class

Best Mockery code snippet using for.isArray

schema-map.php

Source:schema-map.php Github

copy

Full Screen

...

Full Screen

Full Screen

locallib_test.php

Source:locallib_test.php Github

copy

Full Screen

1<?php2// This file is part of Moodle - http://moodle.org/3//4// Moodle is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (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 of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12// GNU General Public License for more details.13//14// You should have received a copy of the GNU General Public License15// along with Moodle. If not, see <http://www.gnu.org/licenses/>.16//17// This file is part of BasicLTI4Moodle18//19// BasicLTI4Moodle is an IMS BasicLTI (Basic Learning Tools for Interoperability)20// consumer for Moodle 1.9 and Moodle 2.0. BasicLTI is a IMS Standard that allows web21// based learning tools to be easily integrated in LMS as native ones. The IMS BasicLTI22// specification is part of the IMS standard Common Cartridge 1.1 Sakai and other main LMS23// are already supporting or going to support BasicLTI. This project Implements the consumer24// for Moodle. Moodle is a Free Open source Learning Management System by Martin Dougiamas.25// BasicLTI4Moodle is a project iniciated and leaded by Ludo(Marc Alier) and Jordi Piguillem26// at the GESSI research group at UPC.27// SimpleLTI consumer for Moodle is an implementation of the early specification of LTI28// by Charles Severance (Dr Chuck) htp://dr-chuck.com , developed by Jordi Piguillem in a29// Google Summer of Code 2008 project co-mentored by Charles Severance and Marc Alier.30//31// BasicLTI4Moodle is copyright 2009 by Marc Alier Forment, Jordi Piguillem and Nikolas Galanis32// of the Universitat Politecnica de Catalunya http://www.upc.edu33// Contact info: Marc Alier Forment granludo @ gmail.com or marc.alier @ upc.edu.34/**35 * This file contains unit tests for (some of) lti/locallib.php36 *37 * @package mod_lti38 * @category phpunit39 * @copyright 2009 Marc Alier, Jordi Piguillem, Nikolas Galanis40 * @copyright 2009 Universitat Politecnica de Catalunya http://www.upc.edu41 * @author Charles Severance csev@unmich.edu42 * @author Marc Alier (marc.alier@upc.edu)43 * @author Jordi Piguillem44 * @author Nikolas Galanis45 * @author Chris Scribner46 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later47 */48defined('MOODLE_INTERNAL') || die;49global $CFG;50require_once($CFG->dirroot . '/mod/lti/locallib.php');51require_once($CFG->dirroot . '/mod/lti/servicelib.php');52/**53 * Local library tests54 *55 * @package mod_lti56 * @copyright Copyright (c) 2012 Moodlerooms Inc. (http://www.moodlerooms.com)57 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later58 */59class mod_lti_locallib_testcase extends advanced_testcase {60 public function test_split_custom_parameters() {61 $this->resetAfterTest();62 $tool = new stdClass();63 $tool->enabledcapability = '';64 $tool->parameter = '';65 $tool->ltiversion = 'LTI-1p0';66 $this->assertEquals(lti_split_custom_parameters(null, $tool, array(), "x=1\ny=2", false),67 array('custom_x' => '1', 'custom_y' => '2'));68 // Check params with caps.69 $this->assertEquals(lti_split_custom_parameters(null, $tool, array(), "X=1", true),70 array('custom_x' => '1', 'custom_X' => '1'));71 // Removed repeat of previous test with a semicolon separator.72 $this->assertEquals(lti_split_custom_parameters(null, $tool, array(), 'Review:Chapter=1.2.56', true),73 array(74 'custom_review_chapter' => '1.2.56',75 'custom_Review:Chapter' => '1.2.56'));76 $this->assertEquals(lti_split_custom_parameters(null, $tool, array(),77 'Complex!@#$^*(){}[]KEY=Complex!@#$^*;(){}[]½Value', true),78 array(79 'custom_complex____________key' => 'Complex!@#$^*;(){}[]½Value',80 'custom_Complex!@#$^*(){}[]KEY' => 'Complex!@#$^*;(){}[]½Value'));81 // Test custom parameter that returns $USER property.82 $user = $this->getDataGenerator()->create_user(array('middlename' => 'SOMETHING'));83 $this->setUser($user);84 $this->assertEquals(array('custom_x' => '1', 'custom_y' => 'SOMETHING'),85 lti_split_custom_parameters(null, $tool, array(), "x=1\ny=\$Person.name.middle", false));86 }87 /**88 * This test has been disabled because the test-tool is89 * being moved and probably it won't work anymore for this.90 * We should be testing here local stuff only and leave91 * outside-checks to the conformance tests. MDL-3034792 */93 public function disabled_test_sign_parameters() {94 $correct = array ( 'context_id' => '12345', 'context_label' => 'SI124', 'context_title' => 'Social Computing',95 'ext_submit' => 'Click Me', 'lti_message_type' => 'basic-lti-launch-request', 'lti_version' => 'LTI-1p0',96 'oauth_consumer_key' => 'lmsng.school.edu', 'oauth_nonce' => '47458148e33a8f9dafb888c3684cf476',97 'oauth_signature' => 'qWgaBIezihCbeHgcwUy14tZcyDQ=', 'oauth_signature_method' => 'HMAC-SHA1',98 'oauth_timestamp' => '1307141660', 'oauth_version' => '1.0', 'resource_link_id' => '123',99 'resource_link_title' => 'Weekly Blog', 'roles' => 'Learner', 'tool_consumer_instance_guid' => 'lmsng.school.edu',100 'user_id' => '789');101 $requestparams = array('resource_link_id' => '123', 'resource_link_title' => 'Weekly Blog', 'user_id' => '789',102 'roles' => 'Learner', 'context_id' => '12345', 'context_label' => 'SI124', 'context_title' => 'Social Computing');103 $parms = lti_sign_parameters($requestparams, 'http://www.imsglobal.org/developer/LTI/tool.php', 'POST',104 'lmsng.school.edu', 'secret', 'Click Me', 'lmsng.school.edu' /*, $org_desc*/);105 $this->assertTrue(isset($parms['oauth_nonce']));106 $this->assertTrue(isset($parms['oauth_signature']));107 $this->assertTrue(isset($parms['oauth_timestamp']));108 // Those things that are hard to mock.109 $correct['oauth_nonce'] = $parms['oauth_nonce'];110 $correct['oauth_signature'] = $parms['oauth_signature'];111 $correct['oauth_timestamp'] = $parms['oauth_timestamp'];112 ksort($parms);113 ksort($correct);114 $this->assertEquals($parms, $correct);115 }116 /**117 * This test has been disabled because, since its creation,118 * the sourceId generation has changed and surely this is outdated.119 * Some day these should be replaced by proper tests, but until then120 * conformance tests say this is working. MDL-30347121 */122 public function disabled_test_parse_grade_replace_message() {123 $message = '124 <imsx_POXEnvelopeRequest xmlns = "http://www.imsglobal.org/services/ltiv1p1/xsd/imsoms_v1p0">125 <imsx_POXHeader>126 <imsx_POXRequestHeaderInfo>127 <imsx_version>V1.0</imsx_version>128 <imsx_messageIdentifier>999998123</imsx_messageIdentifier>129 </imsx_POXRequestHeaderInfo>130 </imsx_POXHeader>131 <imsx_POXBody>132 <replaceResultRequest>133 <resultRecord>134 <sourcedGUID>135 <sourcedId>' .136 '{&quot;data&quot;:{&quot;instanceid&quot;:&quot;2&quot;,&quot;userid&quot;:&quot;2&quot;},&quot;hash&quot;:' .137 '&quot;0b5078feab59b9938c333ceaae21d8e003a7b295e43cdf55338445254421076b&quot;}' .138 '</sourcedId>139 </sourcedGUID>140 <result>141 <resultScore>142 <language>en-us</language>143 <textString>0.92</textString>144 </resultScore>145 </result>146 </resultRecord>147 </replaceResultRequest>148 </imsx_POXBody>149 </imsx_POXEnvelopeRequest>150';151 $parsed = lti_parse_grade_replace_message(new SimpleXMLElement($message));152 $this->assertEquals($parsed->userid, '2');153 $this->assertEquals($parsed->instanceid, '2');154 $this->assertEquals($parsed->sourcedidhash, '0b5078feab59b9938c333ceaae21d8e003a7b295e43cdf55338445254421076b');155 $ltiinstance = (object)array('servicesalt' => '4e5fcc06de1d58.44963230');156 lti_verify_sourcedid($ltiinstance, $parsed);157 }158 public function test_lti_ensure_url_is_https() {159 $this->assertEquals('https://moodle.org', lti_ensure_url_is_https('http://moodle.org'));160 $this->assertEquals('https://moodle.org', lti_ensure_url_is_https('moodle.org'));161 $this->assertEquals('https://moodle.org', lti_ensure_url_is_https('https://moodle.org'));162 }163 /**164 * Test lti_get_url_thumbprint against various URLs165 */166 public function test_lti_get_url_thumbprint() {167 // Note: trailing and double slash are expected right now. Must evaluate if it must be removed at some point.168 $this->assertEquals('moodle.org/', lti_get_url_thumbprint('http://MOODLE.ORG'));169 $this->assertEquals('moodle.org/', lti_get_url_thumbprint('http://www.moodle.org'));170 $this->assertEquals('moodle.org/', lti_get_url_thumbprint('https://www.moodle.org'));171 $this->assertEquals('moodle.org/', lti_get_url_thumbprint('moodle.org'));172 $this->assertEquals('moodle.org//this/is/moodle', lti_get_url_thumbprint('http://moodle.org/this/is/moodle'));173 $this->assertEquals('moodle.org//this/is/moodle', lti_get_url_thumbprint('https://moodle.org/this/is/moodle'));174 $this->assertEquals('moodle.org//this/is/moodle', lti_get_url_thumbprint('moodle.org/this/is/moodle'));175 $this->assertEquals('moodle.org//this/is/moodle', lti_get_url_thumbprint('moodle.org/this/is/moodle?'));176 $this->assertEquals('moodle.org//this/is/moodle?foo=bar', lti_get_url_thumbprint('moodle.org/this/is/moodle?foo=bar'));177 }178 /*179 * Verify that lti_build_request does handle resource_link_id as expected180 */181 public function test_lti_buid_request_resource_link_id() {182 $this->resetAfterTest();183 self::setUser($this->getDataGenerator()->create_user());184 $course = $this->getDataGenerator()->create_course();185 $instance = $this->getDataGenerator()->create_module('lti', array(186 'intro' => "<p>This</p>\nhas\r\n<p>some</p>\nnew\n\rlines",187 'introformat' => FORMAT_HTML,188 'course' => $course->id,189 ));190 $typeconfig = array(191 'acceptgrades' => 1,192 'forcessl' => 0,193 'sendname' => 2,194 'sendemailaddr' => 2,195 'customparameters' => '',196 );197 // Normal call, we expect $instance->id to be used as resource_link_id.198 $params = lti_build_request($instance, $typeconfig, $course, null);199 $this->assertSame($instance->id, $params['resource_link_id']);200 // If there is a resource_link_id set, it gets precedence.201 $instance->resource_link_id = $instance->id + 99;202 $params = lti_build_request($instance, $typeconfig, $course, null);203 $this->assertSame($instance->resource_link_id, $params['resource_link_id']);204 // With none set, resource_link_id is not set either.205 unset($instance->id);206 unset($instance->resource_link_id);207 $params = lti_build_request($instance, $typeconfig, $course, null);208 $this->assertArrayNotHasKey('resource_link_id', $params);209 }210 /**211 * Test lti_build_request's resource_link_description and ensure212 * that the newlines in the description are correct.213 */214 public function test_lti_build_request_description() {215 $this->resetAfterTest();216 self::setUser($this->getDataGenerator()->create_user());217 $course = $this->getDataGenerator()->create_course();218 $instance = $this->getDataGenerator()->create_module('lti', array(219 'intro' => "<p>This</p>\nhas\r\n<p>some</p>\nnew\n\rlines",220 'introformat' => FORMAT_HTML,221 'course' => $course->id,222 ));223 $typeconfig = array(224 'acceptgrades' => 1,225 'forcessl' => 0,226 'sendname' => 2,227 'sendemailaddr' => 2,228 'customparameters' => '',229 );230 $params = lti_build_request($instance, $typeconfig, $course, null);231 $ncount = substr_count($params['resource_link_description'], "\n");232 $this->assertGreaterThan(0, $ncount);233 $rcount = substr_count($params['resource_link_description'], "\r");234 $this->assertGreaterThan(0, $rcount);235 $this->assertEquals($ncount, $rcount, 'The number of \n characters should be the same as the number of \r characters');236 $rncount = substr_count($params['resource_link_description'], "\r\n");237 $this->assertGreaterThan(0, $rncount);238 $this->assertEquals($ncount, $rncount, 'All newline characters should be a combination of \r\n');239 }240 /**241 * Tests lti_prepare_type_for_save's handling of the "Force SSL" configuration.242 */243 public function test_lti_prepare_type_for_save_forcessl() {244 $type = new stdClass();245 $config = new stdClass();246 // Try when the forcessl config property is not set.247 lti_prepare_type_for_save($type, $config);248 $this->assertObjectHasAttribute('lti_forcessl', $config);249 $this->assertEquals(0, $config->lti_forcessl);250 $this->assertEquals(0, $type->forcessl);251 // Try when forcessl config property is set.252 $config->lti_forcessl = 1;253 lti_prepare_type_for_save($type, $config);254 $this->assertObjectHasAttribute('lti_forcessl', $config);255 $this->assertEquals(1, $config->lti_forcessl);256 $this->assertEquals(1, $type->forcessl);257 // Try when forcessl config property is set to 0.258 $config->lti_forcessl = 0;259 lti_prepare_type_for_save($type, $config);260 $this->assertObjectHasAttribute('lti_forcessl', $config);261 $this->assertEquals(0, $config->lti_forcessl);262 $this->assertEquals(0, $type->forcessl);263 }264 /**265 * Tests lti_load_type_from_cartridge and lti_load_type_if_cartridge266 */267 public function test_lti_load_type_from_cartridge() {268 $type = new stdClass();269 $type->lti_toolurl = $this->getExternalTestFileUrl('/ims_cartridge_basic_lti_link.xml');270 lti_load_type_if_cartridge($type);271 $this->assertEquals('Example tool', $type->lti_typename);272 $this->assertEquals('Example tool description', $type->lti_description);273 $this->assertEquals('http://www.example.com/lti/provider.php', $type->lti_toolurl);274 $this->assertEquals('http://download.moodle.org/unittest/test.jpg', $type->lti_icon);275 $this->assertEquals('https://download.moodle.org/unittest/test.jpg', $type->lti_secureicon);276 }277 /**278 * Tests lti_load_tool_from_cartridge and lti_load_tool_if_cartridge279 */280 public function test_lti_load_tool_from_cartridge() {281 $lti = new stdClass();282 $lti->toolurl = $this->getExternalTestFileUrl('/ims_cartridge_basic_lti_link.xml');283 lti_load_tool_if_cartridge($lti);284 $this->assertEquals('Example tool', $lti->name);285 $this->assertEquals('Example tool description', $lti->intro);286 $this->assertEquals('http://www.example.com/lti/provider.php', $lti->toolurl);287 $this->assertEquals('https://www.example.com/lti/provider.php', $lti->securetoolurl);288 $this->assertEquals('http://download.moodle.org/unittest/test.jpg', $lti->icon);289 $this->assertEquals('https://download.moodle.org/unittest/test.jpg', $lti->secureicon);290 }291 /**292 * Tests for lti_build_content_item_selection_request().293 */294 public function test_lti_build_content_item_selection_request() {295 $this->resetAfterTest();296 $this->setAdminUser();297 // Create a tool proxy.298 $proxy = mod_lti_external::create_tool_proxy('Test proxy', $this->getExternalTestFileUrl('/test.html'), array(), array());299 // Create a tool type, associated with that proxy.300 $type = new stdClass();301 $data = new stdClass();302 $data->lti_contentitem = true;303 $type->state = LTI_TOOL_STATE_CONFIGURED;304 $type->name = "Test tool";305 $type->description = "Example description";306 $type->toolproxyid = $proxy->id;307 $type->baseurl = $this->getExternalTestFileUrl('/test.html');308 $typeid = lti_add_type($type, $data);309 $typeconfig = lti_get_type_config($typeid);310 $course = $this->getDataGenerator()->create_course();311 $returnurl = new moodle_url('/');312 // Default parameters.313 $result = lti_build_content_item_selection_request($typeid, $course, $returnurl);314 $this->assertNotEmpty($result);315 $this->assertNotEmpty($result->params);316 $this->assertNotEmpty($result->url);317 $params = $result->params;318 $url = $result->url;319 $this->assertEquals($typeconfig['toolurl'], $url);320 $this->assertEquals('ContentItemSelectionRequest', $params['lti_message_type']);321 $this->assertEquals(LTI_VERSION_1, $params['lti_version']);322 $this->assertEquals('application/vnd.ims.lti.v1.ltilink', $params['accept_media_types']);323 $this->assertEquals('frame,iframe,window', $params['accept_presentation_document_targets']);324 $this->assertEquals($returnurl->out(false), $params['content_item_return_url']);325 $this->assertEquals('false', $params['accept_unsigned']);326 $this->assertEquals('false', $params['accept_multiple']);327 $this->assertEquals('false', $params['accept_copy_advice']);328 $this->assertEquals('false', $params['auto_create']);329 $this->assertEquals($type->name, $params['title']);330 $this->assertFalse(isset($params['resource_link_id']));331 $this->assertFalse(isset($params['resource_link_title']));332 $this->assertFalse(isset($params['resource_link_description']));333 $this->assertFalse(isset($params['launch_presentation_return_url']));334 $this->assertFalse(isset($params['lis_result_sourcedid']));335 // Custom parameters.336 $title = 'My custom title';337 $text = 'This is the tool description';338 $mediatypes = ['image/*', 'video/*'];339 $targets = ['embed', 'iframe'];340 $result = lti_build_content_item_selection_request($typeid, $course, $returnurl, $title, $text, $mediatypes, $targets,341 true, true, true, true, true);342 $this->assertNotEmpty($result);343 $this->assertNotEmpty($result->params);344 $this->assertNotEmpty($result->url);345 $params = $result->params;346 $this->assertEquals(implode(',', $mediatypes), $params['accept_media_types']);347 $this->assertEquals(implode(',', $targets), $params['accept_presentation_document_targets']);348 $this->assertEquals('true', $params['accept_unsigned']);349 $this->assertEquals('true', $params['accept_multiple']);350 $this->assertEquals('true', $params['accept_copy_advice']);351 $this->assertEquals('true', $params['auto_create']);352 $this->assertEquals($title, $params['title']);353 $this->assertEquals($text, $params['text']);354 // Invalid flag values.355 $result = lti_build_content_item_selection_request($typeid, $course, $returnurl, $title, $text, $mediatypes, $targets,356 'aa', -1, 0, 1, 0xabc);357 $this->assertNotEmpty($result);358 $this->assertNotEmpty($result->params);359 $this->assertNotEmpty($result->url);360 $params = $result->params;361 $this->assertEquals(implode(',', $mediatypes), $params['accept_media_types']);362 $this->assertEquals(implode(',', $targets), $params['accept_presentation_document_targets']);363 $this->assertEquals('false', $params['accept_unsigned']);364 $this->assertEquals('false', $params['accept_multiple']);365 $this->assertEquals('false', $params['accept_copy_advice']);366 $this->assertEquals('false', $params['auto_create']);367 $this->assertEquals($title, $params['title']);368 $this->assertEquals($text, $params['text']);369 }370 /**371 * Test for lti_build_content_item_selection_request() with nonexistent tool type ID parameter.372 */373 public function test_lti_build_content_item_selection_request_invalid_tooltype() {374 $this->resetAfterTest();375 $this->setAdminUser();376 $course = $this->getDataGenerator()->create_course();377 $returnurl = new moodle_url('/');378 // Should throw Exception on non-existent tool type.379 $this->expectException('moodle_exception');380 lti_build_content_item_selection_request(1, $course, $returnurl);381 }382 /**383 * Test for lti_build_content_item_selection_request() with invalid media types parameter.384 */385 public function test_lti_build_content_item_selection_request_invalid_mediatypes() {386 $this->resetAfterTest();387 $this->setAdminUser();388 // Create a tool type, associated with that proxy.389 $type = new stdClass();390 $data = new stdClass();391 $data->lti_contentitem = true;392 $type->state = LTI_TOOL_STATE_CONFIGURED;393 $type->name = "Test tool";394 $type->description = "Example description";395 $type->baseurl = $this->getExternalTestFileUrl('/test.html');396 $typeid = lti_add_type($type, $data);397 $course = $this->getDataGenerator()->create_course();398 $returnurl = new moodle_url('/');399 // Should throw coding_exception on non-array media types.400 $mediatypes = 'image/*,video/*';401 $this->expectException('coding_exception');402 lti_build_content_item_selection_request($typeid, $course, $returnurl, '', '', $mediatypes);403 }404 /**405 * Test for lti_build_content_item_selection_request() with invalid presentation targets parameter.406 */407 public function test_lti_build_content_item_selection_request_invalid_presentationtargets() {408 $this->resetAfterTest();409 $this->setAdminUser();410 // Create a tool type, associated with that proxy.411 $type = new stdClass();412 $data = new stdClass();413 $data->lti_contentitem = true;414 $type->state = LTI_TOOL_STATE_CONFIGURED;415 $type->name = "Test tool";416 $type->description = "Example description";417 $type->baseurl = $this->getExternalTestFileUrl('/test.html');418 $typeid = lti_add_type($type, $data);419 $course = $this->getDataGenerator()->create_course();420 $returnurl = new moodle_url('/');421 // Should throw coding_exception on non-array presentation targets.422 $targets = 'frame,iframe';423 $this->expectException('coding_exception');424 lti_build_content_item_selection_request($typeid, $course, $returnurl, '', '', [], $targets);425 }426 /**427 * Provider for test_lti_get_best_tool_by_url.428 *429 * @return array of [urlToTest, expectedTool, allTools]430 */431 public function lti_get_best_tool_by_url_provider() {432 $tools = [433 (object) [434 'name' => 'Here',435 'baseurl' => 'https://example.com/i/am/?where=here',436 'tooldomain' => 'example.com',437 'state' => LTI_TOOL_STATE_CONFIGURED,438 'course' => SITEID439 ],440 (object) [441 'name' => 'There',442 'baseurl' => 'https://example.com/i/am/?where=there',443 'tooldomain' => 'example.com',444 'state' => LTI_TOOL_STATE_CONFIGURED,445 'course' => SITEID446 ],447 (object) [448 'name' => 'Not here',449 'baseurl' => 'https://example.com/i/am/?where=not/here',450 'tooldomain' => 'example.com',451 'state' => LTI_TOOL_STATE_CONFIGURED,452 'course' => SITEID453 ],454 (object) [455 'name' => 'Here',456 'baseurl' => 'https://example.com/i/am/',457 'tooldomain' => 'example.com',458 'state' => LTI_TOOL_STATE_CONFIGURED,459 'course' => SITEID460 ],461 (object) [462 'name' => 'Here',463 'baseurl' => 'https://example.com/i/was',464 'tooldomain' => 'example.com',465 'state' => LTI_TOOL_STATE_CONFIGURED,466 'course' => SITEID467 ],468 (object) [469 'name' => 'Here',470 'baseurl' => 'https://badexample.com/i/am/?where=here',471 'tooldomain' => 'badexample.com',472 'state' => LTI_TOOL_STATE_CONFIGURED,473 'course' => SITEID474 ],475 ];476 $data = [477 [478 'url' => $tools[0]->baseurl,479 'expected' => $tools[0],480 ],481 [482 'url' => $tools[1]->baseurl,483 'expected' => $tools[1],484 ],485 [486 'url' => $tools[2]->baseurl,487 'expected' => $tools[2],488 ],489 [490 'url' => $tools[3]->baseurl,491 'expected' => $tools[3],492 ],493 [494 'url' => $tools[4]->baseurl,495 'expected' => $tools[4],496 ],497 [498 'url' => $tools[5]->baseurl,499 'expected' => $tools[5],500 ],501 [502 'url' => 'https://nomatch.com/i/am/',503 'expected' => null504 ],505 [506 'url' => 'https://example.com',507 'expected' => null508 ],509 [510 'url' => 'https://example.com/i/am/?where=unknown',511 'expected' => $tools[3]512 ]513 ];514 // Construct the final array as required by the provider API. Each row515 // of the array contains the URL to test, the expected tool, and516 // the complete list of tools.517 return array_map(function($data) use ($tools) {518 return [$data['url'], $data['expected'], $tools];519 }, $data);520 }521 /**522 * Test lti_get_best_tool_by_url.523 *524 * @dataProvider lti_get_best_tool_by_url_provider525 * @param string $url The URL to test.526 * @param object $expected The expected tool matching the URL.527 * @param array $tools The pool of tools to match the URL with.528 */529 public function test_lti_get_best_tool_by_url($url, $expected, $tools) {530 $actual = lti_get_best_tool_by_url($url, $tools, null);531 $this->assertSame($expected, $actual);532 }533 /**534 * Test lti_get_jwt_message_type_mapping().535 */536 public function test_lti_get_jwt_message_type_mapping() {537 $mapping = [538 'basic-lti-launch-request' => 'LtiResourceLinkRequest',539 'ContentItemSelectionRequest' => 'LtiDeepLinkingRequest',540 'LtiDeepLinkingResponse' => 'ContentItemSelection',541 ];542 $this->assertEquals($mapping, lti_get_jwt_message_type_mapping());543 }544 /**545 * Test lti_get_jwt_claim_mapping()546 */547 public function test_lti_get_jwt_claim_mapping() {548 $mapping = [549 'accept_copy_advice' => [550 'suffix' => 'dl',551 'group' => 'deep_linking_settings',552 'claim' => 'accept_copy_advice',553 'isarray' => false554 ],555 'accept_media_types' => [556 'suffix' => 'dl',557 'group' => 'deep_linking_settings',558 'claim' => 'accept_media_types',559 'isarray' => true560 ],561 'accept_multiple' => [562 'suffix' => 'dl',563 'group' => 'deep_linking_settings',564 'claim' => 'accept_multiple',565 'isarray' => false566 ],567 'accept_presentation_document_targets' => [568 'suffix' => 'dl',569 'group' => 'deep_linking_settings',570 'claim' => 'accept_presentation_document_targets',571 'isarray' => true572 ],573 'accept_types' => [574 'suffix' => 'dl',575 'group' => 'deep_linking_settings',576 'claim' => 'accept_types',577 'isarray' => true578 ],579 'accept_unsigned' => [580 'suffix' => 'dl',581 'group' => 'deep_linking_settings',582 'claim' => 'accept_unsigned',583 'isarray' => false584 ],585 'auto_create' => [586 'suffix' => 'dl',587 'group' => 'deep_linking_settings',588 'claim' => 'auto_create',589 'isarray' => false590 ],591 'can_confirm' => [592 'suffix' => 'dl',593 'group' => 'deep_linking_settings',594 'claim' => 'can_confirm',595 'isarray' => false596 ],597 'content_item_return_url' => [598 'suffix' => 'dl',599 'group' => 'deep_linking_settings',600 'claim' => 'deep_link_return_url',601 'isarray' => false602 ],603 'content_items' => [604 'suffix' => 'dl',605 'group' => '',606 'claim' => 'content_items',607 'isarray' => true608 ],609 'data' => [610 'suffix' => 'dl',611 'group' => 'deep_linking_settings',612 'claim' => 'data',613 'isarray' => false614 ],615 'text' => [616 'suffix' => 'dl',617 'group' => 'deep_linking_settings',618 'claim' => 'text',619 'isarray' => false620 ],621 'title' => [622 'suffix' => 'dl',623 'group' => 'deep_linking_settings',624 'claim' => 'title',625 'isarray' => false626 ],627 'lti_msg' => [628 'suffix' => 'dl',629 'group' => '',630 'claim' => 'msg',631 'isarray' => false632 ],633 'lti_log' => [634 'suffix' => 'dl',635 'group' => '',636 'claim' => 'log',637 'isarray' => false638 ],639 'lti_errormsg' => [640 'suffix' => 'dl',641 'group' => '',642 'claim' => 'errormsg',643 'isarray' => false644 ],645 'lti_errorlog' => [646 'suffix' => 'dl',647 'group' => '',648 'claim' => 'errorlog',649 'isarray' => false650 ],651 'context_id' => [652 'suffix' => '',653 'group' => 'context',654 'claim' => 'id',655 'isarray' => false656 ],657 'context_label' => [658 'suffix' => '',659 'group' => 'context',660 'claim' => 'label',661 'isarray' => false662 ],663 'context_title' => [664 'suffix' => '',665 'group' => 'context',666 'claim' => 'title',667 'isarray' => false668 ],669 'context_type' => [670 'suffix' => '',671 'group' => 'context',672 'claim' => 'type',673 'isarray' => true674 ],675 'lis_course_offering_sourcedid' => [676 'suffix' => '',677 'group' => 'lis',678 'claim' => 'course_offering_sourcedid',679 'isarray' => false680 ],681 'lis_course_section_sourcedid' => [682 'suffix' => '',683 'group' => 'lis',684 'claim' => 'course_section_sourcedid',685 'isarray' => false686 ],687 'launch_presentation_css_url' => [688 'suffix' => '',689 'group' => 'launch_presentation',690 'claim' => 'css_url',691 'isarray' => false692 ],693 'launch_presentation_document_target' => [694 'suffix' => '',695 'group' => 'launch_presentation',696 'claim' => 'document_target',697 'isarray' => false698 ],699 'launch_presentation_height' => [700 'suffix' => '',701 'group' => 'launch_presentation',702 'claim' => 'height',703 'isarray' => false704 ],705 'launch_presentation_locale' => [706 'suffix' => '',707 'group' => 'launch_presentation',708 'claim' => 'locale',709 'isarray' => false710 ],711 'launch_presentation_return_url' => [712 'suffix' => '',713 'group' => 'launch_presentation',714 'claim' => 'return_url',715 'isarray' => false716 ],717 'launch_presentation_width' => [718 'suffix' => '',719 'group' => 'launch_presentation',720 'claim' => 'width',721 'isarray' => false722 ],723 'lis_person_contact_email_primary' => [724 'suffix' => '',725 'group' => null,726 'claim' => 'email',727 'isarray' => false728 ],729 'lis_person_name_family' => [730 'suffix' => '',731 'group' => null,732 'claim' => 'family_name',733 'isarray' => false734 ],735 'lis_person_name_full' => [736 'suffix' => '',737 'group' => null,738 'claim' => 'name',739 'isarray' => false740 ],741 'lis_person_name_given' => [742 'suffix' => '',743 'group' => null,744 'claim' => 'given_name',745 'isarray' => false746 ],747 'lis_person_sourcedid' => [748 'suffix' => '',749 'group' => 'lis',750 'claim' => 'person_sourcedid',751 'isarray' => false752 ],753 'user_id' => [754 'suffix' => '',755 'group' => null,756 'claim' => 'sub',757 'isarray' => false758 ],759 'user_image' => [760 'suffix' => '',761 'group' => null,762 'claim' => 'picture',763 'isarray' => false764 ],765 'roles' => [766 'suffix' => '',767 'group' => '',768 'claim' => 'roles',769 'isarray' => true770 ],771 'role_scope_mentor' => [772 'suffix' => '',773 'group' => '',774 'claim' => 'role_scope_mentor',775 'isarray' => false776 ],777 'deployment_id' => [778 'suffix' => '',779 'group' => '',780 'claim' => 'deployment_id',781 'isarray' => false782 ],783 'lti_message_type' => [784 'suffix' => '',785 'group' => '',786 'claim' => 'message_type',787 'isarray' => false788 ],789 'lti_version' => [790 'suffix' => '',791 'group' => '',792 'claim' => 'version',793 'isarray' => false794 ],795 'resource_link_description' => [796 'suffix' => '',797 'group' => 'resource_link',798 'claim' => 'description',799 'isarray' => false800 ],801 'resource_link_id' => [802 'suffix' => '',803 'group' => 'resource_link',804 'claim' => 'id',805 'isarray' => false806 ],807 'resource_link_title' => [808 'suffix' => '',809 'group' => 'resource_link',810 'claim' => 'title',811 'isarray' => false812 ],813 'tool_consumer_info_product_family_code' => [814 'suffix' => '',815 'group' => 'tool_platform',816 'claim' => 'family_code',817 'isarray' => false818 ],819 'tool_consumer_info_version' => [820 'suffix' => '',821 'group' => 'tool_platform',822 'claim' => 'version',823 'isarray' => false824 ],825 'tool_consumer_instance_contact_email' => [826 'suffix' => '',827 'group' => 'tool_platform',828 'claim' => 'contact_email',829 'isarray' => false830 ],831 'tool_consumer_instance_description' => [832 'suffix' => '',833 'group' => 'tool_platform',834 'claim' => 'description',835 'isarray' => false836 ],837 'tool_consumer_instance_guid' => [838 'suffix' => '',839 'group' => 'tool_platform',840 'claim' => 'guid',841 'isarray' => false842 ],843 'tool_consumer_instance_name' => [844 'suffix' => '',845 'group' => 'tool_platform',846 'claim' => 'name',847 'isarray' => false848 ],849 'tool_consumer_instance_url' => [850 'suffix' => '',851 'group' => 'tool_platform',852 'claim' => 'url',853 'isarray' => false854 ],855 'custom_context_memberships_url' => [856 'suffix' => 'nrps',857 'group' => 'namesroleservice',858 'claim' => 'context_memberships_url',859 'isarray' => false860 ],861 'custom_context_memberships_versions' => [862 'suffix' => 'nrps',863 'group' => 'namesroleservice',864 'claim' => 'service_versions',865 'isarray' => true866 ],867 'custom_gradebookservices_scope' => [868 'suffix' => 'ags',869 'group' => 'endpoint',870 'claim' => 'scope',871 'isarray' => true872 ],873 'custom_lineitems_url' => [874 'suffix' => 'ags',875 'group' => 'endpoint',876 'claim' => 'lineitems',877 'isarray' => false878 ],879 'custom_lineitem_url' => [880 'suffix' => 'ags',881 'group' => 'endpoint',882 'claim' => 'lineitem',883 'isarray' => false884 ],885 'custom_results_url' => [886 'suffix' => 'ags',887 'group' => 'endpoint',888 'claim' => 'results',889 'isarray' => false890 ],891 'custom_result_url' => [892 'suffix' => 'ags',893 'group' => 'endpoint',894 'claim' => 'result',895 'isarray' => false896 ],897 'custom_scores_url' => [898 'suffix' => 'ags',899 'group' => 'endpoint',900 'claim' => 'scores',901 'isarray' => false902 ],903 'custom_score_url' => [904 'suffix' => 'ags',905 'group' => 'endpoint',906 'claim' => 'score',907 'isarray' => false908 ],909 'lis_outcome_service_url' => [910 'suffix' => 'bos',911 'group' => 'basicoutcomesservice',912 'claim' => 'lis_outcome_service_url',913 'isarray' => false914 ],915 'lis_result_sourcedid' => [916 'suffix' => 'bos',917 'group' => 'basicoutcomesservice',918 'claim' => 'lis_result_sourcedid',919 'isarray' => false920 ],921 ];922 $this->assertEquals($mapping, lti_get_jwt_claim_mapping());923 }924 /**925 * Test lti_build_standard_message().926 */927 public function test_lti_build_standard_message_institution_name_set() {928 global $CFG;929 $this->resetAfterTest();930 $CFG->mod_lti_institution_name = 'some institution name lols';931 $course = $this->getDataGenerator()->create_course();932 $instance = $this->getDataGenerator()->create_module('lti',933 [934 'course' => $course->id,935 ]936 );937 $message = lti_build_standard_message($instance, '2', LTI_VERSION_1);938 $this->assertEquals('moodle-2', $message['ext_lms']);939 $this->assertEquals('moodle', $message['tool_consumer_info_product_family_code']);940 $this->assertEquals(LTI_VERSION_1, $message['lti_version']);941 $this->assertEquals('basic-lti-launch-request', $message['lti_message_type']);942 $this->assertEquals('2', $message['tool_consumer_instance_guid']);943 $this->assertEquals('some institution name lols', $message['tool_consumer_instance_name']);944 $this->assertEquals('PHPUnit test site', $message['tool_consumer_instance_description']);945 }946 /**947 * Test lti_build_standard_message().948 */949 public function test_lti_build_standard_message_institution_name_not_set() {950 $this->resetAfterTest();951 $course = $this->getDataGenerator()->create_course();952 $instance = $this->getDataGenerator()->create_module('lti',953 [954 'course' => $course->id,955 ]956 );957 $message = lti_build_standard_message($instance, '2', LTI_VERSION_2);958 $this->assertEquals('moodle-2', $message['ext_lms']);959 $this->assertEquals('moodle', $message['tool_consumer_info_product_family_code']);960 $this->assertEquals(LTI_VERSION_2, $message['lti_version']);961 $this->assertEquals('basic-lti-launch-request', $message['lti_message_type']);962 $this->assertEquals('2', $message['tool_consumer_instance_guid']);963 $this->assertEquals('phpunit', $message['tool_consumer_instance_name']);964 $this->assertEquals('PHPUnit test site', $message['tool_consumer_instance_description']);965 }966 /**967 * Test lti_verify_jwt_signature().968 */969 public function test_lti_verify_jwt_signature() {970 $this->resetAfterTest();971 $this->setAdminUser();972 // Create a tool type, associated with that proxy.973 $type = new stdClass();974 $type->state = LTI_TOOL_STATE_CONFIGURED;975 $type->name = "Test tool";976 $type->description = "Example description";977 $type->baseurl = $this->getExternalTestFileUrl('/test.html');978 $config = new stdClass();979 $config->lti_publickey = '-----BEGIN PUBLIC KEY-----980MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnzyis1ZjfNB0bBgKFMSv981vkTtwlvBsaJq7S5wA+kzeVOVpVWwkWdVha4s38XM/pa/yr47av7+z3VTmvDRyAHc982aT92whREFpLv9cj5lTeJSibyr/Mrm/YtjCZVWgaOYIhwrXwKLqPr/11inWsAkfIy983tvHWTxZYEcXLgAXFuUuaS3uF9gEiNQwzGTU1v0FqkqTBr4B8nW3HCN47XUu0t8Y0984e+lf4s4OxQawWD79J9/5d3Ry0vbV3Am1FtGJiJvOwRsIfVChDpYStTcHTCMqtvWb985V6L11BWkpzGXSW4Hv43qa+GSYOD2QU68Mb59oSk2OB+BtOLpJofmbGEGgvmwyCI9986MwIDAQAB987-----END PUBLIC KEY-----';988 $typeid = lti_add_type($type, $config);989 lti_verify_jwt_signature($typeid, '', 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4g' .990 'RG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMn0.POstGetfAytaZS82wHcjoTyoqhMyxXiWdR7Nn7A29DNSl0EiXLdwJ6xC6AfgZWF1bOs' .991 'S_TuYI3OG85AmiExREkrS6tDfTQ2B3WXlrr-wp5AokiRbz3_oB4OxG-W9KcEEbDRcZc0nH3L7LzYptiy1PtAylQGxHTWZXtGz4ht0bAecBgmpdgXMgu' .992 'EIcoqPJ1n3pIWk_dUZegpqx0Lka21H6XxUTxiy8OcaarA8zdnPUnV6AmNP3ecFawIFYdvJB_cm-GvpCSbr8G8y_Mllj8f4x9nBH8pQux89_6gUY618iY' .993 'v7tuPWBFfEbLxtF2pZS6YC1aSfLQxeNe8djT9YjpvRZA');994 }995 /**996 * Test lti_verify_jwt_signature().997 */998 public function test_lti_verify_jwt_signature_with_lti2() {999 $this->resetAfterTest();1000 $this->setAdminUser();1001 // Create a tool proxy.1002 $proxy = mod_lti_external::create_tool_proxy('Test proxy', $this->getExternalTestFileUrl('/test.html'), array(), array());1003 // Create a tool type, associated with that proxy.1004 $type = new stdClass();1005 $type->state = LTI_TOOL_STATE_CONFIGURED;1006 $type->name = "Test tool";1007 $type->description = "Example description";1008 $type->toolproxyid = $proxy->id;1009 $type->baseurl = $this->getExternalTestFileUrl('/test.html');1010 $data = new stdClass();1011 $data->lti_contentitem = true;1012 $typeid = lti_add_type($type, $data);1013 $this->expectExceptionMessage('JWT security not supported with LTI 2');1014 lti_verify_jwt_signature($typeid, '', '');1015 }1016 /**1017 * Test lti_verify_jwt_signature().1018 */1019 public function test_lti_verify_jwt_signature_no_consumer_key() {1020 $this->resetAfterTest();1021 $this->setAdminUser();1022 // Create a tool type, associated with that proxy.1023 $type = new stdClass();1024 $type->state = LTI_TOOL_STATE_CONFIGURED;1025 $type->name = "Test tool";1026 $type->description = "Example description";1027 $type->clientid = 'consumerkey';1028 $type->baseurl = $this->getExternalTestFileUrl('/test.html');1029 $config = new stdClass();1030 $typeid = lti_add_type($type, $config);1031 $this->expectExceptionMessage(get_string('errorincorrectconsumerkey', 'mod_lti'));1032 lti_verify_jwt_signature($typeid, '', '');1033 }1034 /**1035 * Test lti_verify_jwt_signature().1036 */1037 public function test_lti_verify_jwt_signature_no_public_key() {1038 $this->resetAfterTest();1039 $this->setAdminUser();1040 // Create a tool type, associated with that proxy.1041 $type = new stdClass();1042 $type->state = LTI_TOOL_STATE_CONFIGURED;1043 $type->name = "Test tool";1044 $type->description = "Example description";1045 $type->clientid = 'consumerkey';1046 $type->baseurl = $this->getExternalTestFileUrl('/test.html');1047 $config = new stdClass();1048 $typeid = lti_add_type($type, $config);1049 $this->expectExceptionMessage('No public key configured');1050 lti_verify_jwt_signature($typeid, 'consumerkey', '');1051 }1052 /**1053 * Test lti_convert_content_items().1054 */1055 public function test_lti_convert_content_items() {1056 $contentitems = [];1057 $contentitems[] = [1058 'type' => 'ltiResourceLink',1059 'url' => 'http://example.com/messages/launch',1060 'title' => 'Test title',1061 'text' => 'Test text',1062 'frame' => []1063 ];1064 $contentitems = json_encode($contentitems);1065 $json = lti_convert_content_items($contentitems);1066 $jsondecode = json_decode($json);1067 $strcontext = '@context';1068 $strgraph = '@graph';1069 $strtype = '@type';1070 $objgraph = new stdClass();1071 $objgraph->url = 'http://example.com/messages/launch';1072 $objgraph->title = 'Test title';1073 $objgraph->text = 'Test text';1074 $objgraph->frame = [];1075 $objgraph->{$strtype} = 'LtiLinkItem';1076 $objgraph->mediaType = 'application\/vnd.ims.lti.v1.ltilink';1077 $expected = new stdClass();1078 $expected->{$strcontext} = 'http://purl.imsglobal.org/ctx/lti/v1/ContentItem';1079 $expected->{$strgraph} = [];1080 $expected->{$strgraph}[] = $objgraph;1081 $this->assertEquals($expected, $jsondecode);1082 }1083 /**1084 * Test lti_sign_jwt().1085 */1086 public function test_lti_sign_jwt() {1087 $this->resetAfterTest();1088 $this->setAdminUser();1089 // Create a tool type, associated with that proxy.1090 $type = new stdClass();1091 $type->state = LTI_TOOL_STATE_CONFIGURED;1092 $type->name = "Test tool";1093 $type->description = "Example description";1094 $type->clientid = 'consumerkey';1095 $type->baseurl = $this->getExternalTestFileUrl('/test.html');1096 $config = new stdClass();1097 $typeid = lti_add_type($type, $config);1098 $params = [];1099 $params['roles'] = 'urn:lti:role:ims/lis/testrole,' .1100 'urn:lti:instrole:ims/lis/testinstrole,' .1101 'urn:lti:sysrole:ims/lis/testsysrole,' .1102 'hi';1103 $params['accept_copy_advice'] = [1104 'suffix' => 'dl',1105 'group' => 'deep_linking_settings',1106 'claim' => 'accept_copy_advice',1107 'isarray' => false1108 ];1109 $params['lis_result_sourcedid'] = [1110 'suffix' => 'bos',1111 'group' => 'basicoutcomesservice',1112 'claim' => 'lis_result_sourcedid',1113 'isarray' => false1114 ];1115 $endpoint = 'https://www.example.com/moodle';1116 $oauthconsumerkey = 'consumerkey';1117 $nonce = '';1118 $jwt = lti_sign_jwt($params, $endpoint, $oauthconsumerkey, $typeid, $nonce);1119 $this->assertArrayHasKey('id_token', $jwt);1120 $this->assertNotEmpty($jwt['id_token']);1121 }1122 /**1123 * Test lti_convert_from_jwt()1124 */1125 public function test_lti_convert_from_jwt() {1126 $this->resetAfterTest();1127 $this->setAdminUser();1128 // Create a tool type, associated with that proxy.1129 $type = new stdClass();1130 $type->state = LTI_TOOL_STATE_CONFIGURED;1131 $type->name = "Test tool";1132 $type->description = "Example description";1133 $type->clientid = 'sso.example.com';1134 $type->baseurl = $this->getExternalTestFileUrl('/test.html');1135 $config = new stdClass();1136 $config->lti_publickey = '-----BEGIN PUBLIC KEY-----1137MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnzyis1ZjfNB0bBgKFMSv1138vkTtwlvBsaJq7S5wA+kzeVOVpVWwkWdVha4s38XM/pa/yr47av7+z3VTmvDRyAHc1139aT92whREFpLv9cj5lTeJSibyr/Mrm/YtjCZVWgaOYIhwrXwKLqPr/11inWsAkfIy1140tvHWTxZYEcXLgAXFuUuaS3uF9gEiNQwzGTU1v0FqkqTBr4B8nW3HCN47XUu0t8Y01141e+lf4s4OxQawWD79J9/5d3Ry0vbV3Am1FtGJiJvOwRsIfVChDpYStTcHTCMqtvWb1142V6L11BWkpzGXSW4Hv43qa+GSYOD2QU68Mb59oSk2OB+BtOLpJofmbGEGgvmwyCI91143MwIDAQAB1144-----END PUBLIC KEY-----';1145 $typeid = lti_add_type($type, $config);1146 $params = lti_convert_from_jwt($typeid, 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwib' .1147 'mFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMiwiaXNzIjoic3NvLmV4YW1wbGUuY29tIn0.XURVvEb5ueAvFsn-S9EB' .1148 'BSfKbsgUzfRQqmJ6evlrYdx7sXWoZXw1nYjaLTg-mawvBr7MVvrdG9qh6oN8OfkQ7bfMwiz4tjBMJ4B4q_sig5BDYIKwMNjZL5GGCBs89FQrgqZBhxw' .1149 '3exTjPBEn69__w40o0AhCsBohPMh0ZsAyHug5dhm8vIuOP667repUJzM8uKCD6L4bEL6vQE8EwU6WQOmfJ2SDmRs-1pFkiaFd6hmPn6AVX7ETtzQmlT' .1150 'X-nXe9weQjU1lH4AQG2Yfnn-7lS94bt6E76Zt-XndP3IY7W48EpnRfUK9Ff1fZlomT4MPahdNP1eP8gT2iMz7vYpCfmA');1151 $this->assertEquals('sso.example.com', $params['oauth_consumer_key']);1152 $this->assertEquals('John Doe', $params['lis_person_name_full']);1153 }1154 /**1155 * Test lti_get_permitted_service_scopes().1156 */1157 public function test_lti_get_permitted_service_scopes() {1158 $this->resetAfterTest();1159 $this->setAdminUser();1160 // Create a tool type, associated with that proxy.1161 $type = new stdClass();1162 $type->state = LTI_TOOL_STATE_CONFIGURED;1163 $type->name = "Test tool";1164 $type->description = "Example description";1165 $type->baseurl = $this->getExternalTestFileUrl('/test.html');1166 $typeconfig = new stdClass();1167 $typeconfig->lti_acceptgrades = true;1168 $typeid = lti_add_type($type, $typeconfig);1169 $tool = lti_get_type($typeid);1170 $config = lti_get_type_config($typeid);1171 $permittedscopes = lti_get_permitted_service_scopes($tool, $config);1172 $expected = [1173 'https://purl.imsglobal.org/spec/lti-bo/scope/basicoutcome'1174 ];1175 $this->assertEquals($expected, $permittedscopes);1176 }1177 /**1178 * Test get_tool_type_config().1179 */1180 public function test_get_tool_type_config() {1181 $this->resetAfterTest();1182 $this->setAdminUser();1183 // Create a tool type, associated with that proxy.1184 $type = new stdClass();1185 $type->state = LTI_TOOL_STATE_CONFIGURED;1186 $type->name = "Test tool";1187 $type->description = "Example description";1188 $type->clientid = "Test client ID";1189 $type->baseurl = $this->getExternalTestFileUrl('/test.html');1190 $config = new stdClass();1191 $typeid = lti_add_type($type, $config);1192 $type = lti_get_type($typeid);1193 $typeconfig = get_tool_type_config($type);1194 $this->assertEquals('https://www.example.com/moodle', $typeconfig['platformid']);1195 $this->assertEquals($type->clientid, $typeconfig['clientid']);1196 $this->assertEquals($typeid, $typeconfig['deploymentid']);1197 $this->assertEquals('https://www.example.com/moodle/mod/lti/certs.php', $typeconfig['publickeyseturl']);1198 $this->assertEquals('https://www.example.com/moodle/mod/lti/token.php', $typeconfig['accesstokenurl']);1199 $this->assertEquals('https://www.example.com/moodle/mod/lti/auth.php', $typeconfig['authrequesturl']);1200 }1201 /**1202 * Test lti_new_access_token().1203 */1204 public function test_lti_new_access_token() {1205 global $DB;1206 $this->resetAfterTest();1207 $this->setAdminUser();1208 // Create a tool type, associated with that proxy.1209 $type = new stdClass();1210 $type->state = LTI_TOOL_STATE_CONFIGURED;1211 $type->name = "Test tool";1212 $type->description = "Example description";1213 $type->clientid = "Test client ID";1214 $type->baseurl = $this->getExternalTestFileUrl('/test.html');1215 $config = new stdClass();1216 $typeid = lti_add_type($type, $config);1217 $scopes = ['lti_some_scope', 'lti_another_scope'];1218 lti_new_access_token($typeid, $scopes);1219 $token = $DB->get_records('lti_access_tokens');1220 $this->assertEquals(1, count($token));1221 $token = reset($token);1222 $this->assertEquals($typeid, $token->typeid);1223 $this->assertEquals(json_encode(array_values($scopes)), $token->scope);1224 $this->assertEquals($token->timecreated + LTI_ACCESS_TOKEN_LIFE, $token->validuntil);1225 $this->assertNull($token->lastaccess);1226 }1227}...

Full Screen

Full Screen

Token.php

Source:Token.php Github

copy

Full Screen

...34 * If token prototype is an array.35 *36 * @var bool37 */38 private $isArray;39 /**40 * Flag is token was changed.41 *42 * @var bool43 */44 private $changed = false;45 /**46 * @param array|string $token token prototype47 */48 public function __construct($token)49 {50 if (is_array($token)) {51 $this->isArray = true;52 $this->id = $token[0];53 $this->content = $token[1];54 if ($token[0] && '' === $token[1]) {55 throw new \InvalidArgumentException('Cannot set empty content for id-based Token.');56 }57 } elseif (is_string($token)) {58 $this->isArray = false;59 $this->content = $token;60 } else {61 throw new \InvalidArgumentException(sprintf(62 'Cannot recognize input value as valid Token prototype, got "%s".',63 is_object($token) ? get_class($token) : gettype($token)64 ));65 }66 }67 /**68 * @return int[]69 */70 public static function getCastTokenKinds()71 {72 static $castTokens = [T_ARRAY_CAST, T_BOOL_CAST, T_DOUBLE_CAST, T_INT_CAST, T_OBJECT_CAST, T_STRING_CAST, T_UNSET_CAST];73 return $castTokens;74 }75 /**76 * Get classy tokens kinds: T_CLASS, T_INTERFACE and T_TRAIT.77 *78 * @return int[]79 */80 public static function getClassyTokenKinds()81 {82 static $classTokens = [T_CLASS, T_TRAIT, T_INTERFACE];83 return $classTokens;84 }85 /**86 * Clear token at given index.87 *88 * Clearing means override token by empty string.89 *90 * @deprecated since 2.491 */92 public function clear()93 {94 @trigger_error(__METHOD__.' is deprecated and will be removed in 3.0.', E_USER_DEPRECATED);95 Tokens::setLegacyMode(true);96 $this->content = '';97 $this->id = null;98 $this->isArray = false;99 }100 /**101 * Clear internal flag if token was changed.102 *103 * @deprecated since 2.4104 */105 public function clearChanged()106 {107 @trigger_error(__METHOD__.' is deprecated and will be removed in 3.0.', E_USER_DEPRECATED);108 Tokens::setLegacyMode(true);109 $this->changed = false;110 }111 /**112 * Check if token is equals to given one.113 *114 * If tokens are arrays, then only keys defined in parameter token are checked.115 *116 * @param array|string|Token $other token or it's prototype117 * @param bool $caseSensitive perform a case sensitive comparison118 *119 * @return bool120 */121 public function equals($other, $caseSensitive = true)122 {123 $otherPrototype = $other instanceof self ? $other->getPrototype() : $other;124 if ($this->isArray !== is_array($otherPrototype)) {125 return false;126 }127 if (!$this->isArray) {128 return $this->content === $otherPrototype;129 }130 if (array_key_exists(0, $otherPrototype) && $this->id !== $otherPrototype[0]) {131 return false;132 }133 if (array_key_exists(1, $otherPrototype)) {134 if ($caseSensitive) {135 if ($this->content !== $otherPrototype[1]) {136 return false;137 }138 } elseif (0 !== strcasecmp($this->content, $otherPrototype[1])) {139 return false;140 }141 }142 // detect unknown keys143 unset($otherPrototype[0], $otherPrototype[1]);144 return empty($otherPrototype);145 }146 /**147 * Check if token is equals to one of given.148 *149 * @param array $others array of tokens or token prototypes150 * @param bool $caseSensitive perform a case sensitive comparison151 *152 * @return bool153 */154 public function equalsAny(array $others, $caseSensitive = true)155 {156 foreach ($others as $other) {157 if ($this->equals($other, $caseSensitive)) {158 return true;159 }160 }161 return false;162 }163 /**164 * A helper method used to find out whether or not a certain input token has to be case-sensitively matched.165 *166 * @param array<int, bool>|bool $caseSensitive global case sensitiveness or an array of booleans, whose keys should match167 * the ones used in $others. If any is missing, the default case-sensitive168 * comparison is used169 * @param int $key the key of the token that has to be looked up170 *171 * @return bool172 */173 public static function isKeyCaseSensitive($caseSensitive, $key)174 {175 if (is_array($caseSensitive)) {176 return isset($caseSensitive[$key]) ? $caseSensitive[$key] : true;177 }178 return $caseSensitive;179 }180 /**181 * @return array|string token prototype182 */183 public function getPrototype()184 {185 if (!$this->isArray) {186 return $this->content;187 }188 return [189 $this->id,190 $this->content,191 ];192 }193 /**194 * Get token's content.195 *196 * It shall be used only for getting the content of token, not for checking it against excepted value.197 *198 * @return string199 */200 public function getContent()201 {202 return $this->content;203 }204 /**205 * Get token's id.206 *207 * It shall be used only for getting the internal id of token, not for checking it against excepted value.208 *209 * @return null|int210 */211 public function getId()212 {213 return $this->id;214 }215 /**216 * Get token's name.217 *218 * It shall be used only for getting the name of token, not for checking it against excepted value.219 *220 * @return null|string token name221 */222 public function getName()223 {224 if (null === $this->id) {225 return null;226 }227 return self::getNameForId($this->id);228 }229 /**230 * Get token's name.231 *232 * It shall be used only for getting the name of token, not for checking it against excepted value.233 *234 * @param int $id235 *236 * @return null|string token name237 */238 public static function getNameForId($id)239 {240 if (CT::has($id)) {241 return CT::getName($id);242 }243 $name = token_name($id);244 return 'UNKNOWN' === $name ? null : $name;245 }246 /**247 * Generate array containing all keywords that exists in PHP version in use.248 *249 * @return array<int, int>250 */251 public static function getKeywords()252 {253 static $keywords = null;254 if (null === $keywords) {255 $keywords = self::getTokenKindsForNames(['T_ABSTRACT', 'T_ARRAY', 'T_AS', 'T_BREAK', 'T_CALLABLE', 'T_CASE',256 'T_CATCH', 'T_CLASS', 'T_CLONE', 'T_CONST', 'T_CONTINUE', 'T_DECLARE', 'T_DEFAULT', 'T_DO',257 'T_ECHO', 'T_ELSE', 'T_ELSEIF', 'T_EMPTY', 'T_ENDDECLARE', 'T_ENDFOR', 'T_ENDFOREACH',258 'T_ENDIF', 'T_ENDSWITCH', 'T_ENDWHILE', 'T_EVAL', 'T_EXIT', 'T_EXTENDS', 'T_FINAL',259 'T_FINALLY', 'T_FOR', 'T_FOREACH', 'T_FUNCTION', 'T_GLOBAL', 'T_GOTO', 'T_HALT_COMPILER',260 'T_IF', 'T_IMPLEMENTS', 'T_INCLUDE', 'T_INCLUDE_ONCE', 'T_INSTANCEOF', 'T_INSTEADOF',261 'T_INTERFACE', 'T_ISSET', 'T_LIST', 'T_LOGICAL_AND', 'T_LOGICAL_OR', 'T_LOGICAL_XOR',262 'T_NAMESPACE', 'T_NEW', 'T_PRINT', 'T_PRIVATE', 'T_PROTECTED', 'T_PUBLIC', 'T_REQUIRE',263 'T_REQUIRE_ONCE', 'T_RETURN', 'T_STATIC', 'T_SWITCH', 'T_THROW', 'T_TRAIT', 'T_TRY',264 'T_UNSET', 'T_USE', 'T_VAR', 'T_WHILE', 'T_YIELD',265 ]) + [266 CT::T_ARRAY_TYPEHINT => CT::T_ARRAY_TYPEHINT,267 CT::T_CLASS_CONSTANT => CT::T_CLASS_CONSTANT,268 CT::T_CONST_IMPORT => CT::T_CONST_IMPORT,269 CT::T_FUNCTION_IMPORT => CT::T_FUNCTION_IMPORT,270 CT::T_NAMESPACE_OPERATOR => CT::T_NAMESPACE_OPERATOR,271 CT::T_USE_TRAIT => CT::T_USE_TRAIT,272 CT::T_USE_LAMBDA => CT::T_USE_LAMBDA,273 ];274 }275 return $keywords;276 }277 /**278 * Generate array containing all predefined constants that exists in PHP version in use.279 *280 * @see http://php.net/manual/en/language.constants.predefined.php281 *282 * @return array<int, int>283 */284 public static function getMagicConstants()285 {286 static $magicConstants = null;287 if (null === $magicConstants) {288 $magicConstants = self::getTokenKindsForNames(['T_CLASS_C', 'T_DIR', 'T_FILE', 'T_FUNC_C', 'T_LINE', 'T_METHOD_C', 'T_NS_C', 'T_TRAIT_C']);289 }290 return $magicConstants;291 }292 /**293 * Check if token prototype is an array.294 *295 * @return bool is array296 */297 public function isArray()298 {299 return $this->isArray;300 }301 /**302 * Check if token is one of type cast tokens.303 *304 * @return bool305 */306 public function isCast()307 {308 return $this->isGivenKind(self::getCastTokenKinds());309 }310 /**311 * Check if token was changed.312 *313 * @return bool314 *315 * @deprecated since 2.4316 */317 public function isChanged()318 {319 @trigger_error(__METHOD__.' is deprecated and will be removed in 3.0.', E_USER_DEPRECATED);320 return $this->changed;321 }322 /**323 * Check if token is one of classy tokens: T_CLASS, T_INTERFACE or T_TRAIT.324 *325 * @return bool326 */327 public function isClassy()328 {329 return $this->isGivenKind(self::getClassyTokenKinds());330 }331 /**332 * Check if token is one of comment tokens: T_COMMENT or T_DOC_COMMENT.333 *334 * @return bool335 */336 public function isComment()337 {338 static $commentTokens = [T_COMMENT, T_DOC_COMMENT];339 return $this->isGivenKind($commentTokens);340 }341 /**342 * Check if token is empty, e.g. because of clearing.343 *344 * @return bool345 *346 * @deprecated since 2.4347 */348 public function isEmpty()349 {350 @trigger_error(__METHOD__.' is deprecated and will be removed in 3.0.', E_USER_DEPRECATED);351 return null === $this->id && ('' === $this->content || null === $this->content);352 }353 /**354 * Check if token is one of given kind.355 *356 * @param int|int[] $possibleKind kind or array of kinds357 *358 * @return bool359 */360 public function isGivenKind($possibleKind)361 {362 return $this->isArray && (is_array($possibleKind) ? in_array($this->id, $possibleKind, true) : $this->id === $possibleKind);363 }364 /**365 * Check if token is a keyword.366 *367 * @return bool368 */369 public function isKeyword()370 {371 $keywords = static::getKeywords();372 return $this->isArray && isset($keywords[$this->id]);373 }374 /**375 * Check if token is a native PHP constant: true, false or null.376 *377 * @return bool378 */379 public function isNativeConstant()380 {381 static $nativeConstantStrings = ['true', 'false', 'null'];382 return $this->isArray && in_array(strtolower($this->content), $nativeConstantStrings, true);383 }384 /**385 * Returns if the token is of a Magic constants type.386 *387 * @see http://php.net/manual/en/language.constants.predefined.php388 *389 * @return bool390 */391 public function isMagicConstant()392 {393 $magicConstants = static::getMagicConstants();394 return $this->isArray && isset($magicConstants[$this->id]);395 }396 /**397 * Check if token is a whitespace.398 *399 * @param null|string $whitespaces whitespaces characters, default is " \t\n\r\0\x0B"400 *401 * @return bool402 */403 public function isWhitespace($whitespaces = " \t\n\r\0\x0B")404 {405 if (null === $whitespaces) {406 $whitespaces = " \t\n\r\0\x0B";407 }408 if ($this->isArray && !$this->isGivenKind(T_WHITESPACE)) {409 return false;410 }411 return '' === trim($this->content, $whitespaces);412 }413 /**414 * Override token.415 *416 * If called on Token inside Tokens collection please use `Tokens::overrideAt` instead.417 *418 * @param array|string|Token $other token prototype419 *420 * @deprecated since 2.4421 */422 public function override($other)423 {424 @trigger_error(__METHOD__.' is deprecated and will be removed in 3.0.', E_USER_DEPRECATED);425 Tokens::setLegacyMode(true);426 $prototype = $other instanceof self ? $other->getPrototype() : $other;427 if ($this->equals($prototype)) {428 return;429 }430 $this->changed = true;431 if (is_array($prototype)) {432 $this->isArray = true;433 $this->id = $prototype[0];434 $this->content = $prototype[1];435 return;436 }437 $this->isArray = false;438 $this->id = null;439 $this->content = $prototype;440 }441 /**442 * @param string $content443 *444 * @deprecated since 2.4445 */446 public function setContent($content)447 {448 @trigger_error(__METHOD__.' is deprecated and will be removed in 3.0.', E_USER_DEPRECATED);449 Tokens::setLegacyMode(true);450 if ($this->content === $content) {451 return;452 }453 $this->changed = true;454 $this->content = $content;455 // setting empty content is clearing the token456 if ('' === $content) {457 @trigger_error(__METHOD__.' shall not be used to clear token, use Tokens::clearAt instead.', E_USER_DEPRECATED);458 $this->id = null;459 $this->isArray = false;460 }461 }462 public function toArray()463 {464 return [465 'id' => $this->id,466 'name' => $this->getName(),467 'content' => $this->content,468 'isArray' => $this->isArray,469 'changed' => $this->changed,470 ];471 }472 /**473 * @param null|string[] $options JSON encode option474 *475 * @return string476 */477 public function toJson(array $options = null)478 {479 static $defaultOptions = null;480 if (null === $options) {481 if (null === $defaultOptions) {482 $defaultOptions = Utils::calculateBitmask(['JSON_PRETTY_PRINT', 'JSON_NUMERIC_CHECK']);...

Full Screen

Full Screen

isArray

Using AI Code Generation

copy

Full Screen

1$array = array(1,2,3,4,5,6);2$object = new for();3$object->isArray($array);4$array = array(1,2,3,4,5,6);5$object = new for();6$object->isArray($array);7$array = array(1,2,3,4,5,6);8$object = new for();9$object->isArray($array);10$array = array(1,2,3,4,5,6);11$object = new for();12$object->isArray($array);13$array = array(1,2,3,4,5,6);14$object = new for();15$object->isArray($array);16$array = array(1,2,3,4,5,6);17$object = new for();18$object->isArray($array);19$array = array(1,2,3,4,5,6);20$object = new for();21$object->isArray($array);22$array = array(1,2,3,4,5,6);23$object = new for();24$object->isArray($array);25$array = array(1,2,3,4,5,6);26$object = new for();27$object->isArray($array);28$array = array(1,2,3,4,5,6);29$object = new for();30$object->isArray($array);31$array = array(1,2,3,4,5,6);32$object = new for();33$object->isArray($array);

Full Screen

Full Screen

isArray

Using AI Code Generation

copy

Full Screen

1echo "is array? " . isArray($arr) . "2";3echo "is array? " . isArray($arr2) . "4";5echo "is array? " . isArray($arr3) . "6";7echo "is array? " . isArray($arr4) . "8";9echo "is array? " . isArray($arr5) . "10";11echo "is array? " . isArray($arr6) . "12";13echo "is array? " . isArray($arr7) . "14";15echo "is array? " . isArray($arr8) . "16";17echo "is array? " . isArray($arr9) . "18";19echo "is array? " . isArray($arr10) . "20";21echo "is array? " . isArray($arr11) . "22";23echo "is array? " . isArray($arr12) . "24";25echo "is array? " . isArray($arr13) . "26";27echo "is array? " . isArray($arr14) . "28";29echo "is array? " . isArray($arr15) . "30";31echo "is array? " . isArray($arr16) . "32";33echo "is array? " . isArray($arr17) . "34";35echo "is array? " . isArray($arr18) . "36";37echo "is array? " . isArray($arr19) . "38";39echo "is array? " . isArray($arr20) . "40";41echo "is array? " . isArray($arr21) . "42";43echo "is array? " . isArray($arr22) . "44";45echo "is array? " . isArray($arr23) . "46";47echo "is array? " . isArray($arr24) . "48";49echo "is array? " . isArray($arr25) . "50";51echo "is array? " . isArray($arr26) . "52";53echo "is array? " . isArray($arr27) . "54";55echo "is array? " . isArray($arr28) . "56";57echo "is array? " . isArray($arr29) . "58";59echo "is array? " . isArray($arr30) . "60";61echo "is array? " . isArray($arr31) . "62";63echo "is array? " . isArray($arr32) . "64";65echo "is array? " . isArray($arr33) . "66";

Full Screen

Full Screen

isArray

Using AI Code Generation

copy

Full Screen

1include('ArrayClass.php');2$array = new ArrayClass();3$array->isArray(array(1,2,3,4,5,6,7,8,9,10));4$array->isArray(array(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20));5include('ArrayClass.php');6$array = new ArrayClass();7$array->isNotArray(array(1,2,3,4,5,6,7,8,9,10));8$array->isNotArray(array(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20));9include('ArrayClass.php');10$array = new ArrayClass();11$array->isAssoc(array(1,2,3,4,5,6,7,8,9,10));12$array->isAssoc(array(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20));13include('ArrayClass.php');14$array = new ArrayClass();15$array->isNotAssoc(array(1,2,3,4,5,6,7,8,9,10));16$array->isNotAssoc(array(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20));17include('ArrayClass.php');18$array = new ArrayClass();19$array->isMulti(array(1,2,3,4,5,6,7,8,9,10));20$array->isMulti(array(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20));

Full Screen

Full Screen

isArray

Using AI Code Generation

copy

Full Screen

1$array = array(1,2,3,4,5);2if (is_array($array)) {3 echo "It is an array";4} else {5 echo "It is not an array";6}7is_array() function8is_array(variable)9$array = array(1,2,3,4,5);10if (is_array($array)) {11 echo "It is an array";12} else {13 echo "It is not an array";14}

Full Screen

Full Screen

isArray

Using AI Code Generation

copy

Full Screen

1$myArray = array();2$myArray = array('a', 'b', 'c');3$myArray = array(1, 2, 3);4$myArray = array('a', 2, 'c');5$myArray = array('a', 2, 'c', 5, 6, 7);6$myArray = array(1, 2, 3, 4, 5, 6, 7);7$myArray = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);8$myArray = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50);9$myArray = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11);10$myArray = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50);11$myArray = array(1, 2, 3, 4,

Full Screen

Full Screen

isArray

Using AI Code Generation

copy

Full Screen

1$array = new Array();2$arr = array(1,2,3,4,5,6);3if($array->isArray($arr))4{5echo "It is array";6}7{8echo "It is not array";9}10Related Posts: PHP | Array_change_key_case() function11PHP | Array_chunk() function12PHP | Array_column() function13PHP | Array_combine() function14PHP | Array_count_values() function15PHP | Array_diff() function16PHP | Array_diff_assoc() function17PHP | Array_diff_key() function18PHP | Array_diff_uassoc() function19PHP | Array_diff_ukey() function20PHP | Array_fill() function21PHP | Array_fill_keys() function22PHP | Array_filter() function23PHP | Array_flip() function24PHP | Array_intersect() function25PHP | Array_intersect_assoc() function26PHP | Array_intersect_key() function27PHP | Array_intersect_uassoc() function28PHP | Array_intersect_ukey() function29PHP | Array_key_exists() function30PHP | Array_keys() function31PHP | Array_map() function32PHP | Array_merge() function33PHP | Array_merge_recursive() function34PHP | Array_multisort() function35PHP | Array_pad() function36PHP | Array_pop() function37PHP | Array_product() function38PHP | Array_push() function39PHP | Array_rand() function40PHP | Array_reduce() function41PHP | Array_replace() function42PHP | Array_replace_recursive() function43PHP | Array_reverse() function44PHP | Array_search() function45PHP | Array_shift() function46PHP | Array_slice() function47PHP | Array_splice() function48PHP | Array_sum() function49PHP | Array_udiff() function50PHP | Array_udiff_assoc() function51PHP | Array_udiff_uassoc() function52PHP | Array_uintersect() function53PHP | Array_uintersect_assoc() function54PHP | Array_uintersect_uassoc() function55PHP | Array_unique() function56PHP | Array_unshift() function57PHP | Array_values() function58PHP | Array_walk() function59PHP | Array_walk_recursive() function60PHP | Array() function61PHP | ArrayObject::append() function

Full Screen

Full Screen

isArray

Using AI Code Generation

copy

Full Screen

1$obj = new for();2$arr = array(1,2,3,4,5);3echo $obj->isArray($arr);4{5}6{7function display()8{9echo "This is parent class";10}11}12{13function display()14{15echo "This is child class";16}17}18$obj = new childClass();19$obj->display();20{21function method_name()22{23}24}25{26function method_name()27{28}29}30{31function display()32{33echo "This is parent class";34}35}36{37function display()38{39echo "This is child class";40}41}42$obj = new childClass();43$obj->display();44{45abstract function display();46}47{48function display()49{50echo "This is child class";51}52}53$obj = new childClass();54$obj->display();

Full Screen

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run Mockery automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Trigger isArray code on LambdaTest Cloud Grid

Execute automation tests with isArray on a cloud-based Grid of 3000+ real browsers and operating systems for both web and mobile applications.

Test now for Free

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful