MDL-26854 COMMENT
1. added pluginname_comment_validate callback to comments api
2. change permission callback defaults to false
3. Tidied up serveal areas of comments and implemented callback to
ignore system permissions for view (credits to Sam Hemelryk)
AMOS BEGIN
MOV [modulerejectcomment,error],[callbackrejectcomment,error]
AMOS END
This commit is contained in:
+357
-142
@@ -1,5 +1,4 @@
|
||||
<?php
|
||||
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
@@ -23,18 +22,15 @@
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
class comment {
|
||||
/**
|
||||
* @var integer
|
||||
*/
|
||||
private $page;
|
||||
/**
|
||||
* there may be several comment box in one page
|
||||
* so we need a client_id to recognize them
|
||||
* @var integer
|
||||
*/
|
||||
private $cid;
|
||||
private $contextid;
|
||||
/**
|
||||
* commentarea is used to specify different
|
||||
* parts shared the same itemid
|
||||
@@ -46,80 +42,133 @@ class comment {
|
||||
* @var integer
|
||||
*/
|
||||
private $itemid;
|
||||
|
||||
/**
|
||||
* this html snippet will be used as a template
|
||||
* to build comment content
|
||||
* @var string
|
||||
*/
|
||||
private $template;
|
||||
/**
|
||||
* The context id for comments
|
||||
* @var int
|
||||
*/
|
||||
private $contextid;
|
||||
/**
|
||||
* The context itself
|
||||
* @var stdClass
|
||||
*/
|
||||
private $context;
|
||||
/**
|
||||
* The course id for comments
|
||||
* @var int
|
||||
*/
|
||||
private $courseid;
|
||||
/**
|
||||
* course module object, only be used to help find pluginname automatically
|
||||
* if pluginname is specified, it won't be used at all
|
||||
* @var string
|
||||
* @var stdClass
|
||||
*/
|
||||
private $cm;
|
||||
private $plugintype;
|
||||
/**
|
||||
* When used in module, it is recommended to use it
|
||||
* The component that this comment is for. It is STRONGLY recommended to set this.
|
||||
* @var string
|
||||
*/
|
||||
private $component;
|
||||
/**
|
||||
* This is calculated by normalising the component
|
||||
* @var string
|
||||
*/
|
||||
private $pluginname;
|
||||
private $viewcap;
|
||||
private $postcap;
|
||||
/**
|
||||
* to tell comments api where it is used
|
||||
* This is calculated by normalising the component
|
||||
* @var string
|
||||
*/
|
||||
private $env;
|
||||
private $plugintype;
|
||||
/**
|
||||
* Whether the user has the required capabilities/permissions to view comments.
|
||||
* @var bool
|
||||
*/
|
||||
private $viewcap = false;
|
||||
/**
|
||||
* Whether the user has the required capabilities/permissions to post comments.
|
||||
* @var bool
|
||||
*/
|
||||
private $postcap = false;
|
||||
/**
|
||||
* to costomize link text
|
||||
* @var string
|
||||
*/
|
||||
private $linktext;
|
||||
|
||||
/**
|
||||
* If set to true then comment sections won't be able to be opened and closed
|
||||
* instead they will always be visible.
|
||||
* @var bool
|
||||
*/
|
||||
protected $notoggle = false;
|
||||
|
||||
/**
|
||||
* If set to true comments are automatically loaded as soon as the page loads.
|
||||
* Normally this happens when the user expands the comment section.
|
||||
* @var bool
|
||||
*/
|
||||
protected $autostart = false;
|
||||
|
||||
/**
|
||||
* If set to true the total count of comments is displayed when displaying comments.
|
||||
* @var bool
|
||||
*/
|
||||
protected $displaytotalcount = false;
|
||||
/**
|
||||
* If set to true a cancel button will be shown on the form used to submit comments.
|
||||
* @var bool
|
||||
*/
|
||||
protected $displaycancel = false;
|
||||
/**
|
||||
* The number of comments associated with this comments params
|
||||
* @var int
|
||||
*/
|
||||
protected $totalcommentcount = null;
|
||||
/**
|
||||
* By default a user must have the generic comment capabilities plus any capabilities the
|
||||
* component being commented on requires.
|
||||
* When set to true only the component capabilities are checked, the system capabilities are
|
||||
* ignored.
|
||||
* This can be toggled by the component defining a callback in its lib.php e.g.
|
||||
* function forum_comment_allow_anonymous_access(comment $comment) {}
|
||||
* Note: On the front page this defaults to true.
|
||||
* @var bool
|
||||
*/
|
||||
protected $ignoresystempermissions = false;
|
||||
|
||||
// static variable will be used by non-js comments UI
|
||||
/**#@+
|
||||
* static variable will be used by non-js comments UI
|
||||
*/
|
||||
private static $nonjs = false;
|
||||
private static $comment_itemid = null;
|
||||
private static $comment_context = null;
|
||||
private static $comment_area = null;
|
||||
private static $comment_page = null;
|
||||
private static $comment_component = null;
|
||||
/**#@-*/
|
||||
|
||||
/**
|
||||
* Construct function of comment class, initialise
|
||||
* class members
|
||||
* @param object $options
|
||||
* @param stdClass $options
|
||||
* @param object $options {
|
||||
* context => context context to use for the comment [required]
|
||||
* component => string which plugin will comment being added to [required]
|
||||
* itemid => int the id of the associated item (forum post, glossary item etc) [required]
|
||||
* area => string comment area
|
||||
* cm => stdClass course module
|
||||
* course => course course object
|
||||
* client_id => string an unique id to identify comment area
|
||||
* autostart => boolean automatically expend comments
|
||||
* showcount => boolean display the number of comments
|
||||
* displaycancel => boolean display cancel button
|
||||
* notoggle => boolean don't show/hide button
|
||||
* linktext => string title of show/hide button
|
||||
* }
|
||||
*/
|
||||
public function __construct($options) {
|
||||
global $CFG, $DB;
|
||||
|
||||
if (empty($CFG->commentsperpage)) {
|
||||
$CFG->commentsperpage = 15;
|
||||
}
|
||||
|
||||
public function __construct(stdClass $options) {
|
||||
$this->viewcap = false;
|
||||
$this->postcap = false;
|
||||
|
||||
@@ -142,7 +191,11 @@ class comment {
|
||||
}
|
||||
|
||||
if (!empty($options->component)) {
|
||||
// set and validate component
|
||||
$this->set_component($options->component);
|
||||
} else {
|
||||
// component cannot be empty
|
||||
throw new comment_exception('invalidcomponent');
|
||||
}
|
||||
|
||||
// setup course
|
||||
@@ -174,13 +227,6 @@ class comment {
|
||||
$this->itemid = 0;
|
||||
}
|
||||
|
||||
// setup env
|
||||
if (!empty($options->env)) {
|
||||
$this->env = $options->env;
|
||||
} else {
|
||||
$this->env = '';
|
||||
}
|
||||
|
||||
// setup customized linktext
|
||||
if (!empty($options->linktext)) {
|
||||
$this->linktext = $options->linktext;
|
||||
@@ -188,10 +234,24 @@ class comment {
|
||||
$this->linktext = get_string('comments');
|
||||
}
|
||||
|
||||
if (!empty($options->ignore_permission)) {
|
||||
$this->ignore_permission = true;
|
||||
} else {
|
||||
$this->ignore_permission = false;
|
||||
// setup options for callback functions
|
||||
$this->comment_param = new stdClass();
|
||||
$this->comment_param->context = $this->context;
|
||||
$this->comment_param->courseid = $this->courseid;
|
||||
$this->comment_param->cm = $this->cm;
|
||||
$this->comment_param->commentarea = $this->commentarea;
|
||||
$this->comment_param->itemid = $this->itemid;
|
||||
|
||||
$this->allowanonymousaccess = false;
|
||||
// By default everyone can view comments on the front page
|
||||
if ($this->context->contextlevel == CONTEXT_COURSE && $this->context->instanceid == SITEID) {
|
||||
$this->allowanonymousaccess = true;
|
||||
} else if ($this->context->contextlevel == CONTEXT_MODULE && $this->courseid == SITEID) {
|
||||
$this->allowanonymousaccess = true;
|
||||
}
|
||||
if (!empty($this->plugintype) && !empty($this->pluginname)) {
|
||||
// Plugins can override this if they wish.
|
||||
$this->allowanonymousaccess = plugin_callback($this->plugintype, $this->pluginname, 'comment', 'allow_anonymous_access', array($this), $this->allowanonymousaccess);
|
||||
}
|
||||
|
||||
// setup notoggle
|
||||
@@ -209,38 +269,23 @@ class comment {
|
||||
$this->set_displaycancel($options->displaycancel);
|
||||
}
|
||||
|
||||
// setup displaytotalcount
|
||||
if (!empty($options->showcount)) {
|
||||
$count = $this->count();
|
||||
if (empty($count)) {
|
||||
$this->count = '';
|
||||
} else {
|
||||
$this->count = '('.$count.')';
|
||||
}
|
||||
} else {
|
||||
$this->count = '';
|
||||
$this->set_displaytotalcount($options->showcount);
|
||||
}
|
||||
|
||||
// setup options for callback functions
|
||||
$this->args = new stdClass();
|
||||
$this->args->context = $this->context;
|
||||
$this->args->courseid = $this->courseid;
|
||||
$this->args->cm = $this->cm;
|
||||
$this->args->commentarea = $this->commentarea;
|
||||
$this->args->itemid = $this->itemid;
|
||||
|
||||
// setting post and view permissions
|
||||
$this->check_permissions();
|
||||
|
||||
// load template
|
||||
$this->template = <<<EOD
|
||||
<div class="comment-userpicture">___picture___</div>
|
||||
<div class="comment-content">
|
||||
___name___ - <span>___time___</span>
|
||||
<div>___content___</div>
|
||||
</div>
|
||||
EOD;
|
||||
$this->template = html_writer::tag('div', '___picture___', array('class' => 'comment-userpicture'));
|
||||
$this->template .= html_writer::start_tag('div', array('class' => 'comment-content'));
|
||||
$this->template .= '___name___ - ';
|
||||
$this->template .= html_writer::tag('span', '___time___');
|
||||
$this->template .= html_writer::tag('div', '___content___');
|
||||
$this->template .= html_writer::end_tag('div'); // .comment-content
|
||||
if (!empty($this->plugintype)) {
|
||||
$this->template = plugin_callback($this->plugintype, $this->pluginname, FEATURE_COMMENT, 'template', $this->args, $this->template);
|
||||
$this->template = plugin_callback($this->plugintype, $this->pluginname, 'comment', 'template', array($this->comment_param), $this->template);
|
||||
}
|
||||
|
||||
unset($options);
|
||||
@@ -248,34 +293,63 @@ EOD;
|
||||
|
||||
/**
|
||||
* Receive nonjs comment parameters
|
||||
*
|
||||
* @param moodle_page $page The page object to initialise comments within
|
||||
* If not provided the global $PAGE is used
|
||||
*/
|
||||
public static function init() {
|
||||
global $PAGE, $CFG;
|
||||
public static function init(moodle_page $page = null) {
|
||||
global $PAGE;
|
||||
|
||||
if (empty($page)) {
|
||||
$page = $PAGE;
|
||||
}
|
||||
// setup variables for non-js interface
|
||||
self::$nonjs = optional_param('nonjscomment', '', PARAM_ALPHA);
|
||||
self::$nonjs = optional_param('nonjscomment', '', PARAM_ALPHANUM);
|
||||
self::$comment_itemid = optional_param('comment_itemid', '', PARAM_INT);
|
||||
self::$comment_context = optional_param('comment_context', '', PARAM_INT);
|
||||
self::$comment_page = optional_param('comment_page', '', PARAM_INT);
|
||||
self::$comment_area = optional_param('comment_area', '', PARAM_ALPHAEXT);
|
||||
|
||||
$PAGE->requires->string_for_js('addcomment', 'moodle');
|
||||
$PAGE->requires->string_for_js('deletecomment', 'moodle');
|
||||
$PAGE->requires->string_for_js('comments', 'moodle');
|
||||
$PAGE->requires->string_for_js('commentsrequirelogin', 'moodle');
|
||||
$page->requires->string_for_js('addcomment', 'moodle');
|
||||
$page->requires->string_for_js('deletecomment', 'moodle');
|
||||
$page->requires->string_for_js('comments', 'moodle');
|
||||
$page->requires->string_for_js('commentsrequirelogin', 'moodle');
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the component.
|
||||
*
|
||||
* This method shouldn't be public, changing the component once it has been set potentially
|
||||
* invalidates permission checks.
|
||||
* A coding_error is now thrown if code attempts to change the component.
|
||||
*
|
||||
* @param string $component
|
||||
* @return void
|
||||
*/
|
||||
public function set_component($component) {
|
||||
if (!empty($this->component) && $this->component !== $component) {
|
||||
throw new coding_exception('You cannot change the component of a comment once it has been set');
|
||||
}
|
||||
$this->component = $component;
|
||||
list($this->plugintype, $this->pluginname) = normalize_component($component);
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the user can view the comment.
|
||||
*
|
||||
* @param bool $value
|
||||
*/
|
||||
public function set_view_permission($value) {
|
||||
$this->viewcap = $value;
|
||||
$this->viewcap = (bool)$value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the user can post a comment
|
||||
*
|
||||
* @param bool $value
|
||||
*/
|
||||
public function set_post_permission($value) {
|
||||
$this->postcap = $value;
|
||||
$this->postcap = (bool)$value;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -285,12 +359,11 @@ EOD;
|
||||
* function named $pluginname_check_comment_post must be implemented
|
||||
*/
|
||||
private function check_permissions() {
|
||||
global $CFG;
|
||||
$this->postcap = has_capability('moodle/comment:post', $this->context);
|
||||
$this->viewcap = has_capability('moodle/comment:view', $this->context);
|
||||
if (!empty($this->plugintype)) {
|
||||
$permissions = plugin_callback($this->plugintype, $this->pluginname, FEATURE_COMMENT, 'permissions', array($this->args), array('post'=>true, 'view'=>true));
|
||||
if ($this->ignore_permission) {
|
||||
$permissions = plugin_callback($this->plugintype, $this->pluginname, 'comment', 'permissions', array($this->comment_param), array('post'=>false, 'view'=>false));
|
||||
if ($this->allowanonymousaccess) {
|
||||
$this->postcap = $permissions['post'];
|
||||
$this->viewcap = $permissions['view'];
|
||||
} else {
|
||||
@@ -319,7 +392,7 @@ EOD;
|
||||
'comment_context' => $this->context->id,
|
||||
'comment_area' => $this->commentarea,
|
||||
));
|
||||
$link->remove_params(array('nonjscomment', 'comment_page'));
|
||||
$link->remove_params(array('comment_page'));
|
||||
return $link;
|
||||
}
|
||||
|
||||
@@ -359,6 +432,18 @@ EOD;
|
||||
$this->displaycancel = (bool)$newvalue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the displaytotalcount option
|
||||
*
|
||||
* If set to true then the total number of comments will be displayed
|
||||
* when printing comments.
|
||||
*
|
||||
* @param bool $newvalue
|
||||
*/
|
||||
public function set_displaytotalcount($newvalue = true) {
|
||||
$this->displaytotalcount = (bool)$newvalue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialises the JavaScript that enchances the comment API.
|
||||
*
|
||||
@@ -374,7 +459,6 @@ EOD;
|
||||
$options->page = 0;
|
||||
$options->courseid = $this->courseid;
|
||||
$options->contextid = $this->contextid;
|
||||
$options->env = $this->env;
|
||||
$options->component = $this->component;
|
||||
$options->notoggle = $this->notoggle;
|
||||
$options->autostart = $this->autostart;
|
||||
@@ -404,12 +488,12 @@ EOD;
|
||||
|
||||
// print html template
|
||||
// Javascript will use the template to render new comments
|
||||
if (empty($template_printed) && !empty($this->viewcap)) {
|
||||
if (empty($template_printed) && $this->can_view()) {
|
||||
$html .= html_writer::tag('div', $this->template, array('style' => 'display:none', 'id' => 'cmt-tmpl'));
|
||||
$template_printed = true;
|
||||
}
|
||||
|
||||
if (!empty($this->viewcap)) {
|
||||
if ($this->can_view()) {
|
||||
// print commenting icon and tooltip
|
||||
$html .= html_writer::start_tag('div', array('class' => 'mdl-left'));
|
||||
$html .= html_writer::link($this->get_nojslink($PAGE), get_string('showcommentsnonjs'), array('class' => 'showcommentsnonjs'));
|
||||
@@ -417,27 +501,33 @@ EOD;
|
||||
if (!$this->notoggle) {
|
||||
// If toggling is enabled (notoggle=false) then print the controls to toggle
|
||||
// comments open and closed
|
||||
$countstring = '';
|
||||
if ($this->displaytotalcount) {
|
||||
$countstring = '('.$this->count().')';
|
||||
}
|
||||
$html .= html_writer::start_tag('a', array('class' => 'comment-link', 'id' => 'comment-link-'.$this->cid, 'href' => '#'));
|
||||
$html .= html_writer::empty_tag('img', array('id' => 'comment-img-'.$this->cid, 'src' => $OUTPUT->pix_url('t/collapsed'), 'alt' => $this->linktext, 'title' => $this->linktext));
|
||||
$html .= html_writer::tag('span', $this->linktext.' '.$this->count, array('id' => 'comment-link-text-'.$this->cid));
|
||||
$html .= html_writer::tag('span', $this->linktext.' '.$countstring, array('id' => 'comment-link-text-'.$this->cid));
|
||||
$html .= html_writer::end_tag('a');
|
||||
}
|
||||
|
||||
$html .= html_writer::start_tag('div', array('id' => 'comment-ctrl-'.$this->cid, 'class' => 'comment-ctrl'));
|
||||
$html .= html_writer::start_tag('ul', array('id' => 'comment-list-'.$this->cid, 'class' => 'comment-list'));
|
||||
$html .= html_writer::tag('li', '', array('class' => 'first'));
|
||||
|
||||
if ($this->autostart) {
|
||||
// If autostart has been enabled print the comments list immediatly
|
||||
$html .= html_writer::start_tag('ul', array('id' => 'comment-list-'.$this->cid, 'class' => 'comment-list comments-loaded'));
|
||||
$html .= html_writer::tag('li', '', array('class' => 'first'));
|
||||
$html .= $this->print_comments(0, true, false);
|
||||
$html .= html_writer::end_tag('ul'); // .comment-list
|
||||
$html .= $this->get_pagination(0);
|
||||
} else {
|
||||
$html .= html_writer::start_tag('ul', array('id' => 'comment-list-'.$this->cid, 'class' => 'comment-list'));
|
||||
$html .= html_writer::tag('li', '', array('class' => 'first'));
|
||||
$html .= html_writer::end_tag('ul'); // .comment-list
|
||||
$html .= html_writer::tag('div', '', array('id' => 'comment-pagination-'.$this->cid, 'class' => 'comment-pagination'));
|
||||
}
|
||||
|
||||
if (!empty($this->postcap)) {
|
||||
if ($this->can_post()) {
|
||||
// print posting textarea
|
||||
$html .= html_writer::start_tag('div', array('class' => 'comment-area'));
|
||||
$html .= html_writer::start_tag('div', array('class' => 'db'));
|
||||
@@ -478,15 +568,15 @@ EOD;
|
||||
*/
|
||||
public function get_comments($page = '') {
|
||||
global $DB, $CFG, $USER, $OUTPUT;
|
||||
if (empty($this->viewcap)) {
|
||||
if (!$this->can_view()) {
|
||||
return false;
|
||||
}
|
||||
if (!is_numeric($page)) {
|
||||
$page = 0;
|
||||
}
|
||||
$this->page = $page;
|
||||
$params = array();
|
||||
$start = $page * $CFG->commentsperpage;
|
||||
$perpage = (!empty($CFG->commentsperpage))?$CFG->commentsperpage:15;
|
||||
$start = $page * $perpage;
|
||||
$ufields = user_picture::fields('u');
|
||||
$sql = "SELECT $ufields, c.id AS cid, c.content AS ccontent, c.format AS cformat, c.timecreated AS ctimecreated
|
||||
FROM {comments} c
|
||||
@@ -498,9 +588,8 @@ EOD;
|
||||
$params['itemid'] = $this->itemid;
|
||||
|
||||
$comments = array();
|
||||
$candelete = has_capability('moodle/comment:delete', $this->context);
|
||||
$formatoptions = array('overflowdiv' => true);
|
||||
$rs = $DB->get_recordset_sql($sql, $params, $start, $CFG->commentsperpage);
|
||||
$rs = $DB->get_recordset_sql($sql, $params, $start, $perpage);
|
||||
foreach ($rs as $u) {
|
||||
$c = new stdClass();
|
||||
$c->id = $u->cid;
|
||||
@@ -512,8 +601,9 @@ EOD;
|
||||
$c->fullname = fullname($u);
|
||||
$c->time = userdate($c->timecreated, get_string('strftimerecent', 'langconfig'));
|
||||
$c->content = format_text($c->content, $c->format, $formatoptions);
|
||||
|
||||
$c->avatar = $OUTPUT->user_picture($u, array('size'=>18));
|
||||
|
||||
$candelete = $this->can_delete($c->id);
|
||||
if (($USER->id == $u->id) || !empty($candelete)) {
|
||||
$c->delete = true;
|
||||
}
|
||||
@@ -523,31 +613,45 @@ EOD;
|
||||
|
||||
if (!empty($this->plugintype)) {
|
||||
// moodle module will filter comments
|
||||
$comments = plugin_callback($this->plugintype, $this->pluginname, FEATURE_COMMENT, 'display', array($comments, $this->args), $comments);
|
||||
$comments = plugin_callback($this->plugintype, $this->pluginname, 'comment', 'display', array($comments, $this->comment_param), $comments);
|
||||
}
|
||||
|
||||
return $comments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of comments associated with the details of this object
|
||||
*
|
||||
* @global moodle_database $DB
|
||||
* @return int
|
||||
*/
|
||||
public function count() {
|
||||
global $DB;
|
||||
if ($count = $DB->count_records('comments', array('itemid'=>$this->itemid, 'commentarea'=>$this->commentarea, 'contextid'=>$this->context->id))) {
|
||||
return $count;
|
||||
} else {
|
||||
return 0;
|
||||
if ($this->totalcommentcount === null) {
|
||||
$this->totalcommentcount = $DB->count_records('comments', array('itemid' => $this->itemid, 'commentarea' => $this->commentarea, 'contextid' => $this->context->id));
|
||||
}
|
||||
return $this->totalcommentcount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns HTML to display a pagination bar
|
||||
*
|
||||
* @global stdClass $CFG
|
||||
* @global core_renderer $OUTPUT
|
||||
* @param int $page
|
||||
* @return string
|
||||
*/
|
||||
public function get_pagination($page = 0) {
|
||||
global $DB, $CFG, $OUTPUT;
|
||||
global $CFG, $OUTPUT;
|
||||
$count = $this->count();
|
||||
$pages = (int)ceil($count/$CFG->commentsperpage);
|
||||
$perpage = (!empty($CFG->commentsperpage))?$CFG->commentsperpage:15;
|
||||
$pages = (int)ceil($count/$perpage);
|
||||
if ($pages == 1 || $pages == 0) {
|
||||
return html_writer::tag('div', '', array('id' => 'comment-pagination-'.$this->cid, 'class' => 'comment-pagination'));
|
||||
}
|
||||
if (!empty(self::$nonjs)) {
|
||||
// used in non-js interface
|
||||
return $OUTPUT->paging_bar($count, $page, $CFG->commentsperpage, $this->get_nojslink(), 'comment_page');
|
||||
return $OUTPUT->paging_bar($count, $page, $perpage, $this->get_nojslink(), 'comment_page');
|
||||
} else {
|
||||
// return ajax paging bar
|
||||
$str = '';
|
||||
@@ -567,16 +671,18 @@ EOD;
|
||||
|
||||
/**
|
||||
* Add a new comment
|
||||
*
|
||||
* @global moodle_database $DB
|
||||
* @param string $content
|
||||
* @return mixed
|
||||
*/
|
||||
public function add($content, $format = FORMAT_MOODLE) {
|
||||
global $CFG, $DB, $USER, $OUTPUT;
|
||||
if (empty($this->postcap)) {
|
||||
if (!$this->can_post()) {
|
||||
throw new comment_exception('nopermissiontocomment');
|
||||
}
|
||||
$now = time();
|
||||
$newcmt = new stdClass();
|
||||
$newcmt = new stdClass;
|
||||
$newcmt->contextid = $this->contextid;
|
||||
$newcmt->commentarea = $this->commentarea;
|
||||
$newcmt->itemid = $this->itemid;
|
||||
@@ -585,20 +691,15 @@ EOD;
|
||||
$newcmt->userid = $USER->id;
|
||||
$newcmt->timecreated = $now;
|
||||
|
||||
if (!empty($this->plugintype)) {
|
||||
// moodle module will check content
|
||||
$ret = plugin_callback($this->plugintype, $this->pluginname, FEATURE_COMMENT, 'add', array(&$newcmt, $this->args), true);
|
||||
if (!$ret) {
|
||||
throw new comment_exception('modulererejectcomment');
|
||||
}
|
||||
}
|
||||
// This callback allow module to modify the content of comment, such as filter or replacement
|
||||
plugin_callback($this->plugintype, $this->pluginname, 'comment', 'add', array(&$newcmt, $this->comment_param));
|
||||
|
||||
$cmt_id = $DB->insert_record('comments', $newcmt);
|
||||
if (!empty($cmt_id)) {
|
||||
$newcmt->id = $cmt_id;
|
||||
$newcmt->time = userdate($now, get_string('strftimerecent', 'langconfig'));
|
||||
$newcmt->fullname = fullname($USER);
|
||||
$url = new moodle_url('/user/view.php', array('id'=>$USER->id, 'course'=>$this->courseid));
|
||||
$url = new moodle_url('/user/view.php', array('id' => $USER->id, 'course' => $this->courseid));
|
||||
$newcmt->profileurl = $url->out();
|
||||
$newcmt->content = format_text($newcmt->content, $format, array('overflowdiv'=>true));
|
||||
$newcmt->avatar = $OUTPUT->user_picture($USER, array('size'=>16));
|
||||
@@ -610,7 +711,7 @@ EOD;
|
||||
|
||||
/**
|
||||
* delete by context, commentarea and itemid
|
||||
* @param object $param {
|
||||
* @param stdClass|array $param {
|
||||
* contextid => int the context in which the comments exist [required]
|
||||
* commentarea => string the comment area [optional]
|
||||
* itemid => int comment itemid [optional]
|
||||
@@ -629,7 +730,8 @@ EOD;
|
||||
|
||||
/**
|
||||
* Delete page_comments in whole course, used by course reset
|
||||
* @param object $context course context
|
||||
*
|
||||
* @param stdClass $context course context
|
||||
*/
|
||||
public function reset_course_page_comments($context) {
|
||||
global $DB;
|
||||
@@ -645,6 +747,7 @@ EOD;
|
||||
|
||||
/**
|
||||
* Delete a comment
|
||||
*
|
||||
* @param int $commentid
|
||||
* @return mixed
|
||||
*/
|
||||
@@ -663,6 +766,7 @@ EOD;
|
||||
|
||||
/**
|
||||
* Print comments
|
||||
*
|
||||
* @param int $page
|
||||
* @param boolean $return return comments list string or print it out
|
||||
* @param boolean $nonjs print nonjs comments list or not?
|
||||
@@ -670,6 +774,11 @@ EOD;
|
||||
*/
|
||||
public function print_comments($page = 0, $return = true, $nonjs = true) {
|
||||
global $DB, $CFG, $PAGE;
|
||||
|
||||
if (!$this->can_view()) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$html = '';
|
||||
if (!(self::$comment_itemid == $this->itemid &&
|
||||
self::$comment_context == $this->context->id &&
|
||||
@@ -680,38 +789,34 @@ EOD;
|
||||
|
||||
$html = '';
|
||||
if ($nonjs) {
|
||||
$html .= '<h3>'.get_string('comments').'</h3>';
|
||||
$html .= "<ul id='comment-list-$this->cid' class='comment-list'>";
|
||||
$html .= html_writer::tag('h3', get_string('comments'));
|
||||
$html .= html_writer::start_tag('ul', array('id' => 'comment-list-'.$this->cid, 'class' => 'comment-list'));
|
||||
}
|
||||
$results = array();
|
||||
$list = '';
|
||||
|
||||
foreach ($comments as $cmt) {
|
||||
$list = '<li id="comment-'.$cmt->id.'-'.$this->cid.'">'.$this->print_comment($cmt, $nonjs).'</li>' . $list;
|
||||
// Reverse the comments array to display them in the correct direction
|
||||
foreach (array_reverse($comments) as $cmt) {
|
||||
$html .= html_writer::tag('li', $this->print_comment($cmt, $nonjs), array('id' => 'comment-'.$cmt->id.'-'.$this->cid));
|
||||
}
|
||||
$html .= $list;
|
||||
if ($nonjs) {
|
||||
$html .= '</ul>';
|
||||
$html .= html_writer::end_tag('ul');
|
||||
$html .= $this->get_pagination($page);
|
||||
}
|
||||
$sesskey = sesskey();
|
||||
$returnurl = $PAGE->url;
|
||||
$strsubmit = get_string('submit');
|
||||
if ($nonjs) {
|
||||
$html .= <<<EOD
|
||||
<form method="POST" action="{$CFG->wwwroot}/comment/comment_post.php">
|
||||
<textarea name="content" rows="2"></textarea>
|
||||
<input type="hidden" name="contextid" value="$this->contextid" />
|
||||
<input type="hidden" name="action" value="add" />
|
||||
<input type="hidden" name="area" value="$this->commentarea" />
|
||||
<input type="hidden" name="component" value="$this->component" />
|
||||
<input type="hidden" name="itemid" value="$this->itemid" />
|
||||
<input type="hidden" name="courseid" value="{$this->courseid}" />
|
||||
<input type="hidden" name="sesskey" value="{$sesskey}" />
|
||||
<input type="hidden" name="returnurl" value="{$returnurl}" />
|
||||
<input type="submit" value="{$strsubmit}" />
|
||||
</form>
|
||||
EOD;
|
||||
if ($nonjs && $this->can_post()) {
|
||||
// Form to add comments
|
||||
$html .= html_writer::start_tag('form', array('method' => 'post', 'action' => new moodle_url('/comment/comment_post.php')));
|
||||
// Comment parameters
|
||||
$html .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'contextid', 'value' => $this->contextid));
|
||||
$html .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'action', 'value' => 'add'));
|
||||
$html .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'area', 'value' => $this->commentarea));
|
||||
$html .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'component', 'value' => $this->component));
|
||||
$html .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'itemid', 'value' => $this->itemid));
|
||||
$html .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'courseid', 'value' => $this->courseid));
|
||||
$html .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'sesskey', 'value' => sesskey()));
|
||||
$html .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'returnurl', 'value' => $PAGE->url));
|
||||
// Textarea for the actual comment
|
||||
$html .= html_writer::tag('textarea', '', array('name' => 'content', 'rows' => 2));
|
||||
// Submit button to add the comment
|
||||
$html .= html_writer::empty_tag('input', array('type' => 'submit', 'value' => get_string('submit')));
|
||||
$html .= html_writer::end_tag('form');
|
||||
}
|
||||
if ($return) {
|
||||
return $html;
|
||||
@@ -720,14 +825,35 @@ EOD;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array containing comments in HTML format.
|
||||
*
|
||||
* @global core_renderer $OUTPUT
|
||||
* @param stdClass $cmt {
|
||||
* id => int comment id
|
||||
* content => string comment content
|
||||
* format => int comment text format
|
||||
* timecreated => int comment's timecreated
|
||||
* profileurl => string link to user profile
|
||||
* fullname => comment author's full name
|
||||
* avatar => string user's avatar
|
||||
* delete => boolean does user have permission to delete comment?
|
||||
* }
|
||||
* @param bool $nonjs
|
||||
* @return array
|
||||
*/
|
||||
public function print_comment($cmt, $nonjs = true) {
|
||||
global $OUTPUT;
|
||||
$patterns = array();
|
||||
$replacements = array();
|
||||
|
||||
if (!empty($cmt->delete) && empty($nonjs)) {
|
||||
$cmt->content = '<div class="comment-delete"><a href="#" id ="comment-delete-'.$this->cid.'-'.$cmt->id.'"><img src="'.$OUTPUT->pix_url('t/delete').'" alt="'.get_string('delete').'" /></a></div>' . $cmt->content;
|
||||
// add the button
|
||||
$deletelink = html_writer::start_tag('div', array('class'=>'comment-delete'));
|
||||
$deletelink .= html_writer::start_tag('a', array('href' => '#', 'id' => 'comment-delete-'.$this->cid.'-'.$cmt->id));
|
||||
$deletelink .= $OUTPUT->pix_icon('t/delete', get_string('delete'));
|
||||
$deletelink .= html_writer::end_tag('a');
|
||||
$deletelink .= html_writer::end_tag('div');
|
||||
$cmt->content = $deletelink . $cmt->content;
|
||||
}
|
||||
$patterns[] = '___picture___';
|
||||
$patterns[] = '___name___';
|
||||
@@ -741,12 +867,101 @@ EOD;
|
||||
// use html template to format a single comment.
|
||||
return str_replace($patterns, $replacements, $this->template);
|
||||
}
|
||||
|
||||
/**
|
||||
* Revoke validate callbacks
|
||||
*
|
||||
* @param stdClass $params addtionall parameters need to add to callbacks
|
||||
*/
|
||||
protected function validate($params=array()) {
|
||||
foreach ($params as $key=>$value) {
|
||||
$this->comment_param->$key = $value;
|
||||
}
|
||||
$validation = plugin_callback($this->plugintype, $this->pluginname, 'comment', 'validate', array($this->comment_param), false);
|
||||
if (!$validation) {
|
||||
throw new comment_exception('invalidcommentparam');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the user is able to view comments
|
||||
* @return bool
|
||||
*/
|
||||
public function can_view() {
|
||||
$this->validate();
|
||||
return !empty($this->viewcap);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the user can add comments against this comment description
|
||||
* @return bool
|
||||
*/
|
||||
public function can_post() {
|
||||
$this->validate();
|
||||
return isloggedin() && !empty($this->postcap);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the user can delete this comment
|
||||
* @param int $commentid
|
||||
* @return bool
|
||||
*/
|
||||
public function can_delete($commentid) {
|
||||
$this->validate(array('commentid'=>$commentid));
|
||||
return has_capability('moodle/comment:delete', $this->context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the component associated with the comment
|
||||
* @return string
|
||||
*/
|
||||
public function get_compontent() {
|
||||
return $this->component;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the context associated with the comment
|
||||
* @return stdClass
|
||||
*/
|
||||
public function get_context() {
|
||||
return $this->context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the course id associated with the comment
|
||||
* @return int
|
||||
*/
|
||||
public function get_courseid() {
|
||||
return $this->courseid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the course module associated with the comment
|
||||
*
|
||||
* @return stdClass
|
||||
*/
|
||||
public function get_cm() {
|
||||
return $this->cm;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the item id associated with the comment
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function get_itemid() {
|
||||
return $this->itemid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the comment area associated with the commentarea
|
||||
*
|
||||
* @return stdClass
|
||||
*/
|
||||
public function get_commentarea() {
|
||||
return $this->commentarea;
|
||||
}
|
||||
}
|
||||
|
||||
class comment_exception extends moodle_exception {
|
||||
public $message;
|
||||
function __construct($errorcode) {
|
||||
$this->errorcode = $errorcode;
|
||||
$this->message = get_string($errorcode, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user