diff --git a/admin/tool/usertours/classes/local/target/block.php b/admin/tool/usertours/classes/local/target/block.php index 3f38f0a9062..095e9018c4c 100644 --- a/admin/tool/usertours/classes/local/target/block.php +++ b/admin/tool/usertours/classes/local/target/block.php @@ -102,7 +102,7 @@ class block extends base { */ public static function add_disabled_constraints_to_form(\MoodleQuickForm $mform) { $mform->hideIf('targetvalue_block', 'targettype', 'noteq', - \tool_usertours\target::get_target_constant_for_class(get_class())); + \tool_usertours\target::get_target_constant_for_class(self::class)); } /** diff --git a/admin/tool/usertours/classes/local/target/selector.php b/admin/tool/usertours/classes/local/target/selector.php index 3e3fd58c325..b0cc92682f0 100644 --- a/admin/tool/usertours/classes/local/target/selector.php +++ b/admin/tool/usertours/classes/local/target/selector.php @@ -92,7 +92,7 @@ class selector extends base { */ public static function add_disabled_constraints_to_form(\MoodleQuickForm $mform) { $mform->hideIf('targetvalue_selector', 'targettype', 'noteq', - \tool_usertours\target::get_target_constant_for_class(get_class())); + \tool_usertours\target::get_target_constant_for_class(self::class)); } /** diff --git a/admin/tool/usertours/classes/local/target/unattached.php b/admin/tool/usertours/classes/local/target/unattached.php index 696efe57241..316fdea4b85 100644 --- a/admin/tool/usertours/classes/local/target/unattached.php +++ b/admin/tool/usertours/classes/local/target/unattached.php @@ -81,7 +81,7 @@ class unattached extends base { * @param MoodleQuickForm $mform The form to add configuration to. */ public static function add_disabled_constraints_to_form(\MoodleQuickForm $mform) { - $myvalue = \tool_usertours\target::get_target_constant_for_class(get_class()); + $myvalue = \tool_usertours\target::get_target_constant_for_class(self::class); foreach (array_keys(self::$forcedsettings) as $settingname) { $mform->hideIf($settingname, 'targettype', 'eq', $myvalue); diff --git a/course/lib.php b/course/lib.php index 72b0b637d16..03cb1e1dda8 100644 --- a/course/lib.php +++ b/course/lib.php @@ -639,7 +639,7 @@ function course_add_cm_to_section($courseorid, $cmid, $sectionnum, $beforemod = $modarray = explode(",", trim($section->sequence)); if (empty($section->sequence)) { $newsequence = "$cmid"; - } else if ($beforemod && ($key = array_keys($modarray, $beforemod))) { + } else if ($beforemod && ($key = moodle_array_keys_filter($modarray, $beforemod))) { $insertarray = array($cmid, $beforemod); array_splice($modarray, $key[0], 1, $insertarray); $newsequence = implode(",", $modarray); @@ -1111,7 +1111,7 @@ function delete_mod_from_section($modid, $sectionid) { $modarray = explode(",", $section->sequence); - if ($key = array_keys ($modarray, $modid)) { + if ($key = moodle_array_keys_filter($modarray, $modid)) { array_splice($modarray, $key[0], 1); $newsequence = implode(",", $modarray); $DB->set_field("course_sections", "sequence", $newsequence, array("id"=>$section->id)); diff --git a/files/classes/converter.php b/files/classes/converter.php index da8c5ba0cbd..46b501c878a 100644 --- a/files/classes/converter.php +++ b/files/classes/converter.php @@ -165,7 +165,7 @@ class converter { */ protected function get_next_converter($converters, $currentconverter = null) { if ($currentconverter) { - $keys = array_keys($converters, $currentconverter); + $keys = moodle_array_keys_filter($converters, $currentconverter); $key = $keys[0]; if (isset($converters[$key + 1])) { return $converters[$key + 1]; diff --git a/lib/classes/session/database.php b/lib/classes/session/database.php index c8c842fcf7b..6b15884018b 100644 --- a/lib/classes/session/database.php +++ b/lib/classes/session/database.php @@ -24,7 +24,7 @@ namespace core\session; -defined('MOODLE_INTERNAL') || die(); +use SessionHandlerInterface; /** * Database based session handler. @@ -33,7 +33,7 @@ defined('MOODLE_INTERNAL') || die(); * @copyright 2013 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class database extends handler { +class database extends handler implements SessionHandlerInterface { /** @var \stdClass $record session record */ protected $recordid = null; @@ -70,12 +70,7 @@ class database extends handler { throw new exception('sessionhandlerproblem', 'error', '', null, 'Database does not support session locking'); } - $result = session_set_save_handler(array($this, 'handler_open'), - array($this, 'handler_close'), - array($this, 'handler_read'), - array($this, 'handler_write'), - array($this, 'handler_destroy'), - array($this, 'handler_gc')); + $result = session_set_save_handler($this); if (!$result) { throw new exception('dbsessionhandlerproblem', 'error'); } @@ -117,11 +112,11 @@ class database extends handler { * * {@see http://php.net/manual/en/function.session-set-save-handler.php} * - * @param string $save_path - * @param string $session_name + * @param string $path + * @param string $name * @return bool success */ - public function handler_open($save_path, $session_name) { + public function open(string $path, string $name): bool { // Note: we use the already open database. return true; } @@ -133,7 +128,7 @@ class database extends handler { * * @return bool success */ - public function handler_close() { + public function close(): bool { if ($this->recordid) { try { $this->database->release_session_lock($this->recordid); @@ -152,9 +147,9 @@ class database extends handler { * {@see http://php.net/manual/en/function.session-set-save-handler.php} * * @param string $sid - * @return string + * @return string|false */ - public function handler_read($sid) { + public function read(string $sid): string|false { try { if (!$record = $this->database->get_record('sessions', array('sid'=>$sid), 'id')) { // Let's cheat and skip locking if this is the first access, @@ -221,17 +216,18 @@ class database extends handler { * NOTE: Do not write to output or throw any exceptions! * Hopefully the next page is going to display nice error or it recovers... * - * @param string $sid - * @param string $session_data + * @param string $id + * @param string $data * @return bool success */ - public function handler_write($sid, $session_data) { + public function write(string $id, string $data): bool { if ($this->failed) { // Do not write anything back - we failed to start the session properly. return false; } - $sessdata = base64_encode($session_data); // There might be some binary mess :-( + // There might be some binary mess. + $sessdata = base64_encode($data); $hash = sha1($sessdata); if ($hash === $this->lasthash) { @@ -240,14 +236,17 @@ class database extends handler { try { if ($this->recordid) { - $this->database->set_field('sessions', 'sessdata', $sessdata, array('id'=>$this->recordid)); + $this->database->set_field('sessions', 'sessdata', $sessdata, ['id' => $this->recordid]); } else { // This happens in the first request when session record was just created in manager. - $this->database->set_field('sessions', 'sessdata', $sessdata, array('sid'=>$sid)); + $this->database->set_field('sessions', 'sessdata', $sessdata, ['sid' => $id]); } } catch (\Exception $ex) { // Do not rethrow exceptions here, this should not happen. - error_log('Unknown exception when writing database session data : '.$sid.' - '.$ex->getMessage()); + // phpcs:ignore moodle.PHP.ForbiddenFunctions.FoundWithAlternative + error_log( + "Unknown exception when writing database session data : {$id} - " . $ex->getMessage(), + ); } return true; @@ -258,19 +257,19 @@ class database extends handler { * * {@see http://php.net/manual/en/function.session-set-save-handler.php} * - * @param string $sid + * @param string $id * @return bool success */ - public function handler_destroy($sid) { - if (!$session = $this->database->get_record('sessions', array('sid'=>$sid), 'id, sid')) { - if ($sid == session_id()) { + public function destroy(string $id): bool { + if (!$session = $this->database->get_record('sessions', ['sid' => $id], 'id, sid')) { + if ($id == session_id()) { $this->recordid = null; $this->lasthash = null; } return true; } - if ($this->recordid and $session->id == $this->recordid) { + if ($this->recordid && ($session->id == $this->recordid)) { try { $this->database->release_session_lock($this->recordid); } catch (\Exception $ex) { @@ -280,7 +279,7 @@ class database extends handler { $this->lasthash = null; } - $this->database->delete_records('sessions', array('id'=>$session->id)); + $this->database->delete_records('sessions', ['id' => $session->id]); return true; } @@ -290,16 +289,19 @@ class database extends handler { * * {@see http://php.net/manual/en/function.session-set-save-handler.php} * - * @param int $ignored_maxlifetime moodle uses special timeout rules + * @param int $max_lifetime moodle uses special timeout rules * @return bool success */ - public function handler_gc($ignored_maxlifetime) { + // phpcs:ignore moodle.NamingConventions.ValidVariableName.VariableNameUnderscore + public function gc(int $max_lifetime): int|false { // This should do something only if cron is not running properly... if (!$stalelifetime = ini_get('session.gc_maxlifetime')) { - return true; + return false; } - $params = array('purgebefore' => (time() - $stalelifetime)); + $params = ['purgebefore' => (time() - $stalelifetime)]; + $count = $this->database->count_records_select('sessions', 'userid = 0 AND timemodified < :purgebefore', $params); $this->database->delete_records_select('sessions', 'userid = 0 AND timemodified < :purgebefore', $params); - return true; + + return $count; } } diff --git a/lib/classes/session/redis.php b/lib/classes/session/redis.php index c3b623d78f2..b6b3cf95404 100644 --- a/lib/classes/session/redis.php +++ b/lib/classes/session/redis.php @@ -25,8 +25,7 @@ namespace core\session; use RedisException; - -defined('MOODLE_INTERNAL') || die(); +use SessionHandlerInterface; /** * Redis based session handler. @@ -39,7 +38,7 @@ defined('MOODLE_INTERNAL') || die(); * @copyright 2016 Russell Smith * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class redis extends handler { +class redis extends handler implements SessionHandlerInterface { /** * Compressor: none. */ @@ -204,12 +203,8 @@ class redis extends handler { $this->connection = new \Redis(); - $result = session_set_save_handler(array($this, 'handler_open'), - array($this, 'handler_close'), - array($this, 'handler_read'), - array($this, 'handler_write'), - array($this, 'handler_destroy'), - array($this, 'handler_gc')); + $result = session_set_save_handler($this); + if (!$result) { throw new exception('redissessionhandlerproblem', 'error'); } @@ -288,11 +283,11 @@ class redis extends handler { /** * Update our session search path to include session name when opened. * - * @param string $savepath unused session save path. (ignored) - * @param string $sessionname Session name for this session. (ignored) + * @param string $path unused session save path. (ignored) + * @param string $name Session name for this session. (ignored) * @return bool true always as we will succeed. */ - public function handler_open($savepath, $sessionname) { + public function open(string $path, string $name): bool { return true; } @@ -301,7 +296,7 @@ class redis extends handler { * * @return bool true on success. false on unable to unlock sessions. */ - public function handler_close() { + public function close(): bool { $this->lasthash = null; try { foreach ($this->locks as $id => $expirytime) { @@ -317,6 +312,7 @@ class redis extends handler { return true; } + /** * Read the session data from storage * @@ -325,7 +321,7 @@ class redis extends handler { * * @throws RedisException when we are unable to talk to the Redis server. */ - public function handler_read($id) { + public function read(string $id): string|false { try { if ($this->requires_write_lock()) { $this->lock_session($id); @@ -402,7 +398,7 @@ class redis extends handler { * @param string $data session data * @return bool true on write success, false on failure */ - public function handler_write($id, $data) { + public function write(string $id, string $data): bool { $hash = sha1(base64_encode($data)); @@ -438,7 +434,7 @@ class redis extends handler { * @param string $id the session id to destroy. * @return bool true if the session was deleted, false otherwise. */ - public function handler_destroy($id) { + public function destroy(string $id): bool { $this->lasthash = null; try { $this->connection->del($id); @@ -454,11 +450,12 @@ class redis extends handler { /** * Garbage collect sessions. We don't we any as Redis does it for us. * - * @param integer $maxlifetime All sessions older than this should be removed. + * @param integer $max_lifetime All sessions older than this should be removed. * @return bool true, as Redis handles expiry for us. */ - public function handler_gc($maxlifetime) { - return true; + // phpcs:ignore moodle.NamingConventions.ValidVariableName.VariableNameUnderscore + public function gc(int $max_lifetime): int|false { + return false; } /** @@ -601,7 +598,7 @@ class redis extends handler { $rs = $DB->get_recordset('sessions', array(), 'id DESC', 'id, sid'); foreach ($rs as $record) { - $this->handler_destroy($record->sid); + $this->destroy($record->sid); } $rs->close(); } @@ -616,6 +613,6 @@ class redis extends handler { return; } - $this->handler_destroy($sid); + $this->destroy($sid); } } diff --git a/lib/dml/tests/dml_read_slave_test.php b/lib/dml/tests/dml_read_slave_test.php index 4ded903cb7d..d0f04e0c09e 100644 --- a/lib/dml/tests/dml_read_slave_test.php +++ b/lib/dml/tests/dml_read_slave_test.php @@ -562,7 +562,7 @@ class dml_read_slave_test extends \base_testcase { $this->assertNull($DB->get_dbhwrite()); $session = new \core\session\database(); - $session->handler_read('dummy'); + $session->read('dummy'); $this->assertEquals(0, $DB->perf_get_reads_slave()); $this->assertTrue($DB->perf_get_reads() > 0); diff --git a/lib/google/readme_moodle.txt b/lib/google/readme_moodle.txt index 16d6f9104bb..7c7f007e020 100644 --- a/lib/google/readme_moodle.txt +++ b/lib/google/readme_moodle.txt @@ -53,6 +53,8 @@ Local changes (to reapply until upstream upgrades contain them): cd lib/google/src for file in `find . -name '*.php' `; do sed -i '/^class /i #[AllowDynamicProperties]' $file; done ``` + * MDL-46563 - PHP 8.3 compliance + - Converted use of `get_class()` to `static::class` Information ----------- diff --git a/lib/google/src/Google/Http/REST.php b/lib/google/src/Google/Http/REST.php index 2d91326f8d5..e3489d28240 100644 --- a/lib/google/src/Google/Http/REST.php +++ b/lib/google/src/Google/Http/REST.php @@ -40,7 +40,7 @@ class Google_Http_REST $runner = new Google_Task_Runner( $client, sprintf('%s %s', $req->getRequestMethod(), $req->getUrl()), - array(get_class(), 'doExecute'), + array(self::class, 'doExecute'), array($client, $req) ); diff --git a/lib/grade/grade_category.php b/lib/grade/grade_category.php index 88b4028f2a7..2494c7060f5 100644 --- a/lib/grade/grade_category.php +++ b/lib/grade/grade_category.php @@ -1097,7 +1097,7 @@ class grade_category extends grade_object { $freq = array_count_values($converted_grade_values); arsort($freq); // sort by frequency keeping keys $top = reset($freq); // highest frequency count - $modes = array_keys($freq, $top); // search for all modes (have the same highest count) + $modes = moodle_array_keys_filter($freq, $top); // Search for all modes (have the same highest count). rsort($modes, SORT_NUMERIC); // get highest mode $agg_grade = reset($modes); // Record the weights as used. diff --git a/lib/horde/framework/Horde/Imap/Client/Cache/Backend/Cache.php b/lib/horde/framework/Horde/Imap/Client/Cache/Backend/Cache.php index 378be889217..d8fa4fd116a 100644 --- a/lib/horde/framework/Horde/Imap/Client/Cache/Backend/Cache.php +++ b/lib/horde/framework/Horde/Imap/Client/Cache/Backend/Cache.php @@ -143,7 +143,7 @@ extends Horde_Imap_Client_Cache_Backend foreach (array_keys(array_flip($val['slice'])) as $slice) { $data = array(); - foreach (array_keys($s['s'], $slice) as $uid) { + foreach (moodle_array_keys_filter($s['s'], $slice) as $uid) { $data[$uid] = is_array($d[$uid]) ? serialize($d[$uid]) : $d[$uid]; @@ -297,7 +297,7 @@ extends Horde_Imap_Client_Cache_Backend foreach (array_unique($deleted) as $slice) { /* Get rid of slice if less than 10% of capacity. */ if (($slice != $slicemap['i']) && - ($slice_uids = array_keys($slicemap['s'], $slice)) && + ($slice_uids = moodle_array_keys_filter($slicemap['s'], $slice)) && ($this->_params['slicesize'] * 0.1) > count($slice_uids)) { $this->_toUpdate($mailbox, 'add', $slice_uids); $this->_cache->expire($this->_getCid($mailbox, $slice)); @@ -416,7 +416,7 @@ extends Horde_Imap_Client_Cache_Backend $ptr = &$this->_slicemap[$mailbox]; // Slice data is corrupt; remove from slicemap. - foreach (array_keys($ptr['s'], $slice) as $val) { + foreach (moodle_array_keys_filter($ptr['s'], $slice) as $val) { unset($ptr['s'][$val]); } diff --git a/lib/horde/readme_moodle.txt b/lib/horde/readme_moodle.txt index d7a1ff49203..a88a4258f63 100644 --- a/lib/horde/readme_moodle.txt +++ b/lib/horde/readme_moodle.txt @@ -16,6 +16,8 @@ Description of import of Horde libraries Notes: * 2023-01-20 Applied patch https://github.com/horde/Util/pull/10 * 2023-01-20 Horde/Mail is copied from https://github.com/bytestream/Mail/tree/v2.7.1 for PHP 8.1 compatibility +* MDL-79890: Calls to array_keys() passing a second parameter have been modified to call `moodle_array_keys_filter` instead for PHP 8.3 compat. + This change is not fed upstream as Horde appears abandoned. ==== #!/bin/sh diff --git a/lib/listlib.php b/lib/listlib.php index 26ca97a023a..38dae01a23a 100644 --- a/lib/listlib.php +++ b/lib/listlib.php @@ -628,7 +628,7 @@ abstract class list_item { */ public function create_children(&$records, &$children, $thisrecordid) { //keys where value is $thisrecordid - $thischildren = array_keys($children, $thisrecordid); + $thischildren = moodle_array_keys_filter($children, $thisrecordid); foreach ($thischildren as $child) { $thisclass = get_class($this); $newlistitem = new $thisclass($records[$child], $this->children, $this->attributes); diff --git a/lib/moodlelib.php b/lib/moodlelib.php index 9c7476030b3..11a7ebf1cea 100644 --- a/lib/moodlelib.php +++ b/lib/moodlelib.php @@ -11039,3 +11039,30 @@ function site_is_public() { function exceeds_password_length(string $password, int $pepperlength = 0): bool { return (strlen($password) > (MAX_PASSWORD_CHARACTERS + $pepperlength)); } + +/** + * A helper to replace PHP 8.3 usage of array_keys with two args. + * + * There is an indication that this will become a new method in PHP 8.4, but that has not happened yet. + * Therefore this non-polyfill has been created with a different naming convention. + * In the future it can be deprecated if a core PHP method is created. + * + * https://wiki.php.net/rfc/deprecate_functions_with_overloaded_signatures#array_keys + * + * @param array $array + * @param mixed $filter The value to filter on + * @param bool $strict Whether to apply a strit test with the filter + * @return array + */ +function moodle_array_keys_filter(array $array, mixed $filter, bool $strict = false): array { + return array_keys(array_filter( + $array, + function($value, $key) use ($filter, $strict): bool { + if ($strict) { + return $value === $filter; + } + return $value == $filter; + }, + ARRAY_FILTER_USE_BOTH, + )); +} diff --git a/lib/tests/accesslib_test.php b/lib/tests/accesslib_test.php index c610d8e58fe..ba4f0f143ac 100644 --- a/lib/tests/accesslib_test.php +++ b/lib/tests/accesslib_test.php @@ -1968,7 +1968,7 @@ class accesslib_test extends advanced_testcase { $mockedplugins->setAccessible(true); $plugins = $mockedplugins->getValue(); $plugins['fake'] = [$pluginname => "{$CFG->dirroot}/lib/tests/fixtures/fakeplugins/$pluginname"]; - $mockedplugins->setValue($plugins); + $mockedplugins->setValue(null, $plugins); update_capabilities('fake_access'); $this->resetDebugging(); // We have debugging messages here that we need to get rid of. // End of the component loader mock. diff --git a/lib/tests/moodlelib_test.php b/lib/tests/moodlelib_test.php index 21c4e56b1c9..90bb9f1ad60 100644 --- a/lib/tests/moodlelib_test.php +++ b/lib/tests/moodlelib_test.php @@ -5445,4 +5445,87 @@ EOT; $this->assertEquals($expected, is_proxybypass($url)); } + /** + * Test that the moodle_array_keys_filter method behaves in the same way + * that array_keys behaved before Moodle 8.3. + * + * @dataProvider moodle_array_keys_filter_provider + * @param array $array + * @param mixed $filter + * @param bool $strict + * @param array $expected + * @covers ::moodle_array_keys_filter + */ + public function test_moodle_array_keys_filter( + array $array, + mixed $filter, + bool $strict, + array $expected, + ): void { + $this->assertSame( + $expected, + moodle_array_keys_filter($array, $filter, $strict), + ); + } + + /** + * Data provider for moodle_array_keys_filter tests. + * + * @return array + */ + public static function moodle_array_keys_filter_provider(): array { + return [ + [['a', 'b', 'c'], 'b', false, [1]], + [ + [ + 'alpha' => 'a', + 'bravo' => 'b', + 'charlie' => 'c', + ], + 'b', + false, + ['bravo'], + ], + [ + [ + 'zero' => 0, + 'one' => 1, + 'true' => true, + ], + '1', + false, + ['one', 'true'], + ], + [ + [ + 'zero' => 0, + 'one' => 1, + 'true' => true, + ], + true, + false, + ['one', 'true'], + ], + [ + [ + 'zero' => 0, + 'one' => 1, + 'true' => true, + ], + true, + true, + ['true'], + ], + [ + [ + 'zero' => 0, + 'one' => 1, + 'true' => true, + ], + 1, + true, + ['one'], + ], + ]; + } } diff --git a/lib/tests/session_redis_test.php b/lib/tests/session_redis_test.php index b5d9253c5e8..a77a3375f00 100644 --- a/lib/tests/session_redis_test.php +++ b/lib/tests/session_redis_test.php @@ -113,24 +113,24 @@ class session_redis_test extends \advanced_testcase { $sess = new \core\session\redis(); $sess->set_requires_write_lock(false); $sess->init(); - $this->assertSame('', $sess->handler_read('sess1')); - $this->assertTrue($sess->handler_close()); + $this->assertSame('', $sess->read('sess1')); + $this->assertTrue($sess->close()); } public function test_normal_session_start_stop_works() { $sess = new \core\session\redis(); $sess->init(); $sess->set_requires_write_lock(true); - $this->assertTrue($sess->handler_open('Not used', 'Not used')); - $this->assertSame('', $sess->handler_read('sess1')); - $this->assertTrue($sess->handler_write('sess1', 'DATA')); - $this->assertTrue($sess->handler_close()); + $this->assertTrue($sess->open('Not used', 'Not used')); + $this->assertSame('', $sess->read('sess1')); + $this->assertTrue($sess->write('sess1', 'DATA')); + $this->assertTrue($sess->close()); // Read the session again to ensure locking did what it should. - $this->assertTrue($sess->handler_open('Not used', 'Not used')); - $this->assertSame('DATA', $sess->handler_read('sess1')); - $this->assertTrue($sess->handler_write('sess1', 'DATA-new')); - $this->assertTrue($sess->handler_close()); + $this->assertTrue($sess->open('Not used', 'Not used')); + $this->assertSame('DATA', $sess->read('sess1')); + $this->assertTrue($sess->write('sess1', 'DATA-new')); + $this->assertTrue($sess->close()); $this->assertSessionNoLocks(); } @@ -141,18 +141,18 @@ class session_redis_test extends \advanced_testcase { $sess = new \core\session\redis(); $sess->init(); - $this->assertTrue($sess->handler_write('sess1', 'DATA')); - $this->assertSame('DATA', $sess->handler_read('sess1')); - $this->assertTrue($sess->handler_close()); + $this->assertTrue($sess->write('sess1', 'DATA')); + $this->assertSame('DATA', $sess->read('sess1')); + $this->assertTrue($sess->close()); if (extension_loaded('zstd')) { $CFG->session_redis_compressor = \core\session\redis::COMPRESSION_ZSTD; $sess = new \core\session\redis(); $sess->init(); - $this->assertTrue($sess->handler_write('sess2', 'DATA')); - $this->assertSame('DATA', $sess->handler_read('sess2')); - $this->assertTrue($sess->handler_close()); + $this->assertTrue($sess->write('sess2', 'DATA')); + $this->assertSame('DATA', $sess->read('sess2')); + $this->assertTrue($sess->close()); } $CFG->session_redis_compressor = \core\session\redis::COMPRESSION_NONE; @@ -162,25 +162,25 @@ class session_redis_test extends \advanced_testcase { $sess = new \core\session\redis(); $sess->init(); $sess->set_requires_write_lock(true); - $this->assertTrue($sess->handler_open('Not used', 'Not used')); - $this->assertSame('', $sess->handler_read('sess1')); - $this->assertTrue($sess->handler_write('sess1', 'DATA')); - $this->assertTrue($sess->handler_close()); + $this->assertTrue($sess->open('Not used', 'Not used')); + $this->assertSame('', $sess->read('sess1')); + $this->assertTrue($sess->write('sess1', 'DATA')); + $this->assertTrue($sess->close()); // Sessions are not locked until they have been saved once. - $this->assertTrue($sess->handler_open('Not used', 'Not used')); - $this->assertSame('DATA', $sess->handler_read('sess1')); + $this->assertTrue($sess->open('Not used', 'Not used')); + $this->assertSame('DATA', $sess->read('sess1')); $sessblocked = new \core\session\redis(); $sessblocked->init(); $sessblocked->set_requires_write_lock(true); - $this->assertTrue($sessblocked->handler_open('Not used', 'Not used')); + $this->assertTrue($sessblocked->open('Not used', 'Not used')); // Trap the error log and send it to stdOut so we can expect output at the right times. $errorlog = tempnam(sys_get_temp_dir(), "rediserrorlog"); $this->iniSet('error_log', $errorlog); try { - $sessblocked->handler_read('sess1'); + $sessblocked->read('sess1'); $this->fail('Session lock must fail to be obtained.'); } catch (\core\session\exception $e) { $this->assertStringContainsString("Unable to obtain lock for session id sess1", $e->getMessage()); @@ -189,9 +189,9 @@ class session_redis_test extends \advanced_testcase { $this->assertStringContainsString('Cannot obtain session lock for sid: sess1', file_get_contents($errorlog)); } - $this->assertTrue($sessblocked->handler_close()); - $this->assertTrue($sess->handler_write('sess1', 'DATA-new')); - $this->assertTrue($sess->handler_close()); + $this->assertTrue($sessblocked->close()); + $this->assertTrue($sess->write('sess1', 'DATA-new')); + $this->assertTrue($sess->close()); $this->assertSessionNoLocks(); } @@ -199,8 +199,8 @@ class session_redis_test extends \advanced_testcase { $sess = new \core\session\redis(); $sess->init(); $sess->set_requires_write_lock(true); - $this->assertTrue($sess->handler_open('Not used', 'Not used')); - $this->assertTrue($sess->handler_destroy('sess-destroy')); + $this->assertTrue($sess->open('Not used', 'Not used')); + $this->assertTrue($sess->destroy('sess-destroy')); $this->assertSessionNoLocks(); } @@ -208,10 +208,10 @@ class session_redis_test extends \advanced_testcase { $sess = new \core\session\redis(); $sess->init(); $sess->set_requires_write_lock(true); - $this->assertTrue($sess->handler_open('Not used', 'Not used')); - $this->assertSame('', $sess->handler_read('sess-destroy')); - $this->assertTrue($sess->handler_destroy('sess-destroy')); - $this->assertTrue($sess->handler_close()); + $this->assertTrue($sess->open('Not used', 'Not used')); + $this->assertSame('', $sess->read('sess-destroy')); + $this->assertTrue($sess->destroy('sess-destroy')); + $this->assertTrue($sess->close()); $this->assertSessionNoLocks(); } @@ -224,36 +224,36 @@ class session_redis_test extends \advanced_testcase { $sess2->init(); // Initialize session 1. - $this->assertTrue($sess1->handler_open('Not used', 'Not used')); - $this->assertSame('', $sess1->handler_read('sess1')); - $this->assertTrue($sess1->handler_write('sess1', 'DATA')); - $this->assertTrue($sess1->handler_close()); + $this->assertTrue($sess1->open('Not used', 'Not used')); + $this->assertSame('', $sess1->read('sess1')); + $this->assertTrue($sess1->write('sess1', 'DATA')); + $this->assertTrue($sess1->close()); // Initialize session 2. - $this->assertTrue($sess2->handler_open('Not used', 'Not used')); - $this->assertSame('', $sess2->handler_read('sess2')); - $this->assertTrue($sess2->handler_write('sess2', 'DATA2')); - $this->assertTrue($sess2->handler_close()); + $this->assertTrue($sess2->open('Not used', 'Not used')); + $this->assertSame('', $sess2->read('sess2')); + $this->assertTrue($sess2->write('sess2', 'DATA2')); + $this->assertTrue($sess2->close()); // Open and read session 1 and 2. - $this->assertTrue($sess1->handler_open('Not used', 'Not used')); - $this->assertSame('DATA', $sess1->handler_read('sess1')); - $this->assertTrue($sess2->handler_open('Not used', 'Not used')); - $this->assertSame('DATA2', $sess2->handler_read('sess2')); + $this->assertTrue($sess1->open('Not used', 'Not used')); + $this->assertSame('DATA', $sess1->read('sess1')); + $this->assertTrue($sess2->open('Not used', 'Not used')); + $this->assertSame('DATA2', $sess2->read('sess2')); // Write both sessions. - $this->assertTrue($sess1->handler_write('sess1', 'DATAX')); - $this->assertTrue($sess2->handler_write('sess2', 'DATA2X')); + $this->assertTrue($sess1->write('sess1', 'DATAX')); + $this->assertTrue($sess2->write('sess2', 'DATA2X')); // Read both sessions. - $this->assertTrue($sess1->handler_open('Not used', 'Not used')); - $this->assertTrue($sess2->handler_open('Not used', 'Not used')); - $this->assertEquals('DATAX', $sess1->handler_read('sess1')); - $this->assertEquals('DATA2X', $sess2->handler_read('sess2')); + $this->assertTrue($sess1->open('Not used', 'Not used')); + $this->assertTrue($sess2->open('Not used', 'Not used')); + $this->assertEquals('DATAX', $sess1->read('sess1')); + $this->assertEquals('DATA2X', $sess2->read('sess2')); // Close both sessions - $this->assertTrue($sess1->handler_close()); - $this->assertTrue($sess2->handler_close()); + $this->assertTrue($sess1->close()); + $this->assertTrue($sess2->close()); // Read the session again to ensure locking did what it should. $this->assertSessionNoLocks(); @@ -265,19 +265,19 @@ class session_redis_test extends \advanced_testcase { $sess->set_requires_write_lock(true); // Initialize session 1. - $this->assertTrue($sess->handler_open('Not used', 'Not used')); - $this->assertSame('', $sess->handler_read('sess1')); - $this->assertTrue($sess->handler_write('sess1', 'DATA')); - $this->assertSame('', $sess->handler_read('sess2')); - $this->assertTrue($sess->handler_write('sess2', 'DATA2')); - $this->assertSame('DATA', $sess->handler_read('sess1')); - $this->assertSame('DATA2', $sess->handler_read('sess2')); - $this->assertTrue($sess->handler_destroy('sess2')); + $this->assertTrue($sess->open('Not used', 'Not used')); + $this->assertSame('', $sess->read('sess1')); + $this->assertTrue($sess->write('sess1', 'DATA')); + $this->assertSame('', $sess->read('sess2')); + $this->assertTrue($sess->write('sess2', 'DATA2')); + $this->assertSame('DATA', $sess->read('sess1')); + $this->assertSame('DATA2', $sess->read('sess2')); + $this->assertTrue($sess->destroy('sess2')); - $this->assertTrue($sess->handler_close()); + $this->assertTrue($sess->close()); $this->assertSessionNoLocks(); - $this->assertTrue($sess->handler_close()); + $this->assertTrue($sess->close()); } public function test_session_exists_returns_valid_values() { @@ -285,13 +285,13 @@ class session_redis_test extends \advanced_testcase { $sess->init(); $sess->set_requires_write_lock(true); - $this->assertTrue($sess->handler_open('Not used', 'Not used')); - $this->assertSame('', $sess->handler_read('sess1')); + $this->assertTrue($sess->open('Not used', 'Not used')); + $this->assertSame('', $sess->read('sess1')); $this->assertFalse($sess->session_exists('sess1'), 'Session must not exist yet, it has not been saved'); - $this->assertTrue($sess->handler_write('sess1', 'DATA')); + $this->assertTrue($sess->write('sess1', 'DATA')); $this->assertTrue($sess->session_exists('sess1'), 'Session must exist now.'); - $this->assertTrue($sess->handler_destroy('sess1')); + $this->assertTrue($sess->destroy('sess1')); $this->assertFalse($sess->session_exists('sess1'), 'Session should be destroyed.'); } @@ -301,10 +301,10 @@ class session_redis_test extends \advanced_testcase { $sess = new \core\session\redis(); $sess->init(); - $this->assertTrue($sess->handler_open('Not used', 'Not used')); - $this->assertTrue($sess->handler_write('sess1', 'DATA')); - $this->assertTrue($sess->handler_write('sess2', 'DATA')); - $this->assertTrue($sess->handler_write('sess3', 'DATA')); + $this->assertTrue($sess->open('Not used', 'Not used')); + $this->assertTrue($sess->write('sess1', 'DATA')); + $this->assertTrue($sess->write('sess2', 'DATA')); + $this->assertTrue($sess->write('sess3', 'DATA')); $sessiondata = new \stdClass(); $sessiondata->userid = 2; @@ -318,9 +318,9 @@ class session_redis_test extends \advanced_testcase { $sessiondata->sid = 'sess3'; $DB->insert_record('sessions', $sessiondata); - $this->assertNotEquals('', $sess->handler_read('sess1')); + $this->assertNotEquals('', $sess->read('sess1')); $sess->kill_session('sess1'); - $this->assertEquals('', $sess->handler_read('sess1')); + $this->assertEquals('', $sess->read('sess1')); $this->assertEmpty($this->redis->keys($this->keyprefix.'sess1.lock')); diff --git a/mod/bigbluebuttonbn/classes/test/subplugins_test_helper_trait.php b/mod/bigbluebuttonbn/classes/test/subplugins_test_helper_trait.php index c3d31fe2cdd..4844865a763 100644 --- a/mod/bigbluebuttonbn/classes/test/subplugins_test_helper_trait.php +++ b/mod/bigbluebuttonbn/classes/test/subplugins_test_helper_trait.php @@ -52,13 +52,13 @@ trait subplugins_test_helper_trait { $mockedplugins->setAccessible(true); $plugins = $mockedplugins->getValue(); $plugins[extension::BBB_EXTENSION_PLUGIN_NAME] = [$pluginname => $bbbextpath . "/$pluginname"]; - $mockedplugins->setValue($plugins); + $mockedplugins->setValue(null, $plugins); $mockedplugintypes = $mockedcomponent->getProperty('plugintypes'); $mockedplugintypes->setAccessible(true); $pluginstypes = $mockedplugintypes->getValue(); $pluginstypes[extension::BBB_EXTENSION_PLUGIN_NAME] = $bbbextpath; - $mockedplugintypes->setValue($pluginstypes); + $mockedplugintypes->setValue(null, $pluginstypes); $fillclassmap = $mockedcomponent->getMethod('fill_classmap_cache'); $fillclassmap->setAccessible(true); @@ -72,7 +72,7 @@ trait subplugins_test_helper_trait { $mockedsubplugins->setAccessible(true); $subplugins = $mockedsubplugins->getValue(); $subplugins['mod_bigbluebuttonbn'][extension::BBB_EXTENSION_PLUGIN_NAME][] = $pluginname; - $mockedsubplugins->setValue($subplugins); + $mockedsubplugins->setValue(null, $subplugins); // Now write the content of the cache in a file so we can use it later. $content = core_component::get_cache_content(); @@ -149,7 +149,7 @@ trait subplugins_test_helper_trait { // Here we reset the plugin caches. $mockedplugintypes = $mockedcomponent->getProperty('plugintypes'); $mockedplugintypes->setAccessible(true); - $mockedplugintypes->setValue(null); + $mockedplugintypes->setValue(null, null); $fillclassmap = $mockedcomponent->getMethod('init'); $fillclassmap->setAccessible(true); $fillclassmap->invoke(null); diff --git a/mod/bigbluebuttonbn/tests/behat/behat_mod_bigbluebuttonbn.php b/mod/bigbluebuttonbn/tests/behat/behat_mod_bigbluebuttonbn.php index 963efc50ffb..5bda0afbd36 100644 --- a/mod/bigbluebuttonbn/tests/behat/behat_mod_bigbluebuttonbn.php +++ b/mod/bigbluebuttonbn/tests/behat/behat_mod_bigbluebuttonbn.php @@ -263,7 +263,7 @@ XPATH $mockedcomponent = new ReflectionClass(core_component::class); $mockedplugintypes = $mockedcomponent->getProperty('plugintypes'); $mockedplugintypes->setAccessible(true); - $mockedplugintypes->setValue(null); + $mockedplugintypes->setValue(null, null); $init = $mockedcomponent->getMethod('init'); $init->setAccessible(true); $init->invoke(null); diff --git a/mod/workshop/allocation/random/lib.php b/mod/workshop/allocation/random/lib.php index 257e4decae4..876254464e7 100644 --- a/mod/workshop/allocation/random/lib.php +++ b/mod/workshop/allocation/random/lib.php @@ -702,7 +702,7 @@ class workshop_random_allocator implements workshop_allocator { protected function filter_current_assessments(&$newallocations, $assessments) { foreach ($assessments as $assessment) { $allocation = array($assessment->reviewerid => $assessment->authorid); - $foundat = array_keys($newallocations, $allocation); + $foundat = moodle_array_keys_filter($newallocations, $allocation); $newallocations = array_diff_key($newallocations, array_flip($foundat)); } } diff --git a/mod/workshop/eval/best/lib.php b/mod/workshop/eval/best/lib.php index 7a74081642a..72136294723 100644 --- a/mod/workshop/eval/best/lib.php +++ b/mod/workshop/eval/best/lib.php @@ -183,7 +183,7 @@ class workshop_best_evaluation extends workshop_evaluation { } // identify the best assessments - that is those with the shortest distance from the best assessment - $bestids = array_keys($distances, min($distances)); + $bestids = moodle_array_keys_filter($distances, min($distances)); // for every assessment, calculate its distance from the nearest best assessment $distances = array(); diff --git a/question/format/blackboard_six/formatpool.php b/question/format/blackboard_six/formatpool.php index 40dc7ebcf3a..a139e93c2e5 100644 --- a/question/format/blackboard_six/formatpool.php +++ b/question/format/blackboard_six/formatpool.php @@ -446,7 +446,7 @@ class qformat_blackboard_six_pool extends qformat_blackboard_six_base { $choiceid = $this->getpath($choice, array('@', 'id'), '', true); $fiber = array_search($choiceid, $mappings); - $fiber = array_keys ($mappings, $choiceid); + $fiber = moodle_array_keys_filter($mappings, $choiceid); foreach ($fiber as $correctanswerid) { // We have found a correspondance for this choice so we need to take the associated answer. foreach ($answers as $answer) { diff --git a/question/format/blackboard_six/formatqti.php b/question/format/blackboard_six/formatqti.php index f7c8a2ae5c9..1eb5957f1c8 100644 --- a/question/format/blackboard_six/formatqti.php +++ b/question/format/blackboard_six/formatqti.php @@ -837,7 +837,7 @@ class qformat_blackboard_six_qti extends qformat_blackboard_six_base { if ($subanswertext != '') { // Only import non empty subanswers. $subquestion = ''; - $fiber = array_keys ($mappings, $choiceid); + $fiber = moodle_array_keys_filter($mappings, $choiceid); foreach ($fiber as $correctanswerid) { // We have found a correspondance for this subanswer so we need to take the associated subquestion. foreach ($quest->RESPONSE_BLOCK->subquestions as $qid => $subq) { diff --git a/question/type/ddwtos/edit_ddwtos_form.php b/question/type/ddwtos/edit_ddwtos_form.php index aadb68dae11..f61c2a42ef4 100644 --- a/question/type/ddwtos/edit_ddwtos_form.php +++ b/question/type/ddwtos/edit_ddwtos_form.php @@ -56,7 +56,7 @@ class qtype_ddwtos_edit_form extends qtype_gapselect_edit_form_base { protected function extra_slot_validation(array $slots, array $choices): ?string { foreach ($slots as $slot) { - if (count(array_keys($slots, $slot)) > 1) { + if (count(array_filter($slots, fn($value) => $value == $slot)) > 1) { $choice = $choices[$slot - 1]; if (!isset($choice['infinite']) || $choice['infinite'] != 1) { return get_string('errorlimitedchoice', 'qtype_ddwtos',