MDL-63303 core_favourites: add get and count functions
authorRyan Wyllie <ryan@moodle.com>
Mon, 29 Oct 2018 06:57:48 +0000 (14:57 +0800)
committerRyan Wyllie <ryan@moodle.com>
Thu, 15 Nov 2018 06:40:11 +0000 (14:40 +0800)
favourites/classes/local/service/user_favourite_service.php
favourites/tests/service_test.php
lib/db/services.php
message/classes/api.php
message/tests/api_test.php

index 16718b8..a63692a 100644 (file)
@@ -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);
+    }
 }
index 939e544..5ead879 100644 (file)
@@ -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'));
+    }
 }
index 1f4483d..5b96bb5 100644 (file)
@@ -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(
index abc917c..b497ebe 100644 (file)
@@ -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);
+        }
     }
 
     /**
index 78dfbfd..30add02 100644 (file)
@@ -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);
     }
 
     /**