Skip to content

Commit

Permalink
MDL-63658 core_favourites: make favourite a first class object
Browse files Browse the repository at this point in the history
This patch adds several things:
- favourite entity class under local/entity
- refactoring of repository and service to use the new class instead
of stdClass.
- update repository unit tests to use the object instead of stdClass.
- update service_test so that the mock repo requires the object for
the add operation.
- remove unnecessary constructor from favourites_repository class.
  • Loading branch information
snake committed Oct 18, 2018
1 parent 8ffbe9c commit cfaf86b
Show file tree
Hide file tree
Showing 8 changed files with 311 additions and 191 deletions.
77 changes: 77 additions & 0 deletions favourites/classes/local/entity/favourite.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<?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 favourite class, each instance being a representation of a DB row for the 'favourite' table.
*
* @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\entity;

defined('MOODLE_INTERNAL') || die();

/**
* Contains the favourite class, each instance being a representation of a DB row for the 'favourite' table.
*
* @copyright 2018 Jake Dallimore <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class favourite {
/** @var int $id the id of the favourite.*/
public $id;

/** @var string $component the frankenstyle name of the component containing the favourited item. E.g. 'core_course'.*/
public $component;

/** @var string $itemtype the type of the item being marked as a favourite. E.g. 'course', 'conversation', etc.*/
public $itemtype;

/** @var int $itemid the id of the item that is being marked as a favourite. e.g course->id, conversation->id, etc.*/
public $itemid;

/** @var int $contextid the id of the context in which this favourite was created.*/
public $contextid;

/** @var int $userid the id of user who owns this favourite.*/
public $userid;

/** @var int $ordering the ordering of the favourite within it's favourite area.*/
public $ordering;

/** @var int $timecreated the time at which the favourite was created.*/
public $timecreated;

/** @var int $timemodified the time at which the last modification of the favourite took place.*/
public $timemodified;

/**
* Favourite constructor.
* @param string $component the frankenstyle name of the component containing the favourited item. E.g. 'core_course'.
* @param string $itemtype the type of the item being marked as a favourite. E.g. 'course', 'conversation', etc.
* @param int $itemid the id of the item that is being marked as a favourite. e.g course->id, conversation->id, etc.
* @param int $contextid the id of the context in which this favourite was created.
* @param int $userid the id of user who owns this favourite.
*/
public function __construct(string $component, string $itemtype, int $itemid, int $contextid, int $userid) {
$this->component = $component;
$this->itemtype = $itemtype;
$this->itemid = $itemid;
$this->contextid = $contextid;
$this->userid = $userid;
}
}
17 changes: 9 additions & 8 deletions favourites/classes/local/repository/crud_repository.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace core_favourites\local\repository;
use \core_favourites\local\entity\favourite;

defined('MOODLE_INTERNAL') || die();

