diff --git a/course/classes/local/service/content_item_service.php b/course/classes/local/service/content_item_service.php index 3c2a605c9be..76aadb95f74 100644 --- a/course/classes/local/service/content_item_service.php +++ b/course/classes/local/service/content_item_service.php @@ -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; } diff --git a/favourites/classes/local/repository/favourite_repository.php b/favourites/classes/local/repository/favourite_repository.php index d0236b7999d..c9403be5b55 100644 --- a/favourites/classes/local/repository/favourite_repository.php +++ b/favourites/classes/local/repository/favourite_repository.php @@ -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); } diff --git a/favourites/classes/local/service/user_favourite_service.php b/favourites/classes/local/service/user_favourite_service.php index e569523ec63..0246373f267 100644 --- a/favourites/classes/local/service/user_favourite_service.php +++ b/favourites/classes/local/service/user_favourite_service.php @@ -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. *