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
@@ -0,0 +1,153 @@
<?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/>.
defined('MOODLE_INTERNAL') || die();
/**
* Class for glossary display formats management.
*
* @package mod_glossary
* @copyright 2021 Andrew Davis
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class mod_glossary_admin_setting_display_formats extends admin_setting {
/**
* Calls parent::__construct with specific arguments
*/
public function __construct() {
$this->nosave = true;
parent::__construct('glossarydisplayformats', get_string('displayformatssetup', 'glossary'), '', '');
}
/**
* Always returns true, does nothing
*
* @return true
*/
public function get_setting() {
return true;
}
/**
* Always returns true, does nothing
*
* @return true
*/
public function get_defaultsetting() {
return true;
}
/**
* Always returns '', does not write anything
*
* @param string $data Unused
* @return string Always returns ''
*/
public function write_setting($data) {
// Do not write any setting.
return '';
}
/**
* Checks if $query is one of the available display formats
*
* @param string $query The string to search for
* @return bool Returns true if found, false if not
*/
public function is_related($query) {
global $DB;
if (parent::is_related($query)) {
return true;
}
$query = core_text::strtolower($query);
$formats = $DB->get_records("glossary_formats");
foreach ($formats as $format) {
if (strpos(core_text::strtolower($format->name), $query) !== false) {
return true;
}
$localised = get_string("displayformat$format->name", "glossary");
if (strpos(core_text::strtolower($localised), $query) !== false) {
return true;
}
}
return false;
}
/**
* Builds the XHTML to display the control
*
* @param string $data Unused
* @param string $query
* @return string
*/
public function output_html($data, $query='') {
global $CFG, $OUTPUT, $DB;
$stredit = get_string("edit");
$strhide = get_string("hide");
$strshow = get_string("show");
$str = $OUTPUT->heading(get_string('displayformatssetup', 'glossary'), 3, 'main', true);
$recformats = $DB->get_records("glossary_formats");
$formats = array();
// Build alphabetized list of formats.
foreach ($recformats as $format) {
$formats[get_string("displayformat$format->name", "glossary")] = $format;
}
ksort($formats);
$table = new html_table();
$table->align = array('left', 'center');
foreach ($formats as $formatname => $format) {
$editicon = html_writer::link(
new moodle_url(
'/mod/glossary/formats.php',
array('id' => $format->id, 'mode' => 'edit')
),
$OUTPUT->pix_icon('t/edit', $stredit),
array('title' => $stredit));
if ( $format->visible ) {
$vtitle = $strhide;
$vicon = "t/hide";
} else {
$vtitle = $strshow;
$vicon = "t/show";
}
$visibleicon = html_writer::link(
new moodle_url(
'/mod/glossary/formats.php',
array('id' => $format->id, 'mode' => 'visible', 'sesskey' => sesskey())
),
$OUTPUT->pix_icon($vicon, $vtitle),
array('title' => $vtitle)
);
$table->data[] = array(
$formatname,
$editicon . '&nbsp;&nbsp;' . $visibleicon
);
}
$str .= html_writer::table($table);
return highlight($query, $str);
}
}
@@ -0,0 +1,37 @@
<?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/>.
/**
* Activity base class.
*
* @package mod_glossary
* @copyright 2017 onwards Ankit Agarwal <ankit.agrr@gmail.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_glossary\analytics\indicator;
defined('MOODLE_INTERNAL') || die();
/**
* Activity base class.
*
* @package mod_glossary
* @copyright 2017 onwards Ankit Agarwal <ankit.agrr@gmail.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
abstract class activity_base extends \core_analytics\local\indicator\community_of_inquiry_activity {
}
@@ -0,0 +1,56 @@
<?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/>.
/**
* Cognitive depth indicator - glossary.
*
* @package mod_glossary
* @copyright 2017 David Monllao {@link http://www.davidmonllao.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_glossary\analytics\indicator;
defined('MOODLE_INTERNAL') || die();
/**
* Cognitive depth indicator - glossary.
*
* @package mod_glossary
* @copyright 2017 David Monllao {@link http://www.davidmonllao.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class cognitive_depth extends activity_base {
/**
* Returns the name.
*
* If there is a corresponding '_help' string this will be shown as well.
*
* @return \lang_string
*/
public static function get_name(): \lang_string {
return new \lang_string('indicator:cognitivedepth', 'mod_glossary');
}
public function get_indicator_type() {
return self::INDICATOR_COGNITIVE;
}
public function get_cognitive_depth_level(\cm_info $cm) {
return self::COGNITIVE_LEVEL_2;
}
}
@@ -0,0 +1,56 @@
<?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/>.
/**
* Social breadth indicator - glossary.
*
* @package mod_glossary
* @copyright 2017 David Monllao {@link http://www.davidmonllao.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_glossary\analytics\indicator;
defined('MOODLE_INTERNAL') || die();
/**
* Social breadth indicator - glossary.
*
* @package mod_glossary
* @copyright 2017 David Monllao {@link http://www.davidmonllao.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class social_breadth extends activity_base {
/**
* Returns the name.
*
* If there is a corresponding '_help' string this will be shown as well.
*
* @return \lang_string
*/
public static function get_name(): \lang_string {
return new \lang_string('indicator:socialbreadth', 'mod_glossary');
}
public function get_indicator_type() {
return self::INDICATOR_SOCIAL;
}
public function get_social_breadth_level(\cm_info $cm) {
return self::SOCIAL_LEVEL_1;
}
}
@@ -0,0 +1,90 @@
<?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 mod_glossary\completion;
use core_completion\activity_custom_completion;
/**
* Activity custom completion subclass for the glossary activity.
*
* Class for defining mod_glossary's custom completion rules and fetching the completion statuses
* of the custom completion rules for a given glossary instance and a user.
*
* @package mod_glossary
* @copyright Simey Lameze <simey@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class custom_completion extends activity_custom_completion {
/**
* Fetches the completion state for a given completion rule.
*
* @param string $rule The completion rule.
* @return int The completion state.
*/
public function get_state(string $rule): int {
global $DB;
$this->validate_rule($rule);
$glossaryid = $this->cm->instance;
$userid = $this->userid;
$userentries = $DB->count_records('glossary_entries', ['glossaryid' => $glossaryid, 'userid' => $userid,
'approved' => 1]);
$completionentries = $this->cm->customdata['customcompletionrules']['completionentries'];
return ($completionentries <= $userentries) ? COMPLETION_COMPLETE : COMPLETION_INCOMPLETE;
}
/**
* Fetch the list of custom completion rules that this module defines.
*
* @return array
*/
public static function get_defined_custom_rules(): array {
return ['completionentries'];
}
/**
* Returns an associative array of the descriptions of custom completion rules.
*
* @return array
*/
public function get_custom_rule_descriptions(): array {
$completionentries = $this->cm->customdata['customcompletionrules']['completionentries'] ?? 0;
return [
'completionentries' => get_string('completiondetail:entries', 'glossary', $completionentries),
];
}
/**
* Returns an array of all completion rules, in the order they should be displayed to users.
*
* @return array
*/
public function get_sort_order(): array {
return [
'completionview',
'completionentries',
'completionusegrade',
'completionpassgrade',
];
}
}
@@ -0,0 +1,473 @@
<?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/>.
/**
* Entry query builder.
*
* @package mod_glossary
* @copyright 2015 Frédéric Massart - FMCorz.net
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
/**
* Entry query builder class.
*
* The purpose of this class is to avoid duplicating SQL statements to fetch entries
* which are very similar with each other. This builder is not meant to be smart, it
* will not out rule any previously set condition, or join, etc...
*
* You should be using this builder just like you would be creating your SQL query. Only
* some methods are shorthands to avoid logic duplication and common mistakes.
*
* @package mod_glossary
* @copyright 2015 Frédéric Massart - FMCorz.net
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since Moodle 3.1
*/
class mod_glossary_entry_query_builder {
/** Alias for table glossary_alias. */
const ALIAS_ALIAS = 'ga';
/** Alias for table glossary_categories. */
const ALIAS_CATEGORIES = 'gc';
/** Alias for table glossary_entries_categories. */
const ALIAS_ENTRIES_CATEGORIES = 'gec';
/** Alias for table glossary_entries. */
const ALIAS_ENTRIES = 'ge';
/** Alias for table user. */
const ALIAS_USER = 'u';
/** Include none of the entries to approve. */
const NON_APPROVED_NONE = 'na_none';
/** Including all the entries. */
const NON_APPROVED_ALL = 'na_all';
/** Including only the entries to be approved. */
const NON_APPROVED_ONLY = 'na_only';
/** Including my entries to be approved. */
const NON_APPROVED_SELF = 'na_self';
/** @var array Raw SQL statements representing the fields to select. */
protected $fields = array();
/** @var array Raw SQL statements representing the JOINs to make. */
protected $joins = array();
/** @var string Raw SQL statement representing the FROM clause. */
protected $from;
/** @var object The glossary we are fetching from. */
protected $glossary;
/** @var int The number of records to fetch from. */
protected $limitfrom = 0;
/** @var int The number of records to fetch. */
protected $limitnum = 0;
/** @var array List of SQL parameters. */
protected $params = array();
/** @var array Raw SQL statements representing the ORDER clause. */
protected $order = array();
/** @var array Raw SQL statements representing the WHERE clause. */
protected $where = array();
/**
* Constructor.
*
* @param object $glossary The glossary.
*/
public function __construct($glossary = null) {
$this->from = sprintf('FROM {glossary_entries} %s', self::ALIAS_ENTRIES);
if (!empty($glossary)) {
$this->glossary = $glossary;
$this->where[] = sprintf('(%s.glossaryid = :gid OR %s.sourceglossaryid = :gid2)',
self::ALIAS_ENTRIES, self::ALIAS_ENTRIES);
$this->params['gid'] = $glossary->id;
$this->params['gid2'] = $glossary->id;
}
}
/**
* Add a field to select.
*
* @param string $field The field, or *.
* @param string $table The table name, without the prefix 'glossary_'.
* @param string $alias An alias for the field.
*/
public function add_field($field, $table, $alias = null) {
$field = self::resolve_field($field, $table);
if (!empty($alias)) {
$field .= ' AS ' . $alias;
}
$this->fields[] = $field;
}
/**
* Adds the user fields.
*
* @return void
*/
public function add_user_fields() {
$userfieldsapi = \core_user\fields::for_userpic();
$fields = $userfieldsapi->get_sql('u', false, 'userdata', '', false)->selects;
$this->fields[] = $fields;
}
/**
* Internal method to build the query.
*
* @param bool $count Query to count?
* @return string The SQL statement.
*/
protected function build_query($count = false) {
$sql = 'SELECT ';
if ($count) {
$sql .= 'COUNT(\'x\') ';
} else {
$sql .= implode(', ', $this->fields) . ' ';
}
$sql .= $this->from . ' ';
$sql .= implode(' ', $this->joins) . ' ';
if (!empty($this->where)) {
$sql .= 'WHERE (' . implode(') AND (', $this->where) . ') ';
}
if (!$count && !empty($this->order)) {
$sql .= 'ORDER BY ' . implode(', ', $this->order);
}
return $sql;
}
/**
* Count the records.
*
* @return int The number of records.
*/
public function count_records() {
global $DB;
return $DB->count_records_sql($this->build_query(true), $this->params);
}
/**
* Filter a field using a letter.
*
* @param string $letter The letter.
* @param string $finalfield The SQL statement representing the field.
*/
protected function filter_by_letter($letter, $finalfield) {
global $DB;
$letter = core_text::strtoupper($letter);
$len = core_text::strlen($letter);
$sql = $DB->sql_substr(sprintf('upper(%s)', $finalfield), 1, $len);
$this->where[] = "$sql = :letter";
$this->params['letter'] = $letter;
}
/**
* Filter a field by special characters.
*
* @param string $finalfield The SQL statement representing the field.
*/
protected function filter_by_non_letter($finalfield) {
global $DB;
$alphabet = explode(',', get_string('alphabet', 'langconfig'));
list($nia, $aparams) = $DB->get_in_or_equal($alphabet, SQL_PARAMS_NAMED, 'nonletter', false);
$sql = $DB->sql_substr(sprintf('upper(%s)', $finalfield), 1, 1);
$this->where[] = "$sql $nia";
$this->params = array_merge($this->params, $aparams);
}
/**
* Filter the author by letter.
*
* @param string $letter The letter.
* @param bool $firstnamefirst Whether or not the firstname is first in the author's name.
*/
public function filter_by_author_letter($letter, $firstnamefirst = false) {
$field = self::get_fullname_field($firstnamefirst);
$this->filter_by_letter($letter, $field);
}
/**
* Filter the author by special characters.
*
* @param bool $firstnamefirst Whether or not the firstname is first in the author's name.
*/
public function filter_by_author_non_letter($firstnamefirst = false) {
$field = self::get_fullname_field($firstnamefirst);
$this->filter_by_non_letter($field);
}
/**
* Filter the concept by letter.
*
* @param string $letter The letter.
*/
public function filter_by_concept_letter($letter) {
$this->filter_by_letter($letter, self::resolve_field('concept', 'entries'));
}
/**
* Filter the concept by special characters.
*
* @return void
*/
public function filter_by_concept_non_letter() {
$this->filter_by_non_letter(self::resolve_field('concept', 'entries'));
}
/**
* Filter non approved entries.
*
* @param string $constant One of the NON_APPROVED_* constants.
* @param int $userid The user ID when relevant, otherwise current user.
*/
public function filter_by_non_approved($constant, $userid = null) {
global $USER;
if (!$userid) {
$userid = $USER->id;
}
if ($constant === self::NON_APPROVED_ALL) {
// Nothing to do.
} else if ($constant === self::NON_APPROVED_SELF) {
$this->where[] = sprintf('%s != 0 OR %s = :toapproveuserid',
self::resolve_field('approved', 'entries'), self::resolve_field('userid', 'entries'));
$this->params['toapproveuserid'] = $USER->id;
} else if ($constant === self::NON_APPROVED_NONE) {
$this->where[] = sprintf('%s != 0', self::resolve_field('approved', 'entries'));
} else if ($constant === self::NON_APPROVED_ONLY) {
$this->where[] = sprintf('%s = 0', self::resolve_field('approved', 'entries'));
} else {
throw new coding_exception('Invalid constant');
}
}
/**
* Filter by concept or alias.
*
* This requires the alias table to be joined in the query. See {@link self::join_alias()}.
*
* @param string $term What the concept or aliases should be.
*/
public function filter_by_term($term) {
$this->where[] = sprintf("(%s = :filterterma OR %s = :filtertermb)",
self::resolve_field('concept', 'entries'),
self::resolve_field('alias', 'alias'));
$this->params['filterterma'] = $term;
$this->params['filtertermb'] = $term;
}
/**
* Convenience method to get get the SQL statement for the full name.
*
* @param bool $firstnamefirst Whether or not the firstname is first in the author's name.
* @return string The SQL statement.
*/
public static function get_fullname_field($firstnamefirst = false) {
global $DB;
if ($firstnamefirst) {
return $DB->sql_fullname(self::resolve_field('firstname', 'user'), self::resolve_field('lastname', 'user'));
}
return $DB->sql_fullname(self::resolve_field('lastname', 'user'), self::resolve_field('firstname', 'user'));
}
/**
* Get the records.
*
* @return array
*/
public function get_records() {
global $DB;
return $DB->get_records_sql($this->build_query(), $this->params, $this->limitfrom, $this->limitnum);
}
/**
* Get the recordset.
*
* @return moodle_recordset
*/
public function get_recordset() {
global $DB;
return $DB->get_recordset_sql($this->build_query(), $this->params, $this->limitfrom, $this->limitnum);
}
/**
* Retrieve a user object from a record.
*
* This comes handy when {@link self::add_user_fields} was used.
*
* @param stdClass $record The record.
* @return stdClass A user object.
*/
public static function get_user_from_record($record) {
return user_picture::unalias($record, null, 'userdataid', 'userdata');
}
/**
* Join the alias table.
*
* Note that this may cause the same entry to be returned more than once. You might want
* to add a distinct on the entry id.
*
* @return void
*/
public function join_alias() {
$this->joins[] = sprintf('LEFT JOIN {glossary_alias} %s ON %s = %s',
self::ALIAS_ALIAS, self::resolve_field('id', 'entries'), self::resolve_field('entryid', 'alias'));
}
/**
* Join on the category tables.
*
* Depending on the category passed the joins will be different. This is due to the display
* logic that assumes that when displaying all categories the non categorised entries should
* not be returned, etc...
*
* @param int $categoryid The category ID, or GLOSSARY_SHOW_* constant.
*/
public function join_category($categoryid) {
if ($categoryid === GLOSSARY_SHOW_ALL_CATEGORIES) {
$this->joins[] = sprintf('JOIN {glossary_entries_categories} %s ON %s = %s',
self::ALIAS_ENTRIES_CATEGORIES, self::resolve_field('id', 'entries'),
self::resolve_field('entryid', 'entries_categories'));
$this->joins[] = sprintf('JOIN {glossary_categories} %s ON %s = %s',
self::ALIAS_CATEGORIES, self::resolve_field('id', 'categories'),
self::resolve_field('categoryid', 'entries_categories'));
} else if ($categoryid === GLOSSARY_SHOW_NOT_CATEGORISED) {
$this->joins[] = sprintf('LEFT JOIN {glossary_entries_categories} %s ON %s = %s',
self::ALIAS_ENTRIES_CATEGORIES, self::resolve_field('id', 'entries'),
self::resolve_field('entryid', 'entries_categories'));
} else {
$this->joins[] = sprintf('JOIN {glossary_entries_categories} %s ON %s = %s AND %s = :joincategoryid',
self::ALIAS_ENTRIES_CATEGORIES, self::resolve_field('id', 'entries'),
self::resolve_field('entryid', 'entries_categories'),
self::resolve_field('categoryid', 'entries_categories'));
$this->params['joincategoryid'] = $categoryid;
}
}
/**
* Join the user table.
*
* @param bool $strict When strict uses a JOIN rather than a LEFT JOIN.
*/
public function join_user($strict = false) {
$join = $strict ? 'JOIN' : 'LEFT JOIN';
$this->joins[] = sprintf("$join {user} %s ON %s = %s",
self::ALIAS_USER, self::resolve_field('id', 'user'), self::resolve_field('userid', 'entries'));
}
/**
* Limit the number of records to fetch.
* @param int $from Fetch from.
* @param int $num Number to fetch.
*/
public function limit($from, $num) {
$this->limitfrom = $from;
$this->limitnum = $num;
}
/**
* Normalise a direction.
*
* This ensures that the value is either ASC or DESC.
*
* @param string $direction The desired direction.
* @return string ASC or DESC.
*/
protected function normalize_direction($direction) {
$direction = core_text::strtoupper($direction);
if ($direction == 'DESC') {
return 'DESC';
}
return 'ASC';
}
/**
* Order by a field.
*
* @param string $field The field, or *.
* @param string $table The table name, without the prefix 'glossary_'.
* @param string $direction ASC, or DESC.
*/
public function order_by($field, $table, $direction = '') {
$direction = self::normalize_direction($direction);
$this->order[] = self::resolve_field($field, $table) . ' ' . $direction;
}
/**
* Order by author name.
*
* @param bool $firstnamefirst Whether or not the firstname is first in the author's name.
* @param string $direction ASC, or DESC.
*/
public function order_by_author($firstnamefirst = false, $direction = '') {
$field = self::get_fullname_field($firstnamefirst);
$direction = self::normalize_direction($direction);
$this->order[] = $field . ' ' . $direction;
}
/**
* Convenience method to transform a field into SQL statement.
*
* @param string $field The field, or *.
* @param string $table The table name, without the prefix 'glossary_'.
* @return string SQL statement.
*/
protected static function resolve_field($field, $table) {
$prefix = constant(__CLASS__ . '::ALIAS_' . core_text::strtoupper($table));
return sprintf('%s.%s', $prefix, $field);
}
/**
* Simple where conditions.
*
* @param string $field The field, or *.
* @param string $table The table name, without the prefix 'glossary_'.
* @param mixed $value The value to be equal to.
*/
public function where($field, $table, $value) {
static $i = 0;
$sql = self::resolve_field($field, $table) . ' ';
if ($value === null) {
$sql .= 'IS NULL';
} else {
$param = 'where' . $i++;
$sql .= " = :$param";
$this->params[$param] = $value;
}
$this->where[] = $sql;
}
}
@@ -0,0 +1,93 @@
<?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/>.
/**
* The mod_glossary glossary category created event.
*
* @package mod_glossary
* @copyright 2014 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_glossary\event;
defined('MOODLE_INTERNAL') || die();
/**
* The mod_glossary glossary category created event class.
*
* @package mod_glossary
* @since Moodle 2.7
* @copyright 2014 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class category_created extends \core\event\base {
/**
* Init method
*/
protected function init() {
$this->data['crud'] = 'c';
$this->data['edulevel'] = self::LEVEL_PARTICIPATING;
$this->data['objecttable'] = 'glossary_categories';
}
/**
* Returns localised general event name.
*
* @return string
*/
public static function get_name() {
return get_string('eventcategorycreated', 'mod_glossary');
}
/**
* Returns non-localised event description with id's for admin use only.
*
* @return string
*/
public function get_description() {
return "The user with id '$this->userid' created the category with id '$this->objectid' for the " .
"glossary activity with course module id '$this->contextinstanceid'.";
}
/**
* Get URL related to the action.
*
* @return \moodle_url
*/
public function get_url() {
return new \moodle_url("/mod/glossary/editcategories.php",
array('id' => $this->contextinstanceid));
}
/**
* Custom validation.
*
* @throws \coding_exception
* @return void
*/
protected function validate_data() {
parent::validate_data();
// Make sure this class is never used without proper object details.
if (!$this->contextlevel === CONTEXT_MODULE) {
throw new \coding_exception('Context level must be CONTEXT_MODULE.');
}
}
public static function get_objectid_mapping() {
return array('db' => 'glossary_categories', 'restore' => 'glossary_category');
}
}
@@ -0,0 +1,93 @@
<?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/>.
/**
* The mod_glossary glossary category deleted event.
*
* @package mod_glossary
* @copyright 2014 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_glossary\event;
defined('MOODLE_INTERNAL') || die();
/**
* The mod_glossary glossary category deleted event class.
*
* @package mod_glossary
* @since Moodle 2.7
* @copyright 2014 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class category_deleted extends \core\event\base {
/**
* Init method
*/
protected function init() {
$this->data['crud'] = 'd';
$this->data['edulevel'] = self::LEVEL_PARTICIPATING;
$this->data['objecttable'] = 'glossary_categories';
}
/**
* Returns localised general event name.
*
* @return string
*/
public static function get_name() {
return get_string('eventcategorydeleted', 'mod_glossary');
}
/**
* Returns non-localised event description with id's for admin use only.
*
* @return string
*/
public function get_description() {
return "The user with id '$this->userid' deleted the category with id '$this->objectid' in the " .
"glossary activity with course module id '$this->contextinstanceid'.";
}
/**
* Get URL related to the action.
*
* @return \moodle_url
*/
public function get_url() {
return new \moodle_url("/mod/glossary/editcategories.php",
array('id' => $this->contextinstanceid));
}
/**
* Custom validation.
*
* @throws \coding_exception
* @return void
*/
protected function validate_data() {
parent::validate_data();
// Make sure this class is never used without proper object details.
if (!$this->contextlevel === CONTEXT_MODULE) {
throw new \coding_exception('Context level must be CONTEXT_MODULE.');
}
}
public static function get_objectid_mapping() {
return array('db' => 'glossary_categories', 'restore' => 'glossary_category');
}
}
@@ -0,0 +1,93 @@
<?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/>.
/**
* The mod_glossary glossary category updated event.
*
* @package mod_glossary
* @copyright 2014 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_glossary\event;
defined('MOODLE_INTERNAL') || die();
/**
* The mod_glossary glossary category updated event class.
*
* @package mod_glossary
* @since Moodle 2.7
* @copyright 2014 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class category_updated extends \core\event\base {
/**
* Init method
*/
protected function init() {
$this->data['crud'] = 'u';
$this->data['edulevel'] = self::LEVEL_PARTICIPATING;
$this->data['objecttable'] = 'glossary_categories';
}
/**
* Returns localised general event name.
*
* @return string
*/
public static function get_name() {
return get_string('eventcategoryupdated', 'mod_glossary');
}
/**
* Returns non-localised event description with id's for admin use only.
*
* @return string
*/
public function get_description() {
return "The user with id '$this->userid' updated the category with id '$this->objectid' in the " .
"glossary activity with course module id '$this->contextinstanceid'.";
}
/**
* Get URL related to the action.
*
* @return \moodle_url
*/
public function get_url() {
return new \moodle_url("/mod/glossary/editcategories.php",
array('id' => $this->contextinstanceid));
}
/**
* Custom validation.
*
* @throws \coding_exception
* @return void
*/
protected function validate_data() {
parent::validate_data();
// Make sure this class is never used without proper object details.
if (!$this->contextlevel === CONTEXT_MODULE) {
throw new \coding_exception('Context level must be CONTEXT_MODULE.');
}
}
public static function get_objectid_mapping() {
return array('db' => 'glossary_categories', 'restore' => 'glossary_category');
}
}
@@ -0,0 +1,55 @@
<?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/>.
/**
* The mod_glossary comment created event.
*
* @package mod_glossary
* @copyright 2013 Rajesh Taneja <rajesh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_glossary\event;
defined('MOODLE_INTERNAL') || die();
/**
* The mod_glossary comment created event class.
*
* @package mod_glossary
* @since Moodle 2.7
* @copyright 2013 Rajesh Taneja <rajesh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class comment_created extends \core\event\comment_created {
/**
* Get URL related to the action.
*
* @return \moodle_url
*/
public function get_url() {
return new \moodle_url('/mod/glossary/view.php', array('id' => $this->contextinstanceid));
}
/**
* Returns description of what happened.
*
* @return string
*/
public function get_description() {
return "The user with id '$this->userid' added the comment with id '$this->objectid' to the glossary activity " .
"with course module id '$this->contextinstanceid'.";
}
}
@@ -0,0 +1,55 @@
<?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/>.
/**
* The mod_glossary comment deleted event.
*
* @package mod_glossary
* @copyright 2013 Rajesh Taneja <rajesh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_glossary\event;
defined('MOODLE_INTERNAL') || die();
/**
* The mod_glossary comment deleted event class.
*
* @package mod_glossary
* @since Moodle 2.7
* @copyright 2013 Rajesh Taneja <rajesh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class comment_deleted extends \core\event\comment_deleted {
/**
* Get URL related to the action.
*
* @return \moodle_url
*/
public function get_url() {
return new \moodle_url('/mod/glossary/view.php', array('id' => $this->contextinstanceid));
}
/**
* Returns description of what happened.
*
* @return string
*/
public function get_description() {
return "The user with id '$this->userid' deleted the comment with id '$this->objectid' from the glossary activity " .
"with course module id '$this->contextinstanceid'.";
}
}
@@ -0,0 +1,39 @@
<?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/>.
/**
* The mod_glossary instance list viewed event.
*
* @package mod_glossary
* @copyright 2014 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_glossary\event;
defined('MOODLE_INTERNAL') || die();
/**
* The mod_glossary instance list viewed event class.
*
* @package mod_glossary
* @since Moodle 2.7
* @copyright 2014 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class course_module_instance_list_viewed extends \core\event\course_module_instance_list_viewed {
// No code required here as the parent class handles it all.
}
@@ -0,0 +1,74 @@
<?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/>.
/**
* The mod_glossary course module viewed event.
*
* @package mod_glossary
* @copyright 2014 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_glossary\event;
defined('MOODLE_INTERNAL') || die();
/**
* The mod_glossary course module viewed event class.
*
* @property-read array $other {
* Extra information about event.
*
* - string mode: (optional)
* }
*
* @package mod_glossary
* @since Moodle 2.7
* @copyright 2014 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class course_module_viewed extends \core\event\course_module_viewed {
/**
* Init method.
*/
protected function init() {
$this->data['crud'] = 'r';
$this->data['edulevel'] = self::LEVEL_PARTICIPATING;
$this->data['objecttable'] = 'glossary';
}
/**
* Get URL related to the action.
*
* @return \moodle_url
*/
public function get_url() {
$params = array('id' => $this->contextinstanceid);
if (!empty($this->other['mode'])) {
$params['mode'] = $this->other['mode'];
}
return new \moodle_url("/mod/$this->objecttable/view.php", $params);
}
public static function get_objectid_mapping() {
return array('db' => 'glossary', 'restore' => 'glossary');
}
public static function get_other_mapping() {
// Nothing to map.
return false;
}
}
@@ -0,0 +1,95 @@
<?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/>.
/**
* The mod_glossary entry approved event.
*
* @package mod_glossary
* @copyright 2014 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_glossary\event;
defined('MOODLE_INTERNAL') || die();
/**
* The mod_glossary entry approved event class.
*
* @package mod_glossary
* @since Moodle 2.7
* @copyright 2014 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class entry_approved extends \core\event\base {
/**
* Init method
*/
protected function init() {
$this->data['crud'] = 'u';
$this->data['edulevel'] = self::LEVEL_PARTICIPATING;
$this->data['objecttable'] = 'glossary_entries';
}
/**
* Returns localised general event name.
*
* @return string
*/
public static function get_name() {
return get_string('evententryapproved', 'mod_glossary');
}
/**
* Returns non-localised event description with id's for admin use only.
*
* @return string
*/
public function get_description() {
return "The user with id '$this->userid' has approved the glossary entry with id '$this->objectid' for " .
"the glossary activity with course module id '$this->contextinstanceid'.";
}
/**
* Get URL related to the action.
*
* @return \moodle_url
*/
public function get_url() {
return new \moodle_url("/mod/glossary/view.php",
array('id' => $this->contextinstanceid,
'mode' => 'entry',
'hook' => $this->objectid));
}
/**
* Custom validation.
*
* @throws \coding_exception
* @return void
*/
protected function validate_data() {
parent::validate_data();
// Make sure this class is never used without proper object details.
if (!$this->contextlevel === CONTEXT_MODULE) {
throw new \coding_exception('Context level must be CONTEXT_MODULE.');
}
}
public static function get_objectid_mapping() {
return array('db' => 'glossary_entries', 'restore' => 'glossary_entry');
}
}
@@ -0,0 +1,106 @@
<?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/>.
/**
* The mod_glossary entry created event.
*
* @package mod_glossary
* @copyright 2014 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_glossary\event;
defined('MOODLE_INTERNAL') || die();
/**
* The mod_glossary entry created event class.
*
* @property-read array $other {
* Extra information about event.
*
* - string concept: (optional) the concept of created entry.
* }
*
* @package mod_glossary
* @since Moodle 2.7
* @copyright 2014 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class entry_created extends \core\event\base {
/**
* Init method
*/
protected function init() {
$this->data['crud'] = 'c';
$this->data['edulevel'] = self::LEVEL_PARTICIPATING;
$this->data['objecttable'] = 'glossary_entries';
}
/**
* Returns localised general event name.
*
* @return string
*/
public static function get_name() {
return get_string('evententrycreated', 'mod_glossary');
}
/**
* Returns non-localised event description with id's for admin use only.
*
* @return string
*/
public function get_description() {
return "The user with id '$this->userid' has created the glossary entry with id '$this->objectid' for " .
"the glossary activity with course module id '$this->contextinstanceid'.";
}
/**
* Get URL related to the action.
*
* @return \moodle_url
*/
public function get_url() {
return new \moodle_url("/mod/glossary/view.php",
array('id' => $this->contextinstanceid,
'mode' => 'entry',
'hook' => $this->objectid));
}
/**
* Custom validation.
*
* @throws \coding_exception
* @return void
*/
protected function validate_data() {
parent::validate_data();
// Make sure this class is never used without proper object details.
if (!$this->contextlevel === CONTEXT_MODULE) {
throw new \coding_exception('Context level must be CONTEXT_MODULE.');
}
}
public static function get_objectid_mapping() {
return array('db' => 'glossary_entries', 'restore' => 'glossary_entry');
}
public static function get_other_mapping() {
// Nothing to map.
return false;
}
}
@@ -0,0 +1,113 @@
<?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/>.
/**
* The mod_glossary entry deleted event.
*
* @package mod_glossary
* @copyright 2014 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_glossary\event;
defined('MOODLE_INTERNAL') || die();
/**
* The mod_glossary entry deleted event class.
*
* @property-read array $other {
* Extra information about event.
*
* - string concept: (optional) the concept of deleted entry.
* - string mode: (optional) view mode user was in before deleting entry.
* - int|string hook: (optional) hook parameter in the previous view mode.
* }
*
* @package mod_glossary
* @since Moodle 2.7
* @copyright 2014 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class entry_deleted extends \core\event\base {
/**
* Init method
*/
protected function init() {
$this->data['crud'] = 'd';
$this->data['edulevel'] = self::LEVEL_PARTICIPATING;
$this->data['objecttable'] = 'glossary_entries';
}
/**
* Returns localised general event name.
*
* @return string
*/
public static function get_name() {
return get_string('evententrydeleted', 'mod_glossary');
}
/**
* Returns non-localised event description with id's for admin use only.
*
* @return string
*/
public function get_description() {
return "The user with id '$this->userid' has deleted the glossary entry with id '$this->objectid' in " .
"the glossary activity with course module id '$this->contextinstanceid'.";
}
/**
* Get URL related to the action.
*
* @return \moodle_url
*/
public function get_url() {
// Entry does not exist any more, returning link to the module view page in the mode it was before deleting entry.
$params = array('id' => $this->contextinstanceid);
if (isset($this->other['hook'])) {
$params['hook'] = $this->other['hook'];
}
if (isset($this->other['mode'])) {
$params['mode'] = $this->other['mode'];
}
return new \moodle_url("/mod/glossary/view.php", $params);
}
/**
* Custom validation.
*
* @throws \coding_exception
* @return void
*/
protected function validate_data() {
parent::validate_data();
// Make sure this class is never used without proper object details.
if (!$this->contextlevel === CONTEXT_MODULE) {
throw new \coding_exception('Context level must be CONTEXT_MODULE.');
}
}
public static function get_objectid_mapping() {
return array('db' => 'glossary_entries', 'restore' => 'glossary_entry');
}
public static function get_other_mapping() {
// Nothing to map.
return false;
}
}
@@ -0,0 +1,95 @@
<?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/>.
/**
* The mod_glossary entry disapproved event.
*
* @package mod_glossary
* @copyright 2014 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_glossary\event;
defined('MOODLE_INTERNAL') || die();
/**
* The mod_glossary entry disapproved event.
*
* @package mod_glossary
* @since Moodle 2.7
* @copyright 2014 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class entry_disapproved extends \core\event\base {
/**
* Init method
*/
protected function init() {
$this->data['crud'] = 'u';
$this->data['edulevel'] = self::LEVEL_PARTICIPATING;
$this->data['objecttable'] = 'glossary_entries';
}
/**
* Returns localised general event name.
*
* @return string
*/
public static function get_name() {
return get_string('evententrydisapproved', 'mod_glossary');
}
/**
* Returns non-localised event description with id's for admin use only.
*
* @return string
*/
public function get_description() {
return "The user with id '$this->userid' has disapproved the glossary entry with id '$this->objectid' for " .
"the glossary activity with course module id '$this->contextinstanceid'.";
}
/**
* Get URL related to the action.
*
* @return \moodle_url
*/
public function get_url() {
return new \moodle_url("/mod/glossary/view.php",
array('id' => $this->contextinstanceid,
'mode' => 'entry',
'hook' => $this->objectid));
}
/**
* Custom validation.
*
* @throws \coding_exception
* @return void
*/
protected function validate_data() {
parent::validate_data();
// Make sure this class is never used without proper object details.
if (!$this->contextlevel === CONTEXT_MODULE) {
throw new \coding_exception('Context level must be CONTEXT_MODULE.');
}
}
public static function get_objectid_mapping() {
return array('db' => 'glossary_entries', 'restore' => 'glossary_entry');
}
}
@@ -0,0 +1,106 @@
<?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/>.
/**
* The mod_glossary entry updated event.
*
* @package mod_glossary
* @copyright 2014 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_glossary\event;
defined('MOODLE_INTERNAL') || die();
/**
* The mod_glossary entry updated event.
*
* @property-read array $other {
* Extra information about event.
*
* - string concept: (optional) the concept of updated entry (after update).
* }
*
* @package mod_glossary
* @since Moodle 2.7
* @copyright 2014 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class entry_updated extends \core\event\base {
/**
* Init method
*/
protected function init() {
$this->data['crud'] = 'u';
$this->data['edulevel'] = self::LEVEL_PARTICIPATING;
$this->data['objecttable'] = 'glossary_entries';
}
/**
* Returns localised general event name.
*
* @return string
*/
public static function get_name() {
return get_string('evententryupdated', 'mod_glossary');
}
/**
* Returns non-localised event description with id's for admin use only.
*
* @return string
*/
public function get_description() {
return "The user with id '$this->userid' has updated the glossary entry with id '$this->objectid' in " .
"the glossary activity with course module id '$this->contextinstanceid'.";
}
/**
* Get URL related to the action.
*
* @return \moodle_url
*/
public function get_url() {
return new \moodle_url("/mod/glossary/view.php",
array('id' => $this->contextinstanceid,
'mode' => 'entry',
'hook' => $this->objectid));
}
/**
* Custom validation.
*
* @throws \coding_exception
* @return void
*/
protected function validate_data() {
parent::validate_data();
// Make sure this class is never used without proper object details.
if (!$this->contextlevel === CONTEXT_MODULE) {
throw new \coding_exception('Context level must be CONTEXT_MODULE.');
}
}
public static function get_objectid_mapping() {
return array('db' => 'glossary_entries', 'restore' => 'glossary_entry');
}
public static function get_other_mapping() {
// Nothing to map.
return false;
}
}
@@ -0,0 +1,95 @@
<?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/>.
/**
* The mod_glossary entry viwed event.
*
* @package mod_glossary
* @copyright 2014 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_glossary\event;
defined('MOODLE_INTERNAL') || die();
/**
* The mod_glossary entry viewed event class.
*
* Triggered when glossary entry is autolinked and viewed by user from another context.
*
* @package mod_glossary
* @since Moodle 2.7
* @copyright 2014 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class entry_viewed extends \core\event\base {
/**
* Init method
*/
protected function init() {
$this->data['crud'] = 'r';
$this->data['edulevel'] = self::LEVEL_PARTICIPATING;
$this->data['objecttable'] = 'glossary_entries';
}
/**
* Returns localised general event name.
*
* @return string
*/
public static function get_name() {
return get_string('evententryviewed', 'mod_glossary');
}
/**
* Returns non-localised event description with id's for admin use only.
*
* @return string
*/
public function get_description() {
return "The user with id '$this->userid' has viewed the glossary entry with id '$this->objectid' in " .
"the glossary activity with course module id '$this->contextinstanceid'.";
}
/**
* Get URL related to the action.
*
* @return \moodle_url
*/
public function get_url() {
return new \moodle_url("/mod/glossary/showentry.php",
array('eid' => $this->objectid));
}
/**
* Custom validation.
*
* @throws \coding_exception
* @return void
*/
protected function validate_data() {
parent::validate_data();
// Make sure this class is never used without proper object details.
if (!$this->contextlevel === CONTEXT_MODULE) {
throw new \coding_exception('Context level must be CONTEXT_MODULE.');
}
}
public static function get_objectid_mapping() {
return array('db' => 'glossary_entries', 'restore' => 'glossary_entry');
}
}
File diff suppressed because it is too large Load Diff
+95
View File
@@ -0,0 +1,95 @@
<?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/>.
/**
* This is the external method for deleting a content.
*
* @package mod_glossary
* @since Moodle 3.10
* @copyright 2020 Juan Leyva <juan@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_glossary\external;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/mod/glossary/lib.php');
use core_external\external_api;
use core_external\external_function_parameters;
use core_external\external_single_structure;
use core_external\external_value;
use core_external\external_warnings;
/**
* This is the external method for deleting a content.
*
* @copyright 2020 Juan Leyva <juan@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class delete_entry extends external_api {
/**
* Parameters.
*
* @return external_function_parameters
*/
public static function execute_parameters(): external_function_parameters {
return new external_function_parameters([
'entryid' => new external_value(PARAM_INT, 'Glossary entry id to delete'),
]);
}
/**
* Delete the indicated entry from the glossary.
*
* @param int $entryid The entry to delete
* @return array with result and warnings
* @throws moodle_exception
*/
public static function execute(int $entryid): array {
global $DB;
$params = self::validate_parameters(self::execute_parameters(), compact('entryid'));
$id = $params['entryid'];
// Get and validate the glossary.
$entry = $DB->get_record('glossary_entries', ['id' => $id], '*', MUST_EXIST);
list($glossary, $context, $course, $cm) = \mod_glossary_external::validate_glossary($entry->glossaryid);
// Check and delete.
mod_glossary_can_delete_entry($entry, $glossary, $context, false);
mod_glossary_delete_entry($entry, $glossary, $cm, $context, $course);
return [
'result' => true,
'warnings' => [],
];
}
/**
* Return.
*
* @return external_single_structure
*/
public static function execute_returns(): external_single_structure {
return new external_single_structure([
'result' => new external_value(PARAM_BOOL, 'The processing result'),
'warnings' => new external_warnings()
]);
}
}
+152
View File
@@ -0,0 +1,152 @@
<?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/>.
/**
* This is the external method for preparing a entry for edition.
*
* @package mod_glossary
* @since Moodle 3.10
* @copyright 2020 Juan Leyva <juan@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_glossary\external;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/mod/glossary/lib.php');
use core_external\external_api;
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;
/**
* This is the external method for preparing a entry for edition.
*
* @copyright 2020 Juan Leyva <juan@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class prepare_entry extends external_api {
/**
* Parameters.
*
* @return external_function_parameters
*/
public static function execute_parameters(): external_function_parameters {
return new external_function_parameters([
'entryid' => new external_value(PARAM_INT, 'Glossary entry id to update'),
]);
}
/**
* Prepare for update the indicated entry from the glossary.
*
* @param int $entryid The entry to update
* @return array with result and warnings
* @throws moodle_exception
*/
public static function execute(int $entryid): array {
global $DB;
$params = self::validate_parameters(self::execute_parameters(), compact('entryid'));
$id = $params['entryid'];
// Get and validate the glossary.
$entry = $DB->get_record('glossary_entries', ['id' => $id], '*', MUST_EXIST);
list($glossary, $context, $course, $cm) = \mod_glossary_external::validate_glossary($entry->glossaryid);
// Check permissions.
mod_glossary_can_update_entry($entry, $glossary, $context, $cm, false);
list($definitionoptions, $attachmentoptions) = glossary_get_editor_and_attachment_options($course, $context, $entry);
$entry->aliases = '';
$entry->categories = [];
$entry = mod_glossary_prepare_entry_for_edition($entry);
$entry = file_prepare_standard_editor($entry, 'definition', $definitionoptions, $context, 'mod_glossary', 'entry',
$entry->id);
$entry = file_prepare_standard_filemanager($entry, 'attachment', $attachmentoptions, $context, 'mod_glossary', 'attachment',
$entry->id);
// Just get a structure compatible with external API.
array_walk($definitionoptions, function(&$item, $key) use (&$definitionoptions) {
if (!is_scalar($item)) {
unset($definitionoptions[$key]);
return;
}
$item = ['name' => $key, 'value' => $item];
});
array_walk($attachmentoptions, function(&$item, $key) use (&$attachmentoptions) {
if (!is_scalar($item)) {
unset($attachmentoptions[$key]);
return;
}
$item = ['name' => $key, 'value' => $item];
});
return [
'inlineattachmentsid' => $entry->definition_editor['itemid'],
'attachmentsid' => $entry->attachment_filemanager,
'areas' => [
[
'area' => 'definition',
'options' => $definitionoptions,
],
[
'area' => 'attachment',
'options' => $attachmentoptions,
],
],
'aliases' => explode("\n", trim($entry->aliases)),
'categories' => $entry->categories,
];
}
/**
* Return.
*
* @return external_single_structure
*/
public static function execute_returns(): external_single_structure {
return new external_single_structure([
'inlineattachmentsid' => new external_value(PARAM_INT, 'Draft item id for the text editor.'),
'attachmentsid' => new external_value(PARAM_INT, 'Draft item id for the file manager.'),
'areas' => new external_multiple_structure(
new external_single_structure(
[
'area' => new external_value(PARAM_ALPHA, 'File area name.'),
'options' => new external_multiple_structure(
new external_single_structure(
[
'name' => new external_value(PARAM_RAW, 'Name of option.'),
'value' => new external_value(PARAM_RAW, 'Value of option.'),
]
), 'Draft file area options.'
)
]
), 'File areas including options'
),
'aliases' => new external_multiple_structure(new external_value(PARAM_RAW, 'Alias name.')),
'categories' => new external_multiple_structure(new external_value(PARAM_INT, 'Category id')),
'warnings' => new external_warnings(),
]);
}
}
+175
View File
@@ -0,0 +1,175 @@
<?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/>.
/**
* This is the external method for updating a glossary entry.
*
* @package mod_glossary
* @since Moodle 3.10
* @copyright 2020 Juan Leyva <juan@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_glossary\external;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/mod/glossary/lib.php');
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;
use core_text;
use moodle_exception;
/**
* This is the external method for updating a glossary entry.
*
* @copyright 2020 Juan Leyva <juan@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class update_entry extends external_api {
/**
* Parameters.
*
* @return external_function_parameters
*/
public static function execute_parameters(): external_function_parameters {
return new external_function_parameters([
'entryid' => new external_value(PARAM_INT, 'Glossary entry id to update'),
'concept' => new external_value(PARAM_TEXT, 'Glossary concept'),
'definition' => new external_value(PARAM_RAW, 'Glossary concept definition'),
'definitionformat' => new external_format_value('definition'),
'options' => new external_multiple_structure (
new external_single_structure(
[
'name' => new external_value(PARAM_ALPHANUM,
'The allowed keys (value format) are:
inlineattachmentsid (int); the draft file area id for inline attachments
attachmentsid (int); the draft file area id for attachments
categories (comma separated int); comma separated category ids
aliases (comma separated str); comma separated aliases
usedynalink (bool); whether the entry should be automatically linked.
casesensitive (bool); whether the entry is case sensitive.
fullmatch (bool); whether to match whole words only.'),
'value' => new external_value(PARAM_RAW, 'the value of the option (validated inside the function)')
]
), 'Optional settings', VALUE_DEFAULT, []
)
]);
}
/**
* Update the indicated glossary entry.
*
* @param int $entryid The entry to update
* @param string $concept the glossary concept
* @param string $definition the concept definition
* @param int $definitionformat the concept definition format
* @param array $options additional settings
* @return array with result and warnings
* @throws moodle_exception
*/
public static function execute(int $entryid, string $concept, string $definition, int $definitionformat,
array $options = []): array {
global $DB;
$params = self::validate_parameters(self::execute_parameters(), compact('entryid', 'concept', 'definition',
'definitionformat', 'options'));
$id = $params['entryid'];
// Get and validate the glossary entry.
$entry = $DB->get_record('glossary_entries', ['id' => $id], '*', MUST_EXIST);
list($glossary, $context, $course, $cm) = \mod_glossary_external::validate_glossary($entry->glossaryid);
// Check if the user can update the entry.
mod_glossary_can_update_entry($entry, $glossary, $context, $cm, false);
// Check for duplicates if the concept changes.
if (!$glossary->allowduplicatedentries &&
core_text::strtolower($entry->concept) != core_text::strtolower(trim($params['concept']))) {
if (glossary_concept_exists($glossary, $params['concept'])) {
throw new moodle_exception('errconceptalreadyexists', 'glossary');
}
}
// Prepare the entry object.
$entry->aliases = '';
$entry = mod_glossary_prepare_entry_for_edition($entry);
$entry->concept = $params['concept'];
$entry->definition_editor = [
'text' => $params['definition'],
'format' => $params['definitionformat'],
];
// Options.
foreach ($params['options'] as $option) {
$name = trim($option['name']);
switch ($name) {
case 'inlineattachmentsid':
$entry->definition_editor['itemid'] = clean_param($option['value'], PARAM_INT);
break;
case 'attachmentsid':
$entry->attachment_filemanager = clean_param($option['value'], PARAM_INT);
break;
case 'categories':
$entry->categories = clean_param($option['value'], PARAM_SEQUENCE);
$entry->categories = explode(',', $entry->categories);
break;
case 'aliases':
$entry->aliases = clean_param($option['value'], PARAM_NOTAGS);
// Convert to the expected format.
$entry->aliases = str_replace(",", "\n", $entry->aliases);
break;
case 'usedynalink':
case 'casesensitive':
case 'fullmatch':
// Only allow if linking is enabled.
if ($glossary->usedynalink) {
$entry->{$name} = clean_param($option['value'], PARAM_BOOL);
}
break;
default:
throw new moodle_exception('errorinvalidparam', 'webservice', '', $name);
}
}
$entry = glossary_edit_entry($entry, $course, $cm, $glossary, $context);
return [
'result' => true,
'warnings' => [],
];
}
/**
* Return.
*
* @return external_single_structure
*/
public static function execute_returns(): external_single_structure {
return new external_single_structure([
'result' => new external_value(PARAM_BOOL, 'The update result'),
'warnings' => new external_warnings()
]);
}
}
@@ -0,0 +1,295 @@
<?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/>.
/**
* Entry caching for glossary filter.
*
* @package mod_glossary
* @copyright 2014 Petr Skoda
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_glossary\local;
defined('MOODLE_INTERNAL') || die();
/**
* Concept caching for glossary filter.
*
* @package mod_glossary
* @copyright 2014 Petr Skoda
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class concept_cache {
/**
* Event observer, do not call directly.
* @param \core\event\course_module_updated $event
*/
public static function cm_updated(\core\event\course_module_updated $event) {
if ($event->other['modulename'] !== 'glossary') {
return;
}
// We do not know what changed exactly, so let's reset everything that might be affected.
concept_cache::reset_course_muc($event->courseid);
concept_cache::reset_global_muc();
}
/**
* Reset concept related caches.
* @param bool $phpunitreset
*/
public static function reset_caches($phpunitreset = false) {
if ($phpunitreset) {
return;
}
$cache = \cache::make('mod_glossary', 'concepts');
$cache->purge();
}
/**
* Reset the cache for course concepts.
* @param int $courseid
*/
public static function reset_course_muc($courseid) {
if (empty($courseid)) {
return;
}
$cache = \cache::make('mod_glossary', 'concepts');
$cache->delete((int)$courseid);
}
/**
* Reset the cache for global concepts.
*/
public static function reset_global_muc() {
$cache = \cache::make('mod_glossary', 'concepts');
$cache->delete(0);
}
/**
* Utility method to purge caches related to given glossary.
* @param \stdClass $glossary
*/
public static function reset_glossary($glossary) {
if (!$glossary->usedynalink) {
return;
}
self::reset_course_muc($glossary->course);
if ($glossary->globalglossary) {
self::reset_global_muc();
}
}
/**
* Fetch concepts for given glossaries.
* @param int[] $glossaries
* @return array
*/
protected static function fetch_concepts(array $glossaries) {
global $DB;
$glossarylist = implode(',', $glossaries);
$sql = "SELECT id, glossaryid, concept, casesensitive, 0 AS category, fullmatch
FROM {glossary_entries}
WHERE glossaryid IN ($glossarylist) AND usedynalink = 1 AND approved = 1
UNION
SELECT id, glossaryid, name AS concept, 1 AS casesensitive, 1 AS category, 1 AS fullmatch
FROM {glossary_categories}
WHERE glossaryid IN ($glossarylist) AND usedynalink = 1
UNION
SELECT ge.id, ge.glossaryid, ga.alias AS concept, ge.casesensitive, 0 AS category, ge.fullmatch
FROM {glossary_alias} ga
JOIN {glossary_entries} ge ON (ga.entryid = ge.id)
WHERE ge.glossaryid IN ($glossarylist) AND ge.usedynalink = 1 AND ge.approved = 1";
$concepts = array();
$rs = $DB->get_recordset_sql($sql);
foreach ($rs as $concept) {
$currentconcept = trim(strip_tags($concept->concept));
// Concept must be HTML-escaped, so do the same as format_string to turn ampersands into &amp;.
$currentconcept = replace_ampersands_not_followed_by_entity($currentconcept);
if (empty($currentconcept)) {
continue;
}
// Rule out any small integers, see MDL-1446.
if (is_number($currentconcept) and $currentconcept < 1000) {
continue;
}
$concept->concept = $currentconcept;
$concepts[$concept->glossaryid][] = $concept;
}
$rs->close();
return $concepts;
}
/**
* Get all linked concepts from course.
* @param int $courseid
* @return array
*/
protected static function get_course_concepts($courseid) {
global $DB;
if (empty($courseid)) {
return array(array(), array());
}
$courseid = (int)$courseid;
// Get info on any glossaries in this course.
$modinfo = get_fast_modinfo($courseid);
$cminfos = $modinfo->get_instances_of('glossary');
if (!$cminfos) {
// No glossaries in this course, so don't do any work.
return array(array(), array());
}
$cache = \cache::make('mod_glossary', 'concepts');
$data = $cache->get($courseid);
if (is_array($data)) {
list($glossaries, $allconcepts) = $data;
} else {
// Find all course glossaries.
$sql = "SELECT g.id, g.name
FROM {glossary} g
JOIN {course_modules} cm ON (cm.instance = g.id)
JOIN {modules} m ON (m.name = 'glossary' AND m.id = cm.module)
WHERE g.usedynalink = 1 AND g.course = :course AND cm.visible = 1 AND m.visible = 1
ORDER BY g.globalglossary, g.id";
$glossaries = $DB->get_records_sql_menu($sql, array('course' => $courseid));
if (!$glossaries) {
$data = array(array(), array());
$cache->set($courseid, $data);
return $data;
}
foreach ($glossaries as $id => $name) {
$name = str_replace(':', '-', $name);
$glossaries[$id] = replace_ampersands_not_followed_by_entity(strip_tags($name));
}
$allconcepts = self::fetch_concepts(array_keys($glossaries));
foreach ($glossaries as $gid => $unused) {
if (!isset($allconcepts[$gid])) {
unset($glossaries[$gid]);
}
}
if (!$glossaries) {
// This means there are no interesting concepts in the existing glossaries.
$data = array(array(), array());
$cache->set($courseid, $data);
return $data;
}
$cache->set($courseid, array($glossaries, $allconcepts));
}
$concepts = $allconcepts;
// Verify access control to glossary instances.
foreach ($concepts as $modid => $unused) {
if (!isset($cminfos[$modid])) {
// This should not happen.
unset($concepts[$modid]);
unset($glossaries[$modid]);
continue;
}
if (!$cminfos[$modid]->uservisible) {
unset($concepts[$modid]);
unset($glossaries[$modid]);
continue;
}
}
return array($glossaries, $concepts);
}
/**
* Get all linked global concepts.
* @return array
*/
protected static function get_global_concepts() {
global $DB;
$cache = \cache::make('mod_glossary', 'concepts');
$data = $cache->get(0);
if (is_array($data)) {
list($glossaries, $allconcepts) = $data;
} else {
// Find all global glossaries - no access control here.
$sql = "SELECT g.id, g.name
FROM {glossary} g
JOIN {course_modules} cm ON (cm.instance = g.id)
JOIN {modules} m ON (m.name = 'glossary' AND m.id = cm.module)
WHERE g.usedynalink = 1 AND g.globalglossary = 1 AND cm.visible = 1 AND m.visible = 1
ORDER BY g.globalglossary, g.id";
$glossaries = $DB->get_records_sql_menu($sql);
if (!$glossaries) {
$data = array(array(), array());
$cache->set(0, $data);
return $data;
}
foreach ($glossaries as $id => $name) {
$name = str_replace(':', '-', $name);
$glossaries[$id] = replace_ampersands_not_followed_by_entity(strip_tags($name));
}
$allconcepts = self::fetch_concepts(array_keys($glossaries));
foreach ($glossaries as $gid => $unused) {
if (!isset($allconcepts[$gid])) {
unset($glossaries[$gid]);
}
}
$cache->set(0, array($glossaries, $allconcepts));
}
// NOTE: no access control is here because it would be way too expensive to check access
// to all courses that contain the global glossaries.
return array($glossaries, $allconcepts);
}
/**
* Get all concepts that should be linked in the given course.
* @param int $courseid
* @return array with two elements - array of glossaries and concepts for each glossary
*/
public static function get_concepts($courseid) {
list($glossaries, $concepts) = self::get_course_concepts($courseid);
list($globalglossaries, $globalconcepts) = self::get_global_concepts();
foreach ($globalconcepts as $gid => $cs) {
if (!isset($concepts[$gid])) {
$concepts[$gid] = $cs;
}
}
foreach ($globalglossaries as $gid => $name) {
if (!isset($glossaries[$gid])) {
$glossaries[$gid] = $name;
}
}
return array($glossaries, $concepts);
}
}
@@ -0,0 +1,47 @@
<?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/>.
namespace mod_glossary\navigation\views;
use core\navigation\views\secondary as core_secondary;
/**
* Class secondary_navigation_view.
*
* Custom implementation for a plugin.
*
* @package mod_glossary
* @category navigation
* @copyright 2021 onwards Peter Dias
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class secondary extends core_secondary {
/**
* Define a custom secondary nav order/view
*
* @return array
*/
protected function get_default_module_mapping(): array {
return [
self::TYPE_SETTING => [
'modedit' => 1,
],
self::TYPE_CUSTOM => [
'pendingapproval' => 2,
],
];
}
}
+41
View File
@@ -0,0 +1,41 @@
<?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/>.
namespace mod_glossary\output;
use plugin_renderer_base;
/**
* Class actionbar - Display the action bar
*
* @package mod_glossary
* @copyright 2021 Peter Dias
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class renderer extends plugin_renderer_base {
/**
* Render the glossary tertiary nav
*
* @param standard_action_bar $actionmenu
* @return bool|string
* @throws \moodle_exception
*/
public function main_action_bar(standard_action_bar $actionmenu) {
$context = $actionmenu->export_for_template($this);
return $this->render_from_template('mod_glossary/standard_action_menu', $context);
}
}
@@ -0,0 +1,289 @@
<?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/>.
namespace mod_glossary\output;
use moodle_url;
use context_module;
use renderable;
use renderer_base;
use single_button;
use templatable;
use url_select;
/**
* Class standard_action_bar - Display the action bar
*
* @package mod_glossary
* @copyright 2021 Peter Dias
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class standard_action_bar implements renderable, templatable {
/** @var object $cm The course module. */
private $cm;
/** @var string $mode The type of view. */
private $mode;
/** @var string $hook The term, entry, cat, etc... to look for based on mode. */
private $hook;
/** @var string $sortkey Sorted view: CREATION | UPDATE | FIRSTNAME | LASTNAME. */
private $sortkey;
/** @var string $sortorder The sort order (ASC or DESC). */
private $sortorder;
/** @var int $offset Entries to bypass (for paging purposes). */
private $offset;
/** @var int $pagelimit The page to resume with. */
private $pagelimit;
/** @var int $context The context of the glossary. */
private $context;
/** @var object $module The glossary record . */
private $module;
/** @var int $fullsearch Full search (concept and definition) when searching. */
private $fullsearch;
/** @var object $displayformat Override of the glossary display format. */
private $displayformat;
/** @var string $tab Browsing entries by categories. */
private $tab;
/**
* standard_action_bar constructor.
*
* @param object $cm
* @param object $module
* @param object $displayformat
* @param string $mode
* @param string $hook
* @param string $sortkey
* @param string $sortorder
* @param int $offset
* @param int $pagelimit
* @param int $fullsearch
* @param string $tab
* @param string $defaulttab
* @throws \coding_exception
*/
public function __construct(object $cm, object $module, object $displayformat, string $mode, string $hook,
string $sortkey, string $sortorder, int $offset, int $pagelimit, int $fullsearch,
string $tab, string $defaulttab) {
$this->cm = $cm;
$this->module = $module;
$this->displayformat = $displayformat;
$this->mode = $mode;
$this->tab = $tab;
$this->hook = $hook;
$this->sortkey = $sortkey;
$this->sortorder = $sortorder;
$this->offset = $offset;
$this->pagelimit = $pagelimit;
$this->fullsearch = $fullsearch;
$this->context = context_module::instance($this->cm->id);
if (!has_capability('mod/glossary:approve', $this->context) && $this->tab == GLOSSARY_APPROVAL_VIEW) {
// Non-teachers going to approval view go to defaulttab.
$this->tab = $defaulttab;
}
}
/**
* Export the action bar
*
* @param renderer_base $output
* @return array
*/
public function export_for_template(renderer_base $output) {
return [
'addnewbutton' => $this->create_add_button($output),
'searchbox' => $this->create_search_box(),
'tools' => $this->get_additional_tools($output),
'tabjumps' => $this->generate_tab_jumps($output)
];
}
/**
* Render the search box with the checkbox
*
* @return array
*/
private function create_search_box(): array {
global $OUTPUT;
$fullsearchchecked = false;
if ($this->fullsearch || $this->mode != 'search') {
$fullsearchchecked = true;
}
$check = [
'name' => 'fullsearch',
'id' => 'fullsearch',
'value' => '1',
'checked' => $fullsearchchecked,
'label' => get_string("searchindefinition", "glossary"),
];
$checkbox = $OUTPUT->render_from_template('core/checkbox', $check);
$hiddenfields = [
(object) ['name' => 'id', 'value' => $this->cm->id],
(object) ['name' => 'mode', 'value' => 'search'],
];
$data = [
'action' => new moodle_url('/mod/glossary/view.php'),
'hiddenfields' => $hiddenfields,
'otherfields' => $checkbox,
'inputname' => 'hook',
'query' => ($this->mode == 'search') ? s($this->hook) : '',
'searchstring' => get_string('search'),
];
return $data;
}
/**
* Render the add entry button
*
* @param renderer_base $output
* @return \stdClass|null
*/
private function create_add_button(renderer_base $output): ?\stdClass {
if (!has_capability('mod/glossary:write', $this->context)) {
return null;
}
$btn = new single_button(new moodle_url('/mod/glossary/edit.php', ['cmid' => $this->cm->id]),
get_string('addsingleentry', 'glossary'), 'post', single_button::BUTTON_PRIMARY);
return $btn->export_for_template($output);
}
/**
* Render the additional tools required by the glossary
*
* @param renderer_base $output
* @return array
*/
private function get_additional_tools(renderer_base $output): array {
global $USER, $CFG;
$items = [];
$buttons = [];
$openinnewwindow = [];
if (has_capability('mod/glossary:import', $this->context)) {
$items['button'] = new single_button(
new moodle_url('/mod/glossary/import.php', ['id' => $this->cm->id]),
get_string('importentries', 'glossary')
);
}
if (has_capability('mod/glossary:export', $this->context)) {
$url = new moodle_url('/mod/glossary/export.php', [
'id' => $this->cm->id,
'mode' => $this->mode,
'hook' => $this->hook
]);
$buttons[get_string('export', 'glossary')] = $url->out(false);
}
if (has_capability('mod/glossary:manageentries', $this->context) or $this->module->allowprintview) {
$params = array(
'id' => $this->cm->id,
'mode' => $this->mode,
'hook' => $this->hook,
'sortkey' => $this->sortkey,
'sortorder' => $this->sortorder,
'offset' => $this->offset,
'pagelimit' => $this->pagelimit
);
$printurl = new moodle_url('/mod/glossary/print.php', $params);
$buttons[get_string('printerfriendly', 'glossary')] = $printurl->out(false);
$openinnewwindow[] = $printurl->out(false);
}
if (!empty($CFG->enablerssfeeds) && !empty($CFG->glossary_enablerssfeeds)
&& $this->module->rsstype && $this->module->rssarticles
&& has_capability('mod/glossary:view', $this->context)) {
require_once("$CFG->libdir/rsslib.php");
$string = get_string('rssfeed', 'glossary');
$url = new moodle_url(rss_get_url($this->context->id, $USER->id, 'mod_glossary', $this->cm->instance));
$buttons[$string] = $url->out(false);
$openinnewwindow[] = $url->out(false);
}
foreach ($items as $key => $value) {
$items[$key] = $value->export_for_template($output);
}
if ($buttons) {
foreach ($buttons as $index => $value) {
$items['select']['options'][] = [
'url' => $value,
'string' => $index,
'openinnewwindow' => ($openinnewwindow ? in_array($value, $openinnewwindow) : false)
];
}
}
return $items;
}
/**
* Generate a url select to match any types of glossary views
*
* @param renderer_base $output
* @return \stdClass|null
*/
private function generate_tab_jumps(renderer_base $output) {
$tabs = glossary_get_visible_tabs($this->displayformat);
$validtabs = [
GLOSSARY_STANDARD => [
'mode' => 'letter',
'descriptor' => 'standardview'
],
GLOSSARY_CATEGORY => [
'mode' => 'cat',
'descriptor' => 'categoryview'
],
GLOSSARY_DATE => [
'mode' => 'date',
'descriptor' => 'dateview'
],
GLOSSARY_AUTHOR => [
'mode' => 'author',
'descriptor' => 'authorview'
],
];
$baseurl = new moodle_url('/mod/glossary/view.php', ['id' => $this->cm->id]);
$active = null;
$options = [];
foreach ($validtabs as $key => $tabinfo) {
if (in_array($key, $tabs)) {
$baseurl->params(['mode' => $tabinfo['mode']]);
$active = $active ?? $baseurl->out(false);
$active = ($tabinfo['mode'] == $this->mode ? $baseurl->out(false) : $active);
$options[get_string($tabinfo['descriptor'], 'glossary')] = $baseurl->out(false);
}
}
if ($this->tab < GLOSSARY_STANDARD_VIEW || $this->tab > GLOSSARY_AUTHOR_VIEW) {
$options[get_string('edit')] = '#';
}
if (count($options) > 1) {
$select = new url_select(array_flip($options), $active, null);
$select->set_label(get_string('explainalphabet', 'glossary'), ['class' => 'sr-only']);
return $select->export_for_template($output);
}
return null;
}
}
+467
View File
@@ -0,0 +1,467 @@
<?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 Subsystem implementation for mod_glossary.
*
* @package mod_glossary
* @copyright 2018 Simey Lameze <simey@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_glossary\privacy;
use core_privacy\local\metadata\collection;
use core_privacy\local\request\approved_contextlist;
use core_privacy\local\request\approved_userlist;
use core_privacy\local\request\contextlist;
use core_privacy\local\request\deletion_criteria;
use core_privacy\local\request\helper;
use core_privacy\local\request\userlist;
use core_privacy\local\request\writer;
defined('MOODLE_INTERNAL') || die();
/**
* Implementation of the privacy subsystem plugin provider for the glossary activity module.
*
* @copyright 2018 Simey Lameze <simey@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider implements
// This plugin stores personal data.
\core_privacy\local\metadata\provider,
// This plugin is capable of determining which users have data within it.
\core_privacy\local\request\core_userlist_provider,
// This plugin is a core_user_data_provider.
\core_privacy\local\request\plugin\provider {
/**
* Return the fields which contain personal data.
*
* @param collection $items a reference to the collection to use to store the metadata.
* @return collection the updated collection of metadata items.
*/
public static function get_metadata(collection $items): collection {
$items->add_database_table(
'glossary_entries',
[
'glossaryid' => 'privacy:metadata:glossary_entries:glossaryid',
'userid' => 'privacy:metadata:glossary_entries:userid',
'concept' => 'privacy:metadata:glossary_entries:concept',
'definition' => 'privacy:metadata:glossary_entries:definition',
'attachment' => 'privacy:metadata:glossary_entries:attachment',
'timemodified' => 'privacy:metadata:glossary_entries:timemodified',
],
'privacy:metadata:glossary_entries'
);
$items->add_subsystem_link('core_files', [], 'privacy:metadata:core_files');
$items->add_subsystem_link('core_comment', [], 'privacy:metadata:core_comments');
$items->add_subsystem_link('core_tag', [], 'privacy:metadata:core_tag');
$items->add_subsystem_link('core_rating', [], 'privacy:metadata:core_rating');
return $items;
}
/**
* Get the list of contexts that contain user information for the specified user.
*
* @param int $userid the userid.
* @return contextlist the list of contexts containing user info for the user.
*/
public static function get_contexts_for_userid(int $userid): contextlist {
$contextlist = new contextlist();
// Glossary entries.
$sql = "SELECT c.id
FROM {context} c
JOIN {course_modules} cm ON cm.id = c.instanceid AND c.contextlevel = :contextlevel
JOIN {modules} m ON m.id = cm.module AND m.name = :modname
JOIN {glossary} g ON g.id = cm.instance
JOIN {glossary_entries} ge ON ge.glossaryid = g.id
WHERE ge.userid = :glossaryentryuserid";
$params = [
'contextlevel' => CONTEXT_MODULE,
'modname' => 'glossary',
'commentarea' => 'glossary_entry',
'glossaryentryuserid' => $userid,
];
$contextlist->add_from_sql($sql, $params);
// Where the user has rated something.
$ratingquery = \core_rating\privacy\provider::get_sql_join('r', 'mod_glossary', 'entry', 'ge.id', $userid, true);
$sql = "SELECT c.id
FROM {context} c
JOIN {course_modules} cm ON cm.id = c.instanceid AND c.contextlevel = :contextlevel
JOIN {modules} m ON m.id = cm.module AND m.name = :modname
JOIN {glossary} g ON g.id = cm.instance
JOIN {glossary_entries} ge ON ge.glossaryid = g.id
{$ratingquery->join}
WHERE {$ratingquery->userwhere}";
$params = [
'contextlevel' => CONTEXT_MODULE,
'modname' => 'glossary',
] + $ratingquery->params;
$contextlist->add_from_sql($sql, $params);
// Comments.
$sql = "SELECT c.id
FROM {context} c
JOIN {course_modules} cm ON cm.id = c.instanceid AND c.contextlevel = :contextlevel
JOIN {modules} m ON m.id = cm.module AND m.name = :modname
JOIN {glossary} g ON g.id = cm.instance
JOIN {glossary_entries} ge ON ge.glossaryid = g.id
JOIN {comments} com ON com.commentarea =:commentarea AND com.itemid = ge.id
WHERE com.userid = :commentuserid";
$params = [
'contextlevel' => CONTEXT_MODULE,
'modname' => 'glossary',
'commentarea' => 'glossary_entry',
'commentuserid' => $userid,
];
$contextlist->add_from_sql($sql, $params);
return $contextlist;
}
/**
* Get the list of users who have data within a context.
*
* @param userlist $userlist The userlist containing the list of users who have data in this context/plugin combination.
*
*/
public static function get_users_in_context(userlist $userlist) {
$context = $userlist->get_context();
if (!is_a($context, \context_module::class)) {
return;
}
// Find users with glossary entries.
$sql = "SELECT ge.userid
FROM {context} c
JOIN {course_modules} cm ON cm.id = c.instanceid AND c.contextlevel = :contextlevel
JOIN {modules} m ON m.id = cm.module AND m.name = :modname
JOIN {glossary} g ON g.id = cm.instance
JOIN {glossary_entries} ge ON ge.glossaryid = g.id
WHERE c.id = :contextid";
$params = [
'contextid' => $context->id,
'contextlevel' => CONTEXT_MODULE,
'modname' => 'glossary',
];
$userlist->add_from_sql('userid', $sql, $params);
// Find users with glossary comments.
\core_comment\privacy\provider::get_users_in_context_from_sql($userlist, 'com', 'mod_glossary', 'glossary_entry',
$context->id);
// Find users with glossary ratings.
$sql = "SELECT ge.id
FROM {context} c
JOIN {course_modules} cm ON cm.id = c.instanceid AND c.contextlevel = :contextlevel
JOIN {modules} m ON m.id = cm.module AND m.name = :modname
JOIN {glossary} g ON g.id = cm.instance
JOIN {glossary_entries} ge ON ge.glossaryid = g.id
WHERE c.id = :contextid";
$params = [
'contextid' => $context->id,
'contextlevel' => CONTEXT_MODULE,
'modname' => 'glossary',
];
\core_rating\privacy\provider::get_users_in_context_from_sql($userlist, 'rat', 'mod_glossary', 'entry', $sql, $params);
}
/**
* Export personal data for the given approved_contextlist.
*
* User and context information is contained within the contextlist.
*
* @param approved_contextlist $contextlist a list of contexts approved for export.
*/
public static function export_user_data(approved_contextlist $contextlist) {
global $DB;
if (empty($contextlist->count())) {
return;
}
$user = $contextlist->get_user();
list($contextsql, $contextparams) = $DB->get_in_or_equal($contextlist->get_contextids(), SQL_PARAMS_NAMED);
$ratingquery = \core_rating\privacy\provider::get_sql_join('r', 'mod_glossary', 'entry', 'ge.id', $user->id);
$sql = "SELECT ge.id as entryid,
cm.id AS cmid,
ge.userid,
ge.concept,
ge.definition,
ge.definitionformat,
ge.attachment,
ge.timecreated,
ge.timemodified
FROM {glossary_entries} ge
JOIN {glossary} g ON ge.glossaryid = g.id
JOIN {course_modules} cm ON g.id = cm.instance
JOIN {modules} m ON cm.module = m.id AND m.name = :modulename
JOIN {context} c ON cm.id = c.instanceid AND c.contextlevel = :contextlevel
LEFT JOIN {comments} com ON com.itemid = ge.id AND com.commentarea = :commentarea AND com.userid = :commentuserid
{$ratingquery->join}
WHERE c.id {$contextsql}
AND (ge.userid = :userid OR com.id IS NOT NULL OR {$ratingquery->userwhere})
ORDER BY ge.id, cm.id";
$params = [
'userid' => $user->id,
'modulename' => 'glossary',
'contextlevel' => CONTEXT_MODULE,
'commentarea' => 'glossary_entry',
'commentuserid' => $user->id
] + $contextparams;
$params = array_merge($params, $ratingquery->params);
$glossaryentries = $DB->get_recordset_sql($sql, $params);
// Reference to the glossary activity seen in the last iteration of the loop. By comparing this with the
// current record, and because we know the results are ordered, we know when we've moved to the entries
// for a new glossary activity and therefore when we can export the complete data for the last activity.
$lastcmid = null;
$glossarydata = [];
foreach ($glossaryentries as $record) {
$concept = format_string($record->concept);
$path = array_merge([get_string('entries', 'mod_glossary'), $concept . " ({$record->entryid})"]);
// If we've moved to a new glossary, then write the last glossary data and reinit the glossary data array.
if (!is_null($lastcmid)) {
if ($lastcmid != $record->cmid) {
if (!empty($glossarydata)) {
$context = \context_module::instance($lastcmid);
self::export_glossary_data_for_user($glossarydata, $context, [], $user);
$glossarydata = [];
}
}
}
$lastcmid = $record->cmid;
$context = \context_module::instance($lastcmid);
// Export files added on the glossary entry definition field.
$definition = format_text(writer::with_context($context)->rewrite_pluginfile_urls($path, 'mod_glossary',
'entry', $record->entryid, $record->definition), $record->definitionformat);
// Export just the files attached to this user entry.
if ($record->userid == $user->id) {
// Get all files attached to the glossary attachment.
writer::with_context($context)->export_area_files($path, 'mod_glossary', 'entry', $record->entryid);
// Get all files attached to the glossary attachment.
writer::with_context($context)->export_area_files($path, 'mod_glossary', 'attachment', $record->entryid);
}
// Export associated comments.
\core_comment\privacy\provider::export_comments($context, 'mod_glossary', 'glossary_entry',
$record->entryid, $path, $record->userid != $user->id);
// Export associated tags.
\core_tag\privacy\provider::export_item_tags($user->id, $context, $path, 'mod_glossary', 'glossary_entries',
$record->entryid, $record->userid != $user->id);
// Export associated ratings.
\core_rating\privacy\provider::export_area_ratings($user->id, $context, $path, 'mod_glossary', 'entry',
$record->entryid, $record->userid != $user->id);
$glossarydata['entries'][] = [
'concept' => $record->concept,
'definition' => $definition,
'timecreated' => \core_privacy\local\request\transform::datetime($record->timecreated),
'timemodified' => \core_privacy\local\request\transform::datetime($record->timemodified)
];
}
$glossaryentries->close();
// The data for the last activity won't have been written yet, so make sure to write it now!
if (!empty($glossarydata)) {
$context = \context_module::instance($lastcmid);
self::export_glossary_data_for_user($glossarydata, $context, [], $user);
}
}
/**
* Export the supplied personal data for a single glossary activity, along with any generic data or area files.
*
* @param array $glossarydata The personal data to export for the glossary.
* @param \context_module $context The context of the glossary.
* @param array $subcontext The location within the current context that this data belongs.
* @param \stdClass $user the user record
*/
protected static function export_glossary_data_for_user(array $glossarydata, \context_module $context,
array $subcontext, \stdClass $user) {
// Fetch the generic module data for the glossary.
$contextdata = helper::get_context_data($context, $user);
// Merge with glossary data and write it.
$contextdata = (object)array_merge((array)$contextdata, $glossarydata);
writer::with_context($context)->export_data($subcontext, $contextdata);
// Write generic module intro files.
helper::export_context_files($context, $user);
}
/**
* Delete all data for all users in the specified context.
*
* @param \context $context the context to delete in.
*/
public static function delete_data_for_all_users_in_context(\context $context) {
global $DB;
if ($context->contextlevel != CONTEXT_MODULE) {
return;
}
if (!$cm = get_coursemodule_from_id('glossary', $context->instanceid)) {
return;
}
$instanceid = $cm->instance;
$entries = $DB->get_records('glossary_entries', ['glossaryid' => $instanceid], '', 'id');
// Delete related entry aliases.
$DB->delete_records_list('glossary_alias', 'entryid', array_keys($entries));
// Delete related entry categories.
$DB->delete_records_list('glossary_entries_categories', 'entryid', array_keys($entries));
// Delete entry and attachment files.
get_file_storage()->delete_area_files($context->id, 'mod_glossary', 'entry');
get_file_storage()->delete_area_files($context->id, 'mod_glossary', 'attachment');
// Delete related ratings.
\core_rating\privacy\provider::delete_ratings($context, 'mod_glossary', 'entry');
// Delete comments.
\core_comment\privacy\provider::delete_comments_for_all_users($context, 'mod_glossary', 'glossary_entry');
// Delete tags.
\core_tag\privacy\provider::delete_item_tags($context, 'mod_glossary', 'glossary_entries');
// Now delete all user related entries.
$DB->delete_records('glossary_entries', ['glossaryid' => $instanceid]);
}
/**
* Delete all user data for the specified user, in the specified contexts.
*
* @param approved_contextlist $contextlist a list of contexts approved for deletion.
*/
public static function delete_data_for_user(approved_contextlist $contextlist) {
global $DB;
if (empty($contextlist->count())) {
return;
}
$userid = $contextlist->get_user()->id;
foreach ($contextlist->get_contexts() as $context) {
if ($context->contextlevel == CONTEXT_MODULE) {
$instanceid = $DB->get_field('course_modules', 'instance', ['id' => $context->instanceid], MUST_EXIST);
$entries = $DB->get_records('glossary_entries', ['glossaryid' => $instanceid, 'userid' => $userid],
'', 'id');
if (!$entries) {
continue;
}
list($insql, $inparams) = $DB->get_in_or_equal(array_keys($entries), SQL_PARAMS_NAMED);
// Delete related entry aliases.
$DB->delete_records_list('glossary_alias', 'entryid', array_keys($entries));
// Delete related entry categories.
$DB->delete_records_list('glossary_entries_categories', 'entryid', array_keys($entries));
// Delete related entry and attachment files.
get_file_storage()->delete_area_files_select($context->id, 'mod_glossary', 'entry', $insql, $inparams);
get_file_storage()->delete_area_files_select($context->id, 'mod_glossary', 'attachment', $insql, $inparams);
// Delete user tags related to this glossary.
\core_tag\privacy\provider::delete_item_tags_select($context, 'mod_glossary', 'glossary_entries', $insql, $inparams);
// Delete related ratings.
\core_rating\privacy\provider::delete_ratings_select($context, 'mod_glossary', 'entry', $insql, $inparams);
// Delete comments.
\core_comment\privacy\provider::delete_comments_for_user($contextlist, 'mod_glossary', 'glossary_entry');
// Now delete all user related entries.
$DB->delete_records('glossary_entries', ['glossaryid' => $instanceid, 'userid' => $userid]);
}
}
}
/**
* Delete multiple users within a single context.
*
* @param approved_userlist $userlist The approved context and user information to delete information for.
*/
public static function delete_data_for_users(approved_userlist $userlist) {
global $DB;
$context = $userlist->get_context();
$userids = $userlist->get_userids();
$instanceid = $DB->get_field('course_modules', 'instance', ['id' => $context->instanceid], MUST_EXIST);
list($userinsql, $userinparams) = $DB->get_in_or_equal($userids, SQL_PARAMS_NAMED);
$glossaryentrieswhere = "glossaryid = :instanceid AND userid {$userinsql}";
$userinstanceparams = $userinparams + ['instanceid' => $instanceid];
$entriesobject = $DB->get_recordset_select('glossary_entries', $glossaryentrieswhere, $userinstanceparams, 'id', 'id');
$entries = [];
foreach ($entriesobject as $entry) {
$entries[] = $entry->id;
}
$entriesobject->close();
if (!$entries) {
return;
}
list($insql, $inparams) = $DB->get_in_or_equal($entries, SQL_PARAMS_NAMED);
// Delete related entry aliases.
$DB->delete_records_list('glossary_alias', 'entryid', $entries);
// Delete related entry categories.
$DB->delete_records_list('glossary_entries_categories', 'entryid', $entries);
// Delete related entry and attachment files.
get_file_storage()->delete_area_files_select($context->id, 'mod_glossary', 'entry', $insql, $inparams);
get_file_storage()->delete_area_files_select($context->id, 'mod_glossary', 'attachment', $insql, $inparams);
// Delete user tags related to this glossary.
\core_tag\privacy\provider::delete_item_tags_select($context, 'mod_glossary', 'glossary_entries', $insql, $inparams);
// Delete related ratings.
\core_rating\privacy\provider::delete_ratings_select($context, 'mod_glossary', 'entry', $insql, $inparams);
// Delete comments.
\core_comment\privacy\provider::delete_comments_for_users($userlist, 'mod_glossary', 'glossary_entry');
// Now delete all user related entries.
$deletewhere = "glossaryid = :instanceid AND userid {$userinsql}";
$DB->delete_records_select('glossary_entries', $deletewhere, $userinstanceparams);
}
}
+46
View File
@@ -0,0 +1,46 @@
<?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/>.
/**
* Search area for mod_glossary activities.
*
* @package mod_glossary
* @copyright 2015 David Monllao {@link http://www.davidmonllao.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_glossary\search;
defined('MOODLE_INTERNAL') || die();
/**
* Search area for mod_glossary activities.
*
* @package mod_glossary
* @copyright 2015 David Monllao {@link http://www.davidmonllao.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class activity extends \core_search\base_activity {
/**
* Returns true if this area uses file indexing.
*
* @return bool
*/
public function uses_file_indexing() {
return true;
}
}
+225
View File
@@ -0,0 +1,225 @@
<?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/>.
/**
* Glossary entries search.
*
* @package mod_glossary
* @copyright 2015 David Monllao {@link http://www.davidmonllao.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_glossary\search;
defined('MOODLE_INTERNAL') || die();
require_once($CFG->dirroot . '/mod/glossary/lib.php');
/**
* Glossary entries search.
*
* @package mod_glossary
* @copyright 2015 David Monllao {@link http://www.davidmonllao.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class entry extends \core_search\base_mod {
/**
* @var array Internal quick static cache.
*/
protected $entriesdata = array();
/**
* Returns recordset containing required data for indexing glossary entries.
*
* @param int $modifiedfrom timestamp
* @param \context|null $context Optional context to restrict scope of returned results
* @return moodle_recordset|null Recordset (or null if no results)
*/
public function get_document_recordset($modifiedfrom = 0, \context $context = null) {
global $DB;
list ($contextjoin, $contextparams) = $this->get_context_restriction_sql(
$context, 'glossary', 'g');
if ($contextjoin === null) {
return null;
}
$sql = "SELECT ge.*, g.course FROM {glossary_entries} ge
JOIN {glossary} g ON g.id = ge.glossaryid
$contextjoin
WHERE ge.timemodified >= ? ORDER BY ge.timemodified ASC";
return $DB->get_recordset_sql($sql, array_merge($contextparams, [$modifiedfrom]));
}
/**
* Returns the documents associated with this glossary entry id.
*
* @param stdClass $entry glossary entry.
* @param array $options
* @return \core_search\document
*/
public function get_document($entry, $options = array()) {
global $DB;
$keywords = array();
if ($aliases = $DB->get_records('glossary_alias', array('entryid' => $entry->id))) {
foreach ($aliases as $alias) {
$keywords[] = $alias->alias;
}
}
try {
$cm = $this->get_cm('glossary', $entry->glossaryid, $entry->course);
$context = \context_module::instance($cm->id);
} catch (\dml_missing_record_exception $ex) {
// Notify it as we run here as admin, we should see everything.
debugging('Error retrieving mod_glossary ' . $entry->id . ' document, not all required data is available: ' .
$ex->getMessage(), DEBUG_DEVELOPER);
return false;
} catch (\dml_exception $ex) {
// Notify it as we run here as admin, we should see everything.
debugging('Error retrieving mod_glossary' . $entry->id . ' document: ' . $ex->getMessage(), DEBUG_DEVELOPER);
return false;
}
// Prepare associative array with data from DB.
$doc = \core_search\document_factory::instance($entry->id, $this->componentname, $this->areaname);
$doc->set('title', content_to_text($entry->concept, false));
$doc->set('content', content_to_text($entry->definition, $entry->definitionformat));
$doc->set('contextid', $context->id);
$doc->set('courseid', $entry->course);
$doc->set('userid', $entry->userid);
$doc->set('owneruserid', \core_search\manager::NO_OWNER_ID);
$doc->set('modified', $entry->timemodified);
// Check if this document should be considered new.
if (isset($options['lastindexedtime']) && ($options['lastindexedtime'] < $entry->timecreated)) {
// If the document was created after the last index time, it must be new.
$doc->set_is_new(true);
}
// Adding keywords as extra info.
if ($keywords) {
// No need to pass through content_to_text here as this is just a list of keywords.
$doc->set('description1', implode(' ' , $keywords));
}
return $doc;
}
/**
* Whether the user can access the document or not.
*
* @throws \dml_missing_record_exception
* @throws \dml_exception
* @param int $id Glossary entry id
* @return bool
*/
public function check_access($id) {
global $USER;
try {
$entry = $this->get_entry($id);
$cminfo = $this->get_cm('glossary', $entry->glossaryid, $entry->course);
} catch (\dml_missing_record_exception $ex) {
return \core_search\manager::ACCESS_DELETED;
} catch (\dml_exception $ex) {
return \core_search\manager::ACCESS_DENIED;
}
if (!glossary_can_view_entry($entry, $cminfo)) {
return \core_search\manager::ACCESS_DENIED;
}
return \core_search\manager::ACCESS_GRANTED;
}
/**
* Link to glossary entry.
*
* @param \core_search\document $doc
* @return \moodle_url
*/
public function get_doc_url(\core_search\document $doc) {
global $USER;
// The post is already in static cache, we fetch it in self::search_access.
$entry = $this->get_entry($doc->get('itemid'));
$contextmodule = \context::instance_by_id($doc->get('contextid'));
if ($entry->approved == false && $entry->userid != $USER->id) {
// The URL should change when the entry is not approved and it was not created by the user.
$docparams = array('id' => $contextmodule->instanceid, 'mode' => 'approval');
} else {
$docparams = array('id' => $contextmodule->instanceid, 'mode' => 'entry', 'hook' => $doc->get('itemid'));
}
return new \moodle_url('/mod/glossary/view.php', $docparams);
}
/**
* Link to the glossary.
*
* @param \core_search\document $doc
* @return \moodle_url
*/
public function get_context_url(\core_search\document $doc) {
$contextmodule = \context::instance_by_id($doc->get('contextid'));
return new \moodle_url('/mod/glossary/view.php', array('id' => $contextmodule->instanceid));
}
/**
* Returns the specified glossary entry checking the internal cache.
*
* Store minimal information as this might grow.
*
* @throws \dml_exception
* @param int $entryid
* @return stdClass
*/
protected function get_entry($entryid) {
global $DB;
if (empty($this->entriesdata[$entryid])) {
$this->entriesdata[$entryid] = $DB->get_record_sql("SELECT ge.*, g.course, g.defaultapproval FROM {glossary_entries} ge
JOIN {glossary} g ON g.id = ge.glossaryid
WHERE ge.id = ?", array('id' => $entryid), MUST_EXIST);
}
return $this->entriesdata[$entryid];
}
/**
* Returns true if this area uses file indexing.
*
* @return bool
*/
public function uses_file_indexing() {
return true;
}
/**
* Return the context info required to index files for
* this search area.
*
* @return array
*/
public function get_search_fileareas() {
$fileareas = array('attachment', 'entry'); // Fileareas.
return $fileareas;
}
}