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,571 @@
<?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 tool_brickfield;
use context_system;
use moodle_exception;
use moodle_url;
use stdClass;
use tool_brickfield\local\tool\filter;
/**
* Provides the Brickfield Accessibility toolkit API.
*
* @package tool_brickfield
* @copyright 2020 onward Brickfield Education Labs Ltd, https://www.brickfield.ie
* @author Mike Churchward (mike@brickfieldlabs.ie)
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class accessibility {
/** @var string The component sub path */
private static $pluginpath = 'tool/brickfield';
/** @var string Supported format of topics */
const TOOL_BRICKFIELD_FORMAT_TOPIC = 'topics';
/** @var string Supported format of weeks */
const TOOL_BRICKFIELD_FORMAT_WEEKLY = 'weeks';
/**
* Return the state of the site enable condition.
* @return bool
*/
public static function is_accessibility_enabled(): bool {
global $CFG;
return !empty($CFG->enableaccessibilitytools);
}
/**
* Throw an error if the toolkit is not enabled.
* @return bool
* @throws moodle_exception
*/
public static function require_accessibility_enabled(): bool {
if (!static::is_accessibility_enabled()) {
throw new moodle_exception('accessibilitydisabled', manager::PLUGINNAME);
}
return true;
}
/**
* Get a URL for a page within the plugin.
*
* This takes into account the value of the admin config value.
*
* @param string $url The URL within the plugin
* @return moodle_url
*/
public static function get_plugin_url(string $url = ''): moodle_url {
$url = ($url == '') ? 'index.php' : $url;
$pluginpath = self::$pluginpath;
return new moodle_url("/admin/{$pluginpath}/{$url}");
}
/**
* Get a file path for a file within the plugin.
*
* This takes into account the value of the admin config value.
*
* @param string $path The path within the plugin
* @return string
*/
public static function get_file_path(string $path): string {
global $CFG;
return implode(DIRECTORY_SEPARATOR, [$CFG->dirroot, $CFG->admin, self::$pluginpath, $path, ]);
}
/**
* Get the canonicalised name of a capability.
*
* @param string $capability
* @return string
*/
public static function get_capability_name(string $capability): string {
return self::$pluginpath . ':' . $capability;
}
/**
* Get the relevant title.
* @param filter $filter
* @param int $countdata
* @return string
* @throws \coding_exception
* @throws \dml_exception
* @throws \moodle_exception
*/
public static function get_title(filter $filter, int $countdata): string {
global $DB;
$tmp = new \stdClass();
$tmp->count = $countdata;
$langstr = 'title' . $filter->tab . 'partial';
if ($filter->courseid != 0) {
$thiscourse = get_fast_modinfo($filter->courseid)->get_course();
$tmp->name = $thiscourse->fullname;
} else {
$langstr = 'title' . $filter->tab . 'all';
}
return get_string($langstr, manager::PLUGINNAME, $tmp);
}
/**
* Function to be run periodically according to the scheduled task.
* Return true if a process was completed. False if no process executed.
* Finds all unprocessed courses for bulk batch processing and completes them.
* @param int $batch
* @return bool
* @throws \ReflectionException
* @throws \coding_exception
* @throws \ddl_exception
* @throws \ddl_table_missing_exception
* @throws \dml_exception
*/
public static function bulk_process_courses_cron(int $batch = 0): bool {
global $PAGE;
// Run a registration check.
if (!(new registration())->validate()) {
return false;
}
if (analysis::is_enabled()) {
$PAGE->set_context(context_system::instance());
mtrace("Starting cron for bulk_process_courses");
// Do regular processing. True if full deployment type isn't selected as well.
static::bulk_processing($batch);
mtrace("Ending cron for bulk_process_courses");
return true;
} else {
mtrace('Content analysis is currently disabled in settings.');
return false;
}
}
/**
* Bulk processing.
* @param int $batch
* @return bool
*/
protected static function bulk_processing(int $batch = 0): bool {
manager::check_course_updates();
mtrace("check_course_updates completed at " . time());
$recordsprocessed = manager::check_scheduled_areas($batch);
mtrace("check_scheduled_areas completed at " . time());
manager::check_scheduled_deletions();
mtrace("check_scheduled_deletions completed at " . time());
manager::delete_historical_data();
mtrace("delete_historical_data completed at " . time());
return $recordsprocessed;
}
/**
* Function to be run periodically according to the scheduled task.
* Finds all unprocessed courses for cache processing and completes them.
*/
public static function bulk_process_caches_cron() {
global $DB;
// Run a registration check.
if (!(new registration())->validate()) {
return;
}
if (analysis::is_enabled()) {
mtrace("Starting cron for bulk_process_caches");
// Monitor ongoing caching requests.
$fields = 'DISTINCT courseid';
$reruns = $DB->get_records(manager::DB_PROCESS, ['item' => 'cache'], '', $fields);
foreach ($reruns as $rerun) {
mtrace("Running rerun caching for Courseid " . $rerun->courseid);
manager::store_result_summary($rerun->courseid);
mtrace("rerun cache completed at " . time());
$DB->delete_records(manager::DB_PROCESS, ['courseid' => $rerun->courseid, 'item' => 'cache']);
}
mtrace("Ending cron for bulk_process_caches at " . time());
} else {
mtrace('Content analysis is currently disabled in settings.');
}
}
/**
* This function runs the checks on the html item
*
* @param string $html The html string to be analysed; might be NULL.
* @param int $contentid The content area ID
* @param int $processingtime
* @param int $resultstime
*/
public static function run_check(string $html, int $contentid, int &$processingtime, int &$resultstime) {
global $DB;
// Change the limit if 10,000 is not appropriate.
$bulkrecordlimit = manager::BULKRECORDLIMIT;
$bulkrecordcount = 0;
$checkids = static::checkids();
$checknameids = array_flip($checkids);
$testname = 'brickfield';
$stime = time();
// Swapping in new library.
$htmlchecker = new local\htmlchecker\brickfield_accessibility($html, $testname, 'string');
$htmlchecker->run_check();
$tests = $htmlchecker->guideline->get_tests();
$report = $htmlchecker->get_report();
$processingtime += (time() - $stime);
$records = [];
foreach ($tests as $test) {
$records[$test]['count'] = 0;
$records[$test]['errors'] = [];
}
foreach ($report['report'] as $a) {
if (!isset($a['type'])) {
continue;
}
$type = $a['type'];
$records[$type]['errors'][] = $a;
if (!isset($records[$type]['count'])) {
$records[$type]['count'] = 0;
}
$records[$type]['count']++;
}
$stime = time();
$returnchecks = [];
$errors = [];
// Build up records for inserting.
foreach ($records as $key => $rec) {
$recordres = new stdClass();
// Handling if checkid is unknown.
$checkid = (isset($checknameids[$key])) ? $checknameids[$key] : 0;
$recordres->contentid = $contentid;
$recordres->checkid = $checkid;
$recordres->errorcount = $rec['count'];
// Build error inserts if needed.
if ($rec['count'] > 0) {
foreach ($rec['errors'] as $tmp) {
$error = new stdClass();
$error->resultid = 0;
$error->linenumber = $tmp['lineNo'];
$error->htmlcode = $tmp['html'];
$error->errordescription = $tmp['title'];
// Add contentid and checkid so that we can query for the results record id later.
$error->contentid = $contentid;
$error->checkid = $checkid;
$errors[] = $error;
}
}
$returnchecks[] = $recordres;
$bulkrecordcount++;
// If we've hit the bulk limit, write the results records and reset.
if ($bulkrecordcount > $bulkrecordlimit) {
$DB->insert_records(manager::DB_RESULTS, $returnchecks);
$bulkrecordcount = 0;
$returnchecks = [];
// Get the results id value for each error record and write the errors.
foreach ($errors as $key2 => $error) {
$errors[$key2]->resultid = $DB->get_field(manager::DB_RESULTS, 'id',
['contentid' => $error->contentid, 'checkid' => $error->checkid]);
unset($errors[$key2]->contentid);
unset($errors[$key2]->checkid);
}
$DB->insert_records(manager::DB_ERRORS, $errors);
$errors = [];
}
}
// Write any leftover records.
if ($bulkrecordcount > 0) {
$DB->insert_records(manager::DB_RESULTS, $returnchecks);
// Get the results id value for each error record and write the errors.
foreach ($errors as $key => $error) {
$errors[$key]->resultid = $DB->get_field(manager::DB_RESULTS, 'id',
['contentid' => $error->contentid, 'checkid' => $error->checkid]);
unset($errors[$key]->contentid);
unset($errors[$key]->checkid);
}
$DB->insert_records(manager::DB_ERRORS, $errors);
}
$resultstime += (time() - $stime);
}
/**
* This function runs one specified check on the html item
*
* @param string|null $html The html string to be analysed; might be NULL.
* @param int $contentid The content area ID
* @param int $errid The error ID
* @param string $check The check name to run
* @param int $processingtime
* @param int $resultstime
* @throws \coding_exception
* @throws \dml_exception
*/
public static function run_one_check(
?string $html,
int $contentid,
int $errid,
string $check,
int &$processingtime,
int &$resultstime
) {
global $DB;
$stime = time();
$checkdata = $DB->get_record(manager::DB_CHECKS, ['shortname' => $check], 'id,shortname,severity');
$testname = 'brickfield';
// Swapping in new library.
$htmlchecker = new local\htmlchecker\brickfield_accessibility($html, $testname, 'string');
$htmlchecker->run_check();
$report = $htmlchecker->get_test($check);
$processingtime += (time() - $stime);
$record = [];
$record['count'] = 0;
$record['errors'] = [];
foreach ($report as $a) {
$a->html = $a->get_html();
$record['errors'][] = $a;
$record['count']++;
}
// Build up record for inserting.
$recordres = new stdClass();
// Handling if checkid is unknown.
$checkid = (isset($checkdata->id)) ? $checkdata->id : 0;
$recordres->contentid = $contentid;
$recordres->checkid = $checkid;
$recordres->errorcount = $record['count'];
if ($exists = $DB->get_record(manager::DB_RESULTS, ['contentid' => $contentid, 'checkid' => $checkid])) {
$resultid = $exists->id;
$DB->set_field(manager::DB_RESULTS, 'errorcount', $record['count'], ['id' => $resultid]);
// Remove old error records for specific resultid, if existing.
$DB->delete_records(manager::DB_ERRORS, ['id' => $errid]);
} else {
$resultid = $DB->insert_record(manager::DB_RESULTS, $recordres);
}
$errors = [];
// Build error inserts if needed.
if ($record['count'] > 0) {
// Reporting all found errors for this check, so need to ignore existing other error records.
foreach ($record['errors'] as $tmp) {
// Confirm if error is reported separately.
if ($DB->record_exists_select(manager::DB_ERRORS,
'resultid = ? AND ' . $DB->sql_compare_text('htmlcode', 255) . ' = ' . $DB->sql_compare_text('?', 255),
[$resultid, html_entity_decode($tmp->html, ENT_COMPAT)])) {
continue;
}
$error = new stdClass();
$error->resultid = $resultid;
$error->linenumber = $tmp->line;
$error->htmlcode = html_entity_decode($tmp->html, ENT_COMPAT);
$errors[] = $error;
}
$DB->insert_records(manager::DB_ERRORS, $errors);
}
$resultstime += (time() - $stime);
}
/**
* Returns all of the id's and shortnames of all of the checks.
* @param int $status
* @return array
* @throws \dml_exception
*/
public static function checkids(int $status = 1): array {
global $DB;
$checks = $DB->get_records_menu(manager::DB_CHECKS, ['status' => $status], 'id ASC', 'id,shortname');
return $checks;
}
/**
* Returns an array of translations from htmlchecker of all of the checks, and their descriptions.
* @return array
* @throws \dml_exception
*/
public static function get_translations(): array {
global $DB;
$htmlchecker = new local\htmlchecker\brickfield_accessibility('test', 'brickfield', 'string');
$htmlchecker->run_check();
ksort($htmlchecker->guideline->translations);
// Need to limit to active checks.
$activechecks = $DB->get_fieldset_select(manager::DB_CHECKS, 'shortname', 'status = :status', ['status' => 1]);
$translations = [];
foreach ($htmlchecker->guideline->translations as $key => $trans) {
if (in_array($key, $activechecks)) {
$translations[$key] = $trans;
}
}
return $translations;
}
/**
* Returns an array of all of the course id's for a given category.
* @param int $categoryid
* @return array|null
* @throws \dml_exception
*/
public static function get_category_courseids(int $categoryid): ?array {
global $DB;
if (!$DB->record_exists('course_categories', ['id' => $categoryid])) {
return null;
}
$sql = "SELECT {course}.id
FROM {course}, {course_categories}
WHERE {course}.category = {course_categories}.id
AND (
" . $DB->sql_like('path', ':categoryid1') . "
OR " . $DB->sql_like('path', ':categoryid2') . "
)";
$params = ['categoryid1' => "%/$categoryid/%", 'categoryid2' => "%/$categoryid"];
$courseids = $DB->get_fieldset_sql($sql, $params);
return $courseids;
}
/**
* Get summary data for this site.
* @param int $id
* @return \stdClass
* @throws \dml_exception
*/
public static function get_summary_data(int $id): \stdClass {
global $CFG, $DB;
$summarydata = new \stdClass();
$summarydata->siteurl = (substr($CFG->wwwroot, -1) !== '/') ? $CFG->wwwroot . '/' : $CFG->wwwroot;
$summarydata->moodlerelease = (preg_match('/^(\d+\.\d.*?)[. ]/', $CFG->release, $matches)) ? $matches[1] : $CFG->release;
$summarydata->numcourses = $DB->count_records('course') - 1;
$summarydata->numusers = $DB->count_records('user', array('deleted' => 0));
$summarydata->numfiles = $DB->count_records('files');
$summarydata->numfactivities = $DB->count_records('course_modules');
$summarydata->mobileservice = (int)$CFG->enablemobilewebservice === 1 ? true : false;
$summarydata->usersmobileregistered = $DB->count_records('user_devices');
$summarydata->contenttyperesults = static::get_contenttyperesults($id);
$summarydata->contenttypeerrors = static::get_contenttypeerrors();
$summarydata->percheckerrors = static::get_percheckerrors();
return $summarydata;
}
/**
* Get content type results.
* @param int $id
* @return \stdClass
*/
private static function get_contenttyperesults(int $id): \stdClass {
global $DB;
$sql = 'SELECT component, COUNT(id) AS count
FROM {' . manager::DB_AREAS . '}
GROUP BY component';
$components = $DB->get_recordset_sql($sql);
$contenttyperesults = new \stdClass();
$contenttyperesults->id = $id;
$contenttyperesults->contenttype = new \stdClass();
foreach ($components as $component) {
$componentname = $component->component;
$contenttyperesults->contenttype->$componentname = $component->count;
}
$components->close();
$contenttyperesults->summarydatastorage = static::get_summary_data_storage();
$contenttyperesults->datachecked = time();
return $contenttyperesults;
}
/**
* Get per check errors.
* @return stdClass
* @throws dml_exception
*/
private static function get_percheckerrors(): stdClass {
global $DB;
$sql = 'SELECT ' . $DB->sql_concat_join("'_'", ['courseid', 'checkid']) . ' as tmpid,
ca.courseid, ca.status, ca.checkid, ch.shortname, ca.checkcount, ca.errorcount
FROM {' . manager::DB_CACHECHECK . '} ca
INNER JOIN {' . manager::DB_CHECKS . '} ch on ch.id = ca.checkid
ORDER BY courseid, checkid ASC';
$combo = $DB->get_records_sql($sql);
return (object) [
'percheckerrors' => $combo,
];
}
/**
* Get content type errors.
* @return stdClass
* @throws dml_exception
*/
private static function get_contenttypeerrors(): stdClass {
global $DB;
$fields = 'courseid, status, activities, activitiespassed, activitiesfailed,
errorschecktype1, errorschecktype2, errorschecktype3, errorschecktype4,
errorschecktype5, errorschecktype6, errorschecktype7,
failedchecktype1, failedchecktype2, failedchecktype3, failedchecktype4,
failedchecktype5, failedchecktype6, failedchecktype7,
percentchecktype1, percentchecktype2, percentchecktype3, percentchecktype4,
percentchecktype5, percentchecktype6, percentchecktype7';
$combo = $DB->get_records(manager::DB_SUMMARY, null, 'courseid ASC', $fields);
return (object) [
'typeerrors' => $combo,
];
}
/**
* Get summary data storage.
* @return array
* @throws dml_exception
*/
private static function get_summary_data_storage(): array {
global $DB;
$fields = $DB->sql_concat_join("''", ['component', 'courseid']) . ' as tmpid,
courseid, component, errorcount, totalactivities, failedactivities, passedactivities';
$combo = $DB->get_records(manager::DB_CACHEACTS, null, 'courseid, component ASC', $fields);
return $combo;
}
}
@@ -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/>.
namespace tool_brickfield;
use tool_brickfield\task\process_analysis_requests;
/**
* Analysis and deployment class.
*
* @package tool_brickfield
* @copyright 2020 Brickfield Education Labs https://www.brickfield.ie
* @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class analysis {
/**
* Indicates that analysis of content has been enabled.
*/
const ANALYSISDISABLED = '0';
/**
* Indicates that analysis is enabled and using request method.
*/
const ANALYSISBYREQUEST = '1';
/**
* Return the type of analysis being used (currently only request).
*
* @return false|mixed|object|string|null
* @throws \dml_exception
*/
public static function get_type() {
// Moodle caches these calls, so it's not expensive.
return get_config(manager::PLUGINNAME, 'analysistype');
}
/**
* Return true is analysis has been enabled.
*
* @return bool
* @throws \dml_exception
*/
public static function is_enabled(): bool {
$analysistype = static::get_type();
return ($analysistype !== false) && ($analysistype !== self::ANALYSISDISABLED);
}
/**
* Return true if analysis is by request method.
*
* @return bool
* @throws \dml_exception
*/
public static function type_is_byrequest(): bool {
return static::get_type() === self::ANALYSISBYREQUEST;
}
/**
* Return true if the course has been analyzed.
*
* @param int $courseid
* @return bool
* @throws \dml_exception
*/
public static function is_course_analyzed(int $courseid): bool {
return scheduler::is_course_analyzed($courseid);
}
/**
* Return a redirect message with the earliest time expected for analysis to complete.
* @return \lang_string|string
* @throws \coding_exception
*/
public static function redirect_message() {
$epoch = new process_analysis_requests;
$time = userdate($epoch->get_next_scheduled_time(), get_string('strftimetime', 'core_langconfig'));
$message = get_string('confirmationmessage', manager::PLUGINNAME, $time);
return $message;
}
}
+228
View File
@@ -0,0 +1,228 @@
<?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 tool_brickfield;
/**
* Area base class.
*
* @package tool_brickfield
* @copyright 2020 Brickfield Education Labs https://www.brickfield.ie
*/
abstract class area_base {
/**
* Defines the unknown for the 'checkgroup' field in the tool_brickfield_checks table.
*/
const CHECKGROUP_UNKNOWN = 0;
/**
* Defines the form for the 'checkgroup' field in the tool_brickfield_checks table.
*/
const CHECKGROUP_FORM = 1;
/**
* Defines the image for the 'checkgroup' field in the tool_brickfield_checks table.
*/
const CHECKGROUP_IMAGE = 2;
/**
* Defines the layout for the 'checkgroup' field in the tool_brickfield_checks table.
*/
const CHECKGROUP_LAYOUT = 3;
/**
* Defines the link for the 'checkgroup' field in the tool_brickfield_checks table.
*/
const CHECKGROUP_LINK = 4;
/**
* Defines the media for the 'checkgroup' field in the tool_brickfield_checks table.
*/
const CHECKGROUP_MEDIA = 5;
/**
* Defines the table for the 'checkgroup' field in the tool_brickfield_checks table.
*/
const CHECKGROUP_TABLE = 6;
/**
* Defines the text for the 'checkgroup' field in the tool_brickfield_checks table.
*/
const CHECKGROUP_TEXT = 7;
/** @var string[] Array for quick access of string names for 'checkgroups'. */
const CHECKGROUP_NAMES = [
self::CHECKGROUP_UNKNOWN => 'unknown',
self::CHECKGROUP_FORM => 'form',
self::CHECKGROUP_IMAGE => 'image',
self::CHECKGROUP_LAYOUT => 'layout',
self::CHECKGROUP_LINK => 'link',
self::CHECKGROUP_MEDIA => 'media',
self::CHECKGROUP_TABLE => 'table',
self::CHECKGROUP_TEXT => 'text'
];
/**
* Defines field value.
*/
const TYPE_FIELD = 0;
/**
* Defines file value.
*/
const TYPE_FILE = 1;
/** @var string To store the filter. */
protected string $filter = '';
/** @var array To store the filter parameters. */
protected array $filterparams = [];
/** @var string To store the filter field name. */
protected $filterfieldname;
/**
* Return the name for the specified checkgroup value, or 'unknown' if no valid name for the value. Preferably, use this rather
* than direct access to CHECKGROUP_NAMES, since it checks value boundaries.
* @param int $checkgroupvalue
* @return string
*/
final public static function checkgroup_name(int $checkgroupvalue): string {
if (($checkgroupvalue < 0) || ($checkgroupvalue >= count(self::CHECKGROUP_NAMES))) {
return self::CHECKGROUP_NAMES[self::CHECKGROUP_UNKNOWN];
} else {
return self::CHECKGROUP_NAMES[$checkgroupvalue];
}
}
/**
* Return the value for the specified checkgroup name, or the unknown value if no valid value for the name.
* @param string $checkgroupname
* @return int
*/
final public static function checkgroup_value(string $checkgroupname): int {
$value = array_search($checkgroupname, self::CHECKGROUP_NAMES);
return ($value !== false) ? $value : self::CHECKGROUP_UNKNOWN;
}
/**
* Return the defined content type.
* @return int
*/
protected function get_type(): int {
return self::TYPE_FIELD;
}
/**
* Return the component from the full class name.
* @return mixed|string
*/
public function get_component(): string {
$parts = preg_split('|\\\\|', get_class($this));
return $parts[3];
}
/**
* Check if the system plugin is avaliable.
* @return bool
*/
public function is_available(): bool {
list($type, $plugin) = \core_component::normalize_component($this->get_component());
if ($type === 'core') {
// We assume that all core components are defined corretly.
return true;
}
// Some contrib plugins may not be installed.
return ($dir = \core_component::get_component_directory($this->get_component()))
&& file_exists($dir . '/version.php');
}
/**
* Return the name of the database table where information is stored
* @return string
*/
abstract public function get_tablename(): string;
/**
* Return the name of the reference data table name.
* @return string
*/
public function get_ref_tablename(): string {
return '';
}
/**
* Return the name of the field in the table that has the content
* @return string
*/
abstract public function get_fieldname(): string;
/**
* Return a recordset of the relevant areas for the component/module.
* @param \core\event\base $event
* @return \moodle_recordset|null
*/
abstract public function find_relevant_areas(\core\event\base $event): ?\moodle_recordset;
/**
* Return a recordset of the course areas for the course id.
* @param int $courseid
* @return \moodle_recordset|null
*/
abstract public function find_course_areas(int $courseid): ?\moodle_recordset;
/**
* Return an array of area objects that contain content at the site and system levels only. Override this where necessary.
* @return \moodle_recordset|null
*/
public function find_system_areas(): ?\moodle_recordset {
return null;
}
/**
* The standard Moodle parameter DML parameter substitution doesn't work on all versions of MySQL or Postgres, so we need to use
* inline function substitution to ensure that the left side is a string.
* @return string
*/
public function get_standard_area_fields_sql(): string {
return '\'' . $this->get_component() . '\' AS component,
\'' . $this->get_tablename() . '\' AS tablename,
\'' . $this->get_fieldname() . '\' AS fieldorarea, ';
}
/**
* The standard Moodle parameter DML parameter substitution doesn't work on all versions of MySQL or Postgres, so we need to use
* inline function substitution to ensure that the left side is a string.
* @return string
*/
public function get_reftable_field_sql(): string {
return '\'' . $this->get_ref_tablename() . '\' AS reftable, ';
}
/**
* Processes any sql filtering data. Implement in extensions.
*
* @return null
* @throws \coding_exception
* @throws \dml_exception
*/
public function get_courseid_filtering() {
$this->filter = '';
$this->filterparams = [];
return null;
}
}
@@ -0,0 +1,257 @@
<?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 tool_brickfield;
defined('MOODLE_INTERNAL') || die;
// The curl class is in filelib.
global $CFG;
require_once("{$CFG->libdir}/filelib.php");
use curl;
use moodle_url;
/**
* Class brickfieldconnect. Contains all function to connect to Brickfield external services.
*
* @package tool_brickfield
* @author 2020 Onwards Mike Churchward <mike@brickfieldlabs.ie>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL
*/
class brickfieldconnect extends curl {
/** @var string The base api uri. */
private static $baseapiuri = 'https://api.mybrickfield.ie/moodle/';
/** @var array Endpoint details for setting and checking a site registration */
const ACTION_CHECK_REGISTRATION = [
'endpoint' => 'checkRegister',
'method' => 'get',
];
/** @var array Endpoint details for sending site summary data */
const ACTION_SEND_SUMMARY = [
'endpoint' => 'summary',
'method' => 'post',
];
/**
* Object method to test whether site is already registered.
* @return bool
*/
public function is_registered(): bool {
return !empty($this->get_registration_id_for_credentials());
}
/**
* Update registration of this site.
* @param string $apikey The API key to use for the registration attempt
* @param string $secretkey The secret key to use
* @return bool
*/
public function update_registration(string $apikey, string $secretkey): bool {
$registrationid = $this->get_registration_id_for_credentials($apikey, $secretkey);
if (empty($registrationid)) {
return false;
}
(new registration())->set_siteid($registrationid);
return true;
}
/**
* Send the summary data to Brickfield.
* @return bool
* @throws \dml_exception
*/
public function send_summary(): bool {
// Run a registration check.
if (!(new registration())->validate()) {
return false;
}
$headers = $this->get_common_headers();
// Sanity-check $headers 'id' value.
if (!isset($headers['id'])) {
return false;
}
$this->set_headers($headers);
$summary = accessibility::get_summary_data($headers['id']);
$body = json_encode($summary, JSON_UNESCAPED_SLASHES);
$result = json_decode($this->call(self::ACTION_SEND_SUMMARY, $body));
if (is_object($result) && ((int)$result->statusCode === 200)) {
return true;
} else {
return false;
}
}
/**
* Get the URL required for the command.
*
* @param array $command The command to call, for example see self::ACTION_REGISTER
* @return string The complete URL
*/
protected function get_url_for_command(array $command): string {
return $this->get_baseapiuri() . $command['endpoint'];
}
/**
* Call the specified command.
*
* @param array $command The command to call, for example see self::ACTION_REGISTER
* @param array|string $params The params provided to the call
* @return string The response body
*/
protected function call(array $command, $params = ''): string {
$url = $this->get_url_for_command($command);
if ($command['method'] === 'get') {
return $this->get($url, $params);
}
if ($command['method'] === 'post') {
return $this->post($url, $params);
}
return '';
}
/**
* Get the common headers used for all calls to the Brickfields endpoints.
*
* @return array
*/
protected function get_common_headers(): array {
$headers = [
'Cache-Control' => 'no-cache',
'Content-Type' => 'application/json',
'siteurl' => static::get_siteurl(),
];
if (static::has_registration_key()) {
$registration = new registration();
$headers['secret'] = $registration->get_api_key();
$headers['userhash'] = $registration->get_secret_key();
$headers['id'] = $registration->get_siteid();
}
return $headers;
}
/**
* Set headers on the request from the specified list of headers.
*
* @param array $headers An array of header name => value
*/
protected function set_headers(array $headers) {
foreach ($headers as $key => $value) {
$this->setHeader("{$key}: {$value}");
}
}
/**
* Whether the site currently has a registration key stored.
*
* @return bool
*/
protected function has_registration_key(): bool {
$registration = new registration();
$localkey = $registration->get_api_key();
$localhash = $registration->get_secret_key();
$localid = $registration->get_siteid();
if (!$localhash || !$localkey || !$localid) {
return false;
}
return true;
}
/**
* Get a normalised URL for the site.
*
* @return string
*/
protected function get_siteurl(): string {
return (new moodle_url('/'))->out(false);
}
/**
* Get the registration ID for the given set of credentials.
* @param null|string $apikey The API key to use for the registration attempt
* @param null|string $secretkey The secret key to use
* @return null|string The registration ID if registration was successful, or null if not
*/
protected function get_registration_id_for_credentials(string $apikey = null, string $secretkey = null): string {
$headers = $this->get_common_headers();
if ($apikey || $secretkey) {
$headers['secret'] = $apikey;
$headers['userhash'] = $secretkey;
} else if (!$this->has_registration_key()) {
return '';
}
$this->set_headers($headers);
$response = $this->call(self::ACTION_CHECK_REGISTRATION);
if ((int)$this->info['http_code'] !== 200) {
// The response was unsuccessful.
return '';
}
$result = json_decode($response);
if (!$result) {
// The response could not be decoded.
return '';
}
if ((int)$result->statusCode !== 200) {
// The data from the response suggests a failure.
return '';
}
// Decode the actual result.
$registrationdata = json_decode($result->body);
if (empty($registrationdata) || !is_array($registrationdata)) {
// Unable to decode the body of the response.
return '';
}
if (!property_exists($registrationdata[0], 'id') || !property_exists($registrationdata[0]->id, 'N')) {
// Unable to find a valid id in the response.
return '';
}
return $registrationdata[0]->id->N;
}
/**
* Get the check registration API URI.
* @return string
*/
protected function get_baseapiuri(): string {
$baseapiuri = get_config(manager::PLUGINNAME, 'baseapiuri');
if (!empty($baseapiuri)) {
return $baseapiuri;
} else {
set_config('baseapiuri', self::$baseapiuri, manager::PLUGINNAME);
return self::$baseapiuri;
}
}
}
@@ -0,0 +1,54 @@
<?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 tool_brickfield\event;
use tool_brickfield\manager;
/**
* Class analysis_requested
*
* @package tool_brickfield
* @copyright 2020 onward Brickfield Education Labs, https://www.brickfield.ie
* @author Mike Churchward <mike@brickfieldlabs.ie>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL
*/
class analysis_requested extends \core\event\base {
/**
* Init function.
*/
protected function init() {
$this->data['crud'] = 'c';
$this->data['edulevel'] = self::LEVEL_OTHER;
}
/**
* Get name.
* @return \lang_string|string
*/
public static function get_name() {
return get_string('eventanalysis_requested', manager::PLUGINNAME);
}
/**
* Get description.
* @return \lang_string|string|null
*/
public function get_description() {
return get_string('eventanalysis_requesteddesc', manager::PLUGINNAME, $this->other['course']);
}
}
@@ -0,0 +1,54 @@
<?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 tool_brickfield\event;
use tool_brickfield\manager;
/**
* Class report_downloaded
*
* @package tool_brickfield
* @copyright 2020 onward Brickfield Education Labs, https://www.brickfield.ie
* @author Mike Churchward <mike@brickfieldlabs.ie>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL
*/
class report_downloaded extends \core\event\base {
/**
* Init function.
*/
protected function init() {
$this->data['crud'] = 'r';
$this->data['edulevel'] = self::LEVEL_OTHER;
}
/**
* Get name.
* @return \lang_string|string
*/
public static function get_name() {
return get_string('eventreport_downloaded', manager::PLUGINNAME);
}
/**
* Get description.
* @return \lang_string|string|null
*/
public function get_description() {
return get_string('eventreport_downloadeddesc', manager::PLUGINNAME, $this->courseid);
}
}
@@ -0,0 +1,54 @@
<?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 tool_brickfield\event;
use tool_brickfield\manager;
/**
* Class report_viewed
*
* @package tool_brickfield
* @copyright 2020 onward Brickfield Education Labs, https://www.brickfield.ie
* @author Mike Churchward <mike@brickfieldlabs.ie>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL
*/
class report_viewed extends \core\event\base {
/**
* Init function.
*/
protected function init() {
$this->data['crud'] = 'r';
$this->data['edulevel'] = self::LEVEL_OTHER;
}
/**
* Get name.
* @return \lang_string|string
*/
public static function get_name() {
return get_string('eventreport_viewed', manager::PLUGINNAME);
}
/**
* Get description.
* @return \lang_string|string|null
*/
public function get_description() {
return get_string('eventreport_vieweddesc', manager::PLUGINNAME, (object)$this->other);
}
}
@@ -0,0 +1,438 @@
<?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 tool_brickfield;
use core\event\base;
use stdClass;
/**
* Observer class containing methods monitoring various events.
*
* @package tool_brickfield
* @copyright 2020 Brickfield Education Labs https://www.brickfield.ie
* @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*
*/
class eventobservers {
/**
* For course events to be handled, the accessibility tool needs to be enabled, and if a courseid is specified, the course
* has to have been added to the scheduler.
* @param int $courseid
* @return bool
* @throws \dml_exception
*/
private static function course_event_should_be_handled(int $courseid): bool {
return accessibility::is_accessibility_enabled() && analysis::is_enabled() &&
(empty($courseid) || (isset($courseid) && scheduler::is_course_in_schedule($courseid)));
}
/**
* Content area altered event observer.
* @param base $event The area altered event.
* @throws \ReflectionException
* @throws \dml_exception
*/
private static function area_altered(base $event) {
// Handle if this feature is enabled and this course is in the schedule.
if (static::course_event_should_be_handled($event->courseid)) {
manager::find_new_or_updated_areas($event);
}
}
/**
* Course event observers.
* These observer monitors course created / restored / updated events,
* then its HTML content is processed with accessibility checking.
*/
/**
* Course created event observer.
* @param \core\event\course_created $event The course created event.
* @throws \ReflectionException
* @throws \dml_exception
*/
public static function course_created(\core\event\course_created $event) {
// Handle if this feature is enabled and this course is in the schedule.
if (static::course_event_should_be_handled($event->courseid)) {
// Need to trigger rerun check for automatically created forum...
$data = new stdClass();
$data->courseid = $event->courseid;
$data->item = 'coursererun';
static::observer_insert($data);
static::course_altered($event);
}
}
/**
* Course deleted event observer.
* @param \core\event\course_deleted $event The course deleted event.
* @throws \dml_exception
*/
public static function course_deleted(\core\event\course_deleted $event) {
// Handle if this feature is enabled and this course is in the schedule.
if (static::course_event_should_be_handled($event->courseid)) {
$data = new stdClass();
$data->courseid = $event->courseid;
$data->contextid = -1;
$data->item = 'core_course';
static::observer_insert($data);
}
}
/**
* Course restored event observer.
* @param \core\event\course_restored $event The course restored event.
* @throws \ReflectionException
* @throws \dml_exception
*/
public static function course_restored(\core\event\course_restored $event) {
// Handle if this feature is enabled and this course is in the schedule.
if (static::course_event_should_be_handled($event->courseid)) {
$data = new stdClass();
$data->courseid = $event->courseid;
$data->item = 'coursererun';
static::observer_insert($data);
static::course_altered($event);
}
}
/**
* Course update event observer.
* @param \core\event\course_updated $event The course updated event.
* @throws \ReflectionException
* @throws \dml_exception
*/
public static function course_updated(\core\event\course_updated $event) {
// Handle if this feature is enabled and this course is in the schedule.
if (static::course_event_should_be_handled($event->courseid)) {
static::course_altered($event);
}
}
/**
* Course update event observer. This is called on both course_created and course_updated, so use the base class as a type hint.
* @param base $event The course updated event.
* @throws \ReflectionException
* @throws \dml_exception
*/
public static function course_altered(base $event) {
// Handle if this feature is enabled and this course is in the schedule.
if (static::course_event_should_be_handled($event->courseid)) {
// Need to rerun caching of allowed courseid, from category white/blacklist.
$data = new stdClass();
$data->courseid = $data->contextid = $event->courseid;
$data->contextid = -1;
$data->item = 'category';
static::observer_insert($data);
static::area_altered($event);
}
}
/**
* Course section created event observer.
* @param \core\event\course_section_created $event The course section created event.
* @throws \ReflectionException
* @throws \dml_exception
*/
public static function course_section_created(\core\event\course_section_created $event) {
// Handle if this feature is enabled and this course is in the schedule.
if (static::course_event_should_be_handled($event->courseid)) {
static::area_altered($event);
}
}
/**
* Course section deleted event observer.
* @param \core\event\course_section_deleted $event The course section deleted event.
* @throws \dml_exception
*/
public static function course_section_deleted(\core\event\course_section_deleted $event) {
// Handle if this feature is enabled and this course is in the schedule.
if (static::course_event_should_be_handled($event->courseid)) {
$data = new stdClass();
$data->courseid = $event->courseid;
$data->contextid = -1;
$data->innercontextid = $event->objectid;
$data->item = 'course_sections';
static::observer_insert($data);
}
}
/**
* Course section update event observer.
* @param \core\event\course_section_updated $event The course section updated event.
* @throws \ReflectionException
* @throws \dml_exception
*/
public static function course_section_updated(\core\event\course_section_updated $event) {
// Handle if this feature is enabled and this course is in the schedule.
if (static::course_event_should_be_handled($event->courseid)) {
static::area_altered($event);
}
}
/**
* Course module event observers.
* These observer monitors course module created / restored / updated events,
* then its HTML content is processed with accessibility checking.
*/
/**
* Course module created event observer.
* @param \core\event\course_module_created $event The course module created event.
* @throws \ReflectionException
* @throws \dml_exception
*/
public static function course_module_created(\core\event\course_module_created $event) {
// Handle if this feature is enabled and this course is in the schedule.
if (static::course_event_should_be_handled($event->courseid)) {
static::area_altered($event);
}
}
/**
* Course module deleted event observer.
* @param \core\event\course_module_deleted $event The course module deleted event.
* @throws \dml_exception
*/
public static function course_module_deleted(\core\event\course_module_deleted $event) {
// Handle if this feature is enabled and this course is in the schedule.
if (static::course_event_should_be_handled($event->courseid)) {
$data = new stdClass();
$data->courseid = $event->courseid;
$data->contextid = -1;
$data->innercontextid = $event->other['instanceid'];
$data->item = 'mod_' . $event->other['modulename'];
static::observer_insert($data);
}
}
/**
* Course module restored event observer.
* @param \core\event\course_module_restored $event The course module restored event.
* @throws \ReflectionException
* @throws \dml_exception
*/
public static function course_module_restored(\core\event\course_module_restored $event) {
// Handle if this feature is enabled and this course is in the schedule.
if (static::course_event_should_be_handled($event->courseid)) {
static::area_altered($event);
}
}
/**
* Course module updated event observer.
* @param \core\event\course_module_updated $event The course module updated event.
* @throws \ReflectionException
* @throws \dml_exception
*/
public static function course_module_updated(\core\event\course_module_updated $event) {
// Handle if this feature is enabled and this course is in the schedule.
if (static::course_event_should_be_handled($event->courseid)) {
static::area_altered($event);
}
}
/**
* course_category created event observer.
* @param \core\event\course_category_created $event The course_category created event.
* @throws \ReflectionException
* @throws \dml_exception
*/
public static function course_category_created(\core\event\course_category_created $event) {
// Handle if this feature is enabled and this course is in the schedule.
if (static::course_event_should_be_handled($event->courseid)) {
static::area_altered($event);
}
}
/**
* course_category deleted event observer.
* @param \core\event\course_category_deleted $event The course_category deleted event.
* @throws \dml_exception
*/
public static function course_category_deleted(\core\event\course_category_deleted $event) {
// Handle if this feature is enabled and this course is in the schedule.
if (static::course_event_should_be_handled($event->courseid)) {
$data = new stdClass();
$data->contextid = $data->courseid = -1;
$data->innercontextid = $event->objectid;
$data->item = 'course_categories';
static::observer_insert($data);
}
}
/**
* course_category update event observer.
* @param \core\event\course_category_updated $event The course_category updated event.
* @throws \ReflectionException
* @throws \dml_exception
*/
public static function course_category_updated(\core\event\course_category_updated $event) {
// Handle if this feature is enabled and this course is in the schedule.
if (static::course_event_should_be_handled($event->courseid)) {
static::area_altered($event);
}
}
/**
* mod_lesson_page created event observer.
* @param \mod_lesson\event\page_created $event The mod_lesson page created event.
* @throws \ReflectionException
* @throws \dml_exception
*/
public static function mod_lesson_page_created(\mod_lesson\event\page_created $event) {
// Handle if this feature is enabled and this course is in the schedule.
if (static::course_event_should_be_handled($event->courseid)) {
static::area_altered($event);
}
}
/**
* mod_lesson_page deleted event observer.
* @param \mod_lesson\event\page_deleted $event The mod_lesson page deleted event.
* @throws \dml_exception
*/
public static function mod_lesson_page_deleted(\mod_lesson\event\page_deleted $event) {
// Handle if this feature is enabled and this course is in the schedule.
if (static::course_event_should_be_handled($event->courseid)) {
$data = new stdClass();
$data->courseid = $event->courseid;
$data->contextid = -1;
$data->innercontextid = $event->objectid;
$data->item = 'lesson_pages';
static::observer_insert($data);
}
}
/**
* mod_lesson_page updated event observer.
* @param \mod_lesson\event\page_updated $event The mod_lesson page updated event.
* @throws \ReflectionException
* @throws \dml_exception
*/
public static function mod_lesson_page_updated(\mod_lesson\event\page_updated $event) {
// Handle if this feature is enabled and this course is in the schedule.
if (static::course_event_should_be_handled($event->courseid)) {
static::area_altered($event);
}
}
/**
* core_question created observer
* @param \core\event\question_created $event The core_question created event.
* @throws \ReflectionException
* @throws \dml_exception
*/
public static function core_question_created(\core\event\question_created $event) {
// Handle if this feature is enabled and this course is in the schedule.
if (static::course_event_should_be_handled($event->courseid)) {
manager::find_new_or_updated_areas($event);
}
}
/**
* core_question updated observer
* @param \core\event\question_updated $event The core_question created event.
* @throws \ReflectionException
* @throws \dml_exception
*/
public static function core_question_updated(\core\event\question_updated $event) {
// Handle if this feature is enabled and this course is in the schedule.
if (static::course_event_should_be_handled($event->courseid)) {
manager::find_new_or_updated_areas($event);
}
}
/**
* core_question deleted observer
* @param \core\event\question_deleted $event The core_question deleted event.
* @throws \dml_exception
*/
public static function core_question_deleted(\core\event\question_deleted $event) {
// Handle if this feature is enabled and this course is in the schedule.
if (static::course_event_should_be_handled($event->courseid)) {
$data = new stdClass();
$data->courseid = $event->courseid;
$data->contextid = -1;
$data->innercontextid = $event->objectid;
$data->item = $event->objecttable;
static::observer_insert($data);
}
}
/**
* Book chapter created event observer.
* @param \mod_book\event\chapter_created $event The book chapter created event.
* @throws \ReflectionException
* @throws \dml_exception
*/
public static function book_chapter_created(\mod_book\event\chapter_created $event) {
// If this feature has been disabled, do nothing.
if (accessibility::is_accessibility_enabled()) {
static::area_altered($event);
}
}
/**
* Book chapter deleted event observer.
* @param \mod_book\event\chapter_deleted $event The book chapter deleted event.
* @throws \dml_exception
*/
public static function book_chapter_deleted(\mod_book\event\chapter_deleted $event) {
// If this feature has been disabled, do nothing.
if (accessibility::is_accessibility_enabled()) {
$data = new stdClass();
$data->courseid = $event->courseid;
$data->contextid = -1;
$data->innercontextid = $event->objectid;
$data->item = 'book_chapters';
static::observer_insert($data);
}
}
/**
* Book chapter update event observer.
* @param \mod_book\event\chapter_updated $event The book chapter updated event.
* @throws \ReflectionException
* @throws \dml_exception
*/
public static function book_chapter_updated(\mod_book\event\chapter_updated $event) {
// If this feature has been disabled, do nothing.
if (accessibility::is_accessibility_enabled()) {
static::area_altered($event);
}
}
/**
* Add an observer record if appropriate.
* @param stdClass $data
* @throws \dml_exception
*/
private static function observer_insert(stdClass $data) {
global $DB;
// Handle if this feature is enabled and this course is in the schedule.
if (static::course_event_should_be_handled($data->courseid)) {
$data->timecreated = time();
$data->timecompleted = 0;
$DB->insert_record(manager::DB_PROCESS, $data);
}
}
}
@@ -0,0 +1,149 @@
<?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/>.
/**
* Class registration_form
*
* @package tool_brickfield
* @copyright 2021 Brickfield Education Labs https://www.brickfield.ie
* @author 2020 JM Tomas <jmtomas@tresipunt.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL
*/
namespace tool_brickfield\form;
defined('MOODLE_INTERNAL') || die();
use coding_exception;
use dml_exception;
use html_writer;
use moodle_exception;
use moodleform;
use stdClass;
use tool_brickfield\manager;
use tool_brickfield\registration;
global $CFG;
require_once($CFG->libdir . '/formslib.php');
/**
* Class registration_form
*
* @package tool_brickfield
* @author 2020 JM Tomas <jmtomas@tresipunt.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL
*/
class registration_form extends moodleform {
/**
* Form definition.
* @throws moodle_exception
*/
public function definition() {
$mform = & $this->_form;
$required = get_string('required');
$info = $this->get_defaultinfo();
$registration = new registration();
$key = $registration->get_api_key();
$hash = $registration->get_secret_key();
$mform->addElement('header', 'activationheader', get_string('activationheader', manager::PLUGINNAME));
$mform->addElement('text', 'key', get_string('secretkey', manager::PLUGINNAME));
$mform->setType('key', PARAM_TEXT);
$mform->setDefault('key', !empty($key) ? $key : '');
$mform->addHelpButton('key', 'secretkey', manager::PLUGINNAME);
$mform->addElement('text', 'hash', get_string('sitehash', manager::PLUGINNAME));
$mform->setType('hash', PARAM_TEXT);
$mform->setDefault('hash', !empty($hash) ? $hash : '');
$mform->addHelpButton('hash', 'sitehash', manager::PLUGINNAME);
$mform->addElement('header', 'moreinfo', get_string('moreinfo', manager::PLUGINNAME));
$mform->addElement('static', 'siteinfosummary', '',
get_string('sendfollowinginfo', manager::PLUGINNAME, $info->moreinfostring));
$mform->addElement('hidden', 'lang', $info->languagecode);
$mform->setType('lang', PARAM_TEXT);
$mform->addElement('hidden', 'countrycode', $info->country);
$mform->setType('countrycode', PARAM_TEXT);
$mform->addElement('hidden', 'url', $info->url);
$mform->setType('url', PARAM_URL);
$this->add_action_buttons(false, get_string('activate', manager::PLUGINNAME, '#'));
}
/**
* Get default data for registration form
*
* @throws moodle_exception
* @return stdClass
*/
protected function get_defaultinfo(): stdClass {
global $CFG;
$admin = get_admin();
$site = get_site();
$data = new stdClass();
$data->name = $site->fullname;
$data->url = $CFG->wwwroot;
$data->language = get_string('thislanguage', 'langconfig');
$data->languagecode = $admin->lang ?: $CFG->lang;
$data->country = $admin->country ?: $CFG->country;
$data->email = $admin->email;
$data->moreinfo = self::get_moreinfo();
$data->moreinfostring = self::get_moreinfostring($data->moreinfo);
return $data;
}
/**
* Get more information.
* @return array
* @throws dml_exception
*/
private static function get_moreinfo(): array {
global $CFG, $DB;
$moreinfo = array();
$moodlerelease = $CFG->release;
if (preg_match('/^(\d+\.\d.*?)[. ]/', $moodlerelease, $matches)) {
$moodlerelease = $matches[1];
}
$moreinfo['release'] = $moodlerelease;
$moreinfo['numcourses'] = $DB->count_records('course') - 1;
$moreinfo['numusers'] = $DB->count_records('user', array('deleted' => 0));
$moreinfo['numfiles'] = $DB->count_records('files');
$moreinfo['numfactivities'] = $DB->count_records('course_modules');
$moreinfo['mobileservice'] = empty($CFG->enablemobilewebservice) ? 0 : $CFG->enablemobilewebservice;
$moreinfo['usersmobileregistered'] = $DB->count_records('user_devices');
$moreinfo['contentyperesults'] = '';
$moreinfo['contenttypeerrors'] = '';
$moreinfo['percheckerrors'] = '';
return $moreinfo;
}
/**
* Get HTML list for more information.
*
* @param array $moreinfo
* @return string
* @throws coding_exception
*/
private static function get_moreinfostring(array $moreinfo): string {
$html = html_writer::start_tag('ul');
foreach ($moreinfo as $key => $value) {
$html .= html_writer::tag('li', get_string($key, manager::PLUGINNAME, $value));
}
$html .= html_writer::end_tag('ul');
return $html;
}
}
@@ -0,0 +1,118 @@
<?php
// This file is part of the Query submission plugin
//
// 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 tool_brickfield\local\areas\core_course;
use core\event\course_created;
use core\event\course_updated;
use core\event\course_restored;
use tool_brickfield\area_base;
/**
* Base class for various course-related areas
*
* This is an abstract class so it will be skipped by manager when it finds all areas
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
abstract class base extends area_base {
/**
* Find recordset of the relevant areas.
* @param \core\event\base $event
* @return \moodle_recordset|null
* @throws \coding_exception
* @throws \dml_exception
*/
public function find_relevant_areas(\core\event\base $event): ?\moodle_recordset {
if ($event instanceof course_created) {
return $this->find_fields_in_course_table(['courseid' => $event->courseid]);
} else if ($event instanceof course_restored) {
return $this->find_fields_in_course_table(['courseid' => $event->courseid]);
} else if ($event instanceof course_updated) {
return $this->find_fields_in_course_table(['courseid' => $event->courseid]);
}
return null;
}
/**
* Find recordset of the course areas.
* @param int $courseid
* @return \moodle_recordset
* @throws \coding_exception
* @throws \dml_exception
*/
public function find_course_areas(int $courseid): ?\moodle_recordset {
return $this->find_fields_in_course_table(['courseid' => $courseid]);
}
/**
* Return an array of area objects that contain content at the site and system levels only.
* @return mixed
*/
public function find_system_areas(): ?\moodle_recordset {
return null;
}
/**
* Helper method that can be used by the classes that define a field in the 'course' table
*
* @param array $params
* @return \moodle_recordset
* @throws \coding_exception
* @throws \dml_exception
*/
protected function find_fields_in_course_table(array $params = []): \moodle_recordset {
global $DB;
$where = [];
if (!empty($params['courseid'])) {
$where[] = 't.id = :courseid';
}
$rs = $DB->get_recordset_sql('SELECT
' . $this->get_type() . ' AS type,
ctx.id AS contextid,
' . $this->get_standard_area_fields_sql() . '
t.id AS itemid,
t.id AS courseid,
t.'.$this->get_fieldname().' AS content
FROM {'.$this->get_tablename().'} t
JOIN {context} ctx ON ctx.instanceid = t.id AND ctx.contextlevel = :pctxlevelcourse '.
($where ? 'WHERE ' . join(' AND ', $where) : '') . '
ORDER BY t.id',
['pctxlevelcourse' => CONTEXT_COURSE] + $params);
return $rs;
}
/**
* Returns the moodle_url of the page to edit the error.
* @param \stdClass $componentinfo
* @return \moodle_url
*/
public static function get_edit_url(\stdClass $componentinfo): \moodle_url {
if ($componentinfo->tablename == 'course_sections') {
return new \moodle_url('/course/editsection.php', ['id' => $componentinfo->itemid]);
} else if ($componentinfo->tablename == 'course_categories') {
return new \moodle_url('/course/editcategory.php', ['id' => $componentinfo->itemid]);
} else {
return new \moodle_url('/course/edit.php', ['id' => $componentinfo->courseid]);
}
}
}
@@ -0,0 +1,92 @@
<?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 tool_brickfield\local\areas\core_course;
use core\event\course_category_created;
use core\event\course_category_updated;
use tool_brickfield\area_base;
/**
* Base class for all areas that represent a field from the course_categories table (such as 'intro' or 'name')
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
abstract class category_base extends area_base {
/**
* Find recordset of the relevant areas.
* @param \core\event\base $event
* @return \moodle_recordset|null
* @throws \dml_exception
*/
public function find_relevant_areas(\core\event\base $event): ?\moodle_recordset {
if ($event instanceof course_category_updated || $event instanceof course_category_created) {
return $this->find_fields_in_course_categories_table(['itemid' => $event->objectid]);
}
return null;
}
/**
* Find recordset of the course areas.
* @param int $courseid
* @return \moodle_recordset|null
*/
public function find_course_areas(int $courseid): ?\moodle_recordset {
return null;
}
/**
* Return an array of area objects that contain content at the site and system levels only. All category content is considered
* system level.
* @return mixed
*/
public function find_system_areas(): ?\moodle_recordset {
return $this->find_fields_in_course_categories_table();
}
/**
* Helper method that can be used by the classes that define a field in the respective module table
*
* @param array $params
* @return \moodle_recordset
* @throws \dml_exception
*/
protected function find_fields_in_course_categories_table(array $params = []): \moodle_recordset {
global $DB;
$where = [];
if (!empty($params['itemid'])) {
$where[] = 't.id = :itemid';
}
$rs = $DB->get_recordset_sql('SELECT
' . $this->get_type() . ' AS type,
ctx.id AS contextid,
' . $this->get_standard_area_fields_sql() . '
t.id AS itemid,
t.id AS categoryid,
t.'.$this->get_fieldname().' AS content
FROM {'.$this->get_tablename().'} t
JOIN {context} ctx ON ctx.instanceid = t.id AND ctx.contextlevel = :pctxlevelcategory '.
($where ? 'WHERE ' . join(' AND ', $where) : '') . '
ORDER BY t.id',
['pctxlevelcategory' => CONTEXT_COURSECAT] + $params);
return $rs;
}
}
@@ -0,0 +1,43 @@
<?php
// This file is part of the Query submission plugin
//
// 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 tool_brickfield\local\areas\core_course;
/**
* Category description observer.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class category_description extends category_base {
/**
* Get table name.
* @return string
*/
public function get_tablename(): string {
return 'course_categories';
}
/**
* Get field name.
* @return string
*/
public function get_fieldname(): string {
return 'description';
}
}
@@ -0,0 +1,43 @@
<?php
// This file is part of the Query submission plugin
//
// 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 tool_brickfield\local\areas\core_course;
/**
* Category name observer.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class category_name extends category_base {
/**
* Get table name.
* @return string
*/
public function get_tablename(): string {
return 'course_categories';
}
/**
* Get field name.
* @return string
*/
public function get_fieldname(): string {
return 'name';
}
}
@@ -0,0 +1,43 @@
<?php
// This file is part of the Query submission plugin
//
// 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 tool_brickfield\local\areas\core_course;
/**
* Course full name observer.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class fullname extends base {
/**
* Get table name.
* @return string
*/
public function get_tablename(): string {
return 'course';
}
/**
* Get field name.
* @return string
*/
public function get_fieldname(): string {
return 'fullname';
}
}
@@ -0,0 +1,126 @@
<?php
// This file is part of the Query submission plugin
//
// 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 tool_brickfield\local\areas\core_course;
use core\event\course_section_created;
use core\event\course_section_updated;
use tool_brickfield\area_base;
/**
* Course section name observer.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class sectionname extends area_base {
/**
* Get table name.
* @return string
*/
public function get_tablename(): string {
return 'course_sections';
}
/**
* Get field name.
* @return string
*/
public function get_fieldname(): string {
return 'name';
}
/**
* Get table name reference.
* @return string
*/
public function get_ref_tablename(): string {
return 'course';
}
/**
* Find recordset of the relevant areas.
* @param \core\event\base $event
* @return \moodle_recordset|null
* @throws \coding_exception
* @throws \dml_exception
*/
public function find_relevant_areas(\core\event\base $event): ?\moodle_recordset {
if ($event instanceof course_section_created) {
return $this->find_fields_in_course_sections_table(['courseid' => $event->courseid, 'sectionid' => $event->objectid]);
} else if ($event instanceof course_section_updated) {
return $this->find_fields_in_course_sections_table(['courseid' => $event->courseid, 'sectionid' => $event->objectid]);
}
return null;
}
/**
* Find recordset of the course areas.
* @param int $courseid
* @return \moodle_recordset
* @throws \coding_exception
* @throws \dml_exception
*/
public function find_course_areas(int $courseid): ?\moodle_recordset {
return $this->find_fields_in_course_sections_table(['courseid' => $courseid]);
}
/**
* Helper method that can be used by the classes that define a field in the 'course_sections' table
*
* @param array $params
* @return \moodle_recordset
* @throws \coding_exception
* @throws \dml_exception
*/
protected function find_fields_in_course_sections_table(array $params = []): \moodle_recordset {
global $DB;
$where = [];
if (!empty($params['courseid'])) {
$where[] = 't.course = :courseid';
}
if (!empty($params['sectionid'])) {
$where[] = 't.id = :sectionid';
}
// Filter against approved / non-approved course category listings.
$this->filterfieldname = 'co.id';
$this->get_courseid_filtering();
if ($this->filter != '') {
$params = $params + $this->filterparams;
}
$rs = $DB->get_recordset_sql('SELECT
' . $this->get_type() . ' AS type,
ctx.id AS contextid,
' . $this->get_standard_area_fields_sql() . '
t.id AS itemid,
' . $this->get_reftable_field_sql() . '
t.course AS refid,
t.course AS courseid,
t.'.$this->get_fieldname().' AS content
FROM {'.$this->get_tablename().'} t
JOIN {course} co ON co.id = t.course
JOIN {context} ctx ON ctx.instanceid = co.id AND ctx.contextlevel = :pctxlevelcourse '.
($where ? 'WHERE ' . join(' AND ', $where) : '') . $this->filter . '
ORDER BY t.course',
['pctxlevelcourse' => CONTEXT_COURSE] + $params);
return $rs;
}
}
@@ -0,0 +1,126 @@
<?php
// This file is part of the Query submission plugin
//
// 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 tool_brickfield\local\areas\core_course;
use core\event\course_section_created;
use core\event\course_section_updated;
use tool_brickfield\area_base;
/**
* Course section summary observer.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class sectionsummary extends area_base {
/**
* Get table name.
* @return string
*/
public function get_tablename(): string {
return 'course_sections';
}
/**
* Get field name.
* @return string
*/
public function get_fieldname(): string {
return 'summary';
}
/**
* Get table name reference.
* @return string
*/
public function get_ref_tablename(): string {
return 'course';
}
/**
* Find recordset of the relevant areas.
* @param \core\event\base $event
* @return \moodle_recordset|null
* @throws \coding_exception
* @throws \dml_exception
*/
public function find_relevant_areas(\core\event\base $event): ?\moodle_recordset {
if ($event instanceof course_section_created) {
return $this->find_fields_in_course_sections_table(['courseid' => $event->courseid, 'sectionid' => $event->objectid]);
} else if ($event instanceof course_section_updated) {
return $this->find_fields_in_course_sections_table(['courseid' => $event->courseid, 'sectionid' => $event->objectid]);
}
return null;
}
/**
* Find recordset of the course areas.
* @param int $courseid
* @return \moodle_recordset
* @throws \coding_exception
* @throws \dml_exception
*/
public function find_course_areas(int $courseid): ?\moodle_recordset {
return $this->find_fields_in_course_sections_table(['courseid' => $courseid]);
}
/**
* Helper method that can be used by the classes that define a field in the 'course_sections' table
*
* @param array $params
* @return \moodle_recordset
* @throws \coding_exception
* @throws \dml_exception
*/
protected function find_fields_in_course_sections_table(array $params = []): \moodle_recordset {
global $DB;
$where = [];
if (!empty($params['courseid'])) {
$where[] = 't.course = :courseid';
}
if (!empty($params['sectionid'])) {
$where[] = 't.id = :sectionid';
}
// Filter against approved / non-approved course category listings.
$this->filterfieldname = 'co.id';
$this->get_courseid_filtering();
if ($this->filter != '') {
$params = $params + $this->filterparams;
}
$rs = $DB->get_recordset_sql('SELECT
' . $this->get_type() . ' AS type,
ctx.id AS contextid,
' . $this->get_standard_area_fields_sql() . '
t.id AS itemid,
' . $this->get_reftable_field_sql() . '
t.course AS refid,
t.course AS courseid,
t.'.$this->get_fieldname().' AS content
FROM {'.$this->get_tablename().'} t
JOIN {course} co ON co.id = t.course
JOIN {context} ctx ON ctx.instanceid = co.id AND ctx.contextlevel = :pctxlevelcourse '.
($where ? 'WHERE ' . join(' AND ', $where) : '') . $this->filter . '
ORDER BY t.section',
['pctxlevelcourse' => CONTEXT_COURSE] + $params);
return $rs;
}
}
@@ -0,0 +1,43 @@
<?php
// This file is part of the Query submission plugin
//
// 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 tool_brickfield\local\areas\core_course;
/**
* Course shortname observer.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class shortname extends base {
/**
* Get table name.
* @return string
*/
public function get_tablename(): string {
return 'course';
}
/**
* Get field name.
* @return string
*/
public function get_fieldname(): string {
return 'shortname';
}
}
@@ -0,0 +1,43 @@
<?php
// This file is part of the Query submission plugin
//
// 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 tool_brickfield\local\areas\core_course;
/**
* Course summary observer.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class summary extends base {
/**
* Get table name.
* @return string
*/
public function get_tablename(): string {
return 'course';
}
/**
* Get field name.
* @return string
*/
public function get_fieldname(): string {
return 'summary';
}
}
@@ -0,0 +1,169 @@
<?php
// This file is part of the Query submission plugin
//
// 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 tool_brickfield\local\areas\core_question;
use core\event\question_created;
use core\event\question_updated;
/**
* Base class for various question-related areas.
*
* This is an abstract class so it will be skipped by manager when it finds all areas.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
abstract class answerbase extends base {
/**
* Get table name reference.
*
* @return string
*/
public function get_ref_tablename(): string {
return 'question';
}
/**
* Find recordset of the relevant areas.
*
* @param \core\event\base $event
* @return \moodle_recordset|null
*/
public function find_relevant_areas(\core\event\base $event): ?\moodle_recordset {
global $DB;
if (($event instanceof question_created) || ($event instanceof question_updated)) {
$sql = "SELECT {$this->get_type()} AS type,
ctx.id AS contextid,
{$this->get_standard_area_fields_sql()}
a.id AS itemid,
{$this->get_reftable_field_sql()}
q.id AS refid,
{$this->get_course_and_cat_sql($event)}
a.{$this->get_fieldname()} AS content
FROM {question} q
INNER JOIN {question_answers} a
ON a.question = q.id
INNER JOIN {question_versions} qv
ON qv.questionid = q.id
INNER JOIN {question_bank_entries} qbe
ON qbe.id = qv.questionbankentryid
INNER JOIN {question_categories} qc
ON qc.id = qbe.questioncategoryid
INNER JOIN {context} ctx
ON ctx.id = qc.contextid
WHERE (q.id = :refid)
ORDER BY a.id";
$rs = $DB->get_recordset_sql($sql, ['refid' => $event->objectid]);
return $rs;
}
return null;
}
/**
* Return an array of area objects that contain content at the site and system levels only. This would be question content from
* question categories at the system context, or course category context.
*
* @return mixed
*/
public function find_system_areas(): ?\moodle_recordset {
global $DB;
$params = [
'syscontext' => CONTEXT_SYSTEM,
'coursecat' => CONTEXT_COURSECAT,
'coursecat2' => CONTEXT_COURSECAT,
];
$sql = "SELECT {$this->get_type()} AS type,
qc.contextid AS contextid,
{$this->get_standard_area_fields_sql()}
a.id AS itemid,
{$this->get_reftable_field_sql()}
q.id AS refid,
" . SITEID . " as courseid,
cc.id as categoryid,
a.{$this->get_fieldname()} AS content
FROM {question} q
INNER JOIN {question_answers} a
ON a.question = q.id
INNER JOIN {question_versions} qv
ON qv.questionid = q.id
INNER JOIN {question_bank_entries} qbe
ON qbe.id = qv.questionbankentryid
INNER JOIN {question_categories} qc
ON qc.id = qbe.questioncategoryid
INNER JOIN {context} ctx
ON ctx.id = qc.contextid
LEFT JOIN {course_categories} cc
ON cc.id = ctx.instanceid
AND ctx.contextlevel = :coursecat
WHERE (ctx.contextlevel = :syscontext)
OR (ctx.contextlevel = :coursecat2)
ORDER BY a.id";
return $DB->get_recordset_sql($sql, $params);
}
/**
* Find recordset of the course areas.
*
* @param int $courseid
* @return \moodle_recordset
*/
public function find_course_areas(int $courseid): ?\moodle_recordset {
global $DB;
$coursecontext = \context_course::instance($courseid);
$param = [
'ctxcourse' => CONTEXT_COURSE,
'courseid' => $courseid,
'module' => CONTEXT_MODULE,
'coursecontextpath' => $DB->sql_like_escape($coursecontext->path) . '/%',
];
$sql = "SELECT {$this->get_type()} AS type,
ctx.id AS contextid,
{$this->get_standard_area_fields_sql()}
a.id AS itemid,
{$this->get_reftable_field_sql()}
q.id AS refid,
{$courseid} AS courseid,
a.{$this->get_fieldname()} AS content
FROM {question} q
INNER JOIN {question_answers} a
ON a.question = q.id
INNER JOIN {question_versions} qv
ON qv.questionid = q.id
INNER JOIN {question_bank_entries} qbe
ON qbe.id = qv.questionbankentryid
INNER JOIN {question_categories} qc
ON qc.id = qbe.questioncategoryid
INNER JOIN {context} ctx
ON ctx.id = qc.contextid
WHERE (ctx.contextlevel = :ctxcourse
AND ctx.id = qc.contextid
AND ctx.instanceid = :courseid)
OR (ctx.contextlevel = :module
AND {$DB->sql_like('ctx.path', ':coursecontextpath')})
ORDER BY a.id ASC";
return $DB->get_recordset_sql($sql, $param);
}
}
@@ -0,0 +1,227 @@
<?php
// This file is part of the Query submission plugin
//
// 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 tool_brickfield\local\areas\core_question;
use core\event\question_created;
use core\event\question_updated;
use tool_brickfield\area_base;
/**
* Base class for various question-related areas.
*
* This is an abstract class so it will be skipped by manager when it finds all areas
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
abstract class base extends area_base {
/**
* Find recordset of the relevant areas.
*
* @param \core\event\base $event
* @return \moodle_recordset|null
*/
public function find_relevant_areas(\core\event\base $event): ?\moodle_recordset {
global $DB;
if (($event instanceof question_created) || ($event instanceof question_updated)) {
$sql = "SELECT {$this->get_type()} AS type,
ctx.id AS contextid,
{$this->get_standard_area_fields_sql()}
q.id AS itemid,
{$this->get_course_and_cat_sql($event)}
q.{$this->get_fieldname()} AS content
FROM {question} q
INNER JOIN {question_versions} qv
ON qv.questionid = q.id
INNER JOIN {question_bank_entries} qbe
ON qbe.id = qv.questionbankentryid
INNER JOIN {question_categories} qc
ON qc.id = qbe.questioncategoryid
INNER JOIN {context} ctx
ON ctx.id = qc.contextid
WHERE (q.id = :refid)
ORDER BY q.id";
$rs = $DB->get_recordset_sql($sql, ['refid' => $event->objectid]);
return $rs;
}
return null;
}
/**
* Find recordset of the course areas.
*
* @param int $courseid
* @return \moodle_recordset
*/
public function find_course_areas(int $courseid): ?\moodle_recordset {
global $DB;
$coursecontext = \context_course::instance($courseid);
$param = [
'ctxcourse' => CONTEXT_COURSE,
'courseid' => $courseid,
'module' => CONTEXT_MODULE,
'coursecontextpath' => $DB->sql_like_escape($coursecontext->path) . '/%',
];
$sql = "SELECT {$this->get_type()} AS type,
ctx.id AS contextid,
{$this->get_standard_area_fields_sql()}
q.id AS itemid,
{$courseid} AS courseid,
null AS categoryid,
q.{$this->get_fieldname()} AS content
FROM {question} q
INNER JOIN {question_versions} qv
ON qv.questionid = q.id
INNER JOIN {question_bank_entries} qbe
ON qbe.id = qv.questionbankentryid
INNER JOIN {question_categories} qc
ON qc.id = qbe.questioncategoryid
INNER JOIN {context} ctx
ON ctx.id = qc.contextid
WHERE (ctx.contextlevel = :ctxcourse
AND ctx.id = qc.contextid
AND ctx.instanceid = :courseid)
OR (ctx.contextlevel = :module
AND {$DB->sql_like('ctx.path', ':coursecontextpath')})
ORDER BY q.id ASC";
return $DB->get_recordset_sql($sql, $param);
}
/**
* Return an array of area objects that contain content at the site and system levels only. This would be question content from
* question categories at the system context only.
*
* @return \moodle_recordset
*/
public function find_system_areas(): ?\moodle_recordset {
global $DB;
$params = [
'syscontext' => CONTEXT_SYSTEM,
'coursecat' => CONTEXT_COURSECAT,
'coursecat2' => CONTEXT_COURSECAT,
];
$sql = "SELECT {$this->get_type()} AS type,
qc.contextid AS contextid,
{$this->get_standard_area_fields_sql()}
q.id AS itemid,
" . SITEID . " as courseid,
cc.id as categoryid,
q.{$this->get_fieldname()} AS content
FROM {question} q
INNER JOIN {question_versions} qv
ON qv.questionid = q.id
INNER JOIN {question_bank_entries} qbe
ON qbe.id = qv.questionbankentryid
INNER JOIN {question_categories} qc
ON qc.id = qbe.questioncategoryid
INNER JOIN {context} ctx
ON ctx.id = qc.contextid
LEFT JOIN {course_categories} cc
ON cc.id = ctx.instanceid
AND ctx.contextlevel = :coursecat
WHERE (ctx.contextlevel = :syscontext)
OR (ctx.contextlevel = :coursecat2)
ORDER BY q.id";
return $DB->get_recordset_sql($sql, $params);
}
/**
* Returns the moodle_url of the page to edit the error.
*
* @param \stdClass $componentinfo
* @return \moodle_url
*/
public static function get_edit_url(\stdClass $componentinfo): \moodle_url {
$questionid = $componentinfo->itemid;
// Question answers are editable on main question page.
// Hence, use refid for these links.
if ($componentinfo->tablename === 'question_answers') {
$questionid = $componentinfo->refid;
}
// Default to SITEID if courseid is null, i.e. system or category level questions.
$thiscourseid = ($componentinfo->courseid !== null) ? $componentinfo->courseid : SITEID;
return new \moodle_url('/question/bank/editquestion/question.php', ['courseid' => $thiscourseid, 'id' => $questionid]);
}
/**
* Determine the course and category id SQL depending on the specific context associated with question data.
*
* @param \core\event\base $event
* @return string
*/
protected function get_course_and_cat_sql(\core\event\base $event): string {
$courseid = 'null';
$catid = 'null';
if ($record = self::get_course_and_category(CONTEXT_MODULE, $event->objectid)) {
if ($record->contextlevel == CONTEXT_MODULE) {
$courseid = $record->courseid;
} else if ($record->contextlevel == CONTEXT_COURSE) {
$courseid = $record->instanceid;
} else if ($record->contextlevel == CONTEXT_COURSECAT) {
$catid = $record->instanceid;
} else if ($record->contextlevel == CONTEXT_SYSTEM) {
$courseid = 1;
}
}
return "
{$courseid} AS courseid,
{$catid} AS categoryid,
";
}
/**
* Get the course and category data for the question.
*
* @param int $coursemodule
* @param int $refid
* @return \stdClass|false
*/
public static function get_course_and_category($coursemodule, $refid) {
global $DB;
$sql = 'SELECT ctx.instanceid,
cm.course as courseid,
ctx.contextlevel
FROM {question} q
INNER JOIN {question_versions} qv
ON qv.questionid = q.id
INNER JOIN {question_bank_entries} qbe
ON qbe.id = qv.questionbankentryid
INNER JOIN {question_categories} qc
ON qc.id = qbe.questioncategoryid
INNER JOIN {context} ctx
ON ctx.id = qc.contextid
LEFT JOIN {course_modules} cm
ON cm.id = ctx.instanceid
AND ctx.contextlevel = :coursemodule
WHERE q.id = :refid';
$params = [
'coursemodule' => $coursemodule,
'refid' => $refid
];
return $DB->get_record_sql($sql, $params);
}
}
@@ -0,0 +1,43 @@
<?php
// This file is part of the Query submission plugin
//
// 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 tool_brickfield\local\areas\core_question;
/**
* Question generalfeedback observer.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class generalfeedback extends base {
/**
* Get table name.
* @return string
*/
public function get_tablename(): string {
return 'question';
}
/**
* Get field name.
* @return string
*/
public function get_fieldname(): string {
return 'generalfeedback';
}
}
@@ -0,0 +1,43 @@
<?php
// This file is part of the Query submission plugin
//
// 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 tool_brickfield\local\areas\core_question;
/**
* Question answers observer.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class questionanswers extends answerbase {
/**
* Get table name.
* @return string
*/
public function get_tablename(): string {
return 'question_answers';
}
/**
* Get field name.
* @return string
*/
public function get_fieldname(): string {
return 'answer';
}
}
@@ -0,0 +1,43 @@
<?php
// This file is part of the Query submission plugin
//
// 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 tool_brickfield\local\areas\core_question;
/**
* Question feedback observer.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class questionfeedback extends answerbase {
/**
* Get table name.
* @return string
*/
public function get_tablename(): string {
return 'question_answers';
}
/**
* Get field name.
* @return string
*/
public function get_fieldname(): string {
return 'feedback';
}
}
@@ -0,0 +1,43 @@
<?php
// This file is part of the Query submission plugin
//
// 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 tool_brickfield\local\areas\core_question;
/**
* Question name observer.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class questionname extends base {
/**
* Get table name.
* @return string
*/
public function get_tablename(): string {
return 'question';
}
/**
* Get field name.
* @return string
*/
public function get_fieldname(): string {
return 'name';
}
}
@@ -0,0 +1,43 @@
<?php
// This file is part of the Query submission plugin
//
// 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 tool_brickfield\local\areas\core_question;
/**
* Question text observer.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class questiontext extends base {
/**
* Get table name.
* @return string
*/
public function get_tablename(): string {
return 'question';
}
/**
* Get field name.
* @return string
*/
public function get_fieldname(): string {
return 'questiontext';
}
}
@@ -0,0 +1,45 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace tool_brickfield\local\areas\mod_assign;
use tool_brickfield\local\areas\module_area_base;
/**
* Assignment intro observer.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class intro extends module_area_base {
/**
* Get table name.
* @return string
*/
public function get_tablename(): string {
return 'assign';
}
/**
* Get field name.
* @return string
*/
public function get_fieldname(): string {
return 'intro';
}
}
@@ -0,0 +1,45 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace tool_brickfield\local\areas\mod_assign;
use tool_brickfield\local\areas\module_area_base;
/**
* Assignment name observer.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class name extends module_area_base {
/**
* Get table name.
* @return string
*/
public function get_tablename(): string {
return 'assign';
}
/**
* Get field name.
* @return string
*/
public function get_fieldname(): string {
return 'name';
}
}
@@ -0,0 +1,42 @@
<?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 tool_brickfield\local\areas\mod_book;
use tool_brickfield\local\areas\module_area_base;
/**
* Book base observer.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
abstract class base extends module_area_base {
/**
* Returns the moodle_url of the page to edit the error.
* @param \stdClass $componentinfo
* @return \moodle_url
*/
public static function get_edit_url(\stdClass $componentinfo): \moodle_url {
if (!empty($componentinfo->refid)) {
return new \moodle_url('/mod/book/edit.php',
['cmid' => $componentinfo->cmid, 'id' => $componentinfo->itemid, 'sesskey' => sesskey()]);
} else {
return parent::get_edit_url($componentinfo);
}
}
}
@@ -0,0 +1,128 @@
<?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 tool_brickfield\local\areas\mod_book;
use tool_brickfield\area_base;
/**
* Book chapter content observer.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class chaptercontent extends area_base {
/**
* Get table name.
* @return string
*/
public function get_tablename(): string {
return 'book_chapters';
}
/**
* Get field name.
* @return string
*/
public function get_fieldname(): string {
return 'content';
}
/**
* Get table name reference.
* @return string
*/
public function get_ref_tablename(): string {
return 'book';
}
/**
* Find recordset of the relevant areas.
* @param \core\event\base $event
* @return \moodle_recordset|null
* @throws \coding_exception
* @throws \dml_exception
*/
public function find_relevant_areas(\core\event\base $event): ?\moodle_recordset {
if ($event->eventname == '\mod_book\event\chapter_updated' || $event->eventname == '\mod_book\event\chapter_created') {
return $this->find_areas(['contextid' => $event->contextid, 'objectid' => $event->objectid]);
}
return null;
}
/**
* Find recordset of the course areas.
* @param int $courseid
* @return \moodle_recordset
* @throws \coding_exception
* @throws \dml_exception
*/
public function find_course_areas(int $courseid): ?\moodle_recordset {
return $this->find_areas(['courseid' => $courseid]);
}
/**
* Find recordset of areas.
* @param array $params
* @return \moodle_recordset
* @throws \coding_exception
* @throws \dml_exception
*/
protected function find_areas(array $params = []): \moodle_recordset {
global $DB;
$where = [];
if (!empty($params['contextid'])) {
$where[] = 'ctx.id = :contextid';
$where[] = 'co.id = :objectid';
}
if (!empty($params['courseid'])) {
$where[] = 'cm.course = :courseid';
}
// Filter against approved / non-approved course category listings.
$this->filterfieldname = 'cm.course';
$this->get_courseid_filtering();
if ($this->filter != '') {
$params = $params + $this->filterparams;
}
$rs = $DB->get_recordset_sql('SELECT
' . $this->get_type() . ' AS type,
ctx.id AS contextid,
' . $this->get_standard_area_fields_sql() . '
co.id AS itemid,
' . $this->get_reftable_field_sql() . '
t.id AS refid,
cm.id AS cmid,
cm.course AS courseid,
co.'.$this->get_fieldname().' AS content
FROM {book} t
JOIN {course_modules} cm ON cm.instance = t.id
JOIN {modules} m ON m.id = cm.module AND m.name = :preftablename2
JOIN {context} ctx ON ctx.instanceid = cm.id AND ctx.contextlevel = :pctxlevelmodule
JOIN {'.$this->get_tablename().'} co ON co.bookid = t.id ' .
($where ? 'WHERE ' . join(' AND ', $where) : '') . $this->filter . '
ORDER BY t.id, co.id',
['pctxlevelmodule' => CONTEXT_MODULE,
'preftablename2' => $this->get_ref_tablename(),
] + $params);
return $rs;
}
}
@@ -0,0 +1,128 @@
<?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 tool_brickfield\local\areas\mod_book;
use tool_brickfield\area_base;
/**
* Book chapter title observer.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class chaptertitle extends area_base {
/**
* Get table name.
* @return string
*/
public function get_tablename(): string {
return 'book_chapters';
}
/**
* Get field name.
* @return string
*/
public function get_fieldname(): string {
return 'title';
}
/**
* Get table name reference.
* @return string
*/
public function get_ref_tablename(): string {
return 'book';
}
/**
* Find recordset of the relevant areas.
* @param \core\event\base $event
* @return \moodle_recordset|null
* @throws \coding_exception
* @throws \dml_exception
*/
public function find_relevant_areas(\core\event\base $event): ?\moodle_recordset {
if ($event->eventname == '\mod_book\event\chapter_updated' || $event->eventname == '\mod_book\event\chapter_created') {
return $this->find_areas(['contextid' => $event->contextid, 'objectid' => $event->objectid]);
}
return null;
}
/**
* Find recordset of the course areas.
* @param int $courseid
* @return \moodle_recordset
* @throws \coding_exception
* @throws \dml_exception
*/
public function find_course_areas(int $courseid): ?\moodle_recordset {
return $this->find_areas(['courseid' => $courseid]);
}
/**
* Find recordset of areas.
* @param array $params
* @return \moodle_recordset
* @throws \coding_exception
* @throws \dml_exception
*/
protected function find_areas(array $params = []): \moodle_recordset {
global $DB;
$where = [];
if (!empty($params['contextid'])) {
$where[] = 'ctx.id = :contextid';
$where[] = 'co.id = :objectid';
}
if (!empty($params['courseid'])) {
$where[] = 'cm.course = :courseid';
}
// Filter against approved / non-approved course category listings.
$this->filterfieldname = 'cm.course';
$this->get_courseid_filtering();
if ($this->filter != '') {
$params = $params + $this->filterparams;
}
$rs = $DB->get_recordset_sql('SELECT
' . $this->get_type() . ' AS type,
ctx.id AS contextid,
' . $this->get_standard_area_fields_sql() . '
co.id AS itemid,
' . $this->get_reftable_field_sql() . '
t.id AS refid,
cm.id AS cmid,
cm.course AS courseid,
co.'.$this->get_fieldname().' AS content
FROM {book} t
JOIN {course_modules} cm ON cm.instance = t.id
JOIN {modules} m ON m.id = cm.module AND m.name = :preftablename2
JOIN {context} ctx ON ctx.instanceid = cm.id AND ctx.contextlevel = :pctxlevelmodule
JOIN {'.$this->get_tablename().'} co ON co.bookid = t.id ' .
($where ? 'WHERE ' . join(' AND ', $where) : '') . $this->filter . '
ORDER BY t.id, co.id',
['pctxlevelmodule' => CONTEXT_MODULE,
'preftablename2' => $this->get_ref_tablename(),
] + $params);
return $rs;
}
}
@@ -0,0 +1,45 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace tool_brickfield\local\areas\mod_book;
use tool_brickfield\local\areas\module_area_base;
/**
* Book intro observer.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class intro extends base {
/**
* Get table name.
* @return string
*/
public function get_tablename(): string {
return 'book';
}
/**
* Get field name.
* @return string
*/
public function get_fieldname(): string {
return 'intro';
}
}
@@ -0,0 +1,45 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace tool_brickfield\local\areas\mod_book;
use tool_brickfield\local\areas\module_area_base;
/**
* Book name observer.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class name extends base {
/**
* Get table name.
* @return string
*/
public function get_tablename(): string {
return 'book';
}
/**
* Get field name.
* @return string
*/
public function get_fieldname(): string {
return 'name';
}
}
@@ -0,0 +1,45 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace tool_brickfield\local\areas\mod_chat;
use tool_brickfield\local\areas\module_area_base;
/**
* Chat intro observer.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class intro extends module_area_base {
/**
* Get table name.
* @return string
*/
public function get_tablename(): string {
return 'chat';
}
/**
* Get field name.
* @return string
*/
public function get_fieldname(): string {
return 'intro';
}
}
@@ -0,0 +1,45 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace tool_brickfield\local\areas\mod_chat;
use tool_brickfield\local\areas\module_area_base;
/**
* Chat name observer.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class name extends module_area_base {
/**
* Get table name.
* @return string
*/
public function get_tablename(): string {
return 'chat';
}
/**
* Get field name.
* @return string
*/
public function get_fieldname(): string {
return 'name';
}
}
@@ -0,0 +1,45 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace tool_brickfield\local\areas\mod_choice;
use tool_brickfield\local\areas\module_area_base;
/**
* Chat intro observer.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class intro extends module_area_base {
/**
* Get table name.
* @return string
*/
public function get_tablename(): string {
return 'choice';
}
/**
* Get field name.
* @return string
*/
public function get_fieldname(): string {
return 'intro';
}
}
@@ -0,0 +1,45 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace tool_brickfield\local\areas\mod_choice;
use tool_brickfield\local\areas\module_area_base;
/**
* Choice name observer.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class name extends module_area_base {
/**
* Get table name.
* @return string
*/
public function get_tablename(): string {
return 'choice';
}
/**
* Get field name.
* @return string
*/
public function get_fieldname(): string {
return 'name';
}
}
@@ -0,0 +1,131 @@
<?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 tool_brickfield\local\areas\mod_choice;
use core\event\course_module_created;
use core\event\course_module_updated;
use tool_brickfield\area_base;
/**
* Choice option observer.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class option extends area_base {
/**
* Get table name.
* @return string
*/
public function get_tablename(): string {
return 'choice_options';
}
/**
* Get field name.
* @return string
*/
public function get_fieldname(): string {
return 'text';
}
/**
* Get table name reference.
* @return string
*/
public function get_ref_tablename(): string {
return 'choice';
}
/**
* Find recordset of the relevant areas.
* @param \core\event\base $event
* @return \moodle_recordset|null
* @throws \coding_exception
* @throws \dml_exception
*/
public function find_relevant_areas(\core\event\base $event): ?\moodle_recordset {
if ($event instanceof course_module_updated || $event instanceof course_module_created) {
if ($event->other['modulename'] === 'choice') {
return $this->find_areas(['refid' => $event->other['instanceid']]);
}
}
return null;
}
/**
* Find recordset of the course areas.
* @param int $courseid
* @return \moodle_recordset
* @throws \coding_exception
* @throws \dml_exception
*/
public function find_course_areas(int $courseid): ?\moodle_recordset {
return $this->find_areas(['courseid' => $courseid]);
}
/**
* Find recordset of areas.
* @param array $params
* @return \moodle_recordset
* @throws \coding_exception
* @throws \dml_exception
*/
protected function find_areas(array $params = []): \moodle_recordset {
global $DB;
$where = [];
if (!empty($params['refid'])) {
$where[] = 't.id = :refid';
}
if (!empty($params['courseid'])) {
$where[] = 'cm.course = :courseid';
}
// Filter against approved / non-approved course category listings.
$this->filterfieldname = 'cm.course';
$this->get_courseid_filtering();
if ($this->filter != '') {
$params = $params + $this->filterparams;
}
$rs = $DB->get_recordset_sql('SELECT
' . $this->get_type() . ' AS type,
ctx.id AS contextid,
' . $this->get_standard_area_fields_sql() . '
co.id AS itemid,
' . $this->get_reftable_field_sql() . '
t.id AS refid,
cm.id AS cmid,
cm.course AS courseid,
co.'.$this->get_fieldname().' AS content
FROM {choice} t
JOIN {course_modules} cm ON cm.instance = t.id
JOIN {modules} m ON m.id = cm.module AND m.name = :preftablename2
JOIN {context} ctx ON ctx.instanceid = cm.id AND ctx.contextlevel = :pctxlevelmodule
JOIN {'.$this->get_tablename().'} co ON co.choiceid = t.id ' .
($where ? 'WHERE ' . join(' AND ', $where) : '') . $this->filter . '
ORDER BY t.id, co.id',
['pctxlevelmodule' => CONTEXT_MODULE,
'preftablename2' => $this->get_ref_tablename(),
] + $params);
return $rs;
}
}
@@ -0,0 +1,45 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace tool_brickfield\local\areas\mod_data;
use tool_brickfield\local\areas\module_area_base;
/**
* Data activity intro observer.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class intro extends module_area_base {
/**
* Get table name.
* @return string
*/
public function get_tablename(): string {
return 'data';
}
/**
* Get field name.
* @return string
*/
public function get_fieldname(): string {
return 'intro';
}
}
@@ -0,0 +1,45 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace tool_brickfield\local\areas\mod_data;
use tool_brickfield\local\areas\module_area_base;
/**
* Data activity name observer.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class name extends module_area_base {
/**
* Get table name.
* @return string
*/
public function get_tablename(): string {
return 'data';
}
/**
* Get field name.
* @return string
*/
public function get_fieldname(): string {
return 'name';
}
}
@@ -0,0 +1,45 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace tool_brickfield\local\areas\mod_feedback;
use tool_brickfield\local\areas\module_area_base;
/**
* Feedback activity intro observer.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class intro extends module_area_base {
/**
* Get table name.
* @return string
*/
public function get_tablename(): string {
return 'feedback';
}
/**
* Get field name.
* @return string
*/
public function get_fieldname(): string {
return 'intro';
}
}
@@ -0,0 +1,45 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace tool_brickfield\local\areas\mod_feedback;
use tool_brickfield\local\areas\module_area_base;
/**
* Feedback activity name observer.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class name extends module_area_base {
/**
* Get table name.
* @return string
*/
public function get_tablename(): string {
return 'feedback';
}
/**
* Get field name.
* @return string
*/
public function get_fieldname(): string {
return 'name';
}
}
@@ -0,0 +1,45 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace tool_brickfield\local\areas\mod_folder;
use tool_brickfield\local\areas\module_area_base;
/**
* Folder activity intro observer.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class intro extends module_area_base {
/**
* Get table name.
* @return string
*/
public function get_tablename(): string {
return 'folder';
}
/**
* Get field name.
* @return string
*/
public function get_fieldname(): string {
return 'intro';
}
}
@@ -0,0 +1,45 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace tool_brickfield\local\areas\mod_folder;
use tool_brickfield\local\areas\module_area_base;
/**
* Folder activity name observer.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class name extends module_area_base {
/**
* Get table name.
* @return string
*/
public function get_tablename(): string {
return 'folder';
}
/**
* Get field name.
* @return string
*/
public function get_fieldname(): string {
return 'name';
}
}
@@ -0,0 +1,45 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace tool_brickfield\local\areas\mod_forum;
use tool_brickfield\local\areas\module_area_base;
/**
* Forum activity intro observer.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class intro extends module_area_base {
/**
* Get table name.
* @return string
*/
public function get_tablename(): string {
return 'forum';
}
/**
* Get field name.
* @return string
*/
public function get_fieldname(): string {
return 'intro';
}
}
@@ -0,0 +1,45 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace tool_brickfield\local\areas\mod_forum;
use tool_brickfield\local\areas\module_area_base;
/**
* Forum activity name observer.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class name extends module_area_base {
/**
* Get table name.
* @return string
*/
public function get_tablename(): string {
return 'forum';
}
/**
* Get field name.
* @return string
*/
public function get_fieldname(): string {
return 'name';
}
}
@@ -0,0 +1,45 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace tool_brickfield\local\areas\mod_glossary;
use tool_brickfield\local\areas\module_area_base;
/**
* Glossary activity intro observer.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class intro extends module_area_base {
/**
* Get table name.
* @return string
*/
public function get_tablename(): string {
return 'glossary';
}
/**
* Get field name.
* @return string
*/
public function get_fieldname(): string {
return 'intro';
}
}
@@ -0,0 +1,45 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace tool_brickfield\local\areas\mod_glossary;
use tool_brickfield\local\areas\module_area_base;
/**
* Glossary activity name observer.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class name extends module_area_base {
/**
* Get table name.
* @return string
*/
public function get_tablename(): string {
return 'glossary';
}
/**
* Get field name.
* @return string
*/
public function get_fieldname(): string {
return 'name';
}
}
@@ -0,0 +1,45 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace tool_brickfield\local\areas\mod_imscp;
use tool_brickfield\local\areas\module_area_base;
/**
* IMSCP activity intro observer.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class intro extends module_area_base {
/**
* Get table name.
* @return string
*/
public function get_tablename(): string {
return 'imscp';
}
/**
* Get field name.
* @return string
*/
public function get_fieldname(): string {
return 'intro';
}
}
@@ -0,0 +1,45 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace tool_brickfield\local\areas\mod_imscp;
use tool_brickfield\local\areas\module_area_base;
/**
* IMSCP activity name observer.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class name extends module_area_base {
/**
* Get table name.
* @return string
*/
public function get_tablename(): string {
return 'imscp';
}
/**
* Get field name.
* @return string
*/
public function get_fieldname(): string {
return 'name';
}
}
@@ -0,0 +1,48 @@
<?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 tool_brickfield\local\areas\mod_label;
use tool_brickfield\local\areas\module_area_base;
/**
* Label activity intro observer.
*
* Although {label} has two fields, name and intro, name is a duplication of
* the intro content, therefore it is removed as an area location, to avoid duplicating errors.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class intro extends module_area_base {
/**
* Get table name.
* @return string
*/
public function get_tablename(): string {
return 'label';
}
/**
* Get field name.
* @return string
*/
public function get_fieldname(): string {
return 'intro';
}
}
@@ -0,0 +1,43 @@
<?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 tool_brickfield\local\areas\mod_lesson;
/**
* Lesson answer observer.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class answer_answer extends answer_base {
/**
* Get table name.
* @return string
*/
public function get_tablename(): string {
return 'lesson_answers';
}
/**
* Get field name.
* @return string
*/
public function get_fieldname(): string {
return 'answer';
}
}
@@ -0,0 +1,114 @@
<?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 tool_brickfield\local\areas\mod_lesson;
use tool_brickfield\area_base;
/**
* Lesson answer base.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
abstract class answer_base extends area_base {
/**
* Get table name reference.
* @return string
*/
public function get_ref_tablename(): string {
return 'lesson_pages';
}
/**
* Find recordset of the relevant areas.
* @param \core\event\base $event
* @return \moodle_recordset|null
* @throws \coding_exception
* @throws \dml_exception
*/
public function find_relevant_areas(\core\event\base $event): ?\moodle_recordset {
if ($event->eventname == '\mod_lesson\event\page_created' || $event->eventname == '\mod_lesson\event\page_updated') {
if ($event->component === 'mod_lesson') {
return $this->find_areas(['itemid' => $event->objectid]);
}
}
return null;
}
/**
* Find recordset of the course areas.
* @param int $courseid
* @return \moodle_recordset
* @throws \coding_exception
* @throws \dml_exception
*/
public function find_course_areas(int $courseid): ?\moodle_recordset {
return $this->find_areas(['courseid' => $courseid]);
}
/**
* Find recordset of areas.
* @param array $params
* @return \moodle_recordset
* @throws \coding_exception
* @throws \dml_exception
*/
protected function find_areas(array $params = []): \moodle_recordset {
global $DB;
$where = [];
if (!empty($params['itemid'])) {
$where[] = 'pa.id = :itemid';
}
if (!empty($params['courseid'])) {
$where[] = 'cm.course = :courseid';
}
// Filter against approved / non-approved course category listings.
$this->filterfieldname = 'cm.course';
$this->get_courseid_filtering();
if ($this->filter != '') {
$params = $params + $this->filterparams;
}
$rs = $DB->get_recordset_sql('SELECT
' . $this->get_type() . ' AS type,
ctx.id AS contextid,
' . $this->get_standard_area_fields_sql() . '
co.id AS itemid,
' . $this->get_reftable_field_sql() . '
pa.id AS refid,
cm.id AS cmid,
cm.course AS courseid,
co.'.$this->get_fieldname().' AS content
FROM {lesson} t
JOIN {course_modules} cm ON cm.instance = t.id
JOIN {modules} m ON m.id = cm.module AND m.name = :preftablename2
JOIN {context} ctx ON ctx.instanceid = cm.id AND ctx.contextlevel = :pctxlevelmodule
JOIN {lesson_pages} pa ON pa.lessonid = t.id
JOIN {'.$this->get_tablename().'} co ON co.lessonid = t.id AND co.pageid = pa.id ' .
($where ? 'WHERE ' . join(' AND ', $where) : '') . $this->filter . '
ORDER BY t.id, co.id',
['pctxlevelmodule' => CONTEXT_MODULE,
'preftablename2' => 'lesson',
] + $params);
return $rs;
}
}
@@ -0,0 +1,43 @@
<?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 tool_brickfield\local\areas\mod_lesson;
/**
* Lesson answer response observer.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class answer_response extends answer_base {
/**
* Get table name.
* @return string
*/
public function get_tablename(): string {
return 'lesson_answers';
}
/**
* Get field name.
* @return string
*/
public function get_fieldname(): string {
return 'response';
}
}
@@ -0,0 +1,43 @@
<?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 tool_brickfield\local\areas\mod_lesson;
use tool_brickfield\local\areas\module_area_base;
/**
* Lesson answer base.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
abstract class base extends module_area_base {
/**
* Returns the moodle_url of the page to edit the error.
* @param \stdClass $componentinfo
* @return \moodle_url
*/
public static function get_edit_url(\stdClass $componentinfo): \moodle_url {
if (!empty($componentinfo->refid)) {
$pageid = ($componentinfo->tablename == "lesson_answers") ? $componentinfo->refid : $componentinfo->itemid;
return new \moodle_url('/mod/lesson/editpage.php',
['id' => $componentinfo->cmid, 'pageid' => $pageid, 'edit' => 1, 'sesskey' => sesskey()]);
} else {
return parent::get_edit_url($componentinfo);
}
}
}
@@ -0,0 +1,45 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace tool_brickfield\local\areas\mod_lesson;
use tool_brickfield\local\areas\module_area_base;
/**
* Lesson intro observer.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class intro extends base {
/**
* Get table name.
* @return string
*/
public function get_tablename(): string {
return 'lesson';
}
/**
* Get field name.
* @return string
*/
public function get_fieldname(): string {
return 'intro';
}
}
@@ -0,0 +1,45 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace tool_brickfield\local\areas\mod_lesson;
use tool_brickfield\local\areas\module_area_base;
/**
* Lesson name observer.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class name extends base {
/**
* Get table name.
* @return string
*/
public function get_tablename(): string {
return 'lesson';
}
/**
* Get field name.
* @return string
*/
public function get_fieldname(): string {
return 'name';
}
}
@@ -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/>.
namespace tool_brickfield\local\areas\mod_lesson;
use tool_brickfield\area_base;
/**
* Lesson page base.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
abstract class page_base extends area_base {
/**
* Get table name reference.
* @return string
*/
public function get_ref_tablename(): string {
return 'lesson';
}
/**
* Find recordset of the relevant areas.
* @param \core\event\base $event
* @return \moodle_recordset|null
* @throws \coding_exception
* @throws \dml_exception
*/
public function find_relevant_areas(\core\event\base $event): ?\moodle_recordset {
if ($event->eventname == '\mod_lesson\event\page_created' || $event->eventname == '\mod_lesson\event\page_updated') {
if ($event->component === 'mod_lesson') {
return $this->find_areas(['itemid' => $event->objectid]);
}
}
return null;
}
/**
* Find recordset of the course areas.
* @param int $courseid
* @return \moodle_recordset
* @throws \coding_exception
* @throws \dml_exception
*/
public function find_course_areas(int $courseid): ?\moodle_recordset {
return $this->find_areas(['courseid' => $courseid]);
}
/**
* Find recordset of areas.
* @param array $params
* @return \moodle_recordset
* @throws \coding_exception
* @throws \dml_exception
*/
protected function find_areas(array $params = []): \moodle_recordset {
global $DB;
$where = [];
if (!empty($params['itemid'])) {
$where[] = 'co.id = :itemid';
}
if (!empty($params['courseid'])) {
$where[] = 'cm.course = :courseid';
}
// Filter against approved / non-approved course category listings.
$this->filterfieldname = 'cm.course';
$this->get_courseid_filtering();
if ($this->filter != '') {
$params = $params + $this->filterparams;
}
$rs = $DB->get_recordset_sql('SELECT
' . $this->get_type() . ' AS type,
ctx.id AS contextid,
' . $this->get_standard_area_fields_sql() . '
co.id AS itemid,
' . $this->get_reftable_field_sql() . '
t.id AS refid,
cm.id AS cmid,
cm.course AS courseid,
co.'.$this->get_fieldname().' AS content
FROM {lesson} t
JOIN {course_modules} cm ON cm.instance = t.id
JOIN {modules} m ON m.id = cm.module AND m.name = :preftablename2
JOIN {context} ctx ON ctx.instanceid = cm.id AND ctx.contextlevel = :pctxlevelmodule
JOIN {'.$this->get_tablename().'} co ON co.lessonid = t.id ' .
(!empty($where) ? 'WHERE ' . join(' AND ', $where) : '') . $this->filter . '
ORDER BY t.id, co.id',
['pctxlevelmodule' => CONTEXT_MODULE,
'preftablename2' => $this->get_ref_tablename(),
] + $params);
return $rs;
}
}
@@ -0,0 +1,43 @@
<?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 tool_brickfield\local\areas\mod_lesson;
/**
* Lesson page content observer.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class pagecontent extends page_base {
/**
* Get table name.
* @return string
*/
public function get_tablename(): string {
return 'lesson_pages';
}
/**
* Get field name.
* @return string
*/
public function get_fieldname(): string {
return 'contents';
}
}
@@ -0,0 +1,43 @@
<?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 tool_brickfield\local\areas\mod_lesson;
/**
* Lesson page title observer.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class pagetitle extends page_base {
/**
* Get table name.
* @return string
*/
public function get_tablename(): string {
return 'lesson_pages';
}
/**
* Get field name.
* @return string
*/
public function get_fieldname(): string {
return 'title';
}
}
@@ -0,0 +1,45 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace tool_brickfield\local\areas\mod_lti;
use tool_brickfield\local\areas\module_area_base;
/**
* LTI activity intro observer.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class intro extends module_area_base {
/**
* Get table name.
* @return string
*/
public function get_tablename(): string {
return 'lti';
}
/**
* Get field name.
* @return string
*/
public function get_fieldname(): string {
return 'intro';
}
}
@@ -0,0 +1,45 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace tool_brickfield\local\areas\mod_lti;
use tool_brickfield\local\areas\module_area_base;
/**
* LTI activity name observer.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class name extends module_area_base {
/**
* Get table name.
* @return string
*/
public function get_tablename(): string {
return 'lti';
}
/**
* Get field name.
* @return string
*/
public function get_fieldname(): string {
return 'name';
}
}
@@ -0,0 +1,45 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace tool_brickfield\local\areas\mod_page;
use tool_brickfield\local\areas\module_area_base;
/**
* Page activity content observer.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class content extends module_area_base {
/**
* Get table name.
* @return string
*/
public function get_tablename(): string {
return 'page';
}
/**
* Get field name.
* @return string
*/
public function get_fieldname(): string {
return 'content';
}
}
@@ -0,0 +1,45 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace tool_brickfield\local\areas\mod_page;
use tool_brickfield\local\areas\module_area_base;
/**
* Page activity intro observer.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class intro extends module_area_base {
/**
* Get table name.
* @return string
*/
public function get_tablename(): string {
return 'page';
}
/**
* Get field name.
* @return string
*/
public function get_fieldname(): string {
return 'intro';
}
}
@@ -0,0 +1,45 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace tool_brickfield\local\areas\mod_page;
use tool_brickfield\local\areas\module_area_base;
/**
* Page activity name observer.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class name extends module_area_base {
/**
* Get table name.
* @return string
*/
public function get_tablename(): string {
return 'page';
}
/**
* Get field name.
* @return string
*/
public function get_fieldname(): string {
return 'name';
}
}
@@ -0,0 +1,45 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace tool_brickfield\local\areas\mod_quiz;
use tool_brickfield\local\areas\module_area_base;
/**
* Quiz activity intro observer.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class intro extends module_area_base {
/**
* Get table name.
* @return string
*/
public function get_tablename(): string {
return 'quiz';
}
/**
* Get field name.
* @return string
*/
public function get_fieldname(): string {
return 'intro';
}
}
@@ -0,0 +1,45 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace tool_brickfield\local\areas\mod_quiz;
use tool_brickfield\local\areas\module_area_base;
/**
* Quiz activity name observer.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class name extends module_area_base {
/**
* Get table name.
* @return string
*/
public function get_tablename(): string {
return 'quiz';
}
/**
* Get field name.
* @return string
*/
public function get_fieldname(): string {
return 'name';
}
}
@@ -0,0 +1,45 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace tool_brickfield\local\areas\mod_resource;
use tool_brickfield\local\areas\module_area_base;
/**
* Resource activity intro observer.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class intro extends module_area_base {
/**
* Get table name.
* @return string
*/
public function get_tablename(): string {
return 'resource';
}
/**
* Get field name.
* @return string
*/
public function get_fieldname(): string {
return 'intro';
}
}
@@ -0,0 +1,45 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace tool_brickfield\local\areas\mod_resource;
use tool_brickfield\local\areas\module_area_base;
/**
* Resource activity name observer.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class name extends module_area_base {
/**
* Get table name.
* @return string
*/
public function get_tablename(): string {
return 'resource';
}
/**
* Get field name.
* @return string
*/
public function get_fieldname(): string {
return 'name';
}
}
@@ -0,0 +1,45 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace tool_brickfield\local\areas\mod_scorm;
use tool_brickfield\local\areas\module_area_base;
/**
* Scorm activity intro observer.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class intro extends module_area_base {
/**
* Get table name.
* @return string
*/
public function get_tablename(): string {
return 'scorm';
}
/**
* Get field name.
* @return string
*/
public function get_fieldname(): string {
return 'intro';
}
}
@@ -0,0 +1,45 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace tool_brickfield\local\areas\mod_scorm;
use tool_brickfield\local\areas\module_area_base;
/**
* Scorm activity name observer.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class name extends module_area_base {
/**
* Get table name.
* @return string
*/
public function get_tablename(): string {
return 'scorm';
}
/**
* Get field name.
* @return string
*/
public function get_fieldname(): string {
return 'name';
}
}
@@ -0,0 +1,45 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace tool_brickfield\local\areas\mod_survey;
use tool_brickfield\local\areas\module_area_base;
/**
* Survey activity intro observer.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class intro extends module_area_base {
/**
* Get table name.
* @return string
*/
public function get_tablename(): string {
return 'survey';
}
/**
* Get field name.
* @return string
*/
public function get_fieldname(): string {
return 'intro';
}
}
@@ -0,0 +1,45 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace tool_brickfield\local\areas\mod_survey;
use tool_brickfield\local\areas\module_area_base;
/**
* Survey activity name observer.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class name extends module_area_base {
/**
* Get table name.
* @return string
*/
public function get_tablename(): string {
return 'survey';
}
/**
* Get field name.
* @return string
*/
public function get_fieldname(): string {
return 'name';
}
}
@@ -0,0 +1,45 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace tool_brickfield\local\areas\mod_url;
use tool_brickfield\local\areas\module_area_base;
/**
* URL activity intro observer.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class intro extends module_area_base {
/**
* Get table name.
* @return string
*/
public function get_tablename(): string {
return 'url';
}
/**
* Get field name.
* @return string
*/
public function get_fieldname(): string {
return 'intro';
}
}
@@ -0,0 +1,45 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace tool_brickfield\local\areas\mod_url;
use tool_brickfield\local\areas\module_area_base;
/**
* URL activity name observer.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class name extends module_area_base {
/**
* Get table name.
* @return string
*/
public function get_tablename(): string {
return 'url';
}
/**
* Get field name.
* @return string
*/
public function get_fieldname(): string {
return 'name';
}
}
@@ -0,0 +1,45 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace tool_brickfield\local\areas\mod_wiki;
use tool_brickfield\local\areas\module_area_base;
/**
* Wiki activity intro observer.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class intro extends module_area_base {
/**
* Get table name.
* @return string
*/
public function get_tablename(): string {
return 'wiki';
}
/**
* Get field name.
* @return string
*/
public function get_fieldname(): string {
return 'intro';
}
}
@@ -0,0 +1,45 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace tool_brickfield\local\areas\mod_wiki;
use tool_brickfield\local\areas\module_area_base;
/**
* Wiki activity name observer.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class name extends module_area_base {
/**
* Get table name.
* @return string
*/
public function get_tablename(): string {
return 'wiki';
}
/**
* Get field name.
* @return string
*/
public function get_fieldname(): string {
return 'name';
}
}
@@ -0,0 +1,45 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace tool_brickfield\local\areas\mod_workshop;
use tool_brickfield\local\areas\module_area_base;
/**
* Workshop activity intro observer.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class intro extends module_area_base {
/**
* Get table name.
* @return string
*/
public function get_tablename(): string {
return 'workshop';
}
/**
* Get field name.
* @return string
*/
public function get_fieldname(): string {
return 'intro';
}
}
@@ -0,0 +1,45 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace tool_brickfield\local\areas\mod_workshop;
use tool_brickfield\local\areas\module_area_base;
/**
* Workshop activity name observer.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class name extends module_area_base {
/**
* Get table name.
* @return string
*/
public function get_tablename(): string {
return 'workshop';
}
/**
* Get field name.
* @return string
*/
public function get_fieldname(): string {
return 'name';
}
}
@@ -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/>.
namespace tool_brickfield\local\areas;
use core\event\course_module_created;
use core\event\course_module_updated;
use tool_brickfield\area_base;
/**
* Base class for all areas that represent a field from the module table (such as 'intro' or 'name')
*
* @package tool_brickfield
* @copyright 2020 Brickfield Education Labs https://www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
abstract class module_area_base extends area_base {
/**
* Find recordset of the relevant areas.
* @param \core\event\base $event
* @return \moodle_recordset|null
* @throws \coding_exception
* @throws \dml_exception
*/
public function find_relevant_areas(\core\event\base $event): ?\moodle_recordset {
if ($event instanceof course_module_updated || $event instanceof course_module_created) {
if ($event->other['modulename'] === $this->get_tablename()) {
return $this->find_fields_in_module_table(['itemid' => $event->other['instanceid']]);
}
}
return null;
}
/**
* Find recordset of the course areas.
* @param int $courseid
* @return \moodle_recordset
* @throws \coding_exception
* @throws \dml_exception
*/
public function find_course_areas(int $courseid): ?\moodle_recordset {
return $this->find_fields_in_module_table(['courseid' => $courseid]);
}
/**
* Helper method that can be used by the classes that define a field in the respective module table
*
* @param array $params
* @return \moodle_recordset
* @throws \coding_exception
* @throws \dml_exception
*/
protected function find_fields_in_module_table(array $params = []): \moodle_recordset {
global $DB;
$where = [];
if (!empty($params['itemid'])) {
$where[] = 't.id = :itemid';
}
if (!empty($params['courseid'])) {
$where[] = 'cm.course = :courseid';
}
// Filter against approved / non-approved course category listings.
$this->filterfieldname = 'cm.course';
$this->get_courseid_filtering();
if ($this->filter != '') {
$params = $params + $this->filterparams;
}
$rs = $DB->get_recordset_sql('SELECT
' . $this->get_type() . ' AS type,
ctx.id AS contextid,
' . $this->get_standard_area_fields_sql() . '
t.id AS itemid,
cm.id AS cmid,
cm.course AS courseid,
t.'.$this->get_fieldname().' AS content
FROM {'.$this->get_tablename().'} t
JOIN {course_modules} cm ON cm.instance = t.id
JOIN {modules} m ON m.id = cm.module AND m.name = :ptablename2
JOIN {context} ctx ON ctx.instanceid = cm.id AND ctx.contextlevel = :pctxlevelmodule '.
($where ? 'WHERE ' . join(' AND ', $where) : '') . $this->filter . '
ORDER BY t.id',
['pctxlevelmodule' => CONTEXT_MODULE,
'ptablename2' => $this->get_tablename(),
] + $params);
return $rs;
}
/**
* Returns the moodle_url of the page to edit the error.
* @param \stdClass $componentinfo
* @return \moodle_url
*/
public static function get_edit_url(\stdClass $componentinfo): \moodle_url {
return new \moodle_url('/course/mod.php', ['update' => $componentinfo->cmid, 'sr' => null, 'sesskey' => sesskey()]);
}
}
@@ -0,0 +1,436 @@
<?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 tool_brickfield\local\htmlchecker;
use DOMDocument;
use tool_brickfield\local\htmlchecker\common\brickfield_accessibility_css;
/**
* Brickfield accessibility HTML checker library.
*
* The main interface class for brickfield_accessibility.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class brickfield_accessibility {
/** @var int Failure level severe. */
const BA_TEST_SEVERE = 1;
/** @var int Failure level moderate. */
const BA_TEST_MODERATE = 2;
/** @var int Failure level seggestion. */
const BA_TEST_SUGGESTION = 3;
/** @var string Tag identifier to enclose all error HTML fragments in. */
const BA_ERROR_TAG = 'bferror';
/** @var object The central DOMDocument object */
public $dom;
/** @var string The type of request this is (either 'string', 'file', or 'uri' */
public $type;
/** @var string The value of the request. Either HTML, a URI, or the path to a file */
public $value;
/** @var string The base URI of the current request (used to rebuild page if necessary) */
public $uri = '';
/** @var string The translation domain of the current library */
public $domain;
/** @var string The name of the guideline */
public $guidelinename = 'wcag';
/** @var string The name of the reporter to use */
public $reportername = 'static';
/** @var object A reporting object */
public $reporter;
/** @var object The central guideline object */
public $guideline;
/** @var string The base URL for any request of type URI */
public $baseurl;
/** @var array An array of the current file or URI path */
public $path = [];
/** @var array An array of additional CSS files to load (useful for CMS content) */
public $cssfiles = [];
/** @var object The brickfieldCSS object */
public $css;
/** @var array An array of additional options */
public $options = [
'cms_mode' => false,
'start_element' => 0,
'end_element' => 0,
'cms_template' => []
];
/** @var bool An indicator if the DOMDocument loaded. If not, this means that the
* HTML given to it was so munged it wouldn't even load.
*/
public $isvalid = true;
/**
* The class constructor
* @param string $value Either the HTML string to check or the file/uri of the request
* @param string $guideline The name of the guideline
* @param string $type The type of the request (either file, uri, or string)
* @param string $reporter The name of the reporter to use
* @param string $domain The domain of the translation language to use
*/
public function __construct(string $value = '', string $guideline = 'wcag2aaa', string $type = 'string',
string $reporter = 'static', string $domain = 'en') {
$this->dom = new DOMDocument();
$this->type = $type;
if ($type == 'uri' || $type == 'file') {
$this->uri = $value;
}
$this->domain = $domain;
$this->guidelinename = $guideline;
$this->reportername = $reporter;
$this->value = $value;
}
/**
* Prepares the DOMDocument object for brickfield_accessibility. It loads based on the file type
* declaration and first scrubs the value using prepareValue().
*/
public function prepare_dom() {
$this->prepare_value();
$this->isvalid = @$this->dom->loadHTML('<?xml encoding="utf-8" ?>' . $this->value);
$this->prepare_base_url($this->value, $this->type);
}
/**
* If the CMS mode options are set, then we remove some items front the
* HTML value before sending it back.
*/
public function prepare_value() {
// We ignore the 'string' type because it would mean the value already contains HTML.
if ($this->type == 'file' || $this->type == 'uri') {
$this->value = @file_get_contents($this->value);
}
// If there are no surrounding tags, add self::BA_ERROR_TAG to prevent the DOM from adding a <p> tag.
if (strpos(trim($this->value), '<') !== 0) {
$this->value = '<' . self::BA_ERROR_TAG . '>' . $this->value . '</' . self::BA_ERROR_TAG . '>';
}
}
/**
* Set global predefined options for brickfield_accessibility. First we check that the
* array key has been defined.
* @param mixed $variable Either an array of values, or a variable name of the option
* @param mixed $value If this is a single option, the value of the option
*/
public function set_option($variable, $value = null) {
if (!is_array($variable)) {
$variable = [$variable => $value];
}
foreach ($variable as $k => $value) {
if (isset($this->options[$k])) {
$this->options[$k] = $value;
}
}
}
/**
* Returns an absolute path from a relative one.
* @param string $absolute The absolute URL
* @param string $relative The relative path
* @return string A new path
*/
public function get_absolute_path(string $absolute, string $relative): string {
if (substr($relative, 0, 2) == '//') {
if ($this->uri) {
$current = parse_url($this->uri);
} else {
$current = ['scheme' => 'http'];
}
return $current['scheme'] .':'. $relative;
}
$relativeurl = parse_url($relative);
if (isset($relativeurl['scheme'])) {
return $relative;
}
$absoluteurl = parse_url($absolute);
if (isset($absoluteurl['path'])) {
$path = dirname($absoluteurl['path']);
}
if ($relative[0] == '/') {
$cparts = array_filter(explode('/', $relative));
} else {
$aparts = array_filter(explode('/', $path));
$rparts = array_filter(explode('/', $relative));
$cparts = array_merge($aparts, $rparts);
foreach ($cparts as $i => $part) {
if ($part == '.') {
$cparts[$i] = null;
}
if ($part == '..') {
$cparts[$i - 1] = null;
$cparts[$i] = null;
}
}
$cparts = array_filter($cparts);
}
$path = implode('/', $cparts);
$url = "";
if (isset($absoluteurl['scheme'])) {
$url = $absoluteurl['scheme'] .'://';
}
if (isset($absoluteurl['user'])) {
$url .= $absoluteurl['user'];
if ($absoluteurl['pass']) {
$url .= ':'. $absoluteurl['user'];
}
$url .= '@';
}
if (isset($absoluteurl['host'])) {
$url .= $absoluteurl['host'];
if (isset($absoluteurl['port'])) {
$url .= ':'. $absoluteurl['port'];
}
$url .= '/';
}
$url .= $path;
return $url;
}
/**
* Sets the URI if this is for a string or to change where
* Will look for resources like CSS files
* @param string $uri The URI to set
*/
public function set_uri(string $uri) {
if (parse_url($uri)) {
$this->uri = $uri;
}
}
/**
* Formats the base URL for either a file or uri request. We are essentially
* formatting a base url for future reporters to use to find CSS files or
* for tests that use external resources (images, objects, etc) to run tests on them.
* @param string $value The path value
* @param string $type The type of request
*/
public function prepare_base_url(string $value, string $type) {
if ($type == 'file') {
$path = explode('/', $this->uri);
array_pop($path);
$this->path = $path;
} else if ($type == 'uri' || $this->uri) {
$parts = explode('://', $this->uri);
$this->path[] = $parts[0] .':/';
if (is_array($parts[1])) {
foreach (explode('/', $this->get_base_from_file($parts[1])) as $part) {
$this->path[] = $part;
}
} else {
$this->path[] = $parts[1] .'/';
}
}
}
/**
* Retrieves the absolute path to a file
* @param string $file The path to a file
* @return string The absolute path to a file
*/
public function get_base_from_file(string $file): string {
$find = '/';
$afterfind = substr(strrchr($file, $find), 1);
$strlenstr = strlen($afterfind);
$result = substr($file, 0, -$strlenstr);
return $result;
}
/**
* Helper method to add an additional CSS file
* @param string $css The URI or file path to a CSS file
*/
public function add_css(string $css) {
if (is_array($css)) {
$this->cssfiles = $css;
} else {
$this->cssfiles[] = $css;
}
}
/**
* Retrives a single error from the current reporter
* @param string $error The error key
* @return object A ReportItem object
*/
public function get_error(string $error) {
return $this->reporter->get_error($error);
}
/**
* A local method to load the required file for a reporter and set it for the current object
* @param array $options An array of options for the reporter
*/
public function load_reporter(array $options = []) {
$classname = '\\tool_brickfield\\local\\htmlchecker\\reporters\\'.'report_'.$this->reportername;
$this->reporter = new $classname($this->dom, $this->css, $this->guideline, $this->path);
if (count($options)) {
$this->reporter->set_options($options);
}
}
/**
* Checks that the DOM object is valid or not
* @return bool Whether the DOMDocument is valid
*/
public function is_valid(): bool {
return $this->isvalid;
}
/**
* Starts running automated checks. Loads the CSS file parser
* and the guideline object.
* @param null $options
* @return bool
*/
public function run_check($options = null) {
$this->prepare_dom();
if (!$this->is_valid()) {
return false;
}
$this->get_css_object();
$classname = 'tool_brickfield\\local\\htmlchecker\\guidelines\\'.strtolower($this->guidelinename).'_guideline';
$this->guideline = new $classname($this->dom, $this->css, $this->path, $options, $this->domain, $this->options['cms_mode']);
}
/**
* Loads the brickfield_accessibility_css object
*/
public function get_css_object() {
$this->css = new brickfield_accessibility_css($this->dom, $this->uri, $this->type, $this->path, false, $this->cssfiles);
}
/**
* Returns a formatted report from the current reporter.
* @param array $options An array of all the options
* @return mixed See the documentation on your reporter's getReport method.
*/
public function get_report(array $options = []) {
if (!$this->reporter) {
$this->load_reporter($options);
}
if ($options) {
$this->reporter->set_options($options);
}
$report = $this->reporter->get_report();
$path = $this->path;
return ['report' => $report, 'path' => $path];
}
/**
* Runs one test on the current DOMDocument
* @param string $test The name of the test to run
* @return bool|array The ReportItem returned from the test
*/
public function get_test(string $test) {
$test = 'tool_brickfield\local\htmlchecker\common\checks\\' . $test;
if (!class_exists($test)) {
return false;
}
$testclass = new $test($this->dom, $this->css, $this->path);
return $testclass->report;
}
/**
* Retrieves the default severity of a test
* @param string $test The name of the test to run
* @return object The severity level of the test
*/
public function get_test_severity(string $test) {
$testclass = new $test($this->dom, $this->css, $this->path);
return $testclass->get_severity();
}
/**
* A general cleanup function which just does some memory
* cleanup by unsetting the particularly large local vars.
*/
public function cleanup() {
unset($this->dom);
unset($this->css);
unset($this->guideline);
unset($this->reporter);
}
/**
* Determines if the link text is the same as the link URL, without necessarily being an exact match.
* For example, 'www.google.com' matches 'https://www.google.com'.
* @param string $text
* @param string $href
* @return bool
*/
public static function match_urls(string $text, string $href): bool {
$parsetext = parse_url($text);
$parsehref = parse_url($href);
$parsetextfull = (isset($parsetext['host'])) ? $parsetext['host'] : '';
$parsetextfull .= (isset($parsetext['path'])) ? $parsetext['path'] : '';
$parsehreffull = (isset($parsehref['host'])) ? $parsehref['host'] : '';
$parsehreffull .= (isset($parsehref['path'])) ? $parsehref['path'] : '';
// Remove any last '/' character before comparing.
return (rtrim($parsetextfull, '/') === rtrim($parsehreffull, '/'));
}
}
@@ -0,0 +1,159 @@
<?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 tool_brickfield\local\htmlchecker;
/**
* The base class for a guideline
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class brickfield_accessibility_guideline {
/** @var object The current document's DOMDocument */
public $dom;
/** @var object The current brickfield CSS object */
public $css;
/** @var array The path to the current document */
public $path;
/** @var array An array of report objects */
public $report;
/** @var array An array of translations for all this guideline's tests */
public $translations;
/** @var bool Whether we are running in CMS mode */
public $cmsmode = false;
/** @var array An array of all the severity levels for every test */
public $severity = [];
/** @var array To store all the tests. */
public array $tests = [];
/**
* The class constructor.
* @param object $dom The current DOMDocument object
* @param object $css The current brickfieldCSS object
* @param array $path The current path
* @param null $arg
* @param string $domain
* @param bool $cmsmode
*/
public function __construct(&$dom, &$css, array &$path,
$arg = null, string $domain = 'en', bool $cmsmode = false) {
$this->dom = &$dom;
$this->css = &$css;
$this->path = &$path;
$this->cmsmode = $cmsmode;
$this->load_translations($domain);
$this->run($arg, $domain);
}
/**
* Returns an array of all the tests associated with the current guideline
* @return array
*/
public function get_tests(): array {
return $this->tests;
}
/**
* Loads translations from a file. This can be overriden, just as long as the
* local variable 'translations' is an associative array with test function names
* as the key
* @param string $domain
*/
public function load_translations(string $domain) {
$csv = fopen(dirname(__FILE__) .'/guidelines/translations/'. $domain .'.txt', 'r');
if ($csv) {
while ($translation = fgetcsv($csv)) {
if (count($translation) == 4) {
$this->translations[$translation[0]] = [
'title' => $translation[1],
'description' => $translation[2],
];
}
}
}
}
/**
* Returns the translation for a test name.
* @param string $testname The function name of the test
* @return mixed
*/
public function get_translation(string $testname) {
return (isset($this->translations[$testname]))
? $this->translations[$testname]
: $testname;
}
/**
* Iterates through each test string, makes a new test object, and runs it against the current DOM
* @param null $arg
* @param string $language
*/
public function run($arg = null, string $language = 'en') {
foreach ($this->tests as $testname => $options) {
if (is_numeric($testname) && !is_array($options)) {
$testname = $options;
}
$name = $testname;
$testname = 'tool_brickfield\local\htmlchecker\common\\checks\\'.$testname;
if (class_exists($testname) && $this->dom) {
$testname = new $testname($this->dom, $this->css, $this->path, $language, $arg);
if (!$this->cmsmode || ($testname->cms && $this->cmsmode)) {
$this->report[$name] = $testname->get_report();
}
$this->severity[$name] = $testname->defaultseverity;
unset($testname);
} else {
$this->report[$name] = false;
}
}
}
/**
* Returns all the Report variable
* @return mixed Look to your report to see what it returns
*/
public function get_report() {
return $this->report;
}
/**
* Returns the severity level of a given test
* @param string $testname The name of the test
* @return int The severity level
*/
public function get_severity(string $testname): int {
if (isset($this->tests[$testname]['severity'])) {
return $this->tests[$testname]['severity'];
}
if (isset($this->severity[$testname])) {
return $this->severity[$testname];
}
return brickfield_accessibility::BA_TEST_MODERATE;
}
}
@@ -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/>.
namespace tool_brickfield\local\htmlchecker;
use DOMDocument;
/**
* A report item. There is one per issue with the report
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class brickfield_accessibility_report_item {
/** @var object The DOMElement that the report item refers to (if any) */
public $element;
/** @var string The error message */
public $message;
/** @var bool Whether the check needs to be manually verified */
public $manual;
/** @var bool For document-level tests, this says whether the test passed or not */
public $pass;
/** @var object For issues with more than two possible states, this contains information about the state */
public $state;
/** @var int the line number of the report item */
public $line;
/**
* Returns the line number of the report item. Unfortunately we can't use getLineNo
* if we are before PHP 5.3, so if not we try to get the line number through a more
* circuitous way.
*/
public function get_line() {
if (is_object($this->element) && method_exists($this->element, 'getLineNo')) {
return $this->element->getLineNo();
}
return 0;
}
/**
* Returns the current element in plain HTML form
* @param array $extraattributes An array of extra attributes to add to the element
* @return string An HTML string version of the provided DOMElement object
*/
public function get_html(array $extraattributes = []): string {
if (!$this->element) {
return '';
}
$resultdom = new DOMDocument();
$resultdom->formatOutput = true;
$resultdom->preserveWhiteSpace = false;
try {
$resultelement = $resultdom->importNode($this->element, true);
} catch (Exception $e) {
return false;
}
foreach ($this->element->attributes as $attribute) {
if ($attribute->name != 'brickfield_accessibility_style_index') {
$resultelement->setAttribute($attribute->name, $attribute->value);
}
}
foreach ($extraattributes as $name => $value) {
$resultelement->setAttribute($name, $value);
}
@$resultdom->appendChild($resultelement);
return @$resultdom->saveHTML();
}
}
@@ -0,0 +1,99 @@
<?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 tool_brickfield\local\htmlchecker;
use stdClass;
/**
* The base class for a reporter
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class brickfield_accessibility_reporter {
/** @var object The current document's DOMDocument */
public $dom;
/** @var object The current brickfieldaccessibilitycss object */
public $css;
/** @var array An array of test names and the translation for the problems with it */
public $translation;
/** @var array A collection of ReportItem objects */
public $report;
/** @var array The path to the current document */
public $path;
/** @var object Additional options for this reporter */
public $options;
/** @var array An array of attributes to search for to turn into absolute paths rather than relative paths */
public $absoluteattributes = ['src', 'href'];
/** @var object|null A guideline object. */
public ?object $guideline = null;
/**
* The class constructor
* @param object $dom The current DOMDocument object
* @param object $css The current brickfield CSS object
* @param object $guideline The current guideline object
* @param string $path The current path
*/
public function __construct(&$dom, &$css, &$guideline, $path = '') {
$this->dom = &$dom;
$this->css = &$css;
$this->path = $path;
$this->options = new stdClass;
$this->guideline = &$guideline;
}
/**
* Sets options for the reporter
* @param array $options an array of options
*/
public function set_options(array $options) {
foreach ($options as $key => $value) {
$this->options->$key = $value;
}
}
/**
* Sets the absolute path for an element
* @param object $element A DOMElement object to turn into an absolute path
*/
public function set_absolute_path(&$element) {
$attr = false;
foreach ($this->absoluteattributes as $attribute) {
if ($element->hasAttribute($attribute)) {
$attr = $attribute;
}
}
if ($attr) {
$item = $element->getAttribute($attr);
// We are ignoring items with absolute URLs.
if (strpos($item, '://') === false) {
$item = implode('/', $this->path) . ltrim($item, '/');
$element->setAttribute($attr, $item);
}
}
}
}
@@ -0,0 +1,48 @@
<?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 tool_brickfield\local\htmlchecker\common;
/**
* Helper function to support checking the varous color attributes of the <body> tag against WCAG standards
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class body_color_contrast extends brickfield_accessibility_color_test {
/** @var string The attribute to check for the background color of the <body> tag */
public $background = 'bgcolor';
/** @var string The attribute to check for the foreground color of the <body> tag */
public $foreground = 'text';
/**
* Compares the WCAG contrast on the given color attributes of the <body> tag
*/
public function check() {
$body = $this->get_all_elements('body');
if (!$body) {
return false;
}
$body = $body[0];
if ($body->hasAttribute($this->foreground) && $body->hasAttribute($this->background)) {
if ($this->get_luminosity($body->getAttribute($this->foreground), $body->getAttribute($this->background)) < 5) {
$this->add_report(null, null, false);
}
}
}
}
@@ -0,0 +1,53 @@
<?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 tool_brickfield\local\htmlchecker\common;
/**
* Base class for test dealing with WAI ERT color contrast for the document
*
* Because a lot of the tests deal with text, vlink, alink, etc.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class body_wai_ert_color_contrast extends brickfield_accessibility_color_test {
/** @var string The attribute to check for the background color of the <body> tag */
public $background = 'bgcolor';
/** @var string The attribute to check for the foreground color of the <body> tag */
public $foreground = 'text';
/**
* Compares the WAI ERT contrast on the given color attributes of the <body> tag
*/
public function check() {
$body = $this->get_all_elements('body');
if (!$body) {
return false;
}
$body = $body[0];
if ($body->hasAttribute($this->foreground) && $body->hasAttribute($this->background)) {
if ($this->get_wai_ert_contrast($body->getAttribute($this->foreground), $body->getAttribute($this->background)) < 500) {
$this->add_report(null, null, false);
} else if ($this->get_wai_ert_brightness($body->getAttribute($this->foreground),
$body->getAttribute($this->background)) < 125) {
$this->add_report(null, null, false);
}
}
}
}
@@ -0,0 +1,428 @@
<?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 tool_brickfield\local\htmlchecker\common;
/**
* Helper test base for tests dealing with color difference and luminosity.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class brickfield_accessibility_color_test extends brickfield_accessibility_test {
/** @var string[] Define colour codes. */
public $colornames = [
'aliceblue' => 'f0f8ff',
'antiquewhite' => 'faebd7',
'aqua' => '00ffff',
'aquamarine' => '7fffd4',
'azure' => 'f0ffff',
'beige' => 'f5f5dc',
'bisque' => 'ffe4c4',
'black' => '000000',
'blanchedalmond' => 'ffebcd',
'blue' => '0000ff',
'blueviolet' => '8a2be2',
'brown' => 'a52a2a',
'burlywood' => 'deb887',
'cadetblue' => '5f9ea0',
'chartreuse' => '7fff00',
'chocolate' => 'd2691e',
'coral' => 'ff7f50',
'cornflowerblue' => '6495ed',
'cornsilk' => 'fff8dc',
'crimson' => 'dc143c',
'cyan' => '00ffff',
'darkblue' => '00008b',
'darkcyan' => '008b8b',
'darkgoldenrod' => 'b8860b',
'darkgray' => 'a9a9a9',
'darkgreen' => '006400',
'darkkhaki' => 'bdb76b',
'darkmagenta' => '8b008b',
'darkolivegreen' => '556b2f',
'darkorange' => 'ff8c00',
'darkorchid' => '9932cc',
'darkred' => '8b0000',
'darksalmon' => 'e9967a',
'darkseagreen' => '8fbc8f',
'darkslateblue' => '483d8b',
'darkslategray' => '2f4f4f',
'darkturquoise' => '00ced1',
'darkviolet' => '9400d3',
'deeppink' => 'ff1493',
'deepskyblue' => '00bfff',
'dimgray' => '696969',
'dodgerblue' => '1e90ff',
'firebrick' => 'b22222',
'floralwhite' => 'fffaf0',
'forestgreen' => '228b22',
'fuchsia' => 'ff00ff',
'gainsboro' => 'dcdcdc',
'ghostwhite' => 'f8f8ff',
'gold' => 'ffd700',
'goldenrod' => 'daa520',
'gray' => '808080',
'green' => '008000',
'greenyellow' => 'adff2f',
'grey' => '808080',
'honeydew' => 'f0fff0',
'hotpink' => 'ff69b4',
'indianred' => 'cd5c5c',
'indigo' => '4b0082',
'ivory' => 'fffff0',
'khaki' => 'f0e68c',
'lavender' => 'e6e6fa',
'lavenderblush' => 'fff0f5',
'lawngreen' => '7cfc00',
'lemonchiffon' => 'fffacd',
'lightblue' => 'add8e6',
'lightcoral' => 'f08080',
'lightcyan' => 'e0ffff',
'lightgoldenrodyellow' => 'fafad2',
'lightgrey' => 'd3d3d3',
'lightgreen' => '90ee90',
'lightpink' => 'ffb6c1',
'lightsalmon' => 'ffa07a',
'lightseagreen' => '20b2aa',
'lightskyblue' => '87cefa',
'lightslategray' => '778899',
'lightsteelblue' => 'b0c4de',
'lightyellow' => 'ffffe0',
'lime' => '00ff00',
'limegreen' => '32cd32',
'linen' => 'faf0e6',
'magenta' => 'ff00ff',
'maroon' => '800000',
'mediumaquamarine' => '66cdaa',
'mediumblue' => '0000cd',
'mediumorchid' => 'ba55d3',
'mediumpurple' => '9370d8',
'mediumseagreen' => '3cb371',
'mediumslateblue' => '7b68ee',
'mediumspringgreen' => '00fa9a',
'mediumturquoise' => '48d1cc',
'mediumvioletred' => 'c71585',
'midnightblue' => '191970',
'mintcream' => 'f5fffa',
'mistyrose' => 'ffe4e1',
'moccasin' => 'ffe4b5',
'navajowhite' => 'ffdead',
'navy' => '000080',
'oldlace' => 'fdf5e6',
'olive' => '808000',
'olivedrab' => '6b8e23',
'orange' => 'ffa500',
'orangered' => 'ff4500',
'orchid' => 'da70d6',
'palegoldenrod' => 'eee8aa',
'palegreen' => '98fb98',
'paleturquoise' => 'afeeee',
'palevioletred' => 'd87093',
'papayawhip' => 'ffefd5',
'peachpuff' => 'ffdab9',
'peru' => 'cd853f',
'pink' => 'ffc0cb',
'plum' => 'dda0dd',
'powderblue' => 'b0e0e6',
'purple' => '800080',
'red' => 'ff0000',
'rosybrown' => 'bc8f8f',
'royalblue' => '4169e1',
'saddlebrown' => '8b4513',
'salmon' => 'fa8072',
'sandybrown' => 'f4a460',
'seagreen' => '2e8b57',
'seashell' => 'fff5ee',
'sienna' => 'a0522d',
'silver' => 'c0c0c0',
'skyblue' => '87ceeb',
'slateblue' => '6a5acd',
'slategray' => '708090',
'snow' => 'fffafa',
'springgreen' => '00ff7f',
'steelblue' => '4682b4',
'tan' => 'd2b48c',
'teal' => '008080',
'thistle' => 'd8bfd8',
'tomato' => 'ff6347',
'turquoise' => '40e0d0',
'violet' => 'ee82ee',
'wheat' => 'f5deb3',
'white' => 'ffffff',
'whitesmoke' => 'f5f5f5',
'yellow' => 'ffff00',
'yellowgreen' => '9acd32'
];
/** @var string[] Define estimated relative font-size codes to pt values. */
public $fontsizenames = [
'xx-small' => 9,
'x-small' => 10,
'small' => 11,
'smaller' => 11,
'medium' => 12,
'large' => 14,
'larger' => 14,
'x-large' => 18,
'xx-large' => 24,
];
/**
* Helper method that finds the luminosity between the provided
* foreground and background parameters.
* @param string $foreground The HEX value of the foreground color
* @param string $background The HEX value of the background color
* @return float The luminosity contrast ratio between the colors
*/
public function get_luminosity(string $foreground, string $background): float {
if ($foreground == $background) {
return 0;
}
$forergb = $this->get_rgb($foreground);
$backrgb = $this->get_rgb($background);
// If get_rgb returns null for either, return 0.
if ($forergb === null || $backrgb === null) {
return 0;
}
return $this->luminosity($forergb['r'], $backrgb['r'],
$forergb['g'], $backrgb['g'],
$forergb['b'], $backrgb['b']);
}
/**
* Returns the luminosity between two colors
* @param string $r The first Red value
* @param string $r2 The second Red value
* @param string $g The first Green value
* @param string $g2 The second Green value
* @param string $b The first Blue value
* @param string $b2 The second Blue value
* @return float The luminosity contrast ratio between the colors
*/
public function luminosity(string $r, string $r2, string $g, string $g2, string $b, string $b2): float {
$rsrgb = $r / 255;
$gsrgb = $g / 255;
$bsrgb = $b / 255;
$r3 = ($rsrgb <= 0.03928) ? $rsrgb / 12.92 : pow(($rsrgb + 0.055) / 1.055, 2.4);
$g3 = ($gsrgb <= 0.03928) ? $gsrgb / 12.92 : pow(($gsrgb + 0.055) / 1.055, 2.4);
$b3 = ($bsrgb <= 0.03928) ? $bsrgb / 12.92 : pow(($bsrgb + 0.055) / 1.055, 2.4);
$rsrgb2 = $r2 / 255;
$gsrgb2 = $g2 / 255;
$bsrgb2 = $b2 / 255;
$r4 = ($rsrgb2 <= 0.03928) ? $rsrgb2 / 12.92 : pow(($rsrgb2 + 0.055) / 1.055, 2.4);
$g4 = ($gsrgb2 <= 0.03928) ? $gsrgb2 / 12.92 : pow(($gsrgb2 + 0.055) / 1.055, 2.4);
$b4 = ($bsrgb2 <= 0.03928) ? $bsrgb2 / 12.92 : pow(($bsrgb2 + 0.055) / 1.055, 2.4);
if ($r + $g + $b <= $r2 + $g2 + $b2) {
$l2 = (.2126 * $r3 + 0.7152 * $g3 + 0.0722 * $b3);
$l1 = (.2126 * $r4 + 0.7152 * $g4 + 0.0722 * $b4);
} else {
$l1 = (.2126 * $r3 + 0.7152 * $g3 + 0.0722 * $b3);
$l2 = (.2126 * $r4 + 0.7152 * $g4 + 0.0722 * $b4);
}
// Increase round to 4 to avoid a 4.49 contrast being round up to a false pass of 4.5.
$luminosity = round(($l1 + 0.05) / ($l2 + 0.05), 4);
return $luminosity;
}
/**
* Returns the decimal equivalents for a HEX color. Returns null if it cannot be determined.
* @param string $color The hex color value
* @return array|null An array where 'r' is the Red value, 'g' is Green, and 'b' is Blue
*/
public function get_rgb(string $color): ?array {
$color = $this->convert_color($color);
$c = str_split($color, 2);
if (count($c) != 3) {
return null;
}
$results = ['r' => hexdec($c[0]), 'g' => hexdec($c[1]), 'b' => hexdec($c[2])];
return $results;
}
/**
* Converts multiple color or background styles into a simple hex string
* @param string $color The color attribute to convert (this can also be a multi-value css background value)
* @return string A standard CSS hex value for the color
*/
public function convert_color(string $color): string {
$color = trim($color);
// Search for color in rgb format first, as this can potentially contain a space.
if (strpos($color, 'rgb') !== false) {
$colors = explode('rgb', $color, 2); // Getting 2 only in array.
// Getting end point of rgb value, i.e. the end bracket.
$endpos = strpos($colors[1], ')');
$color = 'rgb' . substr($colors[1], 0, ($endpos + 1)); // Recompiling rgb value.
} else {
// Splitting multi-value css background value.
if (strpos($color, ' ') !== false) {
$colors = explode(' ', $color);
foreach ($colors as $backgroundpart) {
if (substr(trim($backgroundpart), 0, 1) == '#' ||
in_array(trim($backgroundpart), array_keys($this->colornames))) {
$color = $backgroundpart;
}
}
}
}
// Normal hex color.
if (substr($color, 0, 1) == '#') {
if (strlen($color) == 7) {
return str_replace('#', '', $color);
} else if (strlen($color) == 4) {
return substr($color, 1, 1) . substr($color, 1, 1) .
substr($color, 2, 1) . substr($color, 2, 1) .
substr($color, 3, 1) . substr($color, 3, 1);
} else {
return "000000";
}
}
// Named Color.
if (in_array($color, array_keys($this->colornames))) {
return $this->colornames[$color];
}
// RGB values.
if (strtolower(substr($color, 0, 3)) == 'rgb') {
if (strpos($color, 'rgba') !== false) {
$tmpbg = $this->get_rgb($this->defaultbackground);
$colors = explode(',', trim(str_replace('rgba(', '', $color), '()'));
if (count($colors) != 4) {
return false;
}
$colors[0] = round(((1 - $colors[3]) * $tmpbg['r']) + ($colors[3] * $colors[0]));
$colors[1] = round((1 - $colors[3]) * $tmpbg['g']) + ($colors[3] * $colors[1]);
$colors[2] = round((1 - $colors[3]) * $tmpbg['b']) + ($colors[3] * $colors[2]);
} else {
$colors = explode(',', trim(str_replace('rgb(', '', $color), '()'));
if (count($colors) != 3) {
return false;
}
}
$r = intval($colors[0]);
$g = intval($colors[1]);
$b = intval($colors[2]);
$r = dechex($r < 0 ? 0 : ($r > 255 ? 255 : $r));
$g = dechex($g < 0 ? 0 : ($g > 255 ? 255 : $g));
$b = dechex($b < 0 ? 0 : ($b > 255 ? 255 : $b));
$color = (strlen($r) < 2 ? '0' : '') . $r;
$color .= (strlen($g) < 2 ? '0' : '') . $g;
$color .= (strlen($b) < 2 ? '0' : '') . $b;
return $color;
}
return '';
}
/**
* Returns the WAIERT contrast between two colors
* @param string $foreground
* @param string $background
* @return array
* @see get_luminosity
*/
public function get_wai_ert_contrast(string $foreground, string $background): array {
$forergb = $this->get_rgb($foreground);
$backrgb = $this->get_rgb($background);
// If get_rgb returns null for either, return 0.
if ($forergb === null || $backrgb === null) {
return [];
}
$diffs = $this->get_wai_diffs($forergb, $backrgb);
return $diffs['red'] + $diffs['green'] + $diffs['blue'];
}
/**
* Returns the WAI ERT Brightness between two colors
* @param string $foreground
* @param string $background
* @return float|int
*/
public function get_wai_ert_brightness(string $foreground, string $background): float {
$forergb = $this->get_rgb($foreground);
$backrgb = $this->get_rgb($background);
// If get_rgb returns null for either, return 0.
if ($forergb === null || $backrgb === null) {
return 0;
}
$color = $this->get_wai_diffs($forergb, $backrgb);
return (($color['red'] * 299) + ($color['green'] * 587) + ($color['blue'] * 114)) / 1000;
}
/**
* Get the wai differences.
* @param array $forergb
* @param array $backrgb
* @return array
*/
public function get_wai_diffs(array $forergb, array $backrgb): array {
$reddiff = ($forergb['r'] > $backrgb['r'])
? $forergb['r'] - $backrgb['r']
: $backrgb['r'] - $forergb['r'];
$greendiff = ($forergb['g'] > $backrgb['g'])
? $forergb['g'] - $backrgb['g']
: $backrgb['g'] - $forergb['g'];
$bluediff = ($forergb['b'] > $backrgb['b'])
? $forergb['b'] - $backrgb['b']
: $backrgb['b'] - $forergb['b'];
return ['red' => $reddiff, 'green' => $greendiff, 'blue' => $bluediff];
}
/**
* Helper method that finds the estimated font-size for the provided
* string font-size parameter.
* @param string $fontsize The css font-size, in various formats
* @return int The estimated font-size
*/
public function get_fontsize(string $fontsize): int {
$newfontsize = 12; // Default value, in pt, equivalent to 16px.
// Search for rem, em, and px initially, typical font-size values.
$pos1 = stripos($fontsize, 'rem');
$pos2 = stripos($fontsize, 'em');
$pos3 = stripos($fontsize, 'px');
if ($pos1 !== false) {
$rem = substr($fontsize, 0, -3);
$newfontsize = $newfontsize * $rem;
} else if ($pos2 !== false) {
$em = substr($fontsize, 0, -2);
$newfontsize = $newfontsize * $em;
} else if ($pos3 !== false) {
$px = substr($fontsize, 0, -2);
$newfontsize = 0.75 * $px;
} else if (in_array($fontsize, array_keys($this->fontsizenames))) {
$newfontsize = $this->fontsizenames[$fontsize];
} else {
preg_match_all('!\d+!', $fontsize, $matches);
$newfontsize = $matches[0][0] ?? $newfontsize;
}
return (int) $newfontsize;
}
}
@@ -0,0 +1,547 @@
<?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 tool_brickfield\local\htmlchecker\common;
/**
* Parse content to check CSS validity.
*
* This class first parses all the CSS in the document and prepares an index of CSS styles to be used by accessibility tests
* to determine color and positioning.
*
* First, in loadCSS we get all the inline and linked style sheet information and merge it into a large CSS file string.
*
* Second, in setStyles we use XPath queries to find all the DOM elements which are effected by CSS styles and then
* build up an index in style_index of all the CSS styles keyed by an attriute we attach to all DOM objects to lookup
* the style quickly.
*
* Most of the second step is to get around the problem where XPath DOMNodeList objects are only marginally referential
* to the original elements and cannot be altered directly.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class brickfield_accessibility_css {
/** @var object The DOMDocument object of the current document */
public $dom;
/** @var string The URI of the current document */
public $uri;
/** @var string The type of request (inherited from the main htmlchecker object) */
public $type;
/** @var array An array of all the CSS elements and attributes */
public $css;
/** @var string Additional CSS information (usually for CMS mode requests) */
public $cssstring;
/** @var bool Whether or not we are running in CMS mode */
public $cmsmode;
/** @var array An array of all the strings which means the current style inherts from above */
public $inheritancestrings = ['inherit', 'currentColor'];
/** @var array An array of all the styles keyed by the new attribute brickfield_accessibility_style_index */
public $styleindex = [];
/** @var int The next index ID to be applied to a node to lookup later in style_index */
public $nextindex = 0;
/** @var array A list of all the elements which support deprecated styles such as 'background' or 'bgcolor' */
public $deprecatedstyleelements = ['body', 'table', 'tr', 'td', 'th'];
/** @var array */
public array $path = [];
/** @var array To store additional CSS files to load. */
public array $css_files = [];
/**
* Class constructor. We are just building and importing variables here and then loading the CSS
* @param \DOMDocument $dom The DOMDocument object
* @param string $uri The URI of the request
* @param string $type The type of request
* @param array $path
* @param bool $cmsmode Whether we are running in CMS mode
* @param array $cssfiles An array of additional CSS files to load
*/
public function __construct(\DOMDocument &$dom, string $uri, string $type, array $path, bool $cmsmode = false,
array $cssfiles = []) {
$this->dom =& $dom;
$this->type = $type;
$this->uri = $uri;
$this->path = $path;
$this->cmsmode = $cmsmode;
$this->css_files = $cssfiles;
}
/**
* Loads all the CSS files from the document using LINK elements or @import commands
*/
private function load_css() {
if (count($this->css_files) > 0) {
$css = $this->css_files;
} else {
$css = [];
$headerstyles = $this->dom->getElementsByTagName('style');
foreach ($headerstyles as $headerstyle) {
if ($headerstyle->nodeValue) {
$this->cssstring .= $headerstyle->nodeValue;
}
}
$stylesheets = $this->dom->getElementsByTagName('link');
foreach ($stylesheets as $style) {
if ($style->hasAttribute('rel') &&
(strtolower($style->getAttribute('rel')) == 'stylesheet') &&
($style->getAttribute('media') != 'print')) {
$css[] = $style->getAttribute('href');
}
}
}
foreach ($css as $sheet) {
$this->load_uri($sheet);
}
$this->load_imported_files();
$this->cssstring = str_replace(':link', '', $this->cssstring);
$this->format_css();
}
/**
* Imports files from the CSS file using @import commands
*/
private function load_imported_files() {
$matches = [];
preg_match_all('/@import (.*?);/i', $this->cssstring, $matches);
if (count($matches[1]) == 0) {
return null;
}
foreach ($matches[1] as $match) {
$this->load_uri(trim(str_replace('url', '', $match), '"\')('));
}
preg_replace('/@import (.*?);/i', '', $this->cssstring);
}
/**
* Returns a specificity count to the given selector.
* Higher specificity means it overrides other styles.
* @param string $selector The CSS Selector
* @return int $specifity
*/
public function get_specificity(string $selector): int {
$selector = $this->parse_selector($selector);
if ($selector[0][0] == ' ') {
unset($selector[0][0]);
}
$selector = $selector[0];
$specificity = 0;
foreach ($selector as $part) {
switch(substr(str_replace('*', '', $part), 0, 1)) {
case '.':
$specificity += 10;
case '#':
$specificity += 100;
case ':':
$specificity++;
default:
$specificity++;
}
if (strpos($part, '[id=') != false) {
$specificity += 100;
}
}
return $specificity;
}
/**
* Interface method for tests to call to lookup the style information for a given DOMNode
* @param \stdClass $element A DOMElement/DOMNode object
* @return array An array of style information (can be empty)
*/
public function get_style($element): array {
// To prevent having to parse CSS unless the info is needed,
// we check here if CSS has been set, and if not, run off the parsing now.
if (!is_a($element, 'DOMElement')) {
return [];
}
$style = $this->get_node_style($element);
if (isset($style['background-color']) || isset($style['color'])) {
$style = $this->walkup_tree_for_inheritance($element, $style);
}
if ($element->hasAttribute('style')) {
$inlinestyles = explode(';', $element->getAttribute('style'));
foreach ($inlinestyles as $inlinestyle) {
$s = explode(':', $inlinestyle);
if (isset($s[1])) { // Edit: Make sure the style attribute doesn't have a trailing.
$style[trim($s[0])] = trim(strtolower($s[1]));
}
}
}
if ($element->tagName === 'strong') {
$style['font-weight'] = 'bold';
}
if ($element->tagName === 'em') {
$style['font-style'] = 'italic';
}
if (!is_array($style)) {
return [];
}
return $style;
}
/**
* Adds a selector to the CSS index
* @param string $key The CSS selector
* @param string $codestr The CSS Style code string
* @return null
*/
private function add_selector(string $key, string $codestr) {
if (strpos($key, '@import') !== false) {
return null;
}
$key = strtolower($key);
$codestr = strtolower($codestr);
if (!isset($this->css[$key])) {
$this->css[$key] = array();
}
$codes = explode(';', $codestr);
if (count($codes) > 0) {
foreach ($codes as $code) {
$code = trim($code);
$explode = explode(':', $code, 2);
if (count($explode) > 1) {
list($codekey, $codevalue) = $explode;
if (strlen($codekey) > 0) {
$this->css[$key][trim($codekey)] = trim($codevalue);
}
}
}
}
}
/**
* Returns the style from the CSS index for a given element by first
* looking into its tag bucket then iterating over every item for an
* element that matches
* @param \stdClass $element
* @return array An array of all the style elements that _directly_ apply to that element (ignoring inheritance)
*/
private function get_node_style($element): array {
$style = [];
if ($element->hasAttribute('brickfield_accessibility_style_index')) {
$style = $this->styleindex[$element->getAttribute('brickfield_accessibility_style_index')];
}
// To support the deprecated 'bgcolor' attribute.
if ($element->hasAttribute('bgcolor') && in_array($element->tagName, $this->deprecatedstyleelements)) {
$style['background-color'] = $element->getAttribute('bgcolor');
}
if ($element->hasAttribute('style')) {
$inlinestyles = explode(';', $element->getAttribute('style'));
foreach ($inlinestyles as $inlinestyle) {
$s = explode(':', $inlinestyle);
if (isset($s[1])) { // Edit: Make sure the style attribute doesn't have a trailing.
$style[trim($s[0])] = trim(strtolower($s[1]));
}
}
}
return $style;
}
/**
* A helper function to walk up the DOM tree to the end to build an array of styles.
* @param \stdClass $element The DOMNode object to walk up from
* @param array $style The current style built for the node
* @return array The array of the DOM element, altered if it was overruled through css inheritance
*/
private function walkup_tree_for_inheritance($element, array $style): array {
while (property_exists($element->parentNode, 'tagName')) {
$parentstyle = $this->get_node_style($element->parentNode);
if (is_array($parentstyle)) {
foreach ($parentstyle as $k => $v) {
if (!isset($style[$k])) {
$style[$k] = $v;
}
if ((!isset($style['background-color'])) || strtolower($style['background-color']) == strtolower("#FFFFFF")) {
if ($k == 'background-color') {
$style['background-color'] = $v;
}
}
if ((!isset($style['color'])) || strtolower($style['color']) == strtolower("#000000")) {
if ($k == 'color') {
$style['color'] = $v;
}
}
}
}
$element = $element->parentNode;
}
return $style;
}
/**
* Loads a CSS file from a URI
* @param string $rel The URI of the CSS file
*/
private function load_uri(string $rel) {
if ($this->type == 'file') {
$uri = substr($this->uri, 0, strrpos($this->uri, '/')) .'/'.$rel;
} else {
$bfao = new \tool_brickfield\local\htmlchecker\brickfield_accessibility();
$uri = $bfao->get_absolute_path($this->uri, $rel);
}
$this->cssstring .= @file_get_contents($uri);
}
/**
* Formats the CSS to be ready to import into an array of styles
* @return bool Whether there were elements imported or not
*/
private function format_css(): bool {
// Remove comments.
$str = preg_replace("/\/\*(.*)?\*\//Usi", "", $this->cssstring);
// Parse this csscode.
$parts = explode("}", $str);
if (count($parts) > 0) {
foreach ($parts as $part) {
if (strpos($part, '{') !== false) {
list($keystr, $codestr) = explode("{", $part);
$keys = explode(", ", trim($keystr));
if (count($keys) > 0) {
foreach ($keys as $key) {
if (strlen($key) > 0) {
$key = str_replace("\n", "", $key);
$key = str_replace("\\", "", $key);
$this->add_selector($key, trim($codestr));
}
}
}
}
}
}
return (count($this->css) > 0);
}
/**
* Converts a CSS selector to an Xpath query
* @param string $selector The selector to convert
* @return string An Xpath query string
*/
private function get_xpath(string $selector): string {
$query = $this->parse_selector($selector);
$xpath = '//';
foreach ($query[0] as $k => $q) {
if ($q == ' ' && $k) {
$xpath .= '//';
} else if ($q == '>' && $k) {
$xpath .= '/';
} else if (substr($q, 0, 1) == '#') {
$xpath .= '[ @id = "' . str_replace('#', '', $q) . '" ]';
} else if (substr($q, 0, 1) == '.') {
$xpath .= '[ @class = "' . str_replace('.', '', $q) . '" ]';
} else if (substr($q, 0, 1) == '[') {
$xpath .= str_replace('[id', '[ @ id', $q);
} else {
$xpath .= trim($q);
}
}
return str_replace('//[', '//*[', str_replace('//[ @', '//*[ @', $xpath));
}
/**
* Checks that a string is really a regular character
* @param string $char The character
* @return bool Whether the string is a character
*/
private function is_char(string $char): bool {
return extension_loaded('mbstring') ? mb_eregi('\w', $char) : preg_match('@\w@', $char);
}
/**
* Parses a CSS selector into an array of rules.
* @param string $query The CSS Selector query
* @return array An array of the CSS Selector parsed into rule segments
*/
private function parse_selector(string $query): array {
// Clean spaces.
$query = trim(preg_replace('@\s+@', ' ', preg_replace('@\s*(>|\\+|~)\s*@', '\\1', $query)));
$queries = [[]];
if (!$query) {
return $queries;
}
$return =& $queries[0];
$specialchars = ['>', ' '];
$specialcharsmapping = [];
$strlen = mb_strlen($query);
$classchars = ['.', '-'];
$pseudochars = ['-'];
$tagchars = ['*', '|', '-'];
// Split multibyte string
// http://code.google.com/p/phpquery/issues/detail?id=76.
$newquery = [];
for ($i = 0; $i < $strlen; $i++) {
$newquery[] = mb_substr($query, $i, 1);
}
$query = $newquery;
// It works, but i dont like it...
$i = 0;
while ($i < $strlen) {
$c = $query[$i];
$tmp = '';
// TAG.
if ($this->is_char($c) || in_array($c, $tagchars)) {
while (isset($query[$i]) && ($this->is_char($query[$i]) || in_array($query[$i], $tagchars))) {
$tmp .= $query[$i];
$i++;
}
$return[] = $tmp;
// IDs.
} else if ( $c == '#') {
$i++;
while (isset($query[$i]) && ($this->is_char($query[$i]) || $query[$i] == '-')) {
$tmp .= $query[$i];
$i++;
}
$return[] = '#'.$tmp;
// SPECIAL CHARS.
} else if (in_array($c, $specialchars)) {
$return[] = $c;
$i++;
// MAPPED SPECIAL CHARS.
} else if ( isset($specialcharsmapping[$c])) {
$return[] = $specialcharsmapping[$c];
$i++;
// COMMA.
} else if ( $c == ',') {
$queries[] = [];
$return =& $queries[count($queries) - 1];
$i++;
while (isset($query[$i]) && $query[$i] == ' ') {
$i++;
}
// CLASSES.
} else if ($c == '.') {
while (isset($query[$i]) && ($this->is_char($query[$i]) || in_array($query[$i], $classchars))) {
$tmp .= $query[$i];
$i++;
}
$return[] = $tmp;
// General Sibling Selector.
} else if ($c == '~') {
$spaceallowed = true;
$tmp .= $query[$i++];
while (isset($query[$i])
&& ($this->is_char($query[$i])
|| in_array($query[$i], $classchars)
|| $query[$i] == '*'
|| ($query[$i] == ' ' && $spaceallowed)
)) {
if ($query[$i] != ' ') {
$spaceallowed = false;
}
$tmp .= $query[$i];
$i++;
}
$return[] = $tmp;
// Adjacent sibling selectors.
} else if ($c == '+') {
$spaceallowed = true;
$tmp .= $query[$i++];
while (isset($query[$i])
&& ($this->is_char($query[$i])
|| in_array($query[$i], $classchars)
|| $query[$i] == '*'
|| ($spaceallowed && $query[$i] == ' ')
)) {
if ($query[$i] != ' ') {
$spaceallowed = false;
}
$tmp .= $query[$i];
$i++;
}
$return[] = $tmp;
// ATTRS.
} else if ($c == '[') {
$stack = 1;
$tmp .= $c;
while (isset($query[++$i])) {
$tmp .= $query[$i];
if ( $query[$i] == '[') {
$stack++;
} else if ( $query[$i] == ']') {
$stack--;
if (!$stack) {
break;
}
}
}
$return[] = $tmp;
$i++;
// PSEUDO CLASSES.
} else if ($c == ':') {
$stack = 1;
$tmp .= $query[$i++];
while (isset($query[$i]) && ($this->is_char($query[$i]) || in_array($query[$i], $pseudochars))) {
$tmp .= $query[$i];
$i++;
}
// With arguments?
if (isset($query[$i]) && $query[$i] == '(') {
$tmp .= $query[$i];
$stack = 1;
while (isset($query[++$i])) {
$tmp .= $query[$i];
if ( $query[$i] == '(') {
$stack++;
} else if ( $query[$i] == ')') {
$stack--;
if (!$stack) {
break;
}
}
}
$return[] = $tmp;
$i++;
} else {
$return[] = $tmp;
}
} else {
$i++;
}
}
foreach ($queries as $k => $q) {
if (isset($q[0])) {
if (isset($q[0][0]) && $q[0][0] == ':') {
array_unshift($queries[$k], '*');
}
if ($q[0] != '>') {
array_unshift($queries[$k], ' ');
}
}
}
return $queries;
}
}
@@ -0,0 +1,59 @@
<?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 tool_brickfield\local\htmlchecker\common;
use DOMElement;
/**
* Brickfield accessibility HTML checker library.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
/**
* An older attempt at using dom element extensions to introducefinding the styling of an element.
* @package tool_brickfield
* @deprecated
*/
class brickfield_accessibility_dom_element extends DOMElement {
/** @var mixed Css style */
public $cssstyle;
/**
* Set css.
* @param mixed $css
*/
public function set_css($css) {
$this->cssstyle = $css;
}
/**
* Get style.
* @param bool $style
* @return mixed
*/
public function get_style(bool $style = false) {
if (!$style) {
return $this->cssstyle;
} else {
return $this->cssstyle[$style];
}
}
}
@@ -0,0 +1,54 @@
<?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 tool_brickfield\local\htmlchecker\common;
/**
* Special base test class that deals with tests concerning the logical heirarchy of headers.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class brickfield_accessibility_header_test extends brickfield_accessibility_test {
/** @var string The header tag this test applies to. */
public $tag = '';
/** @var array An array of all the header tags */
public $headers = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'];
/**
* The check method gathers all the headers together and walks through them, making sure that
* the logical display of headers makes sense.
*/
public function check() {
$firstheader = $this->dom->getElementsByTagName($this->tag);
if ($firstheader->item(0)) {
$current = $firstheader->item(0);
$previousnumber = intval(substr($current->tagName, -1, 1));
while ($current) {
if (property_exists($current, 'tagName') && in_array($current->tagName, $this->headers)) {
$currentnumber = intval(substr($current->tagName, -1, 1));
if ($currentnumber > ($previousnumber + 1)) {
$this->add_report($current);
}
$previousnumber = intval(substr($current->tagName, -1, 1));
}
$current = $current->nextSibling;
}
}
}
}
@@ -0,0 +1,82 @@
<?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 tool_brickfield\local\htmlchecker\common;
/**
* Special base class which provides helper methods for tables.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class brickfield_accessibility_table_test extends brickfield_accessibility_test {
/**
* Takes the element object of a main table and returns the number of rows and columns in it.
* @param \stdClass $table
* @return array An array with the 'rows' value showing the number of rows, and column showing the number of columns
*/
public function get_table(\stdClass $table): array {
$rows = 0;
$columns = 0;
$firstrow = true;
if ($table->tagName != 'table') {
return false;
}
foreach ($table->childNodes as $child) {
if (property_exists($child, 'tagName') && $child->tagName == 'tr') {
$rows++;
if ($firstrow) {
foreach ($child->childNodes as $columnchild) {
if ($columnchild->tagName == 'th' || $columnchild->tagName == 'td') {
$columns++;
}
}
$firstrow = false;
}
}
}
return ['rows' => $rows, 'columns' => $columns];
}
/**
* Finds whether or not the table is a data table. Checks that the
* table has a logical order and uses 'th' or 'thead' tags to illustrate
* the page author thought it was a data table.
* @param object $table The DOMElement object of the table tag
* @return bool TRUE if the element is a data table, otherwise false
*/
public function is_data($table): bool {
if ($table->tagName != 'table') {
return false;
}
foreach ($table->childNodes as $child) {
if (property_exists($child, 'tagName') && $child->tagName == 'tr') {
foreach ($child->childNodes as $rowchild) {
if (property_exists($rowchild, 'tagName') && $rowchild->tagName == 'th') {
return true;
}
}
}
if (property_exists($child, 'tagName') && $child->tagName == 'thead') {
return true;
}
}
return false;
}
}
@@ -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 tool_brickfield\local\htmlchecker\common;
/**
* Special class test thats only for file a report whenever it hits the specified tag regardless of anything about the element.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class brickfield_accessibility_tag_test extends brickfield_accessibility_test {
/**
* @var string The tag name of this test
*/
public $tag = '';
/**
* Shouldn't need to be overridden. We just file one report item for every
* element we find with this class's $tag var.
*/
public function check() {
foreach ($this->get_all_elements($this->tag) as $element) {
$this->add_report($element);
}
}
}
@@ -0,0 +1,439 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace tool_brickfield\local\htmlchecker\common;
use tool_brickfield\local\htmlchecker\brickfield_accessibility_report_item;
use tool_brickfield\manager;
/**
* This handles importing DOM objects, adding items to the report and provides a few DOM-traversing methods
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class brickfield_accessibility_test {
/** @var object The DOMDocument object */
public $dom;
/** @var object The brickfieldCSS object */
public $css;
/** @var array The path for the request */
public $path;
/** @var bool Whether the test can be used in a CMS (content without HTML head) */
public $cms = true;
/** @var string The base path for this request */
public $basepath;
/** @var array An array of ReportItem objects */
public $report = array();
/** @var int The fallback severity level for all tests */
public $defaultseverity = \tool_brickfield\local\htmlchecker\brickfield_accessibility::BA_TEST_SUGGESTION;
/** @var array An array of all the extensions that are images */
public $imageextensions = array('gif', 'jpg', 'png', 'jpeg', 'tiff', 'svn');
/** @var string The language domain */
public $lang = 'en';
/** @var array An array of translatable strings */
public $strings = array('en' => '');
/** @var mixed Any additional options passed by htmlchecker. */
public $options;
/**
* The class constructor. We pass items by reference so we can alter the DOM if necessary
* @param object $dom The DOMDocument object
* @param object $css The brickfieldCSS object
* @param array $path The path of this request
* @param string $languagedomain The langauge domain to user
* @param mixed $options Any additional options passed by htmlchecker.
*/
public function __construct(&$dom, &$css, &$path, $languagedomain = 'en', $options = null) {
$this->dom = $dom;
$this->css = $css;
$this->path = $path;
$this->lang = $languagedomain;
$this->options = $options;
$this->report = array();
$this->check();
}
/**
* Helper method to collect the report from this test. Some
* tests do additional cleanup by overriding this method
* @return array An array of ReportItem objects
*/
public function get_report(): array {
$this->report['severity'] = $this->defaultseverity;
return $this->report;
}
/**
* Returns the default severity of the test
* @return int The severity level
*/
public function get_severity(): int {
return $this->defaultseverity;
}
/**
* Adds a new ReportItem to this current tests collection of reports.
* Most reports pertain to a particular element (like an IMG with no Alt attribute);
* however, some are document-level and just either pass or don't pass
* @param object $element The DOMElement object that pertains to this report
* @param string $message An additional message to add to the report
* @param bool $pass Whether or not this report passed
* @param object $state Extra information about the error state
* @param bool $manual Whether the report needs a manual check
*/
public function add_report($element = null, $message = null, $pass = null, $state = null, $manual = null) {
$report = new brickfield_accessibility_report_item();
$report->element = $element;
$report->message = $message;
$report->pass = $pass;
$report->state = $state;
$report->manual = $manual;
$report->line = $report->get_line();
$this->report[] = $report;
}
/**
* Retrieves the full path for a file.
* @param string $file The path to a file
* @return string The absolute path to the file.
*/
public function get_path($file): string {
if ((substr($file, 0, 7) == 'http://') || (substr($file, 0, 8) == 'https://')) {
return $file;
}
$file = explode('/', $file);
if (count($file) == 1) {
return implode('/', $this->path) . '/' . $file[0];
}
$path = $this->path;
foreach ($file as $directory) {
if ($directory == '..') {
array_pop($path);
} else {
$filepath[] = $directory;
}
}
return implode('/', $path) .'/'. implode('/', $filepath);
}
/**
* Returns a translated variable. If the translation is unavailable, English is returned
* Because tests only really have one string array, we can get all of this info locally
* @return mixed The translation for the object
*/
public function translation() {
if (isset($this->strings[$this->lang])) {
return $this->strings[$this->lang];
}
if (isset($this->strings['en'])) {
return $this->strings['en'];
}
return false;
}
/**
* Helper method to find all the elements that fit a particular query
* in the document (either by tag name, or by attributes from the htmlElements object)
* @param mixed $tags Either a single tag name in a string, or an array of tag names
* @param string $options The kind of option to select an element by (see htmlElements)
* @param bool $value The value of the above option
* @return array An array of elements that fit the description
*/
public function get_all_elements($tags = null, string $options = '', bool $value = true): array {
if (!is_array($tags)) {
$tags = [$tags];
}
if ($options !== '') {
$temp = new html_elements();
$tags = $temp->get_elements_by_option($options, $value);
}
$result = [];
if (!is_array($tags)) {
return [];
}
foreach ($tags as $tag) {
$elements = $this->dom->getElementsByTagName($tag);
if ($elements) {
foreach ($elements as $element) {
$result[] = $element;
}
}
}
if (count($result) == 0) {
return [];
}
return $result;
}
/**
* Returns true if an element has a child with a given tag name
* @param object $element A DOMElement object
* @param string $childtag The tag name of the child to find
* @return bool TRUE if the element does have a child with
* the given tag name, otherwise FALSE
*/
public function element_has_child($element, string $childtag): bool {
foreach ($element->childNodes as $child) {
if (property_exists($child, 'tagName') && $child->tagName == $childtag) {
return true;
}
}
return false;
}
/**
* Returns the first ancestor reached of a tag, or false if it hits
* the document root or a given tag.
* @param object $element A DOMElement object
* @param string $ancestortag The name of the tag we are looking for
* @param string $limittag Where to stop searching
* @return bool
*/
public function get_element_ancestor($element, string $ancestortag, string $limittag = 'body') {
while (property_exists($element, 'parentNode')) {
if ($element->parentNode->tagName == $ancestortag) {
return $element->parentNode;
}
if ($element->parentNode->tagName == $limittag) {
return false;
}
$element = $element->parentNode;
}
return false;
}
/**
* Finds all the elements with a given tag name that has
* an attribute
* @param string $tag The tag name to search for
* @param string $attribute The attribute to search on
* @param bool $unique Whether we only want one result per attribute
* @return array An array of DOMElements with the attribute
* value as the key.
*/
public function get_elements_by_attribute(string $tag, string $attribute, bool $unique = false): array {
$results = array();
foreach ($this->get_all_elements($tag) as $element) {
if ($element->hasAttribute($attribute)) {
if ($unique) {
$results[$element->getAttribute($attribute)] = $element;
} else {
$results[$element->getAttribute($attribute)][] = $element;
}
}
}
return $results;
}
/**
* Returns the next element after the current one.
* @param object $element A DOMElement object
* @return mixed FALSE if there is no other element, or a DOMElement object
*/
public function get_next_element($element) {
$parent = $element->parentNode;
$next = false;
foreach ($parent->childNodes as $child) {
if ($next) {
return $child;
}
if ($child->isSameNode($element)) {
$next = true;
}
}
return false;
}
/**
* To minimize notices, this compares an object's property to the valus
* and returns true or false. False will also be returned if the object is
* not really an object, or if the property doesn't exist at all
* @param object $object The object too look at
* @param string $property The name of the property
* @param mixed $value The value to check against
* @param bool $trim Whether the property value should be trimmed
* @param bool $lower Whether the property value should be compared on lower case
*
* @return bool
*/
public function property_is_equal($object, string $property, $value, bool $trim = false, bool $lower = false) {
if (!is_object($object)) {
return false;
}
if (!property_exists($object, $property)) {
return false;
}
$propertyvalue = $object->$property;
if ($trim) {
$propertyvalue = trim($propertyvalue);
$value = trim($value);
}
if ($lower) {
$propertyvalue = strtolower($propertyvalue);
$value = strtolower($value);
}
return ($propertyvalue == $value);
}
/**
* Returns the parent of an elment that has a given tag Name, but
* stops the search if it hits the $limiter tag
* @param object $element The DOMElement object to search on
* @param string $tagname The name of the tag of the parent to find
* @param string $limiter The tag name of the element to stop searching on
* regardless of the results (like search for a parent "P" tag
* of this node but stop if you reach "body")
* @return mixed FALSE if no parent is found, or the DOMElement object of the found parent
*/
public function get_parent($element, string $tagname, string $limiter) {
while ($element) {
if ($element->tagName == $tagname) {
return $element;
}
if ($element->tagName == $limiter) {
return false;
}
$element = $element->parentNode;
}
return false;
}
/**
* Returns if a GIF files is animated or not http://us.php.net/manual/en/function.imagecreatefromgif.php#88005
* @param string $filename
* @return int
*/
public function image_is_animated($filename): int {
if (!($fh = @fopen($filename, 'rb'))) {
return false;
}
$count = 0;
// An animated gif contains multiple "frames", with each frame having a
// header made up of:
// * a static 4-byte sequence (\x00\x21\xF9\x04)
// * 4 variable bytes
// * a static 2-byte sequence (\x00\x2C).
// We read through the file til we reach the end of the file, or we've found
// at least 2 frame headers.
while (!feof($fh) && $count < 2) {
$chunk = fread($fh, 1024 * 100); // Read 100kb at a time.
$count += preg_match_all('#\x00\x21\xF9\x04.{4}\x00\x2C#s', $chunk, $matches);
}
fclose($fh);
return $count > 1;
}
/**
* Returns if there are any printable/readable characters within an element.
* This finds both node values or images with alt text.
* @param object $element The given element to look at
* @return bool TRUE if contains readable text, FALSE if otherwise
*/
public function element_contains_readable_text($element): bool {
if (is_a($element, 'DOMText')) {
if (trim($element->wholeText) != '') {
return true;
}
} else {
if (trim($element->nodeValue) != '' ||
($element->hasAttribute('alt') && trim($element->getAttribute('alt')) != '')) {
return true;
}
if (method_exists($element, 'hasChildNodes') && $element->hasChildNodes()) {
foreach ($element->childNodes as $child) {
if ($this->element_contains_readable_text($child)) {
return true;
}
}
}
}
return false;
}
/**
* Returns an array of the newwindowphrases for all enabled language packs.
* @return array of the newwindowphrases for all enabled language packs.
*/
public static function get_all_newwindowphrases(): array {
// Need to process all enabled lang versions of newwindowphrases.
return static::get_all_phrases('newwindowphrases');
}
/**
* Returns an array of the invalidlinkphrases for all enabled language packs.
* @return array of the invalidlinkphrases for all enabled language packs.
*/
public static function get_all_invalidlinkphrases(): array {
// Need to process all enabled lang versions of invalidlinkphrases.
return static::get_all_phrases('invalidlinkphrases');
}
/**
* Returns an array of the relevant phrases for all enabled language packs.
* @param string $stringname the language string identifier you want get the phrases for.
* @return array of the invalidlinkphrases for all enabled language packs.
*/
protected static function get_all_phrases(string $stringname): array {
$stringmgr = get_string_manager();
$allstrings = [];
// Somehow, an invalid string was requested. Add exception handling for this in the future.
if (!$stringmgr->string_exists($stringname, manager::PLUGINNAME)) {
return $allstrings;
}
// Need to process all enabled lang versions of invalidlinkphrases.
$enabledlangs = $stringmgr->get_list_of_translations();
foreach ($enabledlangs as $lang => $value) {
$tmpstring = (string)new \lang_string($stringname, manager::PLUGINNAME, null, $lang);
$tmplangarray = explode('|', $tmpstring);
$allstrings = array_merge($allstrings, $tmplangarray);
}
// Removing duplicates if a lang is enabled, yet using default 'en' due to no relevant lang file.
$allstrings = array_unique($allstrings);
return $allstrings;
}
/**
* Assesses whether a string contains any readable text, which is text that
* contains any characters other than whitespace characters.
*
* @param string $text
* @return bool
*/
public static function is_text_readable(string $text): bool {
// These characters in order are a space, tab, line feed, carriage return,
// NUL-byte, vertical tab and non-breaking space unicode character \xc2\xa0.
$emptycharacters = " \t\n\r\0\x0B\xc2\xa0";
return trim($text, $emptycharacters) != '';
}
}
@@ -0,0 +1,66 @@
<?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 tool_brickfield\local\htmlchecker\common\checks;
use tool_brickfield\local\htmlchecker\common\brickfield_accessibility_test;
/**
* Brickfield accessibility HTML checker library.
*
* Anchor should not open new window without warning.
* a (anchor) element must not contain a target attribute unless the target attribute value is either _self, _top, or _parent.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class a_links_dont_open_new_window extends brickfield_accessibility_test {
/** @var int $defaultseverity The default severity code for this test. */
public $defaultseverity = \tool_brickfield\local\htmlchecker\brickfield_accessibility::BA_TEST_SEVERE;
/** @var string[] A list of targets allowed that don't open a new window. */
public $allowedtargets = array('_self', '_parent', '_top', '');
/**
* The main check function. This is called by the parent class to actually check content.
*/
public function check(): void {
// Need to process all enabled lang versions of newwindowphrases.
$text = brickfield_accessibility_test::get_all_newwindowphrases();
foreach ($this->get_all_elements('a') as $a) {
if ($a->hasAttribute('target') && !in_array($a->getAttribute('target'), $this->allowedtargets)) {
$phrasefound = false;
foreach ($text as $phrase) {
// Sanity check for readable text.
if (!brickfield_accessibility_test::is_text_readable($phrase)) {
break;
}
$pos = stripos($a->nodeValue, $phrase);
if ($pos !== false) {
$phrasefound = true;
break;
}
}
if (!$phrasefound) {
$this->add_report($a);
}
}
}
}
}
@@ -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/>.
namespace tool_brickfield\local\htmlchecker\common\checks;
use tool_brickfield\local\htmlchecker\common\brickfield_accessibility_test;
/**
* Brickfield accessibility HTML checker library.
*
* Each source anchor contains text.
* a (anchor) element must contain text. The text may occur in the anchor text or in the title attribute of the anchor
* or in the Alt text of an image used within the anchor.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class a_must_contain_text extends brickfield_accessibility_test {
/** @var int The default severity code for this test. */
public $defaultseverity = \tool_brickfield\local\htmlchecker\brickfield_accessibility::BA_TEST_SEVERE;
/**
* The main check function. This is called by the parent class to actually check content.
*/
public function check(): void {
foreach ($this->get_all_elements('a') as $a) {
if (!$this->element_contains_readable_text($a) && ($a->hasAttribute('href'))) {
$this->add_report($a);
}
}
}
/**
* Returns if a link is not a candidate to be an anchor (which does
* not need text).
* @param \DOMElement $a
* @return bool Whether is is a link (TRUE) or an anchor (FALSE)
*/
public function is_not_anchor(\DOMElement $a): bool {
return (!($a->hasAttribute('name') && !$a->hasAttribute('href')));
}
}
@@ -0,0 +1,70 @@
<?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 tool_brickfield\local\htmlchecker\common\checks;
use tool_brickfield\local\htmlchecker\brickfield_accessibility;
use tool_brickfield\local\htmlchecker\common\brickfield_accessibility_test;
use tool_brickfield\manager;
/**
* Brickfield accessibility HTML checker library.
*
* Suspicious link text.
* 'a' (anchor) element cannot contain any of the following text, such as (English): "click here".
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class a_suspicious_link_text extends brickfield_accessibility_test {
/**
* @var int The default severity code for this test.
*/
public $defaultseverity = brickfield_accessibility::BA_TEST_SEVERE;
/**
* The main check function. This is called by the parent class to actually check content
*/
public function check(): void {
// Need to process all enabled lang versions of invalidlinkphrases.
$badtext = brickfield_accessibility_test::get_all_invalidlinkphrases();
foreach ($this->get_all_elements('a') as $a) {
if (in_array(strtolower(trim($a->nodeValue)), $badtext) || $a->nodeValue == $a->getAttribute('href')) {
// If the link text matches invalid phrases.
$this->add_report($a);
} else if (brickfield_accessibility::match_urls($a->nodeValue, $a->getAttribute('href'))) {
// If the link text is the same as the link URL.
$this->add_report($a);
}
}
}
/**
* Return all 'a' elements.
*
* @return array
*/
public function search(): array {
$data = [];
foreach ($this->get_all_elements('a') as $a) {
$data[] = $a;
}
return $data;
}
}
@@ -0,0 +1,65 @@
<?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 tool_brickfield\local\htmlchecker\common\checks;
use tool_brickfield\local\htmlchecker\common\brickfield_accessibility_test;
/**
* Brickfield accessibility HTML checker library.
*
* Area should not open new window without warning.
* Area element, target attribute values must contain any one of (case insensitive) _self, _top, _parent.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class area_dont_open_new_window extends brickfield_accessibility_test {
/** @var int The default severity code for this test. */
public $defaultseverity = \tool_brickfield\local\htmlchecker\brickfield_accessibility::BA_TEST_SEVERE;
/** @var string[] A list of targets which are allowed. */
public $allowedtargets = array('_self', '_parent', '_top');
/**
* The main check function. This is called by the parent class to actually check content
*/
public function check(): void {
// Need to process all enabled lang versions of newwindowphrases.
$text = brickfield_accessibility_test::get_all_newwindowphrases();
foreach ($this->get_all_elements('area') as $area) {
if ($area->hasAttribute('target') && !in_array($area->getAttribute('target'), $this->allowedtargets)) {
$phrasefound = false;
foreach ($text as $phrase) {
// Sanity check for readable text.
if (!brickfield_accessibility_test::is_text_readable($phrase)) {
break;
}
$pos = stripos($area->getAttribute('alt'), $phrase);
if ($pos !== false) {
$phrasefound = true;
break;
}
}
if (!$phrasefound) {
$this->add_report($area);
}
}
}
}
}
@@ -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 tool_brickfield\local\htmlchecker\common\checks;
use tool_brickfield\local\htmlchecker\common\brickfield_accessibility_test;
/**
* Brickfield accessibility HTML checker library.
*
* All area elements have an alt attribute.
* Area elements must contain a alt attribute.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class area_has_alt_value extends brickfield_accessibility_test {
/**
* @var int The default severity code for this test.
*/
public $defaultseverity = \tool_brickfield\local\htmlchecker\brickfield_accessibility::BA_TEST_SEVERE;
/**
* The main check function. This is called by the parent class to actually check content
*/
public function check(): void {
foreach ($this->get_all_elements('area') as $area) {
if (!$area->hasAttribute('alt')) {
$this->add_report($area);
}
}
}
}
@@ -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/>.
namespace tool_brickfield\local\htmlchecker\common\checks;
use tool_brickfield\local\htmlchecker\common\brickfield_accessibility_tag_test;
/**
* Brickfield accessibility HTML checker library.
*
* 'basefont' must not be used.
* This error is generated for all basefont elements.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class basefont_is_not_used extends brickfield_accessibility_tag_test {
/** @var int The default severity code for this test. */
public $defaultseverity = \tool_brickfield\local\htmlchecker\brickfield_accessibility::BA_TEST_SEVERE;
/** @var string The tag this test will fire on. */
public $tag = 'basefont';
}
@@ -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/>.
namespace tool_brickfield\local\htmlchecker\common\checks;
use tool_brickfield\local\htmlchecker\common\brickfield_accessibility_tag_test;
/**
* Brickfield accessibility HTML checker library.
*
* 'blink' element is not used.
* This error is generated for all blink elements.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class blink_is_not_used extends brickfield_accessibility_tag_test {
/** @var int The default severity code for this test. */
public $defaultseverity = \tool_brickfield\local\htmlchecker\brickfield_accessibility::BA_TEST_SEVERE;
/** @var string The tag this test will fire on. */
public $tag = 'blink';
}
@@ -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/>.
namespace tool_brickfield\local\htmlchecker\common\checks;
use tool_brickfield\local\htmlchecker\common\brickfield_accessibility_tag_test;
/**
* Brickfield accessibility HTML checker library.
*
* 'b' (bold) element is not used.
* This error will be generated for all B elements.
*
* @package tool_brickfield
* @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class bold_is_not_used extends brickfield_accessibility_tag_test {
/** @var int The default severity code for this test. */
public $defaultseverity = \tool_brickfield\local\htmlchecker\brickfield_accessibility::BA_TEST_SEVERE;
/** @var string The tag this test will fire on. */
public $tag = 'b';
}

Some files were not shown because too many files have changed in this diff Show More