diff --git a/lib/questionlib.php b/lib/questionlib.php index 99a7a2ce6b5..89c274e95cf 100644 --- a/lib/questionlib.php +++ b/lib/questionlib.php @@ -1434,7 +1434,7 @@ function question_has_capability_on($questionorid, $cap, $notused = -1): bool { } else if (is_object($questionorid)) { // All we really need in this function is the contextid and author of the question. // We won't bother fetching other details of the question if these 2 fields are provided. - if (isset($questionorid->contextid) && isset($questionorid->createdby)) { + if (isset($questionorid->contextid) && property_exists($questionorid, 'createdby')) { $question = $questionorid; } else if (!empty($questionorid->id)) { $questionid = $questionorid->id; diff --git a/lib/tests/questionlib_test.php b/lib/tests/questionlib_test.php index a84d41fe126..3102f5c149e 100644 --- a/lib/tests/questionlib_test.php +++ b/lib/tests/questionlib_test.php @@ -2024,6 +2024,35 @@ class questionlib_test extends \advanced_testcase { } } + /** + * Test that question_has_capability_on does not fail when passed an object with a null + * createdby property. + */ + public function test_question_has_capability_on_object_with_null_createdby(): void { + $this->resetAfterTest(); + $generator = $this->getDataGenerator(); + $user = $generator->create_user(); + $category = $generator->create_category(); + $context = \context_coursecat::instance($category->id); + + $role = $generator->create_role(); + role_assign($role, $user->id, $context->id); + assign_capability('moodle/question:editmine', CAP_ALLOW, $role, $context->id); + + $this->setUser($user); + + $fakequestion = (object) [ + 'contextid' => $context->id, + 'createdby' => null, + ]; + + $this->assertFalse(question_has_capability_on($fakequestion, 'edit')); + + $fakequestion->createdby = $user->id; + + $this->assertTrue(question_has_capability_on($fakequestion, 'edit')); + } + /** * Test of question_categorylist function. *