Expand All @@ -31,10 +32,10 @@ interface crud_repository {
/**
* Add one item to this repository.
*
* @param object $item the item to add.
* @return object the item which was added.
* @param favourite $item the item to add.
* @return favourite the item which was added.
*/
public function add($item);
public function add(favourite $item) : favourite;

/**
* Add all the items in the list to this repository.
Expand All @@ -48,9 +49,9 @@ 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 object the item.
* @return favourite the item.
*/
public function find(int $id);
public function find(int $id) : favourite;

/**
* Find all items in this repository.
Expand Down Expand Up @@ -89,10 +90,10 @@ public function count() : int;
/**
* Update an item within this repository.
*
* @param object $item the item to update.
* @return object the updated item.
* @param favourite $item the item to update.
* @return favourite the updated item.
*/
public function update($item);
public function update(favourite $item) : favourite;

/**
* Delete an item by id.
Expand Down
83 changes: 60 additions & 23 deletions favourites/classes/local/repository/favourites_repository.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,14 @@
// 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.
* Contains the favourites_repository class, responsible for CRUD operations for 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\repository;
use \core_favourites\local\entity\favourite;

defined('MOODLE_INTERNAL') || die();

Expand All @@ -40,20 +41,48 @@ class favourites_repository implements ifavourites_repository {
protected $favouritetable = 'favourite';

/**
* The favourites_repository constructor.
* Get a favourite object, based on a full record.
* @param \stdClass $record the record we wish to hydrate.
* @return favourite the favourite record.
*/
public function __construct() {
protected function get_favourite_from_record(\stdClass $record) : favourite {
$favourite = new favourite(
$record->component,
$record->itemtype,
$record->itemid,
$record->contextid,
$record->userid
);
$favourite->id = $record->id;
$favourite->ordering = $record->ordering ?? null;
$favourite->timecreated = $record->timecreated ?? null;
$favourite->timemodified = $record->timemodified ?? null;

return $favourite;
}

/**
* Get a list of favourite objects, based on a list of records.
* @param array $records the record we wish to hydrate.
* @return array the list of favourites.
*/
protected function get_list_of_favourites_from_records(array $records) {
$list = [];
foreach ($records as $index => $record) {
$list[$index] = $this->get_favourite_from_record($record);
}
return $list;
}

/**
* Add a favourite to the repository.
*
* @param \stdClass $favourite the favourite to add.
* @return \stdClass the favourite which has been stored.
* @param favourite $favourite the favourite to add.
* @return favourite 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($favourite) : \stdClass {
public function add(favourite $favourite) : favourite {
global $DB;
$this->validate($favourite);
$favourite = (array)$favourite;
Expand Down Expand Up @@ -83,19 +112,21 @@ public function add_all(array $items) : array {
$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);
$records = $DB->get_records_select($this->favouritetable, "id $insql", $params);
return $this->get_list_of_favourites_from_records($records);
}

/**
* Find a favourite by id.
*
* @param int $id the id of the favourite.
* @return \stdClass the favourite.
* @return favourite the favourite.
* @throws \dml_exception if any database errors are encountered.
*/
public function find(int $id) : \stdClass {
public function find(int $id) : favourite {
global $DB;
return $DB->get_record($this->favouritetable, ['id' => $id], '*', MUST_EXIST);
$record = $DB->get_record($this->favouritetable, ['id' => $id], '*', MUST_EXIST);
return $this->get_favourite_from_record($record);
}

/**
Expand All @@ -109,7 +140,8 @@ public function find(int $id) : \stdClass {
*/
public function find_by(array $criteria, int $limitfrom = 0, int $limitnum = 0) : array {
global $DB;
return $DB->get_records($this->favouritetable, $criteria, '', '*', $limitfrom, $limitnum);
$records = $DB->get_records($this->favouritetable, $criteria, '', '*', $limitfrom, $limitnum);
return $this->get_list_of_favourites_from_records($records);
}

/**
Expand All @@ -122,7 +154,8 @@ public function find_by(array $criteria, int $limitfrom = 0, int $limitnum = 0)
*/
public function find_all(int $limitfrom = 0, int $limitnum = 0) : array {
global $DB;
return $DB->get_records($this->favouritetable, null, '', '*', $limitfrom, $limitnum);
$records = $DB->get_records($this->favouritetable, null, '', '*', $limitfrom, $limitnum);
return $this->get_list_of_favourites_from_records($records);
}

/**
Expand All @@ -135,19 +168,20 @@ public function find_all(int $limitfrom = 0, int $limitnum = 0) : array {
* @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.
* @return favourite 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 {
public function find_favourite(int $userid, string $component, string $itemtype, int $itemid, int $contextid) : favourite {
global $DB;
// Favourites model: We know that only one favourite can exist based on these properties.
return $DB->get_record($this->favouritetable, [
$record = $DB->get_record($this->favouritetable, [
'userid' => $userid,
'component' => $component,
'itemtype' => $itemtype,
'itemid' => $itemid,
'contextid' => $contextid
], '*', MUST_EXIST);
return $this->get_favourite_from_record($record);
}

/**
Expand All @@ -165,11 +199,11 @@ public function exists(int $id) : bool {
/**
* Update a favourite.
*
* @param \stdClass $favourite the favourite to update.
* @return \stdClass the updated favourite.
* @param favourite $favourite the favourite to update.
* @return favourite the updated favourite.
* @throws \dml_exception if any database errors are encountered.
*/
public function update($favourite) : \stdClass {
public function update(favourite $favourite) : favourite {
global $DB;
$time = time();
$favourite->timemodified = $time;
Expand Down Expand Up @@ -260,22 +294,25 @@ public function count_by(array $criteria) : int {
/**
* 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.
* @param favourite $favourite the favourite record to validate.
* @throws \moodle_exception if the supplied favourite has missing or unsupported fields.
*/
protected function validate(\stdClass $favourite) {
protected function validate(favourite $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.
// The allowed fields, and whether or not each is required to create a record.
// The timecreated, timemodified and id fields are generated during create/update.
$allowedfields = [
'userid' => true,
'component' => true,
'itemtype' => true,
'itemid' => true,
'contextid' => true,
'ordering' => false
'ordering' => false,
'timecreated' => false,
'timemodified' => false,
'id' => false
];

$requiredfields = array_filter($allowedfields, function($field) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,12 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace core_favourites\local\repository;
use \core_favourites\local\entity\favourite;

defined('MOODLE_INTERNAL') || die();

/**
* The favourites_repository interface, defining additional operations useful to favourites type repositories.
* The favourites_repository interface, defining additional operations useful to favourite type repositories.
*
* @copyright 2018 Jake Dallimore <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
Expand All @@ -39,7 +40,7 @@ interface ifavourites_repository extends crud_repository {
* @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.
* @return favourite the favourite.
*/
public function find_favourite(int $userid, string $component, string $itemtype, int $itemid, int $contextid) : \stdClass;
public function find_favourite(int $userid, string $component, string $itemtype, int $itemid, int $contextid) : favourite;
}
15 changes: 5 additions & 10 deletions favourites/classes/local/service/user_favourites_service.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace core_favourites\local\service;
use \core_favourites\local\entity\favourite;

defined('MOODLE_INTERNAL') || die();

Expand Down Expand Up @@ -74,26 +75,20 @@ protected function get_component_list() {
* @param int $itemid the id of the item which is to be favourited.
* @param \context $context the context in which the item is to be favourited.
* @param int|null $ordering optional ordering integer used for sorting the favourites in an area.
* @return \stdClass the favourite, once created.
* @return favourite the favourite, once created.
* @throws \moodle_exception if the component name is invalid, or if the repository encounters any errors.
*/
public function create_favourite(string $component, string $itemtype, int $itemid, \context $context,
int $ordering = null) : \stdClass {
int $ordering = null) : favourite {
// Access: Any component can ask to favourite something, we can't verify access to that 'something' here though.

// Validate the component name.
if (!in_array($component, $this->get_component_list())) {
throw new \moodle_exception("Invalid component name '$component'");
}

$favourite = (object) [
'userid' => $this->userid,
'component' => $component,
'itemtype' => $itemtype,
'itemid' => $itemid,
'contextid' => $context->id,
'ordering' => $ordering > 0 ? $ordering : null
];
$favourite = new favourite($component, $itemtype, $itemid, $context->id, $this->userid);
$favourite->ordering = $ordering > 0 ? $ordering : null;
return $this->repo->add($favourite);
}

Expand Down
2 changes: 1 addition & 1 deletion favourites/classes/services.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class services {
* Returns a basic service object providing operations for user favourites.
*
* @param \context_user $context the context of the user to which the service should be scoped.
* @return user_favourites_service the service object.
* @return \core_favourites\local\service\user_favourites_service the service object.
*/
public static function get_service_for_user_context(\context_user $context) : local\service\user_favourites_service {
return new local\service\user_favourites_service($context, new local\repository\favourites_repository());
Expand Down
Loading

0 comments on commit cfaf86b

Please sign in to comment.