MDL-63658 core_favourites: add a user favourites repository
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
/**
|
||||
* Contains the crud_repository interface.
|
||||
*
|
||||
* @package core_favourites
|
||||
* @copyright 2018 Jake Dallimore <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace core_favourites\local;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* The crud_repository interface, defining the basic CRUD operations for any repository types within core_favourites.
|
||||
*/
|
||||
interface crud_repository {
|
||||
/**
|
||||
* Add one item to this repository.
|
||||
*
|
||||
* @param \stdClass $item the item to add.
|
||||
* @return \stdClass the item which was added.
|
||||
*/
|
||||
public function add(\stdClass $item) : \stdClass;
|
||||
|
||||
/**
|
||||
* Add all the items in the list to this repository.
|
||||
*
|
||||
* @param array $items the list of items to add.
|
||||
* @return array the list of items added to this repository.
|
||||
*/
|
||||
public function add_all(array $items) : array;
|
||||
|
||||
/**
|
||||
* Find an item in this repository based on its id.
|
||||
*
|
||||
* @param int $id the id of the item.
|
||||
* @return \stdClass the item.
|
||||
*/
|
||||
public function find(int $id) : \stdClass;
|
||||
|
||||
/**
|
||||
* Find all items in this repository.
|
||||
*
|
||||
* @return array list of all items in this repository.
|
||||
*/
|
||||
public function find_all() : array;
|
||||
|
||||
/**
|
||||
* Find all items with attributes matching certain values.
|
||||
*
|
||||
* @param array $criteria the array of attribute/value pairs.
|
||||
* @return array the list of items matching the criteria.
|
||||
*/
|
||||
public function find_by(array $criteria) : array;
|
||||
|
||||
/**
|
||||
* Check whether an item exists in this repository, based on its id.
|
||||
*
|
||||
* @param int $id the id to search for.
|
||||
* @return bool true if the item could be found, false otherwise.
|
||||
*/
|
||||
public function exists(int $id) : bool;
|
||||
|
||||
/**
|
||||
* Return the total number of items in this repository.
|
||||
*
|
||||
* @return int the total number of items.
|
||||
*/
|
||||
public function count() : int;
|
||||
|
||||
/**
|
||||
* Update an item within this repository.
|
||||
*
|
||||
* @param \stdClass $item the item to update.
|
||||
* @return \stdClass the updated item.
|
||||
*/
|
||||
public function update(\stdClass $item) : \stdClass;
|
||||
|
||||
/**
|
||||
* Delete an item by id.
|
||||
*
|
||||
* @param int $id the id of the item to delete.
|
||||
* @return void
|
||||
*/
|
||||
public function delete(int $id);
|
||||
}
|
||||
@@ -0,0 +1,290 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
/**
|
||||
* Contains the user_favourites_repository class, responsible for CRUD operations for user favourites.
|
||||
*
|
||||
* @package core_favourites
|
||||
* @copyright 2018 Jake Dallimore <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace core_favourites\local;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Class favourites_repository.
|
||||
*
|
||||
* This class handles persistence of favourites. Favourites from all areas are supported by this repository.
|
||||
*
|
||||
* @copyright 2018 Jake Dallimore <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class favourites_repository implements ifavourites_repository {
|
||||
|
||||
/**
|
||||
* @var string the name of the table which favourites are stored in.
|
||||
*/
|
||||
protected $favouritetable = 'favourite';
|
||||
|
||||
/**
|
||||
* The favourites_repository constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a favourite to the repository.
|
||||
*
|
||||
* @param \stdClass $favourite the favourite to add.
|
||||
* @return \stdClass the favourite which has been stored.
|
||||
* @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 {
|
||||
global $DB;
|
||||
$this->validate($favourite);
|
||||
$favourite = (array)$favourite;
|
||||
$time = time();
|
||||
$favourite['timecreated'] = $time;
|
||||
$favourite['timemodified'] = $time;
|
||||
$id = $DB->insert_record($this->favouritetable, $favourite);
|
||||
return $this->find($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a collection of favourites to the repository.
|
||||
*
|
||||
* @param array $items the list of favourites to add.
|
||||
* @return array the list of favourites which have been stored.
|
||||
* @throws \dml_exception if any database errors are encountered.
|
||||
* @throws \moodle_exception if any of the favourites have missing or invalid properties.
|
||||
*/
|
||||
public function add_all(array $items) : array {
|
||||
global $DB;
|
||||
$time = time();
|
||||
foreach ($items as $item) {
|
||||
$this->validate($item);
|
||||
$favourite = (array)$item;
|
||||
$favourite['timecreated'] = $time;
|
||||
$favourite['timemodified'] = $time;
|
||||
$ids[] = $DB->insert_record($this->favouritetable, $favourite);
|
||||
}
|
||||
list($insql, $params) = $DB->get_in_or_equal($ids);
|
||||
return $DB->get_records_select($this->favouritetable, "id $insql", $params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a favourite by id.
|
||||
*
|
||||
* @param int $id the id of the favourite.
|
||||
* @return \stdClass the favourite.
|
||||
* @throws \dml_exception if any database errors are encountered.
|
||||
*/
|
||||
public function find(int $id) : \stdClass {
|
||||
global $DB;
|
||||
return $DB->get_record($this->favouritetable, ['id' => $id], '*', MUST_EXIST);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all items matching the supplied criteria (a [key => value,..] list).
|
||||
*
|
||||
* @param array $criteria the list of key/value criteria pairs.
|
||||
* @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 {
|
||||
global $DB;
|
||||
return $DB->get_records($this->favouritetable, $criteria);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all items in this repository, as an array, indexed by id.
|
||||
*
|
||||
* @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 {
|
||||
global $DB;
|
||||
return $DB->get_records($this->favouritetable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a specific favourite, based on the properties known to identify it.
|
||||
*
|
||||
* Used if we don't know its id.
|
||||
*
|
||||
* @param int $userid the id of the user to which the favourite belongs.
|
||||
* @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 int $contextid the contextid of the item which was favourited.
|
||||
* @return \stdClass the favourite.
|
||||
* @throws \dml_exception if any database errors are encountered or if the record could not be found.
|
||||
*/
|
||||
public function find_favourite(int $userid, string $component, string $itemtype, int $itemid, int $contextid) : \stdClass {
|
||||
global $DB;
|
||||
// Favourites model: We know that only one favourite can exist based on these properties.
|
||||
return $DB->get_record($this->favouritetable, [
|
||||
'userid' => $userid,
|
||||
'component' => $component,
|
||||
'itemtype' => $itemtype,
|
||||
'itemid' => $itemid,
|
||||
'contextid' => $contextid
|
||||
], '*', MUST_EXIST);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether a favourite exists in this repository, based on its id.
|
||||
*
|
||||
* @param int $id the id to search for.
|
||||
* @return bool true if the favourite exists, false otherwise.
|
||||
* @throws \dml_exception if any database errors are encountered.
|
||||
*/
|
||||
public function exists(int $id) : bool {
|
||||
global $DB;
|
||||
return $DB->record_exists($this->favouritetable, ['id' => $id]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a favourite.
|
||||
*
|
||||
* @param \stdClass $favourite the favourite to update.
|
||||
* @return \stdClass the updated favourite.
|
||||
* @throws \dml_exception if any database errors are encountered.
|
||||
*/
|
||||
public function update(\stdClass $favourite) : \stdClass {
|
||||
global $DB;
|
||||
$time = time();
|
||||
$favourite->timemodified = $time;
|
||||
$DB->update_record($this->favouritetable, $favourite);
|
||||
return $this->find($favourite->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a favourite, by id.
|
||||
*
|
||||
* @param int $id the id of the favourite to delete.
|
||||
* @throws \dml_exception if any database errors are encountered.
|
||||
*/
|
||||
public function delete(int $id) {
|
||||
global $DB;
|
||||
$DB->delete_records($this->favouritetable, ['id' => $id]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the total number of favourites in this repository.
|
||||
*
|
||||
* @return int the total number of items.
|
||||
* @throws \dml_exception if any database errors are encountered.
|
||||
*/
|
||||
public function count() : int {
|
||||
global $DB;
|
||||
return $DB->count_records($this->favouritetable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for the existence of a favourite item in the specified area.
|
||||
*
|
||||
* A favourite item is identified by the itemid/contextid pair.
|
||||
* An area is identified by the component/itemtype pair.
|
||||
*
|
||||
* @param int $userid the id of user to whom the favourite belongs.
|
||||
* @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 int $contextid the contextid of the item which was favourited.
|
||||
* @return bool true if the favourited item exists, false otherwise.
|
||||
* @throws \dml_exception if any database errors are encountered.
|
||||
*/
|
||||
public function exists_by_area(int $userid, string $component, string $itemtype, int $itemid, int $contextid) : bool {
|
||||
global $DB;
|
||||
return $DB->record_exists($this->favouritetable,
|
||||
[
|
||||
'userid' => $userid,
|
||||
'component' => $component,
|
||||
'itemtype' => $itemtype,
|
||||
'itemid' => $itemid,
|
||||
'contextid' => $contextid
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all favourites within the component/itemtype.
|
||||
*
|
||||
* @param int $userid the id of the user to whom the favourite belongs.
|
||||
* @param string $component the frankenstyle component name.
|
||||
* @param string $itemtype the type of the favourited item.
|
||||
* @throws \dml_exception if any database errors are encountered.
|
||||
*/
|
||||
public function delete_by_area(int $userid, string $component, string $itemtype) {
|
||||
global $DB;
|
||||
$DB->delete_records($this->favouritetable,
|
||||
[
|
||||
'userid' => $userid,
|
||||
'component' => $component,
|
||||
'itemtype' => $itemtype
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the number of user favourites matching the specified criteria.
|
||||
*
|
||||
* @param array $criteria the list of key/value criteria pairs.
|
||||
* @return int the number of favourites matching the criteria.
|
||||
* @throws \dml_exception if any database errors are encountered.
|
||||
*/
|
||||
public function count_by(array $criteria) : int {
|
||||
global $DB;
|
||||
return $DB->count_records($this->favouritetable, $criteria);
|
||||
}
|
||||
|
||||
/**
|
||||
* Basic validation, confirming we have the minimum field set needed to save a record to the store.
|
||||
*
|
||||
* @param \stdClass $favourite the favourite record to validate.
|
||||
* @throws \moodle_exception if the supplied favourite has missing or unsupported fields.
|
||||
*/
|
||||
protected function validate(\stdClass $favourite) {
|
||||
|
||||
$favourite = (array)$favourite;
|
||||
|
||||
// The allowed fields, and whether or not each is required.
|
||||
// The timecreated field is generated during create/update, and cannot be specified either.
|
||||
$allowedfields = [
|
||||
'userid' => true,
|
||||
'component' => true,
|
||||
'itemtype' => true,
|
||||
'itemid' => true,
|
||||
'contextid' => true,
|
||||
'ordering' => false
|
||||
];
|
||||
|
||||
$requiredfields = array_filter($allowedfields, function($field) {
|
||||
return $field;
|
||||
});
|
||||
|
||||
if ($missingfields = array_keys(array_diff_key($requiredfields, $favourite))) {
|
||||
throw new \moodle_exception("Missing object property(s) '" . join(', ', $missingfields) . "'.");
|
||||
}
|
||||
|
||||
// If the record contains fields we don't allow, throw an exception.
|
||||
if ($unsupportedfields = array_keys(array_diff_key($favourite, $allowedfields))) {
|
||||
throw new \moodle_exception("Unexpected object property(s) '" . join(', ', $unsupportedfields) . "'.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
/**
|
||||
* Contains the favourites_repository interface.
|
||||
*
|
||||
* @package core_favourites
|
||||
* @copyright 2018 Jake Dallimore <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
namespace core_favourites\local;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* The favourites_repository interface, defining additional operations useful to favourites type repositories.
|
||||
*
|
||||
* @copyright 2018 Jake Dallimore <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
interface ifavourites_repository extends crud_repository {
|
||||
/**
|
||||
* Find a single favourite, based on it's unique identifiers.
|
||||
*
|
||||
* @param int $userid the id of the user to which the favourite belongs.
|
||||
* @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 int $contextid the contextid of the item which was favourited.
|
||||
* @return \stdClass the favourite.
|
||||
*/
|
||||
public function find_favourite(int $userid, string $component, string $itemtype, int $itemid, int $contextid) : \stdClass;
|
||||
}
|
||||
@@ -0,0 +1,439 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Testing the repository objects within core_favourites.
|
||||
*
|
||||
* @package core_favourites
|
||||
* @category test
|
||||
* @copyright 2018 Jake Dallimore <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
use \core_favourites\local\favourites_repository;
|
||||
|
||||
/**
|
||||
* Test class covering the favourites_repository.
|
||||
*
|
||||
* @copyright 2018 Jake Dallimore <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class favourites_repository_testcase extends advanced_testcase {
|
||||
|
||||
public function setUp() {
|
||||
$this->resetAfterTest();
|
||||
}
|
||||
|
||||
// Basic setup stuff to be reused in most tests.
|
||||
protected function setup_users_and_courses() {
|
||||
$user1 = self::getDataGenerator()->create_user();
|
||||
$user1context = \context_user::instance($user1->id);
|
||||
$user2 = self::getDataGenerator()->create_user();
|
||||
$user2context = \context_user::instance($user2->id);
|
||||
$course1 = self::getDataGenerator()->create_course();
|
||||
$course2 = self::getDataGenerator()->create_course();
|
||||
$course1context = context_course::instance($course1->id);
|
||||
$course2context = context_course::instance($course2->id);
|
||||
return [$user1context, $user2context, $course1context, $course2context];
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the basic create operation can create records, and is validated.
|
||||
*/
|
||||
public function test_add() {
|
||||
list($user1context, $user2context, $course1context, $course2context) = $this->setup_users_and_courses();
|
||||
|
||||
// Create a favourites repository and favourite a course.
|
||||
$favouritesrepo = new favourites_repository($user1context);
|
||||
|
||||
$favcourse = (object)[
|
||||
'userid' => $user1context->instanceid,
|
||||
'component' => 'core_course',
|
||||
'itemtype' => 'course',
|
||||
'itemid' => $course1context->instanceid,
|
||||
'contextid' => $course1context->id,
|
||||
];
|
||||
$timenow = time(); // Reference only, to check that the created item has a time equal to or greater than this.
|
||||
$favourite = $favouritesrepo->add($favcourse);
|
||||
|
||||
// Verify we get the record back.
|
||||
$this->assertInstanceOf(\stdClass::class, $favourite);
|
||||
$this->assertEquals('core_course', $favourite->component);
|
||||
$this->assertEquals('course', $favourite->itemtype);
|
||||
|
||||
// Verify the returned object has additional properties, created as part of the add.
|
||||
$this->assertObjectHasAttribute('ordering', $favourite);
|
||||
$this->assertObjectHasAttribute('timecreated', $favourite);
|
||||
$this->assertGreaterThanOrEqual($timenow, $favourite->timecreated);
|
||||
|
||||
// Try to save the same record again and confirm the store throws an exception.
|
||||
$this->expectException('dml_write_exception');
|
||||
$favouritesrepo->add($favcourse);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that malformed favourites cannot be saved.
|
||||
*/
|
||||
public function test_add_malformed_favourite() {
|
||||
list($user1context, $user2context, $course1context, $course2context) = $this->setup_users_and_courses();
|
||||
|
||||
// Create a favourites repository and favourite a course.
|
||||
$favouritesrepo = new favourites_repository($user1context);
|
||||
|
||||
$favcourse = (object)[
|
||||
'userid' => $user1context->instanceid,
|
||||
'component' => 'core_course',
|
||||
'itemtype' => 'course',
|
||||
'itemid' => $course1context->instanceid,
|
||||
'contextid' => $course1context->id,
|
||||
'anotherfield' => 'cat'
|
||||
];
|
||||
|
||||
$this->expectException('moodle_exception');
|
||||
$favouritesrepo->add($favcourse);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that incomplete favourites cannot be saved.
|
||||
*/
|
||||
public function test_add_incomplete_favourite() {
|
||||
list($user1context, $user2context, $course1context, $course2context) = $this->setup_users_and_courses();
|
||||
|
||||
// Create a favourites repository and favourite a course.
|
||||
$favouritesrepo = new favourites_repository($user1context);
|
||||
|
||||
$favcourse = (object)[
|
||||
'component' => 'core_course',
|
||||
'itemtype' => 'course',
|
||||
'itemid' => $course1context->instanceid
|
||||
];
|
||||
|
||||
$this->expectException('moodle_exception');
|
||||
$favouritesrepo->add($favcourse);
|
||||
}
|
||||
|
||||
public function test_add_all_basic() {
|
||||
list($user1context, $user2context, $course1context, $course2context) = $this->setup_users_and_courses();
|
||||
|
||||
// Create a favourites repository and favourite several courses.
|
||||
$favouritesrepo = new favourites_repository($user1context);
|
||||
$favcourses = [];
|
||||
|
||||
$favcourses[] = (object)[
|
||||
'userid' => $user1context->instanceid,
|
||||
'component' => 'core_course',
|
||||
'itemtype' => 'course',
|
||||
'itemid' => $course1context->instanceid,
|
||||
'contextid' => $course1context->id,
|
||||
];
|
||||
$favcourses[] = (object)[
|
||||
'userid' => $user1context->instanceid,
|
||||
'component' => 'core_course',
|
||||
'itemtype' => 'course',
|
||||
'itemid' => $course2context->instanceid,
|
||||
'contextid' => $course2context->id,
|
||||
];
|
||||
$timenow = time(); // Reference only, to check that the created item has a time equal to or greater than this.
|
||||
$favourites = $favouritesrepo->add_all($favcourses);
|
||||
|
||||
$this->assertInternalType('array', $favourites);
|
||||
$this->assertCount(2, $favourites);
|
||||
foreach ($favourites as $favourite) {
|
||||
// Verify we get the record back.
|
||||
$this->assertEquals('core_course', $favourite->component);
|
||||
$this->assertEquals('course', $favourite->itemtype);
|
||||
|
||||
// Verify the returned object has additional properties, created as part of the add.
|
||||
$this->assertObjectHasAttribute('ordering', $favourite);
|
||||
$this->assertObjectHasAttribute('timecreated', $favourite);
|
||||
$this->assertGreaterThanOrEqual($timenow, $favourite->timecreated);
|
||||
}
|
||||
|
||||
// Try to save the same record again and confirm the store throws an exception.
|
||||
$this->expectException('dml_write_exception');
|
||||
$favouritesrepo->add_all($favcourses);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests reading from the repository by instance id.
|
||||
*/
|
||||
public function test_find() {
|
||||
list($user1context, $user2context, $course1context, $course2context) = $this->setup_users_and_courses();
|
||||
|
||||
// Create a favourites repository and favourite a course.
|
||||
$favouritesrepo = new favourites_repository($user1context);
|
||||
$favourite = (object) [
|
||||
'userid' => $user1context->instanceid,
|
||||
'component' => 'core_course',
|
||||
'itemtype' => 'course',
|
||||
'itemid' => $course1context->instanceid,
|
||||
'contextid' => $course1context->id
|
||||
];
|
||||
$favourite = $favouritesrepo->add($favourite);
|
||||
|
||||
// Now, from the repo, get the single favourite we just created, by id.
|
||||
$userfavourite = $favouritesrepo->find($favourite->id);
|
||||
$this->assertInstanceOf(\stdClass::class, $userfavourite);
|
||||
$this->assertObjectHasAttribute('timecreated', $userfavourite);
|
||||
|
||||
// Try to get a favourite we know doesn't exist.
|
||||
// We expect an exception in this case.
|
||||
$this->expectException(dml_exception::class);
|
||||
$favouritesrepo->find(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test verifying that find_all() returns all favourites, or an empty array.
|
||||
*/
|
||||
public function test_find_all() {
|
||||
list($user1context, $user2context, $course1context, $course2context) = $this->setup_users_and_courses();
|
||||
|
||||
$favouritesrepo = new favourites_repository($user1context);
|
||||
|
||||
// Verify that for an empty repository, find_all returns an empty array.
|
||||
$this->assertEquals([], $favouritesrepo->find_all());
|
||||
|
||||
// Save a favourite for 2 courses, in different areas.
|
||||
$favourite = (object) [
|
||||
'userid' => $user1context->instanceid,
|
||||
'component' => 'core_course',
|
||||
'itemtype' => 'course',
|
||||
'itemid' => $course1context->instanceid,
|
||||
'contextid' => $course1context->id
|
||||
];
|
||||
$favourite2 = (object) [
|
||||
'userid' => $user1context->instanceid,
|
||||
'component' => 'core_course',
|
||||
'itemtype' => 'anothertype',
|
||||
'itemid' => $course2context->instanceid,
|
||||
'contextid' => $course2context->id
|
||||
];
|
||||
$favouritesrepo->add($favourite);
|
||||
$favouritesrepo->add($favourite2);
|
||||
|
||||
// Verify that find_all returns both of our favourites.
|
||||
$favourites = $favouritesrepo->find_all();
|
||||
$this->assertCount(2, $favourites);
|
||||
foreach ($favourites as $fav) {
|
||||
$this->assertObjectHasAttribute('id', $fav);
|
||||
$this->assertObjectHasAttribute('timecreated', $fav);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test retrieval of a user's favourites for a given criteria, in this case, area.
|
||||
*/
|
||||
public function test_find_by() {
|
||||
list($user1context, $user2context, $course1context, $course2context) = $this->setup_users_and_courses();
|
||||
|
||||
// Create a favourites repository and favourite a course.
|
||||
$favouritesrepo = new favourites_repository($user1context);
|
||||
$favourite = (object) [
|
||||
'userid' => $user1context->instanceid,
|
||||
'component' => 'core_course',
|
||||
'itemtype' => 'course',
|
||||
'itemid' => $course1context->instanceid,
|
||||
'contextid' => $course1context->id
|
||||
];
|
||||
$favouritesrepo->add($favourite);
|
||||
|
||||
// From the repo, get the list of favourites for the 'core_course/course' area.
|
||||
$userfavourites = $favouritesrepo->find_by(['component' => 'core_course', 'itemtype' => 'course']);
|
||||
$this->assertInternalType('array', $userfavourites);
|
||||
$this->assertCount(1, $userfavourites);
|
||||
|
||||
// Try to get a list of favourites for a non-existent area.
|
||||
$userfavourites = $favouritesrepo->find_by(['component' => 'core_cannibalism', 'itemtype' => 'course']);
|
||||
$this->assertInternalType('array', $userfavourites);
|
||||
$this->assertCount(0, $userfavourites);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the count_by() method.
|
||||
*/
|
||||
public function test_count_by() {
|
||||
list($user1context, $user2context, $course1context, $course2context) = $this->setup_users_and_courses();
|
||||
|
||||
// Create a favourites repository and add 2 favourites in different areas.
|
||||
$favouritesrepo = new favourites_repository($user1context);
|
||||
$favourite = (object) [
|
||||
'userid' => $user1context->instanceid,
|
||||
'component' => 'core_course',
|
||||
'itemtype' => 'course',
|
||||
'itemid' => $course1context->instanceid,
|
||||
'contextid' => $course1context->id
|
||||
];
|
||||
$favourite2 = (object) [
|
||||
'userid' => $user1context->instanceid,
|
||||
'component' => 'core_course',
|
||||
'itemtype' => 'anothertype',
|
||||
'itemid' => $course2context->instanceid,
|
||||
'contextid' => $course2context->id
|
||||
];
|
||||
$favouritesrepo->add($favourite);
|
||||
$favouritesrepo->add($favourite2);
|
||||
|
||||
// Verify counts can be restricted by criteria.
|
||||
$this->assertEquals(1, $favouritesrepo->count_by(['userid' => $user1context->instanceid, 'component' => 'core_course',
|
||||
'itemtype' => 'course']));
|
||||
$this->assertEquals(1, $favouritesrepo->count_by(['userid' => $user1context->instanceid, 'component' => 'core_course',
|
||||
'itemtype' => 'anothertype']));
|
||||
$this->assertEquals(0, $favouritesrepo->count_by(['userid' => $user1context->instanceid, 'component' => 'core_course',
|
||||
'itemtype' => 'nonexistenttype']));
|
||||
}
|
||||
|
||||
public function test_exists() {
|
||||
list($user1context, $user2context, $course1context, $course2context) = $this->setup_users_and_courses();
|
||||
|
||||
// Create a favourites repository and favourite a course.
|
||||
$favouritesrepo = new favourites_repository($user1context);
|
||||
$favourite = (object) [
|
||||
'userid' => $user1context->instanceid,
|
||||
'component' => 'core_course',
|
||||
'itemtype' => 'course',
|
||||
'itemid' => $course1context->instanceid,
|
||||
'contextid' => $course1context->id
|
||||
];
|
||||
$createdfavourite = $favouritesrepo->add($favourite);
|
||||
|
||||
// Verify the existence of the favourite in the repo.
|
||||
$this->assertTrue($favouritesrepo->exists($createdfavourite->id));
|
||||
|
||||
// Verify exists returns false for non-existent favourite.
|
||||
$this->assertFalse($favouritesrepo->exists(1));
|
||||
}
|
||||
|
||||
public function test_exists_by_area() {
|
||||
list($user1context, $user2context, $course1context, $course2context) = $this->setup_users_and_courses();
|
||||
|
||||
// Create a favourites repository and favourite two courses, in different areas.
|
||||
$favouritesrepo = new favourites_repository($user1context);
|
||||
$favourite = (object) [
|
||||
'userid' => $user1context->instanceid,
|
||||
'component' => 'core_course',
|
||||
'itemtype' => 'course',
|
||||
'itemid' => $course1context->instanceid,
|
||||
'contextid' => $course1context->id
|
||||
];
|
||||
$favourite2 = (object) [
|
||||
'userid' => $user1context->instanceid,
|
||||
'component' => 'core_course',
|
||||
'itemtype' => 'anothertype',
|
||||
'itemid' => $course2context->instanceid,
|
||||
'contextid' => $course2context->id
|
||||
];
|
||||
$favourite1 = $favouritesrepo->add($favourite);
|
||||
$favourite2 = $favouritesrepo->add($favourite2);
|
||||
|
||||
// Verify the existence of the favourites.
|
||||
$this->assertTrue($favouritesrepo->exists_by_area($user1context->instanceid, 'core_course', 'course', $favourite1->itemid,
|
||||
$favourite1->contextid));
|
||||
$this->assertTrue($favouritesrepo->exists_by_area($user1context->instanceid, 'core_course', 'anothertype',
|
||||
$favourite2->itemid, $favourite2->contextid));
|
||||
|
||||
// Verify that we can't find a favourite from one area, in another.
|
||||
$this->assertFalse($favouritesrepo->exists_by_area($user1context->instanceid, 'core_course', 'anothertype',
|
||||
$favourite1->itemid, $favourite1->contextid));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the update() method, by simulating a user changing the ordering of a favourite.
|
||||
*/
|
||||
public function test_update() {
|
||||
list($user1context, $user2context, $course1context, $course2context) = $this->setup_users_and_courses();
|
||||
|
||||
// Create a favourites repository and favourite a course.
|
||||
$favouritesrepo = new favourites_repository($user1context);
|
||||
$favourite = (object) [
|
||||
'userid' => $user1context->instanceid,
|
||||
'component' => 'core_course',
|
||||
'itemtype' => 'course',
|
||||
'itemid' => $course1context->instanceid,
|
||||
'contextid' => $course1context->id
|
||||
];
|
||||
$favourite1 = $favouritesrepo->add($favourite);
|
||||
|
||||
// Verify we can update the ordering for 2 favourites.
|
||||
$favourite1->ordering = 1;
|
||||
$favourite1 = $favouritesrepo->update($favourite1);
|
||||
$this->assertInstanceOf(stdClass::class, $favourite1);
|
||||
$this->assertAttributeEquals('1', 'ordering', $favourite1);
|
||||
}
|
||||
|
||||
public function test_delete() {
|
||||
list($user1context, $user2context, $course1context, $course2context) = $this->setup_users_and_courses();
|
||||
|
||||
// Create a favourites repository and favourite a course.
|
||||
$favouritesrepo = new favourites_repository($user1context);
|
||||
$favourite = (object) [
|
||||
'userid' => $user1context->instanceid,
|
||||
'component' => 'core_course',
|
||||
'itemtype' => 'course',
|
||||
'itemid' => $course1context->instanceid,
|
||||
'contextid' => $course1context->id
|
||||
];
|
||||
$favourite = $favouritesrepo->add($favourite);
|
||||
|
||||
// Verify the existence of the favourite in the repo.
|
||||
$this->assertTrue($favouritesrepo->exists($favourite->id));
|
||||
|
||||
// Now, delete the favourite and confirm it's not retrievable.
|
||||
$favouritesrepo->delete($favourite->id);
|
||||
$this->assertFalse($favouritesrepo->exists($favourite->id));
|
||||
}
|
||||
|
||||
public function test_delete_by_area() {
|
||||
list($user1context, $user2context, $course1context, $course2context) = $this->setup_users_and_courses();
|
||||
|
||||
// Create a favourites repository and favourite two courses, in different areas.
|
||||
$favouritesrepo = new favourites_repository($user1context);
|
||||
$favourite = (object) [
|
||||
'userid' => $user1context->instanceid,
|
||||
'component' => 'core_course',
|
||||
'itemtype' => 'course',
|
||||
'itemid' => $course1context->instanceid,
|
||||
'contextid' => $course1context->id
|
||||
];
|
||||
$favourite2 = (object) [
|
||||
'userid' => $user1context->instanceid,
|
||||
'component' => 'core_course',
|
||||
'itemtype' => 'anothertype',
|
||||
'itemid' => $course2context->instanceid,
|
||||
'contextid' => $course2context->id
|
||||
];
|
||||
$favourite1 = $favouritesrepo->add($favourite);
|
||||
$favourite2 = $favouritesrepo->add($favourite2);
|
||||
|
||||
// Verify we have 2 items in the repo.
|
||||
$this->assertEquals(2, $favouritesrepo->count());
|
||||
|
||||
// Try to delete by a non-existent area, and confirm it doesn't remove anything.
|
||||
$favouritesrepo->delete_by_area($user1context->instanceid, 'core_course', 'donaldduck');
|
||||
$this->assertEquals(2, $favouritesrepo->count());
|
||||
|
||||
// Try to delete by a non-existent area, and confirm it doesn't remove anything.
|
||||
$favouritesrepo->delete_by_area($user1context->instanceid, 'core_course', 'cat');
|
||||
$this->assertEquals(2, $favouritesrepo->count());
|
||||
|
||||
// Delete by area, and confirm we have one record left, from the 'core_course/anothertype' area.
|
||||
$favouritesrepo->delete_by_area($user1context->instanceid, 'core_course', 'course');
|
||||
$this->assertEquals(1, $favouritesrepo->count());
|
||||
$this->assertFalse($favouritesrepo->exists($favourite1->id));
|
||||
$this->assertTrue($favouritesrepo->exists($favourite2->id));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user