From 9e189a914d950bc1b8f08bdf30407eb7be681006 Mon Sep 17 00:00:00 2001 From: Ryan Wyllie Date: Mon, 29 Oct 2018 14:57:48 +0800 Subject: [PATCH] MDL-63303 core_favourites: add get and count functions --- .../local/service/user_favourite_service.php | 45 ++++++++++ favourites/tests/service_test.php | 85 ++++++++++++++++++- lib/db/services.php | 2 + message/classes/api.php | 7 +- message/tests/api_test.php | 8 +- 5 files changed, 138 insertions(+), 9 deletions(-) diff --git a/favourites/classes/local/service/user_favourite_service.php b/favourites/classes/local/service/user_favourite_service.php index 16718b82f00..a63692a675c 100644 --- a/favourites/classes/local/service/user_favourite_service.php +++ b/favourites/classes/local/service/user_favourite_service.php @@ -156,4 +156,49 @@ class user_favourite_service { ] ); } + + /** + * Get the favourite. + * + * @param string $component the frankenstyle component name. + * @param string $itemtype the type of the favourited item. + * @param int $itemid the id of the item which was favourited (not the favourite's id). + * @param \context $context the context of the item which was favourited. + * @return favourite|null + */ + public function get_favourite(string $component, string $itemtype, int $itemid, \context $context) { + try { + return $this->repo->find_favourite( + $this->userid, + $component, + $itemtype, + $itemid, + $context->id + ); + } catch (\dml_missing_record_exception $e) { + return null; + } + } + + /** + * Count the favourite by item type. + * + * @param string $component the frankenstyle component name. + * @param string $itemtype the type of the favourited item. + * @param \context|null $context the context of the item which was favourited. + * @return favourite|null + */ + public function count_favourites_by_type(string $component, string $itemtype, \context $context = null) { + $criteria = [ + 'userid' => $this->userid, + 'component' => $component, + 'itemtype' => $itemtype + ]; + + if ($context) { + $criteria['contextid'] = $context->id; + } + + return $this->repo->count_by($criteria); + } } diff --git a/favourites/tests/service_test.php b/favourites/tests/service_test.php index 939e5446629..5ead879fff7 100644 --- a/favourites/tests/service_test.php +++ b/favourites/tests/service_test.php @@ -111,7 +111,7 @@ class user_favourite_service_testcase extends advanced_testcase { return $fakerow; } } - throw new \moodle_exception("Item not found"); + throw new \dml_missing_record_exception("Item not found"); }) ); $mockrepo->expects($this->any()) @@ -127,16 +127,17 @@ class user_favourite_service_testcase extends advanced_testcase { }) ); $mockrepo->expects($this->any()) - ->method('exists_by') + ->method('count_by') ->will($this->returnCallback(function(array $criteria) use (&$mockstore) { + $count = 0; // Check the mockstore for all objects with properties matching the key => val pairs in $criteria. foreach ($mockstore as $index => $mockrow) { $mockrowarr = (array)$mockrow; if (array_diff($criteria, $mockrowarr) == []) { - return true; + $count++; } } - return false; + return $count; }) ); $mockrepo->expects($this->any()) @@ -149,6 +150,19 @@ class user_favourite_service_testcase extends advanced_testcase { } }) ); + $mockrepo->expects($this->any()) + ->method('exists_by') + ->will($this->returnCallback(function(array $criteria) use (&$mockstore) { + // Check the mockstore for all objects with properties matching the key => val pairs in $criteria. + foreach ($mockstore as $index => $mockrow) { + $mockrowarr = (array)$mockrow; + if (array_diff($criteria, $mockrowarr) == []) { + return true; + } + } + return false; + }) + ); return $mockrepo; } @@ -352,4 +366,67 @@ class user_favourite_service_testcase extends advanced_testcase { ) ); } + + /** + * Test confirming the behaviour of the get_favourite() method. + */ + public function test_get_favourite() { + list($user1context, $user2context, $course1context, $course2context) = $this->setup_users_and_courses(); + + // Get a user_favourite_service for the user. + $repo = $this->get_mock_repository([]); + $service = new \core_favourites\local\service\user_favourite_service($user1context, $repo); + + // Favourite a course. + $fav1 = $service->create_favourite('core_course', 'course', $course1context->instanceid, $course1context); + + $result = $service->get_favourite( + 'core_course', + 'course', + $course1context->instanceid, + $course1context + ); + // Verify we can get the favourite. + $this->assertEquals($fav1->id, $result->id); + + // And one that we know doesn't exist. + $this->assertNull( + $service->get_favourite( + 'core_course', + 'someothertype', + $course1context->instanceid, + $course1context + ) + ); + } + + /** + * Test confirming the behaviour of the count_favourites_by_type() method. + */ + public function test_count_favourites_by_type() { + list($user1context, $user2context, $course1context, $course2context) = $this->setup_users_and_courses(); + + // Get a user_favourite_service for the user. + $repo = $this->get_mock_repository([]); + $service = new \core_favourites\local\service\user_favourite_service($user1context, $repo); + + $this->assertEquals(0, $service->count_favourites_by_type('core_course', 'course', $course1context)); + // Favourite a course. + $service->create_favourite('core_course', 'course', $course1context->instanceid, $course1context); + + $this->assertEquals(1, $service->count_favourites_by_type('core_course', 'course', $course1context)); + + // Favourite another course. + $service->create_favourite('core_course', 'course', $course2context->instanceid, $course1context); + + $this->assertEquals(2, $service->count_favourites_by_type('core_course', 'course', $course1context)); + + // Favourite a course in another context. + $service->create_favourite('core_course', 'course', $course2context->instanceid, $course2context); + + // Doesn't affect original context. + $this->assertEquals(2, $service->count_favourites_by_type('core_course', 'course', $course1context)); + // Gets counted if we include all contexts. + $this->assertEquals(3, $service->count_favourites_by_type('core_course', 'course')); + } } diff --git a/lib/db/services.php b/lib/db/services.php index 1f4483dc6dc..5b96bb570fa 100644 --- a/lib/db/services.php +++ b/lib/db/services.php @@ -1257,6 +1257,7 @@ $functions = array( 'classpath' => 'message/externallib.php', 'description' => 'Mark a conversation or group of conversations as favourites/starred conversations.', 'type' => 'write', + 'ajax' => true, 'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE), ), 'core_message_unset_favourite_conversations' => array( @@ -1265,6 +1266,7 @@ $functions = array( 'classpath' => 'message/externallib.php', 'description' => 'Unset a conversation or group of conversations as favourites/starred conversations.', 'type' => 'write', + 'ajax' => true, 'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE), ), 'core_notes_create_notes' => array( diff --git a/message/classes/api.php b/message/classes/api.php index abc917c22f5..b497ebe4d89 100644 --- a/message/classes/api.php +++ b/message/classes/api.php @@ -813,8 +813,13 @@ class api { if (!self::is_user_in_conversation($userid, $conversationid)) { throw new \moodle_exception("Conversation doesn't exist or user is not a member"); } + $systemcontext = \context_system::instance(); $ufservice = \core_favourites\service_factory::get_service_for_user_context(\context_user::instance($userid)); - return $ufservice->create_favourite('core_message', 'message_conversations', $conversationid, \context_system::instance()); + if ($favourite = $ufservice->get_favourite('core_message', 'message_conversations', $conversationid, $systemcontext)) { + return $favourite; + } else { + return $ufservice->create_favourite('core_message', 'message_conversations', $conversationid, $systemcontext); + } } /** diff --git a/message/tests/api_test.php b/message/tests/api_test.php index 78dfbfd2f53..30add021e0c 100644 --- a/message/tests/api_test.php +++ b/message/tests/api_test.php @@ -950,7 +950,7 @@ class core_message_api_testcase extends core_message_messagelib_testcase { // Favourite the first conversation as user 1. $conversationid1 = \core_message\api::get_conversation_between_users([$user1->id, $user2->id]); - \core_message\api::set_favourite_conversation($conversationid1, $user1->id); + $favourite = \core_message\api::set_favourite_conversation($conversationid1, $user1->id); // Verify we have a single favourite conversation a user 1. $this->assertCount(1, \core_message\api::get_conversations($user1->id, 0, 20, null, true)); @@ -958,9 +958,9 @@ class core_message_api_testcase extends core_message_messagelib_testcase { // Verify we have no favourites as user2, despite being a member in that conversation. $this->assertCount(0, \core_message\api::get_conversations($user2->id, 0, 20, null, true)); - // Try to favourite the same conversation again. - $this->expectException(\moodle_exception::class); - \core_message\api::set_favourite_conversation($conversationid1, $user1->id); + // Try to favourite the same conversation again should just return the existing favourite. + $repeatresult = \core_message\api::set_favourite_conversation($conversationid1, $user1->id); + $this->assertEquals($favourite->id, $repeatresult->id); } /** -- 2.43.0