MDL-68019 course: Performance improvement with component favourites
authorPeter <peterrolanddias@gmail.com>
Wed, 26 Feb 2020 07:01:04 +0000 (15:01 +0800)
committerPeter Dias <peter@moodle.com>
Fri, 28 Feb 2020 03:28:15 +0000 (11:28 +0800)
Add the ability to get all/select itemtypes within a component

course/classes/local/service/content_item_service.php
favourites/classes/local/repository/favourite_repository.php
favourites/classes/local/service/user_favourite_service.php

index 3c2a605..76aadb9 100644 (file)
@@ -141,10 +141,17 @@ class content_item_service {
 
         $ufservice = \core_favourites\service_factory::get_service_for_user_context($usercontext);
         $favourites = [];
-        foreach ($itemtypes as $itemtype) {
-            $favs = $ufservice->find_favourites_by_type(self::COMPONENT, $itemtype);
-            $favobj = (object) ['itemtype' => $itemtype, 'ids' => array_column($favs, 'itemid')];
-            $favourites[] = $favobj;
+        $favs = $ufservice->find_all_favourites(self::COMPONENT, $itemtypes);
+        $favsreduced = array_reduce($favs, function($carry, $item) {
+            $carry[$item->itemtype][$item->itemid] = 0;
+            return $carry;
+        }, []);
+
+        foreach ($itemtypes as $type) {
+            $favourites[] = (object) [
+                'itemtype' => $type,
+                'ids' => isset($favsreduced[$type]) ? array_keys($favsreduced[$type]) : []
+            ];
         }
         return $favourites;
     }
index d0236b7..c9403be 100644 (file)
@@ -184,7 +184,7 @@ class favourite_repository implements favourite_repository_interface {
     /**
      * Return all items matching the supplied criteria (a [key => value,..] list).
      *
-     * @param array $criteria the list of key/value criteria pairs.
+     * @param array $criteria the list of key/value(s) criteria pairs.
      * @param int $limitfrom optional pagination control for returning a subset of records, starting at this point.
      * @param int $limitnum optional pagination control for returning a subset comprising this many records.
      * @return array the list of favourites matching the criteria.
@@ -192,7 +192,22 @@ class favourite_repository implements favourite_repository_interface {
      */
     public function find_by(array $criteria, int $limitfrom = 0, int $limitnum = 0) : array {
         global $DB;
-        $records = $DB->get_records($this->favouritetable, $criteria, '', '*', $limitfrom, $limitnum);
+        $conditions = [];
+        $params = [];
+        foreach ($criteria as $field => $value) {
+            if (is_array($value) && count($value)) {
+                list($insql, $inparams) = $DB->get_in_or_equal($value, SQL_PARAMS_NAMED);
+                $conditions[] = "$field $insql";
+                $params = array_merge($params, $inparams);
+            } else {
+                $conditions[] = "$field = :$field";
+                $params = array_merge($params, [$field => $value]);
+            }
+        }
+
+        $records = $DB->get_records_select($this->favouritetable, implode(' AND ', $conditions), $params,
+            '', '*', $limitfrom, $limitnum);
+
         return $this->get_list_of_favourites_from_records($records);
     }
 
index e569523..0246373 100644 (file)
@@ -110,6 +110,38 @@ class user_favourite_service {
         );
     }
 
+    /**
+     * Find a list of favourites, by multiple types within a component.
+     *
+     * E.g. "Find all favourites in the activity chooser" might result in:
+     * $favcourses = find_all_favourites('core_course', ['contentitem_mod_assign','contentitem_mod_assignment');
+     *
+     * @param string $component the frankenstyle component name.
+     * @param array $itemtypes optional the type of the favourited item.
+     * @param int $limitfrom optional pagination control for returning a subset of records, starting at this point.
+     * @param int $limitnum optional pagination control for returning a subset comprising this many records.
+     * @return array the list of favourites found.
+     * @throws \moodle_exception if the component name is invalid, or if the repository encounters any errors.
+     */
+    public function find_all_favourites(string $component, array $itemtypes = [], int $limitfrom = 0, int $limitnum = 0) : array {
+        if (!in_array($component, \core_component::get_component_names())) {
+            throw new \moodle_exception("Invalid component name '$component'");
+        }
+        $params = [
+            'userid' => $this->userid,
+            'component' => $component,
+        ];
+        if ($itemtypes) {
+            $params['itemtype'] = $itemtypes;
+        }
+
+        return $this->repo->find_by(
+            $params,
+            $limitfrom,
+            $limitnum
+        );
+    }
+
     /**
      * Returns the SQL required to include favourite information for a given component/itemtype combination.
      *