first commit

This commit is contained in:
CHIEFSOFT\ameye
2024-09-30 18:11:26 -04:00
commit e592ca6823
27270 changed files with 5002257 additions and 0 deletions
+372
View File
@@ -0,0 +1,372 @@
<?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/>.
/**
* External comment API
*
* @package core_comment
* @category external
* @copyright Costantino Cito <ccito@cvaconsulting.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since Moodle 2.9
*/
use core_external\external_api;
use core_external\external_format_value;
use core_external\external_function_parameters;
use core_external\external_multiple_structure;
use core_external\external_single_structure;
use core_external\external_value;
use core_external\external_warnings;
defined('MOODLE_INTERNAL') || die();
require_once("$CFG->dirroot/comment/lib.php");
/**
* External comment API functions
*
* @package core_comment
* @category external
* @copyright Costantino Cito <ccito@cvaconsulting.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since Moodle 2.9
*/
class core_comment_external extends external_api {
/**
* Returns description of method parameters
*
* @return external_function_parameters
* @since Moodle 2.9
*/
public static function get_comments_parameters() {
return new external_function_parameters(
array(
'contextlevel' => new external_value(PARAM_ALPHA, 'contextlevel system, course, user...'),
'instanceid' => new external_value(PARAM_INT, 'the Instance id of item associated with the context level'),
'component' => new external_value(PARAM_COMPONENT, 'component'),
'itemid' => new external_value(PARAM_INT, 'associated id'),
'area' => new external_value(PARAM_AREA, 'string comment area', VALUE_DEFAULT, ''),
'page' => new external_value(PARAM_INT, 'page number (0 based)', VALUE_DEFAULT, 0),
'sortdirection' => new external_value(PARAM_ALPHA, 'Sort direction: ASC or DESC', VALUE_DEFAULT, 'DESC'),
)
);
}
/**
* Return a list of comments
*
* @param string $contextlevel ('system, course, user', etc..)
* @param int $instanceid
* @param string $component the name of the component
* @param int $itemid the item id
* @param string $area comment area
* @param int $page page number
* @param string $sortdirection sort direction
* @return array of comments and warnings
* @since Moodle 2.9
*/
public static function get_comments($contextlevel, $instanceid, $component, $itemid, $area = '', $page = 0,
$sortdirection = 'DESC') {
global $CFG;
$warnings = array();
$arrayparams = array(
'contextlevel' => $contextlevel,
'instanceid' => $instanceid,
'component' => $component,
'itemid' => $itemid,
'area' => $area,
'page' => $page,
'sortdirection' => $sortdirection,
);
$params = self::validate_parameters(self::get_comments_parameters(), $arrayparams);
$sortdirection = strtoupper($params['sortdirection']);
$directionallowedvalues = array('ASC', 'DESC');
if (!in_array($sortdirection, $directionallowedvalues)) {
throw new invalid_parameter_exception('Invalid value for sortdirection parameter (value: ' . $sortdirection . '),' .
'allowed values are: ' . implode(',', $directionallowedvalues));
}
$context = self::get_context_from_params($params);
self::validate_context($context);
require_capability('moodle/comment:view', $context);
$args = new stdClass;
$args->context = $context;
$args->area = $params['area'];
$args->itemid = $params['itemid'];
$args->component = $params['component'];
$commentobject = new comment($args);
$comments = $commentobject->get_comments($params['page'], $sortdirection);
// False means no permissions to see comments.
if ($comments === false) {
throw new moodle_exception('nopermissions', 'error', '', 'view comments');
}
$options = array('blanktarget' => true);
foreach ($comments as $key => $comment) {
list($comments[$key]->content, $comments[$key]->format) = \core_external\util::format_text($comment->content,
$comment->format,
$context->id,
$params['component'],
'',
0,
$options);
}
$results = array(
'comments' => $comments,
'count' => $commentobject->count(),
'perpage' => (!empty($CFG->commentsperpage)) ? $CFG->commentsperpage : 15,
'canpost' => $commentobject->can_post(),
'warnings' => $warnings
);
return $results;
}
/**
* Returns description of method result value
*
* @return \core_external\external_description
* @since Moodle 2.9
*/
public static function get_comments_returns() {
return new external_single_structure(
array(
'comments' => new external_multiple_structure(
self::get_comment_structure(), 'List of comments'
),
'count' => new external_value(PARAM_INT, 'Total number of comments.', VALUE_OPTIONAL),
'perpage' => new external_value(PARAM_INT, 'Number of comments per page.', VALUE_OPTIONAL),
'canpost' => new external_value(PARAM_BOOL, 'Whether the user can post in this comment area.', VALUE_OPTIONAL),
'warnings' => new external_warnings()
)
);
}
/**
* Helper to get the structure of a single comment.
*
* @return external_single_structure the comment structure.
*/
protected static function get_comment_structure() {
return new external_single_structure(
array(
'id' => new external_value(PARAM_INT, 'Comment ID'),
'content' => new external_value(PARAM_RAW, 'The content text formatted'),
'format' => new external_format_value('content'),
'timecreated' => new external_value(PARAM_INT, 'Time created (timestamp)'),
'strftimeformat' => new external_value(PARAM_NOTAGS, 'Time format'),
'profileurl' => new external_value(PARAM_URL, 'URL profile'),
'fullname' => new external_value(PARAM_NOTAGS, 'fullname'),
'time' => new external_value(PARAM_NOTAGS, 'Time in human format'),
'avatar' => new external_value(PARAM_RAW, 'HTML user picture'),
'userid' => new external_value(PARAM_INT, 'User ID'),
'delete' => new external_value(PARAM_BOOL, 'Permission to delete=true/false', VALUE_OPTIONAL)
), 'comment'
);
}
/**
* Returns description of method parameters for the add_comments method.
*
* @return external_function_parameters
* @since Moodle 3.8
*/
public static function add_comments_parameters() {
return new external_function_parameters(
[
'comments' => new external_multiple_structure(
new external_single_structure(
[
'contextlevel' => new external_value(PARAM_ALPHA, 'contextlevel system, course, user...'),
'instanceid' => new external_value(PARAM_INT, 'the id of item associated with the contextlevel'),
'component' => new external_value(PARAM_COMPONENT, 'component'),
'content' => new external_value(PARAM_RAW, 'component'),
'itemid' => new external_value(PARAM_INT, 'associated id'),
'area' => new external_value(PARAM_AREA, 'string comment area', VALUE_DEFAULT, ''),
]
)
)
]
);
}
/**
* Add a comment or comments.
*
* @param array $comments the array of comments to create.
* @return array the array containing those comments created.
* @throws comment_exception
* @since Moodle 3.8
*/
public static function add_comments($comments) {
global $CFG, $SITE;
if (empty($CFG->usecomments)) {
throw new comment_exception('commentsnotenabled', 'moodle');
}
$params = self::validate_parameters(self::add_comments_parameters(), ['comments' => $comments]);
// Validate every intended comment before creating anything, storing the validated comment for use below.
foreach ($params['comments'] as $index => $comment) {
$context = self::get_context_from_params($comment);
self::validate_context($context);
list($context, $course, $cm) = get_context_info_array($context->id);
if ($context->id == SYSCONTEXTID) {
$course = $SITE;
}
// Initialising comment object.
$args = new stdClass();
$args->context = $context;
$args->course = $course;
$args->cm = $cm;
$args->component = $comment['component'];
$args->itemid = $comment['itemid'];
$args->area = $comment['area'];
$manager = new comment($args);
if (!$manager->can_post()) {
throw new comment_exception('nopermissiontocomment');
}
$params['comments'][$index]['preparedcomment'] = $manager;
}
// Create the comments.
$results = [];
foreach ($params['comments'] as $comment) {
$manager = $comment['preparedcomment'];
$newcomment = $manager->add($comment['content']);
$newcomment->delete = true; // USER created the comment, so they can delete it.
$results[] = $newcomment;
}
return $results;
}
/**
* Returns description of method result value for the add_comments method.
*
* @return \core_external\external_description
* @since Moodle 3.8
*/
public static function add_comments_returns() {
return new external_multiple_structure(
self::get_comment_structure()
);
}
/**
* Returns description of method parameters for the delete_comments() method.
*
* @return external_function_parameters
* @since Moodle 3.8
*/
public static function delete_comments_parameters() {
return new external_function_parameters(
[
'comments' => new external_multiple_structure(
new external_value(PARAM_INT, 'id of the comment', VALUE_DEFAULT, 0)
)
]
);
}
/**
* Deletes a comment or comments.
*
* @param array $comments array of comment ids to be deleted
* @return array
* @throws comment_exception
* @since Moodle 3.8
*/
public static function delete_comments(array $comments) {
global $CFG, $DB, $USER, $SITE;
if (empty($CFG->usecomments)) {
throw new comment_exception('commentsnotenabled', 'moodle');
}
$params = self::validate_parameters(self::delete_comments_parameters(), ['comments' => $comments]);
$commentids = $params['comments'];
list($insql, $inparams) = $DB->get_in_or_equal($commentids);
$commentrecords = $DB->get_records_select('comments', "id {$insql}", $inparams);
// If one or more of the records could not be found, report this and fail early.
if (count($commentrecords) != count($comments)) {
$invalidcomments = array_diff($commentids, array_column($commentrecords, 'id'));
$invalidcommentsstr = implode(',', $invalidcomments);
throw new comment_exception("One or more comments could not be found by id: $invalidcommentsstr");
}
// Make sure we can delete every one of the comments before actually doing so.
$comments = []; // Holds the comment objects, for later deletion.
foreach ($commentrecords as $commentrecord) {
// Validate the context.
list($context, $course, $cm) = get_context_info_array($commentrecord->contextid);
if ($context->id == SYSCONTEXTID) {
$course = $SITE;
}
self::validate_context($context);
// Make sure the user is allowed to delete the comment.
$args = new stdClass;
$args->context = $context;
$args->course = $course;
$args->cm = $cm;
$args->component = $commentrecord->component;
$args->itemid = $commentrecord->itemid;
$args->area = $commentrecord->commentarea;
$manager = new comment($args);
if (!$manager->can_delete($commentrecord)) {
throw new comment_exception('nopermissiontodelentry');
}
// User is allowed to delete it, so store the comment object, for use below in final deletion.
$comments[$commentrecord->id] = $manager;
}
// All comments can be deleted by the user. Make it so.
foreach ($comments as $commentid => $comment) {
$comment->delete($commentid);
}
return [];
}
/**
* Returns description of method result value for the delete_comments() method.
*
* @return \core_external\external_description
* @since Moodle 3.8
*/
public static function delete_comments_returns() {
return new external_warnings();
}
}
+140
View File
@@ -0,0 +1,140 @@
<?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/>.
/**
* Exporting a comment area.
*
* A comment area is the set of information about a defined comments area.
*
* @package core_comment
* @copyright 2015 Frédéric Massart - FMCorz.net
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace core_comment\external;
defined('MOODLE_INTERNAL') || die();
require_once($CFG->dirroot . '/comment/lib.php');
use comment;
use renderer_base;
use stdClass;
/**
* Class for exporting a comment area.
*
* @package core_comment
* @copyright 2015 Frédéric Massart - FMCorz.net
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class comment_area_exporter extends \core\external\exporter {
/** @var comment The comment instance. */
protected $comment = null;
public function __construct(comment $comment, $related = array()) {
$this->comment = $comment;
$data = new stdClass();
$data->component = $comment->get_component();
$data->commentarea = $comment->get_commentarea();
$data->itemid = $comment->get_itemid();
$data->courseid = $comment->get_courseid();
$data->contextid = $comment->get_context()->id;
$data->cid = $comment->get_cid();
parent::__construct($data, $related);
}
protected static function define_properties() {
return array(
'component' => array(
'type' => PARAM_COMPONENT,
),
'commentarea' => array(
'type' => PARAM_AREA,
),
'itemid' => array(
'type' => PARAM_INT,
),
'courseid' => array(
'type' => PARAM_INT,
),
'contextid' => array(
'type' => PARAM_INT,
),
'cid' => array(
'type' => PARAM_ALPHANUMEXT,
),
);
}
protected static function define_other_properties() {
return array(
'autostart' => array(
'type' => PARAM_BOOL,
),
'canpost' => array(
'type' => PARAM_BOOL,
),
'canview' => array(
'type' => PARAM_BOOL,
),
'count' => array(
'type' => PARAM_INT,
),
'collapsediconkey' => array(
'type' => PARAM_RAW,
),
'displaytotalcount' => array(
'type' => PARAM_BOOL,
),
'displaycancel' => array(
'type' => PARAM_BOOL,
),
'fullwidth' => array(
'type' => PARAM_BOOL,
),
'linktext' => array(
'type' => PARAM_RAW,
),
'notoggle' => array(
'type' => PARAM_BOOL,
),
'template' => array(
'type' => PARAM_RAW,
),
'canpostorhascomments' => array(
'type' => PARAM_BOOL
)
);
}
public function get_other_values(renderer_base $output) {
$values = array();
$values['autostart'] = $this->comment->get_autostart();
$values['canpost'] = $this->comment->can_post();
$values['canview'] = $this->comment->can_view();
$values['collapsediconkey'] = right_to_left() ? 't/collapsed_rtl' : 't/collapsed';
$values['count'] = $this->comment->count();
$values['displaycancel'] = $this->comment->get_displaycancel();
$values['displaytotalcount'] = $this->comment->get_displaytotalcount();
$values['fullwidth'] = $this->comment->get_fullwidth();
$values['linktext'] = $this->comment->get_linktext();
$values['notoggle'] = $this->comment->get_notoggle();
$values['template'] = $this->comment->get_template();
$values['canpostorhascomments'] = $values['canpost'] || ($values['canview'] && $values['count'] > 0);
return $values;
}
}
+271
View File
@@ -0,0 +1,271 @@
<?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/>.
/**
* Privacy class for requesting user data.
*
* @package core_comment
* @copyright 2018 Adrian Greeve <adrian@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace core_comment\privacy;
defined('MOODLE_INTERNAL') || die();
use \core_privacy\local\metadata\collection;
use \core_privacy\local\request\transform;
use \core_privacy\local\request\userlist;
/**
* Privacy class for requesting user data.
*
* @package core_comment
* @copyright 2018 Adrian Greeve <adrian@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider implements
\core_privacy\local\metadata\provider,
\core_privacy\local\request\subsystem\plugin_provider,
\core_privacy\local\request\shared_userlist_provider
{
/**
* Returns meta data about this system.
*
* @param collection $collection The initialised collection to add items to.
* @return collection A listing of user data stored through this system.
*/
public static function get_metadata(collection $collection): collection {
$collection->add_database_table('comments', [
'content' => 'privacy:metadata:comment:content',
'timecreated' => 'privacy:metadata:comment:timecreated',
'userid' => 'privacy:metadata:comment:userid',
], 'privacy:metadata:comment');
return $collection;
}
/**
* Writes user data to the writer for the user to download.
*
* @param \context $context The context to export data for.
* @param string $component The component that is calling this function
* @param string $commentarea The comment area related to the component
* @param int $itemid An identifier for a group of comments
* @param array $subcontext The sub-context in which to export this data
* @param bool $onlyforthisuser Only return the comments this user made.
*/
public static function export_comments(\context $context, string $component, string $commentarea, int $itemid,
array $subcontext, bool $onlyforthisuser = true) {
global $USER, $DB;
$params = [
'contextid' => $context->id,
'component' => $component,
'commentarea' => $commentarea,
'itemid' => $itemid
];
$sql = "SELECT c.id, c.content, c.format, c.timecreated, c.userid
FROM {comments} c
WHERE c.contextid = :contextid AND
c.commentarea = :commentarea AND
c.itemid = :itemid AND
(c.component IS NULL OR c.component = :component)";
if ($onlyforthisuser) {
$sql .= " AND c.userid = :userid";
$params['userid'] = $USER->id;
}
$sql .= " ORDER BY c.timecreated DESC";
$rs = $DB->get_recordset_sql($sql, $params);
$comments = [];
foreach ($rs as $record) {
if ($record->userid != $USER->id) {
// Clean HTML in comments that were added by other users.
$comment = ['content' => format_text($record->content, $record->format, ['context' => $context])];
} else {
// Export comments made by this user as they are stored.
$comment = ['content' => $record->content, 'contentformat' => $record->format];
}
$comment += [
'time' => transform::datetime($record->timecreated),
'userid' => transform::user($record->userid),
];
$comments[] = (object)$comment;
}
$rs->close();
if (!empty($comments)) {
$subcontext[] = get_string('commentsubcontext', 'core_comment');
\core_privacy\local\request\writer::with_context($context)
->export_data($subcontext, (object) [
'comments' => $comments,
]);
}
}
/**
* Deletes all comments for a specified context, component, and commentarea.
*
* @param \context $context Details about which context to delete comments for.
* @param string $component Component to delete.
* @param string $commentarea Comment area to delete.
* @param int $itemid The item ID for use with deletion.
*/
public static function delete_comments_for_all_users(\context $context, string $component, string $commentarea = null,
int $itemid = null) {
global $DB;
$params = [
'contextid' => $context->id,
'component' => $component
];
if (isset($commentarea)) {
$params['commentarea'] = $commentarea;
}
if (isset($itemid)) {
$params['itemid'] = $itemid;
}
$DB->delete_records('comments', $params);
}
/**
* Deletes all comments for a specified context, component, and commentarea.
*
* @param \context $context Details about which context to delete comments for.
* @param string $component Component to delete.
* @param string $commentarea Comment area to delete.
* @param string $itemidstest an SQL fragment that the itemid must match. Used
* in the query like WHERE itemid $itemidstest. Must use named parameters,
* and may not use named parameters called contextid, component or commentarea.
* @param array $params any query params used by $itemidstest.
*/
public static function delete_comments_for_all_users_select(\context $context, string $component, string $commentarea,
$itemidstest, $params = []) {
global $DB;
$params += ['contextid' => $context->id, 'component' => $component, 'commentarea' => $commentarea];
$DB->delete_records_select('comments',
'contextid = :contextid AND component = :component AND commentarea = :commentarea AND itemid ' . $itemidstest,
$params);
}
/**
* Deletes all records for a user from a list of approved contexts.
*
* @param \core_privacy\local\request\approved_contextlist $contextlist Contains the user ID and a list of contexts to be
* deleted from.
* @param string $component Component to delete from.
* @param string $commentarea Area to delete from.
* @param int $itemid The item id to delete from.
*/
public static function delete_comments_for_user(\core_privacy\local\request\approved_contextlist $contextlist,
string $component, string $commentarea = null, int $itemid = null) {
global $DB;
$userid = $contextlist->get_user()->id;
$contextids = implode(',', $contextlist->get_contextids());
$params = [
'userid' => $userid,
'component' => $component,
];
$areasql = '';
if (isset($commentarea)) {
$params['commentarea'] = $commentarea;
$areasql = 'AND commentarea = :commentarea';
}
$itemsql = '';
if (isset($itemid)) {
$params['itemid'] = $itemid;
$itemsql = 'AND itemid = :itemid';
}
list($insql, $inparams) = $DB->get_in_or_equal($contextlist->get_contextids(), SQL_PARAMS_NAMED);
$params += $inparams;
$select = "userid = :userid AND component = :component $areasql $itemsql AND contextid $insql";
$DB->delete_records_select('comments', $select, $params);
}
/**
* Deletes all records for a context from a list of approved users.
*
* @param \core_privacy\local\request\approved_userlist $userlist Contains the list of users and
* a context to be deleted from.
* @param string $component Component to delete from.
* @param string $commentarea Area to delete from.
* @param int $itemid The item id to delete from.
*/
public static function delete_comments_for_users(\core_privacy\local\request\approved_userlist $userlist,
string $component, string $commentarea = null, int $itemid = null) {
global $DB;
$context = $userlist->get_context();
$params = [
'contextid' => $context->id,
'component' => $component,
];
$areasql = '';
if (isset($commentarea)) {
$params['commentarea'] = $commentarea;
$areasql = 'AND commentarea = :commentarea';
}
$itemsql = '';
if (isset($itemid)) {
$params['itemid'] = $itemid;
$itemsql = 'AND itemid = :itemid';
}
list($insql, $inparams) = $DB->get_in_or_equal($userlist->get_userids(), SQL_PARAMS_NAMED);
$params += $inparams;
$select = "contextid = :contextid AND component = :component {$areasql} {$itemsql} AND userid {$insql}";
$DB->delete_records_select('comments', $select, $params);
}
/**
* Add the list of users who have commented in the specified constraints.
*
* @param userlist $userlist The userlist to add the users to.
* @param string $alias An alias prefix to use for comment selects to avoid interference with your own sql.
* @param string $component The component to check.
* @param string $area The comment area to check.
* @param int $contextid The context id.
* @param string $insql The SQL to use in a sub-select for the itemid query.
* @param array $params The params required for the insql.
*/
public static function get_users_in_context_from_sql(
userlist $userlist, string $alias, string $component, string $area, int $contextid = null, string $insql = '',
array $params = []) {
if ($insql != '') {
$insql = "AND {$alias}.itemid {$insql}";
}
$contextsql = '';
if (isset($contextid)) {
$contextsql = "AND {$alias}.contextid = :{$alias}contextid";
$params["{$alias}contextid"] = $contextid;
}
// Comment authors.
$sql = "SELECT {$alias}.userid
FROM {comments} {$alias}
WHERE {$alias}.component = :{$alias}component
AND {$alias}.commentarea = :{$alias}commentarea
$contextsql $insql";
$params["{$alias}component"] = $component;
$params["{$alias}commentarea"] = $area;
$userlist->add_from_sql('userid', $sql, $params);
}
}
@@ -0,0 +1,118 @@
<?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/>.
declare(strict_types=1);
namespace core_comment\reportbuilder\datasource;
use core\reportbuilder\local\entities\context;
use core_reportbuilder\datasource;
use core_reportbuilder\local\entities\user;
use core_comment\reportbuilder\local\entities\comment;
/**
* Comments datasource
*
* @package core_comment
* @copyright 2022 Paul Holden <paulh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class comments extends datasource {
/**
* Return user friendly name of the report source
*
* @return string
*/
public static function get_name(): string {
return get_string('comments', 'core_comment');
}
/**
* Initialise report
*/
protected function initialise(): void {
$commententity = new comment();
$commentalias = $commententity->get_table_alias('comments');
$this->set_main_table('comments', $commentalias);
$this->add_entity($commententity);
// Join the context entity.
$contextentity = (new context())
->set_table_alias('context', $commententity->get_table_alias('context'));
$this->add_entity($contextentity
->add_join($commententity->get_context_join())
);
// Join the user entity to the comment userid (author).
$userentity = new user();
$useralias = $userentity->get_table_alias('user');
$this->add_entity($userentity
->add_join("LEFT JOIN {user} {$useralias} ON {$useralias}.id = {$commentalias}.userid"));
// Add report elements from each of the entities we added to the report.
$this->add_all_from_entities();
}
/**
* Return the columns that will be added to the report upon creation
*
* @return string[]
*/
public function get_default_columns(): array {
return [
'user:fullname',
'context:name',
'comment:content',
'comment:timecreated',
];
}
/**
* Return the column sorting that will be added to the report upon creation
*
* @return int[]
*/
public function get_default_column_sorting(): array {
return [
'user:fullname' => SORT_ASC,
'comment:timecreated' => SORT_ASC,
];
}
/**
* Return the filters that will be added to the report upon creation
*
* @return string[]
*/
public function get_default_filters(): array {
return [
'comment:content',
];
}
/**
* Return the conditions that will be added to the report upon creation
*
* @return string[]
*/
public function get_default_conditions(): array {
return [
'user:fullname',
];
}
}
@@ -0,0 +1,266 @@
<?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/>.
declare(strict_types=1);
namespace core_comment\reportbuilder\local\entities;
use context;
use context_helper;
use html_writer;
use lang_string;
use stdClass;
use core_reportbuilder\local\entities\base;
use core_reportbuilder\local\filters\{date, text};
use core_reportbuilder\local\helpers\format;
use core_reportbuilder\local\report\{column, filter};
/**
* Comment entity
*
* @package core_comment
* @copyright 2022 Paul Holden <paulh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class comment extends base {
/**
* Database tables that this entity uses
*
* @return string[]
*/
protected function get_default_tables(): array {
return [
'comments',
'context',
];
}
/**
* The default title for this entity
*
* @return lang_string
*/
protected function get_default_entity_title(): lang_string {
return new lang_string('comment', 'core_comment');
}
/**
* Initialise the entity
*
* @return base
*/
public function initialise(): base {
$columns = $this->get_all_columns();
foreach ($columns as $column) {
$this->add_column($column);
}
// All the filters defined by the entity can also be used as conditions.
$filters = $this->get_all_filters();
foreach ($filters as $filter) {
$this
->add_filter($filter)
->add_condition($filter);
}
return $this;
}
/**
* Returns list of all available columns
*
* @return column[]
*/
protected function get_all_columns(): array {
global $DB;
$commentalias = $this->get_table_alias('comments');
$contextalias = $this->get_table_alias('context');
// Content.
$contentfieldsql = "{$commentalias}.content";
if ($DB->get_dbfamily() === 'oracle') {
$contentfieldsql = $DB->sql_order_by_text($contentfieldsql, 1024);
}
$columns[] = (new column(
'content',
new lang_string('content'),
$this->get_entity_name()
))
->add_joins($this->get_joins())
->set_type(column::TYPE_LONGTEXT)
->add_join($this->get_context_join())
->add_field($contentfieldsql, 'content')
->add_fields("{$commentalias}.format, {$commentalias}.contextid, " .
context_helper::get_preload_record_columns_sql($contextalias))
->add_callback(static function($content, stdClass $comment): string {
if ($content === null) {
return '';
}
context_helper::preload_from_record($comment);
$context = context::instance_by_id($comment->contextid);
return format_text($content, $comment->format, ['context' => $context]);
});
// Context.
$columns[] = (new column(
'context',
new lang_string('context'),
$this->get_entity_name()
))
->add_joins($this->get_joins())
->set_type(column::TYPE_TEXT)
->add_join($this->get_context_join())
->add_fields("{$commentalias}.contextid, " . context_helper::get_preload_record_columns_sql($contextalias))
// Sorting may not order alphabetically, but will at least group contexts together.
->set_is_sortable(true)
->set_is_deprecated('See \'context:name\' for replacement')
->add_callback(static function($contextid, stdClass $context): string {
if ($contextid === null) {
return '';
}
context_helper::preload_from_record($context);
return context::instance_by_id($contextid)->get_context_name();
});
// Context URL.
$columns[] = (new column(
'contexturl',
new lang_string('contexturl'),
$this->get_entity_name()
))
->add_joins($this->get_joins())
->set_type(column::TYPE_TEXT)
->add_join($this->get_context_join())
->add_fields("{$commentalias}.contextid, " . context_helper::get_preload_record_columns_sql($contextalias))
// Sorting may not order alphabetically, but will at least group contexts together.
->set_is_sortable(true)
->set_is_deprecated('See \'context:link\' for replacement')
->add_callback(static function($contextid, stdClass $context): string {
if ($contextid === null) {
return '';
}
context_helper::preload_from_record($context);
$context = context::instance_by_id($contextid);
return html_writer::link($context->get_url(), $context->get_context_name());
});
// Component.
$columns[] = (new column(
'component',
new lang_string('plugin'),
$this->get_entity_name()
))
->add_joins($this->get_joins())
->set_type(column::TYPE_TEXT)
->add_fields("{$commentalias}.component")
->set_is_sortable(true);
// Area.
$columns[] = (new column(
'area',
new lang_string('pluginarea'),
$this->get_entity_name()
))
->add_joins($this->get_joins())
->set_type(column::TYPE_TEXT)
->add_fields("{$commentalias}.commentarea")
->set_is_sortable(true);
// Item ID.
$columns[] = (new column(
'itemid',
new lang_string('pluginitemid'),
$this->get_entity_name()
))
->add_joins($this->get_joins())
->set_type(column::TYPE_INTEGER)
->add_fields("{$commentalias}.itemid")
->set_is_sortable(true)
->set_disabled_aggregation_all();
// Time created.
$columns[] = (new column(
'timecreated',
new lang_string('timecreated', 'core_reportbuilder'),
$this->get_entity_name()
))
->add_joins($this->get_joins())
->set_type(column::TYPE_TIMESTAMP)
->add_fields("{$commentalias}.timecreated")
->set_is_sortable(true)
->add_callback([format::class, 'userdate']);
return $columns;
}
/**
* Return list of all available filters
*
* @return filter[]
*/
protected function get_all_filters(): array {
global $DB;
$commentalias = $this->get_table_alias('comments');
// Content.
$filters[] = (new filter(
text::class,
'content',
new lang_string('content'),
$this->get_entity_name(),
$DB->sql_cast_to_char("{$commentalias}.content")
))
->add_joins($this->get_joins());
// Time created.
$filters[] = (new filter(
date::class,
'timecreated',
new lang_string('timecreated', 'core_reportbuilder'),
$this->get_entity_name(),
"{$commentalias}.timecreated"
))
->add_joins($this->get_joins())
->set_limited_operators([
date::DATE_ANY,
date::DATE_RANGE,
date::DATE_LAST,
date::DATE_CURRENT,
]);
return $filters;
}
/**
* Return syntax for joining on the context table
*
* @return string
*/
public function get_context_join(): string {
$commentalias = $this->get_table_alias('comments');
$contextalias = $this->get_table_alias('context');
return "LEFT JOIN {context} {$contextalias} ON {$contextalias}.id = {$commentalias}.contextid";
}
}
@@ -0,0 +1,124 @@
<?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/>.
declare(strict_types=1);
namespace core_comment\reportbuilder\local\systemreports;
use context_system;
use lang_string;
use moodle_url;
use pix_icon;
use stdClass;
use core\reportbuilder\local\entities\context;
use core_reportbuilder\system_report;
use core_reportbuilder\local\entities\user;
use core_reportbuilder\local\report\action;
use core_comment\reportbuilder\local\entities\comment;
/**
* Comments system report
*
* @package core_comment
* @copyright 2022 Paul Holden <paulh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class comments extends system_report {
/**
* Initialise report, we need to set the main table, load our entities and set columns/filters
*/
protected function initialise(): void {
$commententity = new comment();
$commentalias = $commententity->get_table_alias('comments');
$this->set_main_table('comments', $commentalias);
$this->add_entity($commententity);
// Base fields required for action callbacks and checkbox toggle.
$this->add_base_fields("{$commentalias}.id");
$this->set_checkbox_toggleall(static function(stdClass $row): array {
return [$row->id, get_string('select')];
});
// Join the context entity.
$contextentity = (new context())
->set_table_alias('context', $commententity->get_table_alias('context'));
$this->add_entity($contextentity
->add_join($commententity->get_context_join())
);
// Join the user entity to the comment userid (author).
$userentity = new user();
$useralias = $userentity->get_table_alias('user');
$this->add_entity($userentity
->add_join("LEFT JOIN {user} {$useralias} ON {$useralias}.id = {$commentalias}.userid"));
$this->add_columns();
$this->add_filters();
$this->add_actions();
$this->set_downloadable(true, get_string('comments'));
}
/**
* Validates access to view this report
*
* @return bool
*/
protected function can_view(): bool {
return has_capability('moodle/comment:delete', context_system::instance());
}
/**
* Add columns to the report
*/
protected function add_columns(): void {
$this->add_columns_from_entities([
'user:fullnamewithlink',
'comment:content',
'context:link',
'comment:timecreated',
]);
// Default sorting.
$this->set_initial_sort_column('comment:timecreated', SORT_DESC);
}
/**
* Add filters to the report
*/
protected function add_filters(): void {
$this->add_filters_from_entities([
'user:fullname',
'comment:content',
'comment:timecreated',
]);
}
/**
* Add actions to report
*/
protected function add_actions(): void {
$this->add_action(new action(
new moodle_url('#'),
new pix_icon('t/delete', ''),
['data-action' => 'comment-delete', 'data-comment-id' => ':id', 'class' => 'text-danger'],
false,
new lang_string('delete')
));
}
}