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
+64
View File
@@ -0,0 +1,64 @@
<?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/>.
/**
* Provides support for the conversion of moodle1 backup to the moodle2 format
*
* @package block_html
* @copyright 2012 Paul Nicholls
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
/**
* Block conversion handler for html
*/
class moodle1_block_html_handler extends moodle1_block_handler {
private $fileman = null;
protected function convert_configdata(array $olddata) {
global $CFG;
require_once($CFG->libdir . '/db/upgradelib.php');
$instanceid = $olddata['id'];
$contextid = $this->converter->get_contextid(CONTEXT_BLOCK, $olddata['id']);
$decodeddata = base64_decode($olddata['configdata']);
list($updated, $configdata) = upgrade_fix_serialized_objects($decodeddata);
$configdata = unserialize_object($configdata);
// get a fresh new file manager for this instance
$this->fileman = $this->converter->get_file_manager($contextid, 'block_html');
// convert course files embedded in the block content
$this->fileman->filearea = 'content';
$this->fileman->itemid = 0;
$configdata->text = moodle1_converter::migrate_referenced_files($configdata->text ?? '', $this->fileman);
$configdata->format = FORMAT_HTML;
return base64_encode(serialize($configdata));
}
protected function write_inforef_xml($newdata, $data) {
$this->open_xml_writer("course/blocks/{$data['name']}_{$data['id']}/inforef.xml");
$this->xmlwriter->begin_tag('inforef');
$this->xmlwriter->begin_tag('fileref');
foreach ($this->fileman->get_fileids() as $fileid) {
$this->write_xml('file', array('id' => $fileid));
}
$this->xmlwriter->end_tag('fileref');
$this->xmlwriter->end_tag('inforef');
$this->close_xml_writer();
}
}
@@ -0,0 +1,50 @@
<?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/>.
/**
* @package block_html
* @subpackage backup-moodle2
* @copyright 2003 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
/**
* Specialised backup task for the html block
* (requires encode_content_links in some configdata attrs)
*
* TODO: Finish phpdocs
*/
class backup_html_block_task extends backup_block_task {
protected function define_my_settings() {
}
protected function define_my_steps() {
}
public function get_fileareas() {
return array('content');
}
public function get_configdata_encoded_attributes() {
return array('text'); // We need to encode some attrs in configdata
}
public static function encode_content_links($content) {
return $content; // No special encoding of links
}
}
@@ -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/>.
/**
* @package block_html
* @subpackage backup-moodle2
* @copyright 2003 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
/**
* Specialised restore task for the html block
* (requires encode_content_links in some configdata attrs)
*
* TODO: Finish phpdocs
*/
class restore_html_block_task extends restore_block_task {
protected function define_my_settings() {
}
protected function define_my_steps() {
}
public function get_fileareas() {
return array('content');
}
public function get_configdata_encoded_attributes() {
return array('text'); // We need to encode some attrs in configdata
}
public static function define_decode_contents() {
$contents = array();
$contents[] = new restore_html_block_decode_content('block_instances', 'configdata', 'block_instance');
return $contents;
}
public static function define_decode_rules() {
return array();
}
}
/**
* Specialised restore_decode_content provider that unserializes the configdata
* field, to serve the configdata->text content to the restore_decode_processor
* packaging it back to its serialized form after process
*/
class restore_html_block_decode_content extends restore_decode_content {
protected $configdata; // Temp storage for unserialized configdata
protected function get_iterator() {
global $DB;
// Build the SQL dynamically here
$fieldslist = 't.' . implode(', t.', $this->fields);
$sql = "SELECT t.id, $fieldslist
FROM {" . $this->tablename . "} t
JOIN {backup_ids_temp} b ON b.newitemid = t.id
WHERE b.backupid = ?
AND b.itemname = ?
AND t.blockname = 'html'";
$params = array($this->restoreid, $this->mapping);
return ($DB->get_recordset_sql($sql, $params));
}
protected function preprocess_field($field) {
$this->configdata = unserialize_object(base64_decode($field));
return isset($this->configdata->text) ? $this->configdata->text : '';
}
protected function postprocess_field($field) {
$this->configdata->text = $field;
return base64_encode(serialize($this->configdata));
}
}
+235
View File
@@ -0,0 +1,235 @@
<?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/>.
use core_external\util as external_util;
/**
* Form for editing HTML block instances.
*
* @package block_html
* @copyright 1999 onwards Martin Dougiamas (http://dougiamas.com)
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class block_html extends block_base {
function init() {
$this->title = get_string('pluginname', 'block_html');
}
function has_config() {
return true;
}
function applicable_formats() {
return array('all' => true);
}
function specialization() {
if (isset($this->config->title)) {
$this->title = $this->title = format_string($this->config->title, true, ['context' => $this->context]);
} else {
$this->title = get_string('newhtmlblock', 'block_html');
}
}
function instance_allow_multiple() {
return true;
}
function get_content() {
global $CFG;
require_once($CFG->libdir . '/filelib.php');
if ($this->content !== NULL) {
return $this->content;
}
$filteropt = new stdClass;
$filteropt->overflowdiv = true;
if ($this->content_is_trusted()) {
// fancy html allowed only on course, category and system blocks.
$filteropt->noclean = true;
}
$this->content = new stdClass;
$this->content->footer = '';
if (isset($this->config->text)) {
// rewrite url
$this->config->text = file_rewrite_pluginfile_urls($this->config->text, 'pluginfile.php', $this->context->id, 'block_html', 'content', NULL);
// Default to FORMAT_HTML which is what will have been used before the
// editor was properly implemented for the block.
$format = FORMAT_HTML;
// Check to see if the format has been properly set on the config
if (isset($this->config->format)) {
$format = $this->config->format;
}
$this->content->text = format_text($this->config->text, $format, $filteropt);
} else {
$this->content->text = '';
}
unset($filteropt); // memory footprint
return $this->content;
}
public function get_content_for_external($output) {
$bc = new stdClass;
$bc->title = null;
$bc->content = '';
$bc->contenformat = FORMAT_MOODLE;
$bc->footer = '';
$bc->files = [];
if (!$this->hide_header()) {
$bc->title = $this->title;
}
if (isset($this->config->text)) {
$filteropt = new stdClass;
if ($this->content_is_trusted()) {
// Fancy html allowed only on course, category and system blocks.
$filteropt->noclean = true;
}
$format = FORMAT_HTML;
// Check to see if the format has been properly set on the config.
if (isset($this->config->format)) {
$format = $this->config->format;
}
[$bc->content, $bc->contentformat] = \core_external\util::format_text(
$this->config->text,
$format,
$this->context,
'block_html',
'content',
null,
$filteropt
);
$bc->files = external_util::get_area_files($this->context->id, 'block_html', 'content', false, false);
}
return $bc;
}
/**
* Serialize and store config data
*/
function instance_config_save($data, $nolongerused = false) {
global $DB;
$config = clone($data);
// Move embedded files into a proper filearea and adjust HTML links to match
$config->text = file_save_draft_area_files($data->text['itemid'], $this->context->id, 'block_html', 'content', 0, array('subdirs'=>true), $data->text['text']);
$config->format = $data->text['format'];
parent::instance_config_save($config, $nolongerused);
}
function instance_delete() {
global $DB;
$fs = get_file_storage();
$fs->delete_area_files($this->context->id, 'block_html');
return true;
}
/**
* Copy any block-specific data when copying to a new block instance.
* @param int $fromid the id number of the block instance to copy from
* @return boolean
*/
public function instance_copy($fromid) {
$fromcontext = context_block::instance($fromid);
$fs = get_file_storage();
// Do not use draft files hacks outside of forms.
$files = $fs->get_area_files($fromcontext->id, 'block_html', 'content', 0, 'id ASC', false);
foreach ($files as $file) {
$filerecord = ['contextid' => $this->context->id];
$fs->create_file_from_storedfile($filerecord, $file);
}
return true;
}
function content_is_trusted() {
global $SCRIPT;
if (!$context = context::instance_by_id($this->instance->parentcontextid, IGNORE_MISSING)) {
return false;
}
//find out if this block is on the profile page
if ($context->contextlevel == CONTEXT_USER) {
if ($SCRIPT === '/my/index.php') {
// this is exception - page is completely private, nobody else may see content there
// that is why we allow JS here
return true;
} else {
// no JS on public personal pages, it would be a big security issue
return false;
}
}
return true;
}
/**
* The block should only be dockable when the title of the block is not empty
* and when parent allows docking.
*
* @return bool
*/
public function instance_can_be_docked() {
return (!empty($this->config->title) && parent::instance_can_be_docked());
}
/*
* Add custom html attributes to aid with theming and styling
*
* @return array
*/
function html_attributes() {
global $CFG;
$attributes = parent::html_attributes();
if (!empty($CFG->block_html_allowcssclasses)) {
if (!empty($this->config->classes)) {
$attributes['class'] .= ' '.$this->config->classes;
}
}
return $attributes;
}
/**
* Return the plugin config settings for external functions.
*
* @return stdClass the configs for both the block instance and plugin
* @since Moodle 3.8
*/
public function get_config_for_external() {
global $CFG;
// Return all settings for all users since it is safe (no private keys, etc..).
$instanceconfigs = !empty($this->config) ? $this->config : new stdClass();
$pluginconfigs = (object) ['allowcssclasses' => $CFG->block_html_allowcssclasses];
return (object) [
'instance' => $instanceconfigs,
'plugin' => $pluginconfigs,
];
}
}
+243
View File
@@ -0,0 +1,243 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Privacy Subsystem implementation for block_html.
*
* @package block_html
* @copyright 2018 Andrew Nicols <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace block_html\privacy;
defined('MOODLE_INTERNAL') || die();
use \core_privacy\local\request\userlist;
use \core_privacy\local\request\approved_contextlist;
use \core_privacy\local\request\approved_userlist;
use \core_privacy\local\request\writer;
use \core_privacy\local\request\helper;
use \core_privacy\local\request\deletion_criteria;
use \core_privacy\local\metadata\collection;
/**
* Privacy Subsystem implementation for block_html.
*
* @copyright 2018 Andrew Nicols <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider implements
// The block_html block stores user provided data.
\core_privacy\local\metadata\provider,
// This plugin is capable of determining which users have data within it.
\core_privacy\local\request\core_userlist_provider,
// The block_html block provides data directly to core.
\core_privacy\local\request\plugin\provider {
/**
* Returns information about how block_html stores its data.
*
* @param collection $collection The initialised collection to add items to.
* @return collection A listing of user data stored through this system.
*/
public static function get_metadata(collection $collection): collection {
$collection->link_subsystem('block', 'privacy:metadata:block');
return $collection;
}
/**
* Get the list of contexts that contain user information for the specified user.
*
* @param int $userid The user to search.
* @return contextlist $contextlist The contextlist containing the list of contexts used in this plugin.
*/
public static function get_contexts_for_userid(int $userid): \core_privacy\local\request\contextlist {
// This block doesn't know who information is stored against unless it
// is at the user context.
$contextlist = new \core_privacy\local\request\contextlist();
$sql = "SELECT c.id
FROM {block_instances} b
INNER JOIN {context} c ON c.instanceid = b.id AND c.contextlevel = :contextblock
INNER JOIN {context} bpc ON bpc.id = b.parentcontextid
WHERE b.blockname = 'html'
AND bpc.contextlevel = :contextuser
AND bpc.instanceid = :userid";
$params = [
'contextblock' => CONTEXT_BLOCK,
'contextuser' => CONTEXT_USER,
'userid' => $userid,
];
$contextlist->add_from_sql($sql, $params);
return $contextlist;
}
/**
* Get the list of users who have data within a context.
*
* @param userlist $userlist The userlist containing the list of users who have data in this context/plugin combination.
*/
public static function get_users_in_context(userlist $userlist) {
// This block doesn't know who information is stored against unless it
// is at the user context.
$context = $userlist->get_context();
if (!$context instanceof \context_block) {
return;
}
$sql = "SELECT bpc.instanceid AS userid
FROM {block_instances} bi
JOIN {context} bpc ON bpc.id = bi.parentcontextid
WHERE bi.blockname = 'html'
AND bpc.contextlevel = :contextuser
AND bi.id = :blockinstanceid";
$params = [
'contextuser' => CONTEXT_USER,
'blockinstanceid' => $context->instanceid
];
$userlist->add_from_sql('userid', $sql, $params);
}
/**
* Export all user data for the specified user, in the specified contexts.
*
* @param approved_contextlist $contextlist The approved contexts to export information for.
*/
public static function export_user_data(approved_contextlist $contextlist) {
global $DB;
$user = $contextlist->get_user();
list($contextsql, $contextparams) = $DB->get_in_or_equal($contextlist->get_contextids(), SQL_PARAMS_NAMED);
$sql = "SELECT
c.id AS contextid,
bi.*
FROM {context} c
INNER JOIN {block_instances} bi ON bi.id = c.instanceid AND c.contextlevel = :contextlevel
WHERE bi.blockname = 'html'
AND(
c.id {$contextsql}
)
";
$params = [
'contextlevel' => CONTEXT_BLOCK,
];
$params += $contextparams;
$instances = $DB->get_recordset_sql($sql, $params);
foreach ($instances as $instance) {
$context = \context_block::instance($instance->id);
$block = block_instance('html', $instance);
if (empty($block->config)) {
// Skip this block. It has not been configured.
continue;
}
$html = writer::with_context($context)
->rewrite_pluginfile_urls([], 'block_html', 'content', null, $block->config->text);
// Default to FORMAT_HTML which is what will have been used before the
// editor was properly implemented for the block.
$format = isset($block->config->format) ? $block->config->format : FORMAT_HTML;
$filteropt = (object) [
'overflowdiv' => true,
'noclean' => true,
];
$html = format_text($html, $format, $filteropt);
$data = helper::get_context_data($context, $user);
helper::export_context_files($context, $user);
$data->title = $block->config->title;
$data->content = $html;
writer::with_context($context)->export_data([], $data);
}
$instances->close();
}
/**
* Delete all data for all users in the specified context.
*
* @param \context $context The specific context to delete data for.
*/
public static function delete_data_for_all_users_in_context(\context $context) {
if (!$context instanceof \context_block) {
return;
}
// The only way to delete data for the html block is to delete the block instance itself.
if ($blockinstance = static::get_instance_from_context($context)) {
blocks_delete_instance($blockinstance);
}
}
/**
* Delete multiple users within a single context.
*
* @param approved_userlist $userlist The approved context and user information to delete information for.
*/
public static function delete_data_for_users(approved_userlist $userlist) {
$context = $userlist->get_context();
if ($context instanceof \context_block && ($blockinstance = static::get_instance_from_context($context))) {
blocks_delete_instance($blockinstance);
}
}
/**
* Delete all user data for the specified user, in the specified contexts.
*
* @param approved_contextlist $contextlist The approved contexts and user information to delete information for.
*/
public static function delete_data_for_user(approved_contextlist $contextlist) {
// The only way to delete data for the html block is to delete the block instance itself.
foreach ($contextlist as $context) {
if (!$context instanceof \context_block) {
continue;
}
if ($blockinstance = static::get_instance_from_context($context)) {
blocks_delete_instance($blockinstance);
}
}
}
/**
* Get the block instance record for the specified context.
*
* @param \context_block $context The context to fetch
* @return \stdClass
*/
protected static function get_instance_from_context(\context_block $context) {
global $DB;
return $DB->get_record('block_instances', ['id' => $context->instanceid, 'blockname' => 'html']);
}
}
+92
View File
@@ -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/>.
/**
* Search area for block_html blocks
*
* @package block_html
* @copyright 2017 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace block_html\search;
use core_search\moodle_recordset;
defined('MOODLE_INTERNAL') || die();
/**
* Search area for block_html blocks
*
* @package block_html
* @copyright 2017 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class content extends \core_search\base_block {
public function get_document($record, $options = array()) {
// Create empty document.
$doc = \core_search\document_factory::instance($record->id,
$this->componentname, $this->areaname);
// Get stdclass object with data from DB.
$data = unserialize_object(base64_decode($record->configdata));
// Get content.
$content = content_to_text($data->text, $data->format);
$doc->set('content', $content);
if (isset($data->title)) {
// If there is a title, use it as title.
$doc->set('title', content_to_text($data->title, false));
} else {
// If there is no title, use the content text again.
$doc->set('title', shorten_text($content));
}
// Set standard fields.
$doc->set('contextid', $record->contextid);
$doc->set('type', \core_search\manager::TYPE_TEXT);
$doc->set('courseid', $record->courseid);
$doc->set('modified', $record->timemodified);
$doc->set('owneruserid', \core_search\manager::NO_OWNER_ID);
// Mark document new if appropriate.
if (isset($options['lastindexedtime']) &&
($options['lastindexedtime'] < $record->timecreated)) {
// If the document was created after the last index time, it must be new.
$doc->set_is_new(true);
}
return $doc;
}
public function uses_file_indexing() {
return true;
}
public function attach_files($document) {
$fs = get_file_storage();
$context = \context::instance_by_id($document->get('contextid'));
$files = $fs->get_area_files($context->id, 'block_html', 'content',
false, 'itemid, filepath, filename', false);
foreach ($files as $file) {
$document->add_stored_file($file);
}
}
}
+51
View File
@@ -0,0 +1,51 @@
<?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/>.
/**
* HTML block caps.
*
* @package block_html
* @copyright Mark Nelson <markn@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
$capabilities = array(
'block/html:myaddinstance' => array(
'captype' => 'write',
'contextlevel' => CONTEXT_SYSTEM,
'archetypes' => array(
'user' => CAP_ALLOW
),
'clonepermissionsfrom' => 'moodle/my:manageblocks'
),
'block/html:addinstance' => array(
'riskbitmask' => RISK_SPAM | RISK_XSS,
'captype' => 'write',
'contextlevel' => CONTEXT_BLOCK,
'archetypes' => array(
'editingteacher' => CAP_ALLOW,
'manager' => CAP_ALLOW
),
'clonepermissionsfrom' => 'moodle/site:manageblocks'
),
);
+45
View File
@@ -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/>.
/**
* This file keeps track of upgrades to the html block
*
* @since Moodle 2.0
* @package block_html
* @copyright 2010 Dongsheng Cai
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
/**
* Upgrade code for the HTML block.
*
* @param int $oldversion
*/
function xmldb_block_html_upgrade($oldversion) {
// Automatically generated Moodle v4.1.0 release upgrade line.
// Put any upgrade step following this.
// Automatically generated Moodle v4.2.0 release upgrade line.
// Put any upgrade step following this.
// Automatically generated Moodle v4.3.0 release upgrade line.
// Put any upgrade step following this.
// Automatically generated Moodle v4.4.0 release upgrade line.
// Put any upgrade step following this.
return true;
}
+100
View File
@@ -0,0 +1,100 @@
<?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/>.
/**
* Form for editing HTML block instances.
*
* @package block_html
* @copyright 2009 Tim Hunt
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
/**
* Form for editing HTML block instances.
*
* @copyright 2009 Tim Hunt
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class block_html_edit_form extends block_edit_form {
protected function specific_definition($mform) {
global $CFG;
// Fields for editing HTML block title and contents.
$mform->addElement('header', 'configheader', get_string('blocksettings', 'block'));
$mform->addElement('text', 'config_title', get_string('configtitle', 'block_html'));
$mform->setType('config_title', PARAM_TEXT);
$editoroptions = array('maxfiles' => EDITOR_UNLIMITED_FILES, 'noclean'=>true, 'context'=>$this->block->context);
$mform->addElement('editor', 'config_text', get_string('configcontent', 'block_html'), null, $editoroptions);
$mform->addRule('config_text', null, 'required', null, 'client');
$mform->setType('config_text', PARAM_RAW); // XSS is prevented when printing the block contents and serving files
if (!empty($CFG->block_html_allowcssclasses)) {
$mform->addElement('text', 'config_classes', get_string('configclasses', 'block_html'));
$mform->setType('config_classes', PARAM_TEXT);
$mform->addHelpButton('config_classes', 'configclasses', 'block_html');
}
}
function set_data($defaults) {
if (!empty($this->block->config) && !empty($this->block->config->text)) {
$text = $this->block->config->text;
$draftid_editor = file_get_submitted_draft_itemid('config_text');
if (empty($text)) {
$currenttext = '';
} else {
$currenttext = $text;
}
$defaults->config_text['text'] = file_prepare_draft_area($draftid_editor, $this->block->context->id, 'block_html', 'content', 0, array('subdirs'=>true), $currenttext);
$defaults->config_text['itemid'] = $draftid_editor;
$defaults->config_text['format'] = $this->block->config->format ?? FORMAT_MOODLE;
} else {
$text = '';
}
if (!$this->block->user_can_edit() && !empty($this->block->config->title)) {
// If a title has been set but the user cannot edit it format it nicely
$title = $this->block->config->title;
$defaults->config_title = format_string($title, true, $this->page->context);
// Remove the title from the config so that parent::set_data doesn't set it.
unset($this->block->config->title);
}
// have to delete text here, otherwise parent::set_data will empty content
// of editor
unset($this->block->config->text);
parent::set_data($defaults);
// restore $text
if (!isset($this->block->config)) {
$this->block->config = new stdClass();
}
$this->block->config->text = $text;
if (isset($title)) {
// Reset the preserved title
$this->block->config->title = $title;
}
}
/**
* Display the configuration form when block is being added to the page
*
* @return bool
*/
public static function display_form_when_adding(): bool {
return true;
}
}
+36
View File
@@ -0,0 +1,36 @@
<?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/>.
/**
* Strings for component 'block_html', language 'en', branch 'MOODLE_20_STABLE'
*
* @package block_html
* @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
$string['allowadditionalcssclasses'] = 'Allow additional CSS classes';
$string['configallowadditionalcssclasses'] = 'Adds a configuration option to Text block instances allowing additional CSS classes to be set.';
$string['configclasses'] = 'Additional CSS classes';
$string['configclasses_help'] = 'The purpose of this configuration is to aid with theming by helping distinguish text blocks from each other. Any CSS classes entered here (space delimited) will be appended to the block\'s default classes.';
$string['configcontent'] = 'Content';
$string['configtitle'] = 'Text block title';
$string['html:addinstance'] = 'Add a new text block';
$string['html:myaddinstance'] = 'Add a new text block to Dashboard';
$string['newhtmlblock'] = '(new text block)';
$string['pluginname'] = 'Text';
$string['search:content'] = 'Text block content';
$string['privacy:metadata:block'] = 'The Text block stores all of its data within the block subsystem.';
+135
View File
@@ -0,0 +1,135 @@
<?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/>.
/**
* Form for editing HTML block instances.
*
* @copyright 2010 Petr Skoda (http://skodak.org)
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @package block_html
* @category files
* @param stdClass $course course object
* @param stdClass $birecord_or_cm block instance record
* @param context $context context object
* @param string $filearea file area
* @param array $args extra arguments
* @param bool $forcedownload whether or not force download
* @param array $options additional options affecting the file serving
* @return bool
* @todo MDL-36050 improve capability check on stick blocks, so we can check user capability before sending images.
*/
function block_html_pluginfile($course, $birecord_or_cm, $context, $filearea, $args, $forcedownload, array $options=array()) {
global $DB, $CFG, $USER;
if ($context->contextlevel != CONTEXT_BLOCK) {
send_file_not_found();
}
// If block is in course context, then check if user has capability to access course.
if ($context->get_course_context(false)) {
require_course_login($course);
} else if ($CFG->forcelogin) {
require_login();
} else {
// Get parent context and see if user have proper permission.
$parentcontext = $context->get_parent_context();
if ($parentcontext->contextlevel === CONTEXT_COURSECAT) {
// Check if category is visible and user can view this category.
if (!core_course_category::get($parentcontext->instanceid, IGNORE_MISSING)) {
send_file_not_found();
}
} else if ($parentcontext->contextlevel === CONTEXT_USER && $parentcontext->instanceid != $USER->id) {
// The block is in the context of a user, it is only visible to the user who it belongs to.
send_file_not_found();
}
// At this point there is no way to check SYSTEM context, so ignoring it.
}
if ($filearea !== 'content') {
send_file_not_found();
}
$fs = get_file_storage();
$filename = array_pop($args);
$filepath = $args ? '/'.implode('/', $args).'/' : '/';
if (!$file = $fs->get_file($context->id, 'block_html', 'content', 0, $filepath, $filename) or $file->is_directory()) {
send_file_not_found();
}
if ($parentcontext = context::instance_by_id($birecord_or_cm->parentcontextid, IGNORE_MISSING)) {
if ($parentcontext->contextlevel == CONTEXT_USER) {
// force download on all personal pages including /my/
//because we do not have reliable way to find out from where this is used
$forcedownload = true;
}
} else {
// weird, there should be parent context, better force dowload then
$forcedownload = true;
}
// NOTE: it woudl be nice to have file revisions here, for now rely on standard file lifetime,
// do not lower it because the files are dispalyed very often.
\core\session\manager::write_close();
send_stored_file($file, null, 0, $forcedownload, $options);
}
/**
* Perform global search replace such as when migrating site to new URL.
* @param $search
* @param $replace
* @return void
*/
function block_html_global_db_replace($search, $replace) {
global $DB;
$instances = $DB->get_recordset('block_instances', array('blockname' => 'html'));
foreach ($instances as $instance) {
// TODO: intentionally hardcoded until MDL-26800 is fixed
$config = unserialize_object(base64_decode($instance->configdata));
if (isset($config->text) and is_string($config->text)) {
$config->text = str_replace($search, $replace, $config->text);
$DB->update_record('block_instances', ['id' => $instance->id,
'configdata' => base64_encode(serialize($config)), 'timemodified' => time()]);
}
}
$instances->close();
}
/**
* Given an array with a file path, it returns the itemid and the filepath for the defined filearea.
*
* @param string $filearea The filearea.
* @param array $args The path (the part after the filearea and before the filename).
* @return array The itemid and the filepath inside the $args path, for the defined filearea.
*/
function block_html_get_path_from_pluginfile(string $filearea, array $args): array {
// This block never has an itemid (the number represents the revision but it's not stored in database).
array_shift($args);
// Get the filepath.
if (empty($args)) {
$filepath = '/';
} else {
$filepath = '/' . implode('/', $args) . '/';
}
return [
'itemid' => 0,
'filepath' => $filepath,
];
}
+32
View File
@@ -0,0 +1,32 @@
<?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/>.
/**
* Settings for the HTML block
*
* @copyright 2012 Aaron Barnes
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @package block_html
*/
defined('MOODLE_INTERNAL') || die;
if ($ADMIN->fulltree) {
$settings->add(new admin_setting_configcheckbox('block_html_allowcssclasses', get_string('allowadditionalcssclasses', 'block_html'),
get_string('configallowadditionalcssclasses', 'block_html'), 0));
}
@@ -0,0 +1,39 @@
@block @block_html @core_block
Feature: Adding and configuring Text blocks
In order to have custom blocks on a page
As admin
I need to be able to create, configure and change Text blocks
@javascript
Scenario: Configuring the Text block with Javascript on
Given I log in as "admin"
And I am on site homepage
When I turn editing mode on
And I add the "Text" block to the default region with:
| Text block title | |
| Content | Static text without a header |
Then I should not see "(new text block)"
And I configure the "block_html" block
And I set the field "Text block title" to "The Text block header"
And I set the field "Content" to "Static text with a header"
And I press "Save changes"
And "block_html" "block" should exist
And "The Text block header" "block" should exist
And I should see "Static text with a header" in the "The Text block header" "block"
Scenario: Configuring the Text block with Javascript off
Given I log in as "admin"
And I am on site homepage
When I turn editing mode on
And I add the "Text" block
And I configure the "(new text block)" block
And I set the field "Content" to "Static text without a header"
And I press "Save changes"
Then I should not see "(new text block)"
And I configure the "block_html" block
And I set the field "Text block title" to "The Text block header"
And I set the field "Content" to "Static text with a header"
And I press "Save changes"
And "block_html" "block" should exist
And "The Text block header" "block" should exist
And I should see "Static text with a header" in the "The Text block header" "block"
@@ -0,0 +1,35 @@
@block @block_html
Feature: Text blocks in a course
In order to have one or multiple Text blocks in a course
As a teacher
I need to be able to create and change such blocks
Scenario: Adding Text block in a course
Given the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Terry1 | Teacher1 | teacher@example.com |
| student1 | Sam1 | Student1 | student1@example.com |
And the following "courses" exist:
| fullname | shortname |
| Course 1 | C1 |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
When I log in as "teacher1"
And I am on "Course 1" course homepage with editing mode on
And I add the "Text" block
And I configure the "(new text block)" block
And I set the field "Content" to "First block content"
And I set the field "Text block title" to "First block header"
And I press "Save changes"
And I add the "Text" block
And I configure the "(new text block)" block
And I set the field "Content" to "Second block content"
And I set the field "Text block title" to "Second block header"
And I press "Save changes"
And I log out
And I log in as "student1"
And I am on "Course 1" course homepage
And I should see "First block content" in the "First block header" "block"
And I should see "Second block content" in the "Second block header" "block"
@@ -0,0 +1,42 @@
@block @block_html
Feature: Adding and configuring multiple Text blocks
In order to have one or multiple Text blocks on a page
As admin
I need to be able to create, configure and change Text blocks
Background:
Given I log in as "admin"
And I am on site homepage
When I turn editing mode on
And I add the "Text" block
Scenario: Other users can not see Text block that has not been configured
Then "(new text block)" "block" should exist
And I log out
And "(new text block)" "block" should not exist
And "block_html" "block" should not exist
Scenario: Other users can see Text block that has been configured even when it has no header
And I configure the "(new text block)" block
And I set the field "Content" to "Static text without a header"
And I press "Save changes"
Then I should not see "(new text block)"
And I log out
And I am on homepage
And "block_html" "block" should exist
And I should see "Static text without a header" in the "block_html" "block"
And I should not see "(new text block)"
Scenario: Adding multiple instances of Text block on a page
And I configure the "block_html" block
And I set the field "Text block title" to "The Text block header"
And I set the field "Content" to "Static text with a header"
And I press "Save changes"
And I add the "Text" block
And I configure the "(new text block)" block
And I set the field "Text block title" to "The second Text block header"
And I set the field "Content" to "Second block contents"
And I press "Save changes"
And I log out
Then I should see "Static text with a header" in the "The Text block header" "block"
And I should see "Second block contents" in the "The second Text block header" "block"
+96
View File
@@ -0,0 +1,96 @@
<?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 block_html;
/**
* Unit test for block_html class.
*
* @package block_html
* @copyright 2022 Open LMS (https://www.openlms.net/)
* @author Petr Skoda
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*
* @coversDefaultClass \block_html
*/
class block_html_test extends \advanced_testcase {
/**
* Tests instance files copying.
* @covers ::instance_copy
*/
public function test_instance_copy(): void {
global $USER;
$this->resetAfterTest();
$this->setAdminUser();
$fs = get_file_storage();
$course = $this->getDataGenerator()->create_course();
$block1 = $this->create_block($course);
$itemid = file_get_unused_draft_itemid();
$fs = get_file_storage();
$usercontext = \context_user::instance($USER->id);
$fs->create_file_from_string(['component' => 'user', 'filearea' => 'draft',
'contextid' => $usercontext->id, 'itemid' => $itemid, 'filepath' => '/',
'filename' => 'file.txt'], 'File content');
$data = (object)['title' => 'Block title', 'text' => ['text' => 'Block text',
'itemid' => $itemid, 'format' => FORMAT_HTML]];
$block1->instance_config_save($data);
$this->assertTrue($fs->file_exists($block1->context->id, 'block_html', 'content', 0, '/', 'file.txt'));
$block2 = $this->create_block($course);
$this->assertFalse($fs->file_exists($block2->context->id, 'block_html', 'content', 0, '/', 'file.txt'));
$this->setUser(null);
$block2->instance_copy($block1->instance->id);
$this->assertTrue($fs->file_exists($block2->context->id, 'block_html', 'content', 0, '/', 'file.txt'));
}
/**
* Constructs a page object for the test course.
*
* @param \stdClass $course Moodle course object
* @return \moodle_page Page object representing course view
*/
protected static function construct_page($course): \moodle_page {
$context = \context_course::instance($course->id);
$page = new \moodle_page();
$page->set_context($context);
$page->set_course($course);
$page->set_pagelayout('standard');
$page->set_pagetype('course-view');
$page->blocks->load_blocks();
return $page;
}
/**
* Creates an HTML block on a course.
*
* @param \stdClass $course Course object
* @return \block_html Block instance object
*/
protected function create_block($course): \block_html {
$page = self::construct_page($course);
$page->blocks->add_block_at_end_of_default_region('html');
// Load the block.
$page = self::construct_page($course);
$page->blocks->load_blocks();
$blocks = $page->blocks->get_blocks_for_region($page->blocks->get_default_region());
$block = end($blocks);
return $block;
}
}
+440
View File
@@ -0,0 +1,440 @@
<?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/>.
/**
* Unit tests for the block_html implementation of the privacy API.
*
* @package block_html
* @category test
* @copyright 2018 Andrew Nicols <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace block_html\privacy;
defined('MOODLE_INTERNAL') || die();
use core_privacy\local\request\writer;
use core_privacy\local\request\approved_contextlist;
use core_privacy\local\request\approved_userlist;
use block_html\privacy\provider;
/**
* Unit tests for the block_html implementation of the privacy API.
*
* @copyright 2018 Andrew Nicols <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider_test extends \core_privacy\tests\provider_testcase {
/**
* Get the list of standard format options for comparison.
*
* @return \stdClass
*/
protected function get_format_options() {
return (object) [
'overflowdiv' => true,
'noclean' => true,
];
}
/**
* Creates an HTML block on a user.
*
* @param string $title
* @param string $body
* @param string $format
* @return \block_instance
*/
protected function create_user_block($title, $body, $format) {
global $USER;
$configdata = (object) [
'title' => $title,
'text' => [
'itemid' => 19,
'text' => $body,
'format' => $format,
],
];
$this->create_block($this->construct_user_page($USER));
$block = $this->get_last_block_on_page($this->construct_user_page($USER));
$block = block_instance('html', $block->instance);
$block->instance_config_save((object) $configdata);
return $block;
}
/**
* Creates an HTML block on a course.
*
* @param \stdClass $course
* @param string $title
* @param string $body
* @param string $format
* @return \block_instance
*/
protected function create_course_block($course, $title, $body, $format) {
global $USER;
$configdata = (object) [
'title' => $title,
'text' => [
'itemid' => 19,
'text' => $body,
'format' => $format,
],
];
$this->create_block($this->construct_course_page($course));
$block = $this->get_last_block_on_page($this->construct_course_page($course));
$block = block_instance('html', $block->instance);
$block->instance_config_save((object) $configdata);
return $block;
}
/**
* Creates an HTML block on a page.
*
* @param \page $page Page
*/
protected function create_block($page) {
$page->blocks->add_block_at_end_of_default_region('html');
}
/**
* Get the last block on the page.
*
* @param \page $page Page
* @return \block_html Block instance object
*/
protected function get_last_block_on_page($page) {
$blocks = $page->blocks->get_blocks_for_region($page->blocks->get_default_region());
$block = end($blocks);
return $block;
}
/**
* Constructs a Page object for the User Dashboard.
*
* @param \stdClass $user User to create Dashboard for.
* @return \moodle_page
*/
protected function construct_user_page(\stdClass $user) {
$page = new \moodle_page();
$page->set_context(\context_user::instance($user->id));
$page->set_pagelayout('mydashboard');
$page->set_pagetype('my-index');
$page->blocks->load_blocks();
return $page;
}
/**
* Constructs a Page object for the User Dashboard.
*
* @param \stdClass $course Course to create Dashboard for.
* @return \moodle_page
*/
protected function construct_course_page(\stdClass $course) {
$page = new \moodle_page();
$page->set_context(\context_course::instance($course->id));
$page->set_pagelayout('standard');
$page->set_pagetype('course-view');
$page->set_course($course);
$page->blocks->load_blocks();
return $page;
}
/**
* Test that a block on the dashboard is exported.
*/
public function test_user_block(): void {
$this->resetAfterTest();
$title = 'Example title';
$content = 'Example content';
$format = FORMAT_PLAIN;
// Test setup.
$user = $this->getDataGenerator()->create_user();
$this->setUser($user);
$block = $this->create_user_block($title, $content, $format);
$context = \context_block::instance($block->instance->id);
// Get the contexts.
$contextlist = provider::get_contexts_for_userid($user->id);
// Only the user context should be returned.
$this->assertCount(1, $contextlist);
$this->assertEquals($context, $contextlist->current());
// Export the data.
$this->export_context_data_for_user($user->id, $context, 'block_html');
/** @var \core_privacy\tests\request\content_writer $writer */
$writer = \core_privacy\local\request\writer::with_context($context);
$this->assertTrue($writer->has_any_data());
// Check the data.
$data = $writer->get_data([]);
$this->assertInstanceOf('stdClass', $data);
$this->assertEquals($title, $data->title);
$this->assertEquals(format_text($content, $format, $this->get_format_options()), $data->content);
// Delete the context.
provider::delete_data_for_all_users_in_context($context);
// Re-fetch the contexts - it should no longer be returned.
$contextlist = provider::get_contexts_for_userid($user->id);
$this->assertCount(0, $contextlist);
}
/**
* Test that a block on the dashboard which is not configured is _not_ exported.
*/
public function test_user_block_unconfigured(): void {
global $DB;
$this->resetAfterTest();
$title = 'Example title';
$content = 'Example content';
$format = FORMAT_PLAIN;
// Test setup.
$user = $this->getDataGenerator()->create_user();
$this->setUser($user);
$block = $this->create_user_block($title, $content, $format);
$block->instance->configdata = '';
$DB->update_record('block_instances', $block->instance);
$block = block_instance('html', $block->instance);
$context = \context_block::instance($block->instance->id);
// Get the contexts.
$contextlist = provider::get_contexts_for_userid($user->id);
// Only the user context should be returned.
$this->assertCount(1, $contextlist);
$this->assertEquals($context, $contextlist->current());
// Export the data.
$this->export_context_data_for_user($user->id, $context, 'block_html');
/** @var \core_privacy\tests\request\content_writer $writer */
$writer = \core_privacy\local\request\writer::with_context($context);
$this->assertFalse($writer->has_any_data());
}
/**
* Test that a block on the dashboard is exported.
*/
public function test_user_multiple_blocks_exported(): void {
$this->resetAfterTest();
$title = 'Example title';
$content = 'Example content';
$format = FORMAT_PLAIN;
// Test setup.
$blocks = [];
$contexts = [];
$user = $this->getDataGenerator()->create_user();
$this->setUser($user);
$block = $this->create_user_block($title, $content, $format);
$context = \context_block::instance($block->instance->id);
$contexts[$context->id] = $context;
$block = $this->create_user_block($title, $content, $format);
$context = \context_block::instance($block->instance->id);
$contexts[$context->id] = $context;
// Get the contexts.
$contextlist = provider::get_contexts_for_userid($user->id);
// There are now two blocks on the user context.
$this->assertCount(2, $contextlist);
foreach ($contextlist as $context) {
$this->assertTrue(isset($contexts[$context->id]));
}
// Turn them into an approved_contextlist.
$approvedlist = new approved_contextlist($user, 'block_html', $contextlist->get_contextids());
// Delete using delete_data_for_user.
provider::delete_data_for_user($approvedlist);
// Re-fetch the contexts - it should no longer be returned.
$contextlist = provider::get_contexts_for_userid($user->id);
$this->assertCount(0, $contextlist);
}
/**
* Test that a block on the dashboard is not exported.
*/
public function test_course_blocks_not_exported(): void {
$this->resetAfterTest();
$title = 'Example title';
$content = 'Example content';
$format = FORMAT_PLAIN;
// Test setup.
$user = $this->getDataGenerator()->create_user();
$course = $this->getDataGenerator()->create_course();
$this->setUser($user);
$block = $this->create_course_block($course, $title, $content, $format);
$context = \context_block::instance($block->instance->id);
// Get the contexts.
$contextlist = provider::get_contexts_for_userid($user->id);
// No blocks should be returned.
$this->assertCount(0, $contextlist);
}
/**
* Test that a block on the dashboard is exported.
*/
public function test_mixed_multiple_blocks_exported(): void {
$this->resetAfterTest();
$title = 'Example title';
$content = 'Example content';
$format = FORMAT_PLAIN;
// Test setup.
$contexts = [];
$user = $this->getDataGenerator()->create_user();
$course = $this->getDataGenerator()->create_course();
$this->setUser($user);
$block = $this->create_course_block($course, $title, $content, $format);
$context = \context_block::instance($block->instance->id);
$block = $this->create_user_block($title, $content, $format);
$context = \context_block::instance($block->instance->id);
$contexts[$context->id] = $context;
$block = $this->create_user_block($title, $content, $format);
$context = \context_block::instance($block->instance->id);
$contexts[$context->id] = $context;
// Get the contexts.
$contextlist = provider::get_contexts_for_userid($user->id);
// There are now two blocks on the user context.
$this->assertCount(2, $contextlist);
foreach ($contextlist as $context) {
$this->assertTrue(isset($contexts[$context->id]));
}
}
/**
* Test that only users with a user context HTML block are fetched.
*/
public function test_get_users_in_context(): void {
$this->resetAfterTest();
$component = 'block_html';
$title = 'Block title';
$content = 'Block content';
$blockformat = FORMAT_PLAIN;
// Create a user with a user context HTML block.
$user1 = $this->getDataGenerator()->create_user();
$this->setUser($user1);
$userblock = $this->create_user_block($title, $content, $blockformat);
$usercontext = \context_block::instance($userblock->instance->id);
// Create a user with a course context HTML block.
$user2 = $this->getDataGenerator()->create_user();
$this->setUser($user2);
$course = $this->getDataGenerator()->create_course();
$courseblock = $this->create_course_block($course, $title, $content, $blockformat);
$coursecontext = \context_block::instance($courseblock->instance->id);
// Ensure only the user with a user context HTML block is returned.
$userlist = new \core_privacy\local\request\userlist($usercontext, $component);
\block_html\privacy\provider::get_users_in_context($userlist);
$this->assertCount(1, $userlist);
$expected = [$user1->id];
$actual = $userlist->get_userids();
$this->assertEquals($expected, $actual);
// Ensure passing the course context returns no users.
$userlist = new \core_privacy\local\request\userlist($coursecontext, $component);
\mod_forum\privacy\provider::get_users_in_context($userlist);
$this->assertEmpty($userlist);
}
/**
* Test that data for users in approved userlist is deleted.
*/
public function test_delete_data_for_users(): void {
$this->resetAfterTest();
$component = 'block_html';
$title = 'Block title';
$content = 'Block content';
$blockformat = FORMAT_PLAIN;
// Create 2 user swith a user context HTML blocks.
$user1 = $this->getDataGenerator()->create_user();
$this->setUser($user1);
$block1 = $this->create_user_block($title, $content, $blockformat);
$context1 = \context_block::instance($block1->instance->id);
$user2 = $this->getDataGenerator()->create_user();
$this->setUser($user2);
$block2 = $this->create_user_block($title, $content, $blockformat);
$context2 = \context_block::instance($block2->instance->id);
// Create and populate the userlists.
$userlist1 = new \core_privacy\local\request\userlist($context1, $component);
\block_html\privacy\provider::get_users_in_context($userlist1);
$userlist2 = new \core_privacy\local\request\userlist($context2, $component);
\block_html\privacy\provider::get_users_in_context($userlist2);
// Ensure both members are included.
$this->assertCount(1, $userlist1);
$this->assertCount(1, $userlist2);
// Convert $userlist1 into an approved_contextlist.
$approvedlist = new approved_userlist($context1, 'block_html', $userlist1->get_userids());
// Delete using delete_data_for_user.
provider::delete_data_for_users($approvedlist);
// Re-fetch users in the contexts - only the first one should now be empty.
$userlist1 = new \core_privacy\local\request\userlist($context1, $component);
\block_html\privacy\provider::get_users_in_context($userlist1);
$this->assertCount(0, $userlist1);
$userlist2 = new \core_privacy\local\request\userlist($context2, $component);
\block_html\privacy\provider::get_users_in_context($userlist2);
$this->assertCount(1, $userlist2);
}
}
+189
View File
@@ -0,0 +1,189 @@
<?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/>.
/**
* Unit test for search indexing.
*
* @package block_html
* @copyright 2017 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace block_html;
defined('MOODLE_INTERNAL') || die();
/**
* Unit test for search indexing.
*
* @package block_html
* @copyright 2017 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class search_content_test extends \advanced_testcase {
/**
* Creates an HTML block on a course.
*
* @param \stdClass $course Course object
* @return \block_html Block instance object
*/
protected function create_block($course) {
$page = self::construct_page($course);
$page->blocks->add_block_at_end_of_default_region('html');
// Load the block.
$page = self::construct_page($course);
$page->blocks->load_blocks();
$blocks = $page->blocks->get_blocks_for_region($page->blocks->get_default_region());
$block = end($blocks);
return $block;
}
/**
* Constructs a page object for the test course.
*
* @param \stdClass $course Moodle course object
* @return \moodle_page Page object representing course view
*/
protected static function construct_page($course) {
$context = \context_course::instance($course->id);
$page = new \moodle_page();
$page->set_context($context);
$page->set_course($course);
$page->set_pagelayout('standard');
$page->set_pagetype('course-view');
$page->blocks->load_blocks();
return $page;
}
/**
* Tests all functionality in the search area.
*/
public function test_search_area(): void {
global $CFG, $USER, $DB;
require_once($CFG->dirroot . '/search/tests/fixtures/testable_core_search.php');
$this->resetAfterTest();
$this->setAdminUser();
// Create course and add HTML block.
$generator = $this->getDataGenerator();
$course = $generator->create_course();
$before = time();
$block = $this->create_block($course);
// Change block settings to add some text and a file.
$itemid = file_get_unused_draft_itemid();
$fs = get_file_storage();
$usercontext = \context_user::instance($USER->id);
$fs->create_file_from_string(['component' => 'user', 'filearea' => 'draft',
'contextid' => $usercontext->id, 'itemid' => $itemid, 'filepath' => '/',
'filename' => 'file.txt'], 'File content');
$data = (object)['title' => 'Block title', 'text' => ['text' => 'Block text',
'itemid' => $itemid, 'format' => FORMAT_HTML]];
$block->instance_config_save($data);
$after = time();
// Set up fake search engine so we can create documents.
\testable_core_search::instance();
// Do indexing query.
$area = new \block_html\search\content();
$this->assertEquals('html', $area->get_block_name());
$rs = $area->get_recordset_by_timestamp();
$count = 0;
foreach ($rs as $record) {
$count++;
$this->assertEquals($course->id, $record->courseid);
// Check context is correct.
$blockcontext = \context::instance_by_id($record->contextid);
$this->assertInstanceOf('\context_block', $blockcontext);
$coursecontext = $blockcontext->get_parent_context();
$this->assertEquals($course->id, $coursecontext->instanceid);
// Check created and modified times are correct.
$this->assertTrue($record->timecreated >= $before && $record->timecreated <= $after);
$this->assertTrue($record->timemodified >= $before && $record->timemodified <= $after);
// Get config data.
$data = unserialize(base64_decode($record->configdata));
$this->assertEquals('Block title', $data->title);
$this->assertEquals('Block text', $data->text);
$this->assertEquals(FORMAT_HTML, $data->format);
// Check the get_document function 'new' flag.
$doc = $area->get_document($record, ['lastindexedtime' => 1]);
$this->assertTrue($doc->get_is_new());
$doc = $area->get_document($record, ['lastindexedtime' => time() + 1]);
$this->assertFalse($doc->get_is_new());
// Check the attach_files function results in correct list of associated files.
$this->assertCount(0, $doc->get_files());
$area->attach_files($doc);
$files = $doc->get_files();
// The directory entry should NOT be provided for indexing.
$this->assertCount(1, $files);
foreach ($files as $file) {
$this->assertEquals('file.txt', $file->get_filename());
$this->assertEquals('File content', $file->get_content());
}
// Check the document fields are all as expected.
$this->assertEquals('Block title', $doc->get('title'));
$this->assertEquals('Block text', $doc->get('content'));
$this->assertEquals($blockcontext->id, $doc->get('contextid'));
$this->assertEquals(\core_search\manager::TYPE_TEXT, $doc->get('type'));
$this->assertEquals($course->id, $doc->get('courseid'));
$this->assertEquals($record->timemodified, $doc->get('modified'));
$this->assertEquals(\core_search\manager::NO_OWNER_ID, $doc->get('owneruserid'));
// Also check getting the doc url and context url.
$url = new \moodle_url('/course/view.php', ['id' => $course->id], 'inst' . $record->id);
$this->assertTrue($url->compare($area->get_doc_url($doc)));
$this->assertTrue($url->compare($area->get_context_url($doc)));
}
$rs->close();
// Should only be one HTML block systemwide.
$this->assertEquals(1, $count);
// If we run the query starting from 1 second after now, there should be no results.
$rs = $area->get_recordset_by_timestamp($after + 1);
$count = 0;
foreach ($rs as $record) {
$count++;
}
$rs->close();
$this->assertEquals(0, $count);
// Create another block, but this time leave it empty (no data set). Hack the time though.
$block = $this->create_block($course);
$DB->set_field('block_instances', 'timemodified',
$after + 10, ['id' => $block->instance->id]);
$rs = $area->get_recordset_by_timestamp($after + 10);
$count = 0;
foreach ($rs as $record) {
// Because there is no configdata we don't index it.
$count++;
}
$rs->close();
$this->assertEquals(0, $count);
}
}
+29
View File
@@ -0,0 +1,29 @@
<?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/>.
/**
* Version details
*
* @package block_html
* @copyright 1999 onwards Martin Dougiamas (http://dougiamas.com)
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
$plugin->version = 2024042200; // The current plugin version (Date: YYYYMMDDXX).
$plugin->requires = 2024041600; // Requires this Moodle version.
$plugin->component = 'block_html'; // Full name of the plugin (used for diagnostics)