mirror of
https://github.com/moodle/moodle.git
synced 2025-04-22 08:55:15 +02:00
MDL-63658 core_favourites: adding paging support to the service layer
This commit is contained in:
parent
ac9138db1c
commit
8ffbe9c163
@ -31,10 +31,10 @@ interface crud_repository {
|
||||
/**
|
||||
* Add one item to this repository.
|
||||
*
|
||||
* @param \stdClass $item the item to add.
|
||||
* @return \stdClass the item which was added.
|
||||
* @param object $item the item to add.
|
||||
* @return object the item which was added.
|
||||
*/
|
||||
public function add(\stdClass $item) : \stdClass;
|
||||
public function add($item);
|
||||
|
||||
/**
|
||||
* Add all the items in the list to this repository.
|
||||
@ -48,24 +48,28 @@ interface crud_repository {
|
||||
* Find an item in this repository based on its id.
|
||||
*
|
||||
* @param int $id the id of the item.
|
||||
* @return \stdClass the item.
|
||||
* @return object the item.
|
||||
*/
|
||||
public function find(int $id) : \stdClass;
|
||||
public function find(int $id);
|
||||
|
||||
/**
|
||||
* Find all items in this repository.
|
||||
*
|
||||
* @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 list of all items in this repository.
|
||||
*/
|
||||
public function find_all() : array;
|
||||
public function find_all(int $limitfrom = 0, int $limitnum = 0) : array;
|
||||
|
||||
/**
|
||||
* Find all items with attributes matching certain values.
|
||||
*
|
||||
* @param array $criteria the array of attribute/value 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 items matching the criteria.
|
||||
*/
|
||||
public function find_by(array $criteria) : array;
|
||||
public function find_by(array $criteria, int $limitfrom = 0, int $limitnum = 0) : array;
|
||||
|
||||
/**
|
||||
* Check whether an item exists in this repository, based on its id.
|
||||
@ -85,10 +89,10 @@ interface crud_repository {
|
||||
/**
|
||||
* Update an item within this repository.
|
||||
*
|
||||
* @param \stdClass $item the item to update.
|
||||
* @return \stdClass the updated item.
|
||||
* @param object $item the item to update.
|
||||
* @return object the updated item.
|
||||
*/
|
||||
public function update(\stdClass $item) : \stdClass;
|
||||
public function update($item);
|
||||
|
||||
/**
|
||||
* Delete an item by id.
|
||||
|
@ -53,7 +53,7 @@ class favourites_repository implements ifavourites_repository {
|
||||
* @throws \dml_exception if any database errors are encountered.
|
||||
* @throws \moodle_exception if the favourite has missing or invalid properties.
|
||||
*/
|
||||
public function add(\stdClass $favourite) : \stdClass {
|
||||
public function add($favourite) : \stdClass {
|
||||
global $DB;
|
||||
$this->validate($favourite);
|
||||
$favourite = (array)$favourite;
|
||||
@ -102,23 +102,27 @@ class favourites_repository implements ifavourites_repository {
|
||||
* Return all items matching the supplied criteria (a [key => value,..] list).
|
||||
*
|
||||
* @param array $criteria the list of key/value 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.
|
||||
* @throws \dml_exception if any database errors are encountered.
|
||||
*/
|
||||
public function find_by(array $criteria) : array {
|
||||
public function find_by(array $criteria, int $limitfrom = 0, int $limitnum = 0) : array {
|
||||
global $DB;
|
||||
return $DB->get_records($this->favouritetable, $criteria);
|
||||
return $DB->get_records($this->favouritetable, $criteria, '', '*', $limitfrom, $limitnum);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all items in this repository, as an array, indexed by id.
|
||||
*
|
||||
* @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 all favourites stored within this repository.
|
||||
* @throws \dml_exception if any database errors are encountered.
|
||||
*/
|
||||
public function find_all() : array {
|
||||
public function find_all(int $limitfrom = 0, int $limitnum = 0) : array {
|
||||
global $DB;
|
||||
return $DB->get_records($this->favouritetable);
|
||||
return $DB->get_records($this->favouritetable, null, '', '*', $limitfrom, $limitnum);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -165,7 +169,7 @@ class favourites_repository implements ifavourites_repository {
|
||||
* @return \stdClass the updated favourite.
|
||||
* @throws \dml_exception if any database errors are encountered.
|
||||
*/
|
||||
public function update(\stdClass $favourite) : \stdClass {
|
||||
public function update($favourite) : \stdClass {
|
||||
global $DB;
|
||||
$time = time();
|
||||
$favourite->timemodified = $time;
|
||||
|
@ -44,17 +44,6 @@ class user_favourites_service {
|
||||
/** @var int $userid the id of the user to which this favourites service is scoped. */
|
||||
protected $userid;
|
||||
|
||||
/**
|
||||
* Helper, returning a flat list of component names.
|
||||
*
|
||||
* @return array the array of component names.
|
||||
*/
|
||||
protected function get_component_list() {
|
||||
return array_keys(array_reduce(\core_component::get_component_list(), function($carry, $item) {
|
||||
return array_merge($carry, $item);
|
||||
}, []));
|
||||
}
|
||||
|
||||
/**
|
||||
* The user_favourites_service constructor.
|
||||
*
|
||||
@ -66,6 +55,17 @@ class user_favourites_service {
|
||||
$this->userid = $usercontext->instanceid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper, returning a flat list of component names.
|
||||
*
|
||||
* @return array the array of component names.
|
||||
*/
|
||||
protected function get_component_list() {
|
||||
return array_keys(array_reduce(\core_component::get_component_list(), function($carry, $item) {
|
||||
return array_merge($carry, $item);
|
||||
}, []));
|
||||
}
|
||||
|
||||
/**
|
||||
* Favourite an item defined by itemid/context, in the area defined by component/itemtype.
|
||||
*
|
||||
@ -105,14 +105,24 @@ class user_favourites_service {
|
||||
*
|
||||
* @param string $component the frankenstyle component name.
|
||||
* @param string $itemtype 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_favourites_by_type(string $component, string $itemtype) : array {
|
||||
public function find_favourites_by_type(string $component, string $itemtype, int $limitfrom = 0, int $limitnum = 0) : array {
|
||||
if (!in_array($component, $this->get_component_list())) {
|
||||
throw new \moodle_exception("Invalid component name '$component'");
|
||||
}
|
||||
return $this->repo->find_by(['userid' => $this->userid, 'component' => $component, 'itemtype' => $itemtype]);
|
||||
return $this->repo->find_by(
|
||||
[
|
||||
'userid' => $this->userid,
|
||||
'component' => $component,
|
||||
'itemtype' => $itemtype
|
||||
],
|
||||
$limitfrom,
|
||||
$limitnum
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -235,6 +235,48 @@ class favourites_repository_testcase extends advanced_testcase {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Testing the pagination of the find_all method.
|
||||
*/
|
||||
public function test_find_all_pagination() {
|
||||
list($user1context, $user2context, $course1context, $course2context) = $this->setup_users_and_courses();
|
||||
|
||||
$favouritesrepo = new favourites_repository($user1context);
|
||||
|
||||
// Verify that for an empty repository, find_all with any combination of page options returns an empty array.
|
||||
$this->assertEquals([], $favouritesrepo->find_all(0, 0));
|
||||
$this->assertEquals([], $favouritesrepo->find_all(0, 10));
|
||||
$this->assertEquals([], $favouritesrepo->find_all(1, 0));
|
||||
$this->assertEquals([], $favouritesrepo->find_all(1, 10));
|
||||
|
||||
// Save 10 arbitrary favourites to the repo.
|
||||
foreach (range(1, 10) as $i) {
|
||||
$favourite = (object) [
|
||||
'userid' => $user1context->instanceid,
|
||||
'component' => 'core_course',
|
||||
'itemtype' => 'course',
|
||||
'itemid' => $i,
|
||||
'contextid' => $course1context->id
|
||||
];
|
||||
$favouritesrepo->add($favourite);
|
||||
}
|
||||
|
||||
// Verify we have 10 favourites.
|
||||
$this->assertEquals(10, $favouritesrepo->count());
|
||||
|
||||
// Verify we can fetch the first page of 5 records.
|
||||
$favourites = $favouritesrepo->find_all(0, 5);
|
||||
$this->assertCount(5, $favourites);
|
||||
|
||||
// Verify we can fetch the second page.
|
||||
$favourites = $favouritesrepo->find_all(5, 5);
|
||||
$this->assertCount(5, $favourites);
|
||||
|
||||
// Verify the third page request ends with an empty array.
|
||||
$favourites = $favouritesrepo->find_all(10, 5);
|
||||
$this->assertCount(0, $favourites);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test retrieval of a user's favourites for a given criteria, in this case, area.
|
||||
*/
|
||||
@ -263,6 +305,52 @@ class favourites_repository_testcase extends advanced_testcase {
|
||||
$this->assertCount(0, $userfavourites);
|
||||
}
|
||||
|
||||
/**
|
||||
* Testing the pagination of the find_by method.
|
||||
*/
|
||||
public function test_find_by_pagination() {
|
||||
list($user1context, $user2context, $course1context, $course2context) = $this->setup_users_and_courses();
|
||||
|
||||
$favouritesrepo = new favourites_repository($user1context);
|
||||
|
||||
// Verify that for an empty repository, find_all with any combination of page options returns an empty array.
|
||||
$this->assertEquals([], $favouritesrepo->find_by([], 0, 0));
|
||||
$this->assertEquals([], $favouritesrepo->find_by([], 0, 10));
|
||||
$this->assertEquals([], $favouritesrepo->find_by([], 1, 0));
|
||||
$this->assertEquals([], $favouritesrepo->find_by([], 1, 10));
|
||||
|
||||
// Save 10 arbitrary favourites to the repo.
|
||||
foreach (range(1, 10) as $i) {
|
||||
$favourite = (object) [
|
||||
'userid' => $user1context->instanceid,
|
||||
'component' => 'core_course',
|
||||
'itemtype' => 'course',
|
||||
'itemid' => $i,
|
||||
'contextid' => $course1context->id
|
||||
];
|
||||
$favouritesrepo->add($favourite);
|
||||
}
|
||||
|
||||
// Verify we have 10 favourites.
|
||||
$this->assertEquals(10, $favouritesrepo->count());
|
||||
|
||||
// Verify a request for a page, when no criteria match, results in an empty array.
|
||||
$favourites = $favouritesrepo->find_by(['component' => 'core_message'], 0, 5);
|
||||
$this->assertCount(0, $favourites);
|
||||
|
||||
// Verify we can fetch a the first page of 5 records.
|
||||
$favourites = $favouritesrepo->find_by(['component' => 'core_course'], 0, 5);
|
||||
$this->assertCount(5, $favourites);
|
||||
|
||||
// Verify we can fetch the second page.
|
||||
$favourites = $favouritesrepo->find_by(['component' => 'core_course'], 5, 5);
|
||||
$this->assertCount(5, $favourites);
|
||||
|
||||
// Verify the third page request ends with an empty array.
|
||||
$favourites = $favouritesrepo->find_by(['component' => 'core_course'], 10, 5);
|
||||
$this->assertCount(0, $favourites);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the count_by() method.
|
||||
*/
|
||||
|
@ -84,7 +84,7 @@ class user_favourites_service_testcase extends advanced_testcase {
|
||||
);
|
||||
$mockrepo->expects($this->any())
|
||||
->method('find_by')
|
||||
->will($this->returnCallback(function(array $criteria) use (&$mockstore) {
|
||||
->will($this->returnCallback(function(array $criteria, int $limitfrom = 0, int $limitnum = 0) 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;
|
||||
@ -92,6 +92,11 @@ class user_favourites_service_testcase extends advanced_testcase {
|
||||
$returns[$index] = $mockrow;
|
||||
}
|
||||
}
|
||||
// Return a subset of the records, according to the paging options, if set.
|
||||
if ($limitnum != 0) {
|
||||
return array_slice($returns, $limitfrom, $limitnum);
|
||||
}
|
||||
// Otherwise, just return the full set.
|
||||
return $returns;
|
||||
})
|
||||
);
|
||||
@ -245,6 +250,37 @@ class user_favourites_service_testcase extends advanced_testcase {
|
||||
$service->find_favourites_by_type('cccore_notreal', 'something');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test confirming the pagination support for the find_favourites_by_type() method.
|
||||
*/
|
||||
public function test_find_favourites_by_type_pagination() {
|
||||
list($user1context, $user2context, $course1context, $course2context) = $this->setup_users_and_courses();
|
||||
|
||||
// Get a user_favourites_service for the user.
|
||||
$repo = $this->get_mock_repository([]);
|
||||
$service = new \core_favourites\local\service\user_favourites_service($user1context, $repo);
|
||||
|
||||
// Favourite 10 arbitrary items.
|
||||
foreach (range(1, 10) as $i) {
|
||||
$service->create_favourite('core_course', 'course', $i, $course1context);
|
||||
}
|
||||
|
||||
// Verify we have 10 favourites.
|
||||
$this->assertCount(10, $service->find_favourites_by_type('core_course', 'course'));
|
||||
|
||||
// Verify we get back 5 favourites for page 1.
|
||||
$favourites = $service->find_favourites_by_type('core_course', 'course', 0, 5);
|
||||
$this->assertCount(5, $favourites);
|
||||
|
||||
// Verify we get back 5 favourites for page 2.
|
||||
$favourites = $service->find_favourites_by_type('core_course', 'course', 5, 5);
|
||||
$this->assertCount(5, $favourites);
|
||||
|
||||
// Verify we get back an empty array if querying page 3.
|
||||
$favourites = $service->find_favourites_by_type('core_course', 'course', 10, 5);
|
||||
$this->assertCount(0, $favourites);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test confirming the basic deletion behaviour.
|
||||
*/
|
||||
|
Loading…
x
Reference in New Issue
Block a user