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,167 @@
<?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/>.
/**
* Utility class for browsing of content bank files.
*
* @package repository_contentbank
* @copyright 2020 Mihail Geshoski <mihail@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace repository_contentbank\browser;
/**
* Base class for the content bank browsers.
*
* @package repository_contentbank
* @copyright 2020 Mihail Geshoski <mihail@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
abstract class contentbank_browser {
/** @var \context The current context. */
protected $context;
/**
* Get all content nodes in the current context which can be viewed/accessed by the user.
*
* @return array[] The array containing all nodes which can be viewed/accessed by the user in the current context
*/
public function get_content(): array {
return array_merge($this->get_context_folders(), $this->get_contentbank_content());
}
/**
* Generate the full navigation to the current node.
*
* @return array[] The array containing the path to each node in the navigation.
* Each navigation node is an array with keys: name, path.
*/
public function get_navigation(): array {
// Get the current navigation node.
$currentnavigationnode = \repository_contentbank\helper::create_navigation_node($this->context);
$navigationnodes = [$currentnavigationnode];
// Get the parent content bank browser.
$parent = $this->get_parent();
// Prepend parent navigation node in the navigation nodes array until there is no existing parent.
while ($parent !== null) {
$parentnavigationnode = \repository_contentbank\helper::create_navigation_node($parent->context);
array_unshift($navigationnodes, $parentnavigationnode);
$parent = $parent->get_parent();
}
return $navigationnodes;
}
/**
* The required condition to enable the user to view/access the content bank content in this context.
*
* @return bool Whether the user can view/access the content bank content in the context
*/
abstract public function can_access_content(): bool;
/**
* Define the allowed child context levels.
*
* @return int[] The array containing the relevant child context levels
*/
abstract protected function allowed_child_context_levels(): array;
/**
* Get the relevant child contexts.
*
* @return \context[] The array containing the relevant, next-level children contexts
*/
protected function get_child_contexts(): array {
global $DB;
if (empty($allowedcontextlevels = $this->allowed_child_context_levels())) {
// Early return if there aren't any defined child context levels.
return [];
}
list($contextlevelsql, $params) = $DB->get_in_or_equal($allowedcontextlevels, SQL_PARAMS_NAMED);
$pathsql = $DB->sql_like('path', ':path', false, false);
$select = "contextlevel {$contextlevelsql}
AND {$pathsql}
AND depth = :depth";
$params['path'] = "{$this->context->path}/%";
$params['depth'] = $this->context->depth + 1;
$childcontexts = $DB->get_records_select('context', $select, $params);
return array_map(function($childcontext) {
return \context::instance_by_id($childcontext->id);
}, $childcontexts);
}
/**
* Get the content bank browser class of the parent context. Currently used to generate the navigation path.
*
* @return contentbank_browser|null The content bank browser of the parent context
*/
private function get_parent(): ?self {
if ($parentcontext = $this->context->get_parent_context()) {
return \repository_contentbank\helper::get_contentbank_browser($parentcontext);
}
return null;
}
/**
* Generate folder nodes for the relevant child contexts which can be accessed/viewed by the user.
*
* @return array[] The array containing the context folder nodes where each folder node is an array with keys:
* title, datemodified, datecreated, path, thumbnail, children.
*/
private function get_context_folders(): array {
// Get all relevant child contexts.
$children = $this->get_child_contexts();
// Return all child context folder nodes which can be accessed by the user following the defined conditions
// in can_access_content().
return array_reduce($children, function ($list, $child) {
$browser = \repository_contentbank\helper::get_contentbank_browser($child);
if ($browser->can_access_content()) {
$name = $child->get_context_name(false);
$path = base64_encode(json_encode(['contextid' => $child->id]));
$list[] = \repository_contentbank\helper::create_context_folder_node($name, $path);
}
return $list;
}, []);
}
/**
* Generate nodes for the content bank content in the current context which can be accessed/viewed by the user.
*
* @return array[] The array containing the content nodes where each content node is an array with keys:
* shorttitle, title, datemodified, datecreated, author, license, isref, source, icon, thumbnail.
*/
private function get_contentbank_content(): array {
$cb = new \core_contentbank\contentbank();
// Get all content bank files in the current context.
$contents = $cb->search_contents(null, $this->context->id);
// Return all content bank content nodes from the current context which can be accessed by the user following
// the defined conditions in can_access_content().
return array_reduce($contents, function($list, $content) {
if ($this->can_access_content() &&
$contentnode = \repository_contentbank\helper::create_contentbank_content_node($content)) {
$list[] = $contentnode;
}
return $list;
}, []);
}
}
@@ -0,0 +1,68 @@
<?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/>.
/**
* Utility class for browsing of content bank files in the course context.
*
* @package repository_contentbank
* @copyright 2020 Mihail Geshoski <mihail@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace repository_contentbank\browser;
/**
* Represents the content bank browser in the course context.
*
* @package repository_contentbank
* @copyright 2020 Mihail Geshoski <mihail@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class contentbank_browser_context_course extends contentbank_browser {
/**
* Constructor.
*
* @param \context_course $context The current context
*/
public function __construct(\context_course $context) {
$this->context = $context;
}
/**
* Define the allowed child context levels.
*
* @return int[] The array containing the relevant child context levels
*/
protected function allowed_child_context_levels(): array {
// The course context is the last relevant context level, therefore child context levels are not being returned.
return [];
}
/**
* The required condition to enable the user to view/access the content bank content in this context.
*
* @return bool Whether the user can view/access the content bank content in the context
*/
public function can_access_content(): bool {
// When the following conditions are met, the user would be able to share the content created in the course
// context level all over the site.
// The content from the course context level should be available to:
// * Every user which has capability to access the content of a given course.
return has_capability('repository/contentbank:accesscoursecontent', $this->context);
}
}
@@ -0,0 +1,84 @@
<?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/>.
/**
* Utility class for browsing of content bank files in the course category context.
*
* @package repository_contentbank
* @copyright 2020 Mihail Geshoski <mihail@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace repository_contentbank\browser;
/**
* Represents the content bank browser in the course category context.
*
* @package repository_contentbank
* @copyright 2020 Mihail Geshoski <mihail@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class contentbank_browser_context_coursecat extends contentbank_browser {
/**
* Constructor.
*
* @param \context_coursecat $context The current context
*/
public function __construct(\context_coursecat $context) {
$this->context = $context;
}
/**
* Define the allowed child context levels.
*
* @return int[] The array containing the relevant child context levels
*/
protected function allowed_child_context_levels(): array {
// The expected child contexts in the course category context level are the course category context
// (ex. subcategories) and the course context.
return [\CONTEXT_COURSECAT, \CONTEXT_COURSE];
}
/**
* The required condition to enable the user to view/access the content bank content in this context.
*
* @return bool Whether the user can view/access the content bank content in the context
*/
public function can_access_content(): bool {
// When the following conditions are met, the user would be able to share the content created in the course
// category context level all over the site.
// The content from the course category context level should be available to either:
// * Every user which has a capability to access the 'general' content and has capability to access the
// content of any child course of the given course category.
// * Users that have capability to access content at a course category context level.
if (has_capability('repository/contentbank:accesscoursecategorycontent', $this->context)) {
return true;
}
$canaccesschildcontent = false;
foreach ($this->get_child_contexts() as $childcontext) {
$browser = \repository_contentbank\helper::get_contentbank_browser($childcontext);
if ($canaccesschildcontent = $browser->can_access_content()) {
break;
}
}
return $canaccesschildcontent && has_capability('repository/contentbank:accessgeneralcontent',
$this->context);
}
}
@@ -0,0 +1,68 @@
<?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/>.
/**
* Utility class for browsing of content bank files in the system context.
*
* @package repository_contentbank
* @copyright 2020 Mihail Geshoski <mihail@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace repository_contentbank\browser;
/**
* Represents the content bank browser in the system context.
*
* @package repository_contentbank
* @copyright 2020 Mihail Geshoski <mihail@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class contentbank_browser_context_system extends contentbank_browser {
/**
* Constructor.
*
* @param \context_system $context The current context
*/
public function __construct(\context_system $context) {
$this->context = $context;
}
/**
* Define the allowed child context levels.
*
* @return int[] The array containing the relevant child context levels
*/
protected function allowed_child_context_levels(): array {
// The expected child context in the system context level is the course category context.
return [\CONTEXT_COURSECAT];
}
/**
* The required condition to enable the user to view/access the content bank content in this context.
*
* @return bool Whether the user can view/access the content bank content in the context
*/
public function can_access_content(): bool {
// When the following conditions are met, the user would be able to share the content created in the system
// context level all over the site.
// The content from the system context level should be available to:
// * Every user that has a capability to access the 'general' content.
return has_capability('repository/contentbank:accessgeneralcontent', $this->context);
}
}
@@ -0,0 +1,61 @@
<?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/>.
/**
* Utility class for searching of content bank files.
*
* @package repository_contentbank
* @copyright 2020 Mihail Geshoski <mihail@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace repository_contentbank;
/**
* Represents the content bank search related functionality.
*
* @package repository_contentbank
* @copyright 2020 Mihail Geshoski <mihail@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class contentbank_search {
/**
* Generate and return content nodes for all content bank files that match the search criteria
* and can be viewed/accessed by the user.
*
* @param string $search The search string
* @return array[] The array containing all content file nodes that match the search criteria. Each content node is
* an array with keys: shorttitle, title, datemodified, datecreated, author, license, isref, source,
* icon, thumbnail.
*/
public static function get_search_contents(string $search): array {
$contentbank = new \core_contentbank\contentbank();
// Return all content bank content that matches the search criteria and can be viewed/accessed by the user.
$contents = $contentbank->search_contents($search);
return array_reduce($contents, function($list, $content) {
$contentcontext = \context::instance_by_id($content->get_content()->contextid);
$browser = \repository_contentbank\helper::get_contentbank_browser($contentcontext);
// If the user can access the content and content node can be created, add the node into the
// search results list.
if ($browser->can_access_content() &&
$contentnode = \repository_contentbank\helper::create_contentbank_content_node($content)) {
$list[] = $contentnode;
}
return $list;
}, []);
}
}
+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/>.
/**
* Content bank files repository helpers.
*
* @package repository_contentbank
* @copyright 2020 Mihail Geshoski <mihail@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace repository_contentbank;
use repository_contentbank\browser\contentbank_browser;
/**
* Helper class for content bank files repository.
*
* @package repository_contentbank
* @copyright 2020 Mihail Geshoski <mihail@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class helper {
/**
* Get the content bank repository browser for a certain context.
*
* @param \context $context The context
* @return \repository_contentbank\browser\contentbank_browser|null The content bank repository browser
*/
public static function get_contentbank_browser(\context $context): ?contentbank_browser {
switch ($context->contextlevel) {
case CONTEXT_SYSTEM:
return new \repository_contentbank\browser\contentbank_browser_context_system($context);
case CONTEXT_COURSECAT:
return new \repository_contentbank\browser\contentbank_browser_context_coursecat($context);
case CONTEXT_COURSE:
return new \repository_contentbank\browser\contentbank_browser_context_course($context);
}
return null;
}
/**
* Create the context folder node.
*
* @param string $name The name of the context folder node
* @param string $path The path to the context folder node
* @return array The context folder node
*/
public static function create_context_folder_node(string $name, string $path): array {
global $OUTPUT;
return [
'title' => $name,
'datemodified' => '',
'datecreated' => '',
'path' => $path,
'thumbnail' => $OUTPUT->image_url(file_folder_icon())->out(false),
'children' => []
];
}
/**
* Create the content bank content node.
*
* @param \core_contentbank\content $content The content bank content
* @return array|null The content bank content node
*/
public static function create_contentbank_content_node(\core_contentbank\content $content): ?array {
global $OUTPUT;
// Only content files are currently supported, but should be able to create content folder nodes in the future.
// Early return if the content is not a stored file.
if (!$file = $content->get_file()) {
return null;
}
$params = [
'contextid' => $file->get_contextid(),
'component' => $file->get_component(),
'filearea' => $file->get_filearea(),
'itemid' => $file->get_itemid(),
'filepath' => $file->get_filepath(),
'filename' => $file->get_filename()
];
$contenttype = $content->get_content_type_instance();
$encodedpath = base64_encode(json_encode($params));
$node = [
'shorttitle' => $content->get_name(),
'title' => $file->get_filename(),
'datemodified' => $file->get_timemodified(),
'datecreated' => $file->get_timecreated(),
'author' => $file->get_author(),
'license' => $file->get_license(),
'isref' => $file->is_external_file(),
'size' => $file->get_filesize(),
'source' => $encodedpath,
'icon' => $contenttype->get_icon($content),
'thumbnail' => $contenttype->get_icon($content)
];
if ($file->get_status() == 666) {
$node['originalmissing'] = true;
}
return $node;
}
/**
* Generate a navigation node.
*
* @param \context $context The context
* @return array The navigation node
*/
public static function create_navigation_node(\context $context): array {
return [
'path' => base64_encode(json_encode(['contextid' => $context->id])),
'name' => $context->get_context_name(false)
];
}
}
@@ -0,0 +1,44 @@
<?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 repository_contentbank.
*
* @package repository_contentbank
* @copyright 2020 Mihail Geshoski <mihail@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace repository_contentbank\privacy;
/**
* Privacy Subsystem for repository_contentbank implementing null_provider.
*
* @copyright 2020 Mihail Geshoski <mihail@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider implements \core_privacy\local\metadata\null_provider {
/**
* Get the language string identifier with the component's language
* file to explain why this plugin stores no data.
*
* @return string
*/
public static function get_reason(): string {
return 'privacy:metadata';
}
}
+62
View File
@@ -0,0 +1,62 @@
<?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/>.
/**
* Plugin capabilities.
*
* @package repository_contentbank
* @copyright 2020 Mihail Geshoski
* @author Mihail Geshoski <mihail@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
$capabilities = [
'repository/contentbank:view' => [
'captype' => 'read',
'contextlevel' => CONTEXT_MODULE,
'archetypes' => [
'coursecreator' => CAP_ALLOW,
'editingteacher' => CAP_ALLOW,
'manager' => CAP_ALLOW
]
],
'repository/contentbank:accesscoursecontent' => [
'captype' => 'read',
'contextlevel' => CONTEXT_COURSE,
'archetypes' => [
'coursecreator' => CAP_ALLOW,
'editingteacher' => CAP_ALLOW,
'manager' => CAP_ALLOW
]
],
'repository/contentbank:accesscoursecategorycontent' => [
'captype' => 'read',
'contextlevel' => CONTEXT_COURSECAT,
'archetypes' => [
'coursecreator' => CAP_ALLOW,
'manager' => CAP_ALLOW
]
],
'repository/contentbank:accessgeneralcontent' => [
'captype' => 'read',
'contextlevel' => CONTEXT_COURSECAT,
'archetypes' => [
'user' => CAP_ALLOW
]
]
];
+41
View File
@@ -0,0 +1,41 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Installation file for the content bank repository
*
* @package repository_contentbank
* @copyright 2020 Mihail Geshoski <mihail@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
/**
* Create a default instance of the content bank repository
*
* @return bool A status indicating success or failure
*/
function xmldb_repository_contentbank_install() {
global $CFG;
$result = true;
require_once($CFG->dirroot.'/repository/lib.php');
$userplugin = new repository_type('contentbank', [], true);
if (!$id = $userplugin->create(true)) {
$result = false;
}
return $result;
}
@@ -0,0 +1,34 @@
<?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 'repository_contentbank', language 'en'.
*
* @package repository_contentbank
* @copyright 2020 Mihail Geshoski
* @author Mihail Geshoski <mihail@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
$string['configplugin'] = 'Configuration for content bank repository';
$string['pluginname_help'] = 'Files in content bank';
$string['pluginname'] = 'Content bank';
$string['emptyfilelist'] = 'There are no files to show';
$string['contentbank:view'] = 'View content bank repository';
$string['contentbank:accesscoursecontent'] = 'Access course content bank files';
$string['contentbank:accesscoursecategorycontent'] = 'Access course category content bank files';
$string['contentbank:accessgeneralcontent'] = 'Access system content bank files';
$string['privacy:metadata'] = 'The Content bank repository plugin does not store or transmit any personal data.';
+171
View File
@@ -0,0 +1,171 @@
<?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 plugin is used to access the content bank files.
*
* @package repository_contentbank
* @copyright 2020 Mihail Geshoski <mihail@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
require_once($CFG->dirroot . '/repository/lib.php');
/**
* repository_contentbank class is used to browse the content bank files
*
* @package repository_contentbank
* @copyright 2020 Mihail Geshoski <mihail@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class repository_contentbank extends repository {
/**
* Get file listing.
*
* @param string $encodedpath
* @param string $page
* @return array
*/
public function get_listing($encodedpath = '', $page = '') {
global $SITE;
$ret = [];
$ret['dynload'] = true;
$ret['nosearch'] = false;
$ret['nologin'] = true;
// Return the parameters from the encoded path if the encoded path is not empty.
if (!empty($encodedpath)) {
$params = json_decode(base64_decode($encodedpath), true);
if (is_array($params) && isset($params['contextid'])) {
$context = context::instance_by_id(clean_param($params['contextid'], PARAM_INT));
}
}
// Return the current context if the context was not specified in the encoded path.
// The current context should be an instance of context_system, context_coursecat or course related contexts.
if (empty($context) && !empty($this->context)) {
if ($this->context instanceof \context_system || $this->context instanceof \context_coursecat) {
$context = $this->context;
} else if ($coursecontext = $this->context->get_course_context(false)) {
// Skip if front page context.
if ($coursecontext->instanceid !== $SITE->id) {
$context = $coursecontext;
}
}
}
// If not, return the system context as a default context.
if (empty($context)) {
$context = context_system::instance();
}
$ret['list'] = [];
$ret['path'] = [];
// Get the content bank browser for the specified context.
if ($browser = \repository_contentbank\helper::get_contentbank_browser($context)) {
$manageurl = new moodle_url('/contentbank/index.php', ['contextid' => $context->id]);
$canaccesscontent = has_capability('moodle/contentbank:access', $context);
$ret['manage'] = $canaccesscontent ? $manageurl->out() : '';
$ret['list'] = $browser->get_content();
$ret['path'] = $browser->get_navigation();
}
return $ret;
}
/**
* Is this repository used to browse moodle files?
*
* @return boolean
*/
public function has_moodle_files() {
return true;
}
/**
* Tells how the file can be picked from this repository.
*
* @return int
*/
public function supported_returntypes() {
return FILE_INTERNAL | FILE_REFERENCE;
}
/**
* Which return type should be selected by default.
*
* @return int
*/
public function default_returntype() {
return FILE_REFERENCE;
}
/**
* Is this repository accessing private data?
*
* @return bool
*/
public function contains_private_data() {
return false;
}
/**
* Repository method to make sure that user can access particular file.
*
* This is checked when user tries to pick the file from repository to deal with
* potential parameter substitutions in request
*
* @param string $source
* @return bool whether the file is accessible by current user
*/
public function file_is_accessible($source) {
global $DB;
$fileparams = json_decode(base64_decode($source));
$itemid = clean_param($fileparams->itemid, PARAM_INT);
$contextid = clean_param($fileparams->contextid, PARAM_INT);
$contentbankfile = $DB->get_record('contentbank_content', ['id' => $itemid]);
$plugin = \core_plugin_manager::instance()->get_plugin_info($contentbankfile->contenttype);
$managerclass = "\\$contentbankfile->contenttype\\content";
if ($plugin && $plugin->is_enabled() && class_exists($managerclass)) {
$context = \context::instance_by_id($contextid);
$browser = \repository_contentbank\helper::get_contentbank_browser($context);
return $browser->can_access_content();
}
return false;
}
/**
* Return search results.
*
* @param string $search
* @param int $page
* @return array
*/
public function search($search, $page = 0) {
$ret = [];
$ret['nologin'] = true;
$ret['list'] = \repository_contentbank\contentbank_search::get_search_contents($search);
return $ret;
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

+17
View File
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 74 51" style="enable-background:new 0 0 74 51;" xml:space="preserve" preserveAspectRatio="xMinYMid meet">
<style type="text/css">
.st0{fill:#F98012;}
.st1{fill:#333333;}
</style>
<g>
<path class="st0" d="M61.9,50.3V27.4c0-4.8-2-7.2-5.9-7.2c-4,0-5.9,2.4-5.9,7.2v22.9H38.4V27.4c0-4.8-1.9-7.2-5.8-7.2
c-4,0-5.9,2.4-5.9,7.2v22.9H15V26.1c0-5,1.7-8.8,5.2-11.3c3-2.3,7.2-3.4,12.4-3.4c5.3,0,9.2,1.4,11.6,4.1c2.2-2.7,6.1-4.1,11.8-4.1
c5.2,0,9.3,1.1,12.4,3.4c3.5,2.6,5.2,6.3,5.2,11.3v24.3H61.9z"/>
<path class="st1" d="M37.6,9.5l11.6-8.5L49,0.6C28.1,3.1,18.6,4.9,0.7,15.4l0.2,0.5l1.4,0c-0.1,1.4-0.4,5-0.1,10.4
c-2,5.8,0,9.7,1.8,14c0.3-4.4,0.3-9.3-1.1-14.1c-0.3-5.3,0-8.8,0.1-10.2L14.9,16c0,0-0.1,3.6,0.4,7c10.7,3.7,21.4,0,27.1-9.2
C40.7,11.9,37.6,9.5,37.6,9.5z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

@@ -0,0 +1,99 @@
@repository @repository_contentbank @javascript @core_h5p
Feature: Updating a file in the content bank after using in a course
In order to use file alias
As a user
Updated files must update references when is an alias
Background:
Given the following "categories" exist:
| name | category | idnumber |
| Category1 | 0 | CAT1 |
And the following "courses" exist:
| fullname | shortname | category |
| Course1 | C1 | CAT1 |
And the following "contentbank content" exist:
| contextlevel | reference | contenttype | user | contentname | filepath |
| Course | C1 | contenttype_h5p | admin | package.h5p | /h5p/tests/fixtures/guess-the-answer.h5p |
Scenario: Referenced files is the default option and updates alias as well
When I log in as "admin"
And I add an h5pactivity activity to course "Course1" section "1"
And I set the following fields to these values:
| Name | guessFile |
And I click on "Add..." "link" in the ".fp-toolbar" "css_element"
And I select "Content bank" repository in file picker
And I click on "package.h5p" "file" in repository content area
And I click on "Select this file" "button"
And I click on "Save and display" "button"
And I switch to "h5p-player" class iframe
And I switch to "h5p-iframe" class iframe
Then I should see "Press here to reveal answer"
And I switch to the main frame
# Now edit the content in the content bank.
When I am on "Course1" course homepage with editing mode on
And the following config values are set as admin:
| unaddableblocks | | theme_boost|
And I add the "Navigation" block if not present
And I expand "Site pages" node
And I click on "Content bank" "link"
And I click on "package.h5p" "link"
And I click on "Edit" "link"
And I wait until the page is ready
And I switch to "h5p-editor-iframe" class iframe
And I set the field "Title" to "Required title"
And I set the field "Descriptive solution label" to "This is a new text"
And I switch to the main frame
And I click on "Save" "button"
And I switch to "h5p-player" class iframe
And I switch to "h5p-iframe" class iframe
Then I should see "This is a new text"
And I switch to the main frame
# Check the course page is updated.
When I am on "Course1" course homepage with editing mode on
And I click on "guessFile" "link" in the "page-content" "region"
And I switch to "h5p-player" class iframe
And I switch to "h5p-iframe" class iframe
Then I should see "This is a new text"
And I switch to the main frame
Scenario: Copied files should not be updated if the original is edited
When I log in as "admin"
And I add an h5pactivity activity to course "Course1" section "1"
And I set the following fields to these values:
| Name | guessFile |
And I click on "Add..." "link" in the ".fp-toolbar" "css_element"
And I select "Content bank" repository in file picker
And I click on "package.h5p" "file" in repository content area
And I click on "Make a copy of the file" "radio"
And I click on "Select this file" "button"
And I click on "Save and display" "button"
And I switch to "h5p-player" class iframe
And I switch to "h5p-iframe" class iframe
Then I should see "Press here to reveal answer"
And I switch to the main frame
# Now edit the content in the content bank.
When I am on "Course1" course homepage with editing mode on
And the following config values are set as admin:
| unaddableblocks | | theme_boost|
And I add the "Navigation" block if not present
And I expand "Site pages" node
And I click on "Content bank" "link"
And I click on "package.h5p" "link"
And I click on "Edit" "link"
And I wait until the page is ready
And I switch to "h5p-editor-iframe" class iframe
And I set the field "Title" to "Required title"
And I set the field "Descriptive solution label" to "This is a new text"
And I switch to the main frame
And I click on "Save" "button"
And I switch to "h5p-player" class iframe
And I switch to "h5p-iframe" class iframe
Then I should see "This is a new text"
And I switch to the main frame
# Check the course page is not updated.
When I am on "Course1" course homepage with editing mode on
And I click on "guessFile" "link" in the "page-content" "region"
And I switch to "h5p-player" class iframe
And I switch to "h5p-iframe" class iframe
Then I should see "Press here to reveal answer"
And I switch to the main frame
@@ -0,0 +1,109 @@
@repository @repository_contentbank @javascript
Feature: Search content bank files using the content bank files repository
In order to find the content I need to select in the file picker
As a user
I need to be able to search in the content bank files repository by content name
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| student | Student | 1 | student@example.com |
| teacher | Teacher | 1 | teacher1@example.com |
And the following "categories" exist:
| name | category | idnumber |
| Category1 | 0 | CAT1 |
| Category2 | 0 | CAT2 |
And the following "courses" exist:
| fullname | shortname | category |
| Course1 | C1 | CAT1 |
| Course2 | C2 | CAT2 |
And the following "contentbank content" exist:
| contextlevel | reference | contenttype | user | contentname | filepath |
| Course | C1 | contenttype_h5p | admin | coursecontent1.h5p | /h5p/tests/fixtures/filltheblanks.h5p |
| Course | C2 | contenttype_h5p | admin | coursecontent2.h5p | /h5p/tests/fixtures/find-the-words.h5p |
| Category | CAT1 | contenttype_h5p | admin | categorycontent1.h5p | /h5p/tests/fixtures/ipsums.h5p |
| Category | CAT2 | contenttype_h5p | admin | categorycontent2.h5p | /h5p/tests/fixtures/multiple-choice-2-6.h5p |
| System | | contenttype_h5p | admin | systemcontent.h5p | /h5p/tests/fixtures/greeting-card.h5p |
And the following "activities" exist:
| activity | name | intro | introformat | course | idnumber |
| folder | Folder | FolderDesc | 1 | C1 | folder |
And the following "course enrolments" exist:
| user | course | role |
| teacher | C1 | editingteacher |
Scenario: User can see a search field and reset search button in the content bank files repository
Given I am on the Folder "Folder activity" page logged in as admin
And I click on "Edit" "button"
And I click on "Add..." "button"
And I should see "Content bank" in the ".fp-repo-area" "css_element"
When I select "Content bank" repository in file picker
Then "Search repository" "field" should be visible
And "Refresh" "link" should be visible
Scenario: User can see search results when there is content that matches the search criteria
Given I am on the Folder "Folder activity" page logged in as admin
And I click on "Edit" "button"
And I click on "Add..." "button"
And I should see "Content bank" in the ".fp-repo-area" "css_element"
And I select "Content bank" repository in file picker
And I set the field "Search repository" to "content"
When I press enter
Then I should see "5" elements in repository content area
And I should see "systemcontent.h5p" "file" in repository content area
And I should see "categorycontent1.h5p" "file" in repository content area
And I should see "categorycontent2.h5p" "file" in repository content area
And I should see "coursecontent1.h5p" "file" in repository content area
And I should see "coursecontent2.h5p" "file" in repository content area
Scenario: User can see search results when there is content that matches the search criteria ignoring case sensitivity
Given I am on the Folder "Folder activity" page logged in as admin
And I click on "Edit" "button"
And I click on "Add..." "button"
And I should see "Content bank" in the ".fp-repo-area" "css_element"
And I select "Content bank" repository in file picker
And I set the field "Search repository" to "COURSE"
When I press enter
Then I should see "2" elements in repository content area
And I should see "coursecontent1.h5p" "file" in repository content area
And I should see "coursecontent2.h5p" "file" in repository content area
Scenario: User can not see any search results when there is not a content that matches the search criteria
Given I am on the Folder "Folder activity" page logged in as admin
And I click on "Edit" "button"
And I click on "Add..." "button"
And I should see "Content bank" in the ".fp-repo-area" "css_element"
And I select "Content bank" repository in file picker
And I set the field "Search repository" to "somecontent"
When I press enter
Then I should see "0" elements in repository content area
And I should see "No files available" in the ".filepicker .fp-content" "css_element"
Scenario: User can reset search criteria and see all content displayed prior the search action
Given I am on the Folder "Folder activity" page logged in as admin
And I click on "Edit" "button"
And I click on "Add..." "button"
And I should see "Content bank" in the ".fp-repo-area" "css_element"
And I select "Content bank" repository in file picker
And I should see "1" elements in repository content area
And I should see "coursecontent1.h5p" "file" in repository content area
And I set the field "Search repository" to "category"
And I press enter
And I should see "2" elements in repository content area
And I should see "categorycontent1.h5p" "file" in repository content area
And I should see "categorycontent2.h5p" "file" in repository content area
When I click on "Refresh" "link"
Then I should see "1" elements in repository content area
And I should see "coursecontent1.h5p" "file" in repository content area
Scenario: Editing teacher can see search results when the content is available to him and matches the search criteria
Given I am on the Folder "Folder activity" page logged in as teacher
And I click on "Edit" "button"
And I click on "Add..." "button"
And I should see "Content bank" in the ".fp-repo-area" "css_element"
And I select "Content bank" repository in file picker
And I set the field "Search repository" to "content"
When I press enter
Then I should see "3" elements in repository content area
And I should see "coursecontent1.h5p" "file" in repository content area
And I should see "categorycontent1.h5p" "file" in repository content area
And I should see "systemcontent.h5p" "file" in repository content area
@@ -0,0 +1,157 @@
@repository @repository_contentbank @javascript
Feature: Select content bank files using the content bank files repository
In order to re-use content bank files
As a user
I need to be able to view and select content bank files using the content bank repository
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| student | Student | 1 | student@example.com |
| teacher1 | Teacher 1 | 1 | teacher1@example.com |
| teacher2 | Teacher 2 | 1 | teacher2@example.com |
And the following "categories" exist:
| name | category | idnumber |
| Category1 | 0 | CAT1 |
| SubCategory1 | CAT1 | SUBCAT1 |
And the following "courses" exist:
| fullname | shortname | category |
| MiscellaneousCourse1 | mscC1 | 0 |
| MiscellaneousCourse2 | mscC2 | 0 |
| Category1Course1 | cat1C1 | CAT1 |
| SubCategory1Course1 | subcat1C1 | SUBCAT1 |
And the following "contentbank content" exist:
| contextlevel | reference | contenttype | user | contentname | filepath |
| Course | mscC1 | contenttype_h5p | admin | filltheblanks.h5p | /h5p/tests/fixtures/filltheblanks.h5p |
| Course | mscC2 | contenttype_h5p | admin | find-the-words.h5p | /h5p/tests/fixtures/find-the-words.h5p |
| Course | subcat1C1 | contenttype_h5p | admin | greeting-card.h5p | /h5p/tests/fixtures/greeting-card.h5p |
| Category | CAT1 | contenttype_h5p | admin | ipsums.h5p | /h5p/tests/fixtures/ipsums.h5p |
| Category | SUBCAT1 | contenttype_h5p | admin | multiple-choice-2-6.h5p | /h5p/tests/fixtures/multiple-choice-2-6.h5p |
| System | | contenttype_h5p | admin | filltheblanks.h5p | /h5p/tests/fixtures/filltheblanks.h5p |
And the following "activities" exist:
| activity | name | intro | introformat | course | idnumber |
| forum | Forum | | 1 | mscC1 | forum1 |
| folder | Folder | FolderDesc | 1 | mscC1 | folder1 |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | mscC1 | editingteacher |
| teacher2 | mscC1 | teacher |
| student | mscC1 | student |
Scenario: Admin can navigate and see all existing content bank files using the content bank repository
Given I am on the Folder "Folder activity" page logged in as admin
And I click on "Edit" "button"
And I click on "Add..." "button"
And I should see "Content bank" in the ".fp-repo-area" "css_element"
When I select "Content bank" repository in file picker
Then I should see "System > Category 1 > MiscellaneousCourse1" breadcrumb navigation in repository
And I should see "1" elements in repository content area
And I should see "filltheblanks.h5p" "file" in repository content area
And I click on "Category 1" "link" in the ".file-picker .fp-pathbar" "css_element"
And I should see "System > Category 1" breadcrumb navigation in repository
And I should see "2" elements in repository content area
And I should see "MiscellaneousCourse1" "folder" in repository content area
And I should see "MiscellaneousCourse2" "folder" in repository content area
And I click on "MiscellaneousCourse2" "folder" in repository content area
And I should see "System > Category 1 > MiscellaneousCourse2" breadcrumb navigation in repository
And I should see "1" elements in repository content area
And I should see "find-the-words.h5p" "file" in repository content area
And I click on "System" "link" in the ".file-picker .fp-pathbar" "css_element"
And I should see "System" breadcrumb navigation in repository
And I should see "3" elements in repository content area
And I should see "filltheblanks.h5p" "file" in repository content area
And I should see "Category 1" "folder" in repository content area
And I should see "Category1" "folder" in repository content area
And I click on "Category1" "folder" in repository content area
And I should see "System > Category1" breadcrumb navigation in repository
And I should see "3" elements in repository content area
And I should see "SubCategory1" "folder" in repository content area
And I should see "Category1Course1" "folder" in repository content area
And I should see "ipsums.h5p" "file" in repository content area
And I click on "SubCategory1" "folder" in repository content area
And I should see "System > Category1 > SubCategory1" breadcrumb navigation in repository
And I should see "2" elements in repository content area
And I should see "SubCategory1Course1" "folder" in repository content area
And I should see "multiple-choice-2-6.h5p" "file" in repository content area
And I click on "SubCategory1Course1" "folder" in repository content area
And I should see "System > Category1 > SubCategory1 > SubCategory1Course1" breadcrumb navigation in repository
And I should see "1" elements in repository content area
And I should see "greeting-card.h5p" "file" in repository content area
Scenario: Admin can select and re-use content bank files using the content bank repository
Given I am on the Folder "Folder activity" page logged in as admin
And I click on "Edit" "button"
And I click on "Add..." "button"
And I should see "Content bank" in the ".fp-repo-area" "css_element"
And I select "Content bank" repository in file picker
And I should see "System > Category 1 > MiscellaneousCourse1" breadcrumb navigation in repository
And I click on "System" "link" in the ".file-picker .fp-pathbar" "css_element"
And I click on "Category1" "folder" in repository content area
And I should see "ipsums.h5p" "file" in repository content area
And I click on "ipsums.h5p" "file" in repository content area
And I should see "Select ipsums.h5p"
When I click on "Select this file" "button"
Then I should see "1" elements in "Files" filemanager
And I should see "ipsums.h5p" in the ".fp-content .fp-file" "css_element"
Scenario: Editing teacher can navigate and see content bank files available to him using the content bank repository
Given I am on the Folder "Folder activity" page logged in as teacher1
And I click on "Edit" "button"
And I click on "Add..." "button"
And I should see "Content bank" in the ".fp-repo-area" "css_element"
When I select "Content bank" repository in file picker
Then I should see "System > Category 1 > MiscellaneousCourse1" breadcrumb navigation in repository
And I should see "1" elements in repository content area
And I should see "filltheblanks.h5p" "file" in repository content area
And I click on "Category 1" "link" in the ".file-picker .fp-pathbar" "css_element"
And I should see "System > Category 1" breadcrumb navigation in repository
And I should see "1" elements in repository content area
And I should see "MiscellaneousCourse1" "folder" in repository content area
And I click on "System" "link" in the ".file-picker .fp-pathbar" "css_element"
And I should see "System" breadcrumb navigation in repository
And I should see "2" elements in repository content area
And I should see "filltheblanks.h5p" "file" in repository content area
And I should see "Category 1" "folder" in repository content area
Scenario: Editing teacher can select and re-use content bank files available to him using the content bank repository
Given I am on the Folder "Folder activity" page logged in as teacher1
And I click on "Edit" "button"
And I click on "Add..." "button"
And I should see "Content bank" in the ".fp-repo-area" "css_element"
And I select "Content bank" repository in file picker
And I should see "System > Category 1 > MiscellaneousCourse1" breadcrumb navigation in repository
And I click on "System" "link" in the ".file-picker .fp-pathbar" "css_element"
And I should see "filltheblanks.h5p" "file" in repository content area
And I click on "filltheblanks.h5p" "file" in repository content area
And I should see "Select filltheblanks.h5p"
When I click on "Select this file" "button"
Then I should see "1" elements in "Files" filemanager
And I should see "filltheblanks.h5p" in the ".fp-content .fp-file" "css_element"
Scenario: Non-editing teacher can not see the content bank repository
Given I am on the Forum "Forum activity" page logged in as teacher2
And I click on "Add discussion topic" "link"
And I click on "Advanced" "button"
When I click on "Add..." "button"
Then I should not see "Content bank" in the ".fp-repo-area" "css_element"
Scenario: Student can not see the content bank repository
Given I am on the Forum "Forum activity" page logged in as student
And I click on "Add discussion topic" "link"
And I click on "Advanced" "button"
When I click on "Add..." "button"
Then I should not see "Content bank" in the ".fp-repo-area" "css_element"
Scenario: Both content name and file name are shown when a content is selected
Given the following "contentbank content" exist:
| contextlevel | reference | contenttype | user | contentname | filepath |
| Course | mscC1 | contenttype_h5p | admin | My content | /h5p/tests/fixtures/ipsums.h5p |
And I am on the Folder "Folder activity" page logged in as admin
And I click on "Edit" "button"
And I click on "Add..." "button"
And I should see "Content bank" in the ".fp-repo-area" "css_element"
When I select "Content bank" repository in file picker
Then I should see "My content"
And I click on "My content" "link"
And I should see "Select My content"
And the field "Save as" matches value "ipsums.h5p"
@@ -0,0 +1,498 @@
<?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 repository_contentbank;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once("$CFG->dirroot/repository/lib.php");
/**
* Tests for the content bank browser class.
*
* @package repository_contentbank
* @copyright 2020 Mihail Geshoski <mihail@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class browser_test extends \advanced_testcase {
/**
* Test get_content() in the system context with users that have capability to access/view content bank content
* within the system context. By default, every authenticated user should be able to access/view the content in
* the system context.
*/
public function test_get_content_system_context_user_has_capabilities(): void {
global $DB, $CFG;
$this->resetAfterTest(true);
$systemcontext = \context_system::instance();
// Create a course category $coursecategory.
$coursecategory = $this->getDataGenerator()->create_category(['name' => 'Category']);
$coursecatcontext = \context_coursecat::instance($coursecategory->id);
// Get the default course category.
$defaultcat = \core_course_category::get(1);
$defaultcatcontext = \context_coursecat::instance($defaultcat->id);
// Create course.
$course = $this->getDataGenerator()->create_course(['category' => $coursecategory->id]);
$admin = get_admin();
// Create a user (not enrolled in a course).
$user = $this->getDataGenerator()->create_user();
// Add some content to the content bank.
$generator = $this->getDataGenerator()->get_plugin_generator('core_contentbank');
// Add some content bank files in the system context.
$filepath = $CFG->dirroot . '/h5p/tests/fixtures/filltheblanks.h5p';
$contentbankcontents = $generator->generate_contentbank_data('contenttype_h5p', 3, $admin->id,
$systemcontext, true, $filepath);
// Log in as admin.
$this->setUser($admin);
// Get the content bank nodes displayed to the admin in the system context.
$browser = new \repository_contentbank\browser\contentbank_browser_context_system($systemcontext);
$repositorycontentnodes = $browser->get_content();
// All content nodes should be available to the admin user.
// There should be a total of 5 nodes, 3 file nodes representing the existing content bank files in the
// system context and 2 folder nodes representing the default course category and 'Category'.
$this->assertCount(5, $repositorycontentnodes);
$contextfolders = [
[
'name' => get_string('defaultcategoryname'),
'contextid' => $defaultcatcontext->id
],
[
'name' => 'Category',
'contextid' => $coursecatcontext->id
]
];
$expected = $this->generate_expected_content($contextfolders, $contentbankcontents);
$this->assertEqualsCanonicalizing($expected, $repositorycontentnodes);
// Log in as a user.
$this->setUser($user);
// Get the content bank nodes displayed to an authenticated user in the system context.
$browser = new \repository_contentbank\browser\contentbank_browser_context_system($systemcontext);
$repositorycontentnodes = $browser->get_content();
// There should be 3 nodes representing the existing content bank files in the system context.
// The course category context folder node should be ignored as the user does not have an access to
// the content of the category's courses.
$this->assertCount(3, $repositorycontentnodes);
$expected = $this->generate_expected_content([], $contentbankcontents);
$this->assertEqualsCanonicalizing($expected, $repositorycontentnodes);
// Enrol the user as an editing teacher in the course.
$editingteacherrole = $DB->get_field('role', 'id', ['shortname' => 'editingteacher']);
$this->getDataGenerator()->enrol_user($user->id, $course->id, $editingteacherrole);
// Get the content bank nodes displayed to the editing teacher in the system context.
$browser = new \repository_contentbank\browser\contentbank_browser_context_system($systemcontext);
$repositorycontentnodes = $browser->get_content();
// All content nodes should now be available to the editing teacher.
// There should be a total of 4 nodes, 3 file nodes representing the existing content bank files in the
// system context and 1 folder node representing the course category 'Category' (The editing teacher is now
// enrolled in a course from the category).
$this->assertCount(4, $repositorycontentnodes);
$contextfolders = [
[
'name' => 'Category',
'contextid' => $coursecatcontext->id
]
];
$expected = $this->generate_expected_content($contextfolders, $contentbankcontents);
$this->assertEqualsCanonicalizing($expected, $repositorycontentnodes);
}
/**
* Test get_content() in the system context with users that do not have a capability to access/view content bank
* content within the system context. By default, every non-authenticated user should not be able to access/view
* the content in the system context.
*/
public function test_get_content_system_context_user_missing_capabilities(): void {
$this->resetAfterTest(true);
$systemcontext = \context_system::instance();
$admin = get_admin();
// Add some content to the content bank.
$generator = $this->getDataGenerator()->get_plugin_generator('core_contentbank');
// Add some content bank files in the system context.
$generator->generate_contentbank_data('contenttype_h5p', 3, $admin->id, $systemcontext, true);
// Log out.
$this->setUser();
// Get the content bank nodes displayed to a non-authenticated user in the system context.
$browser = new \repository_contentbank\browser\contentbank_browser_context_system($systemcontext);
$repositorycontents = $browser->get_content();
// Content nodes should not be available to the non-authenticated user in the system context.
$this->assertCount(0, $repositorycontents);
}
/**
* Test get_content() in the course category context with users that have capability to access/view content
* bank content within the course category context. By default, every authenticated user that has access to
* any category course should be able to access/view the content in the course category context.
*/
public function test_get_content_course_category_context_user_has_capabilities(): void {
global $CFG;
$this->resetAfterTest(true);
// Create a course category.
$category = $this->getDataGenerator()->create_category(['name' => 'Category']);
$coursecatcontext = \context_coursecat::instance($category->id);
// Create course1.
$course1 = $this->getDataGenerator()->create_course(['fullname' => 'Course1', 'category' => $category->id]);
$course1context = \context_course::instance($course1->id);
// Create course2.
$course2 = $this->getDataGenerator()->create_course(['fullname' => 'Course2', 'category' => $category->id]);
$course2context = \context_course::instance($course2->id);
$admin = get_admin();
// Create editing teacher enrolled in course1.
$editingteacher = $this->getDataGenerator()->create_and_enrol($course1, 'editingteacher');
// Add some content to the content bank.
$generator = $this->getDataGenerator()->get_plugin_generator('core_contentbank');
// Add some content bank files in the course category context.
$filepath = $CFG->dirroot . '/h5p/tests/fixtures/filltheblanks.h5p';
$contentbankcontents = $generator->generate_contentbank_data('contenttype_h5p', 3, $admin->id,
$coursecatcontext, true, $filepath);
$this->setUser($admin);
// Get the content bank nodes displayed to the admin in the course category context.
$browser = new \repository_contentbank\browser\contentbank_browser_context_coursecat($coursecatcontext);
$repositorycontents = $browser->get_content();
// All content nodes should be available to the admin user.
// There should be a total of 5 nodes, 3 file nodes representing the existing content bank files in the
// course category context and 2 folder nodes representing the courses 'Course1' and 'Course2'.
$this->assertCount(5, $repositorycontents);
$contextfolders = [
[
'name' => 'Course1',
'contextid' => $course1context->id
],
[
'name' => 'Course2',
'contextid' => $course2context->id
]
];
$expected = $this->generate_expected_content($contextfolders, $contentbankcontents);
$this->assertEqualsCanonicalizing($expected, $repositorycontents);
// Log in as an editing teacher enrolled in a child course.
$this->setUser($editingteacher);
// Get the content bank nodes displayed to the editing teacher in the course category context.
$browser = new \repository_contentbank\browser\contentbank_browser_context_coursecat($coursecatcontext);
$repositorycontents = $browser->get_content();
// There should be a total of 4 nodes, 3 file nodes representing the existing content bank files in the
// course category context and 1 folder node representing the course 'Course1' (The editing teacher is only
// enrolled in course1).
$this->assertCount(4, $repositorycontents);
$contextfolders = [
[
'name' => 'Course1',
'contextid' => $course1context->id
]
];
$expected = $this->generate_expected_content($contextfolders, $contentbankcontents);
$this->assertEqualsCanonicalizing($expected, $repositorycontents);
}
/**
* Test get_content() in the course category context with users that do not have capability to access/view content
* bank content within the course category context. By default, every non-authenticated user or authenticated users
* that cannot access/view course content from the course category should not be able to access/view the
* content in the course category context.
*/
public function test_get_content_course_category_context_user_missing_capabilities(): void {
$this->resetAfterTest(true);
// Create a course category 'Category'.
$category = $this->getDataGenerator()->create_category(['name' => 'Category']);
// Create course1 in 'Category'.
$course1 = $this->getDataGenerator()->create_course(['fullname' => 'Course1', 'category' => $category->id]);
// Create course2 in default category by default.
$course2 = $this->getDataGenerator()->create_course(['fullname' => 'Course2']);
// Create a teacher enrolled in course1.
$teacher = $this->getDataGenerator()->create_and_enrol($course1, 'teacher');
// Create an editing teacher enrolled in course2.
$editingteacher = $this->getDataGenerator()->create_and_enrol($course2, 'editingteacher');
$admin = get_admin();
// Add some content to the content bank.
$generator = $this->getDataGenerator()->get_plugin_generator('core_contentbank');
// Add some content bank files in the 'Category' context.
$coursecatcontext = \context_coursecat::instance($category->id);
$generator->generate_contentbank_data('contenttype_h5p', 3, $admin->id,
$coursecatcontext, true);
// Log in as a non-editing teacher.
$this->setUser($teacher);
// Get the content bank nodes displayed to a non-editing teacher in the 'Category' context.
$browser = new \repository_contentbank\browser\contentbank_browser_context_coursecat($coursecatcontext);
$repositorycontents = $browser->get_content();
// Content nodes should not be available to a non-editing teacher in the 'Category' context.
$this->assertCount(0, $repositorycontents);
// Log in as an editing teacher.
$this->setUser($editingteacher);
// Get the content bank nodes displayed to a an editing teacher in the 'Category' context.
$browser = new \repository_contentbank\browser\contentbank_browser_context_coursecat($coursecatcontext);
$repositorycontents = $browser->get_content();
// Content nodes should not be available to an editing teacher in the 'Category' context.
$this->assertCount(0, $repositorycontents);
// Log out.
$this->setUser();
// Get the content bank nodes displayed to a non-authenticated user in the course category context.
$browser = new \repository_contentbank\browser\contentbank_browser_context_coursecat($coursecatcontext);
$repositorycontents = $browser->get_content();
// Content nodes should not be available to the non-authenticated user in the course category context.
$this->assertCount(0, $repositorycontents);
}
/**
* Test get_content() in the course context with users that have capability to access/view content
* bank content within the course context. By default, admin, managers, course creators, editing teachers enrolled
* in the course should be able to access/view the content.
*/
public function test_get_content_course_context_user_has_capabilities(): void {
global $CFG;
$this->resetAfterTest(true);
// Create course1.
$course = $this->getDataGenerator()->create_course(['fullname' => 'Course']);
$coursecontext = \context_course::instance($course->id);
$admin = get_admin();
// Create editing teacher enrolled in course.
$editingteacher = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
// Add some content to the content bank.
$generator = $this->getDataGenerator()->get_plugin_generator('core_contentbank');
// Add some content bank files in the course context.
$filepath = $CFG->dirroot . '/h5p/tests/fixtures/filltheblanks.h5p';
$contentbankcontents = $generator->generate_contentbank_data('contenttype_h5p', 3, $admin->id,
$coursecontext, true, $filepath);
$this->setUser($admin);
// Get the content bank nodes displayed to the admin in the course context.
$browser = new \repository_contentbank\browser\contentbank_browser_context_course($coursecontext);
$repositorycontents = $browser->get_content();
// All content nodes should be available to the admin user.
// There should be 3 file nodes representing the existing content bank files in the
// course context.
$this->assertCount(3, $repositorycontents);
$expected = $this->generate_expected_content([], $contentbankcontents);
$this->assertEqualsCanonicalizing($expected, $repositorycontents);
// Log in as an editing teacher.
$this->setUser($editingteacher);
// All content nodes should also be available to the editing teacher.
// Get the content bank nodes displayed to the editing teacher in the course context.
$browser = new \repository_contentbank\browser\contentbank_browser_context_course($coursecontext);
$repositorycontents = $browser->get_content();
// There should be 3 file nodes representing the existing content bank files in the
// course context.
$this->assertCount(3, $repositorycontents);
$expected = $this->generate_expected_content([], $contentbankcontents);
$this->assertEqualsCanonicalizing($expected, $repositorycontents);
}
/**
* Test get_content() in the course context with users that do not have capability to access/view content
* bank content within the course context. By default, every user which is not an admin, manager, course creator,
* editing teacher enrolled in the course should not be able to access/view the content.
*/
public function test_get_content_course_context_user_missing_capabilities(): void {
$this->resetAfterTest(true);
// Create course1.
$course1 = $this->getDataGenerator()->create_course(['fullname' => 'Course1']);
$course1context = \context_course::instance($course1->id);
// Create course2.
$course2 = $this->getDataGenerator()->create_course(['fullname' => 'Course2']);
$course2context = \context_course::instance($course2->id);
$admin = get_admin();
// Create non-editing teacher enrolled in course1.
$teacher = $this->getDataGenerator()->create_and_enrol($course1, 'teacher');
// Create editing teacher enrolled in course1.
$editingteacher = $this->getDataGenerator()->create_and_enrol($course1, 'editingteacher');
// Add some content to the content bank.
$generator = $this->getDataGenerator()->get_plugin_generator('core_contentbank');
// Add some content bank files in the course1 context.
$generator->generate_contentbank_data('contenttype_h5p', 2, $admin->id,
$course1context, true);
// Add some content bank files in the course2 context.
$generator->generate_contentbank_data('contenttype_h5p', 3, $admin->id,
$course2context, true);
// Log in as a non-editing teacher.
$this->setUser($teacher);
// Get the content bank nodes displayed to the non-editing teacher in the course1 context.
$browser = new \repository_contentbank\browser\contentbank_browser_context_course($course1context);
$repositorycontents = $browser->get_content();
// Content nodes should not be available to the teacher in the course1 context.
$this->assertCount(0, $repositorycontents);
// Log in as editing teacher.
$this->setUser($editingteacher);
// Get the content bank nodes displayed to the editing teacher in the course2 context.
$browser = new \repository_contentbank\browser\contentbank_browser_context_course($course2context);
$repositorycontents = $browser->get_content();
// Content nodes should not be available to the teacher in the course2 context. The editing teacher is not
// enrolled in this course.
$this->assertCount(0, $repositorycontents);
}
/**
* Test get_navigation() in the system context.
*/
public function test_get_navigation_system_context(): void {
$this->resetAfterTest(true);
$systemcontext = \context_system::instance();
$browser = new \repository_contentbank\browser\contentbank_browser_context_system($systemcontext);
$navigation = $browser->get_navigation();
// The navigation array should contain only 1 element, representing the system navigation node.
$this->assertCount(1, $navigation);
$expected = [
\repository_contentbank\helper::create_navigation_node($systemcontext)
];
$this->assertEquals($expected, $navigation);
}
/**
* Test get_navigation() in the course category context.
*/
public function test_get_navigation_course_category_context(): void {
$this->resetAfterTest(true);
$systemcontext = \context_system::instance();
// Create a course category.
$category = $this->getDataGenerator()->create_category(['name' => 'category']);
$categorycontext = \context_coursecat::instance($category->id);
// Create a course subcategory.
$subcategory = $this->getDataGenerator()->create_category(['name' => 'subcategory', 'parent' => $category->id]);
$subcategorytcontext = \context_coursecat::instance($subcategory->id);
// Get navigation nodes in the category context.
$browser = new \repository_contentbank\browser\contentbank_browser_context_coursecat($categorycontext);
$navigation = $browser->get_navigation();
// The navigation array should contain 2 elements, representing the system and course category
// navigation nodes.
$this->assertCount(2, $navigation);
$expected = [
\repository_contentbank\helper::create_navigation_node($systemcontext),
\repository_contentbank\helper::create_navigation_node($categorycontext)
];
$this->assertEquals($expected, $navigation);
// Get navigation nodes in the subcategory context.
$browser = new \repository_contentbank\browser\contentbank_browser_context_coursecat($subcategorytcontext);
$navigation = $browser->get_navigation();
// The navigation array should contain 3 elements, representing the system, category and subcategory
// navigation nodes.
$this->assertCount(3, $navigation);
$expected = [
\repository_contentbank\helper::create_navigation_node($systemcontext),
\repository_contentbank\helper::create_navigation_node($categorycontext),
\repository_contentbank\helper::create_navigation_node($subcategorytcontext)
];
$this->assertEquals($expected, $navigation);
}
/**
* Test get_navigation() in the course context.
*/
public function test_get_navigation_course_context(): void {
$this->resetAfterTest(true);
$systemcontext = \context_system::instance();
// Create a category.
$category = $this->getDataGenerator()->create_category(['name' => 'category']);
$categorycontext = \context_coursecat::instance($category->id);
// Create a subcategory.
$subcategory = $this->getDataGenerator()->create_category(['name' => 'category', 'parent' => $category->id]);
$subcategorycontext = \context_coursecat::instance($subcategory->id);
// Create a course in category.
$categorycourse = $this->getDataGenerator()->create_course(['category' => $category->id]);
$categorycoursecontext = \context_course::instance($categorycourse->id);
// Create a course in subcategory.
$subcategorycourse = $this->getDataGenerator()->create_course(['category' => $subcategory->id]);
$subcategorycoursecontext = \context_course::instance($subcategorycourse->id);
// Get navigation nodes in the category course context.
$browser = new \repository_contentbank\browser\contentbank_browser_context_course($categorycoursecontext);
$navigation = $browser->get_navigation();
// The navigation array should contain 3 elements, representing the system, category and course
// navigation nodes.
$this->assertCount(3, $navigation);
$expected = [
\repository_contentbank\helper::create_navigation_node($systemcontext),
\repository_contentbank\helper::create_navigation_node($categorycontext),
\repository_contentbank\helper::create_navigation_node($categorycoursecontext)
];
$this->assertEquals($expected, $navigation);
// Get navigation nodes in the subcategory course context.
$browser = new \repository_contentbank\browser\contentbank_browser_context_course($subcategorycoursecontext);
$navigation = $browser->get_navigation();
// The navigation array should contain 4 elements, representing the system, category, subcategory and
// subcategory course navigation nodes.
$this->assertCount(4, $navigation);
$expected = [
\repository_contentbank\helper::create_navigation_node($systemcontext),
\repository_contentbank\helper::create_navigation_node($categorycontext),
\repository_contentbank\helper::create_navigation_node($subcategorycontext),
\repository_contentbank\helper::create_navigation_node($subcategorycoursecontext)
];
$this->assertEquals($expected, $navigation);
}
/**
* Generate the expected array of content bank nodes.
*
* @param array $contextfolders The array containing the expected folder nodes
* @param array $contentbankcontents The array containing the expected contents
* @return array[] The expected array of content bank nodes
*/
private function generate_expected_content(array $contextfolders = [], array $contentbankcontents = []): array {
$expected = [];
if (!empty($contextfolders)) {
foreach ($contextfolders as $contextfolder) {
$expected[] = \repository_contentbank\helper::create_context_folder_node($contextfolder['name'],
base64_encode(json_encode(['contextid' => $contextfolder['contextid']])));
}
}
if (!empty($contentbankcontents)) {
foreach ($contentbankcontents as $content) {
$expected[] = \repository_contentbank\helper::create_contentbank_content_node($content);
}
}
return $expected;
}
}
@@ -0,0 +1,35 @@
<?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/>.
/**
* Content bank files repository data generator
*
* @package repository_contentbank
* @category test
* @copyright 2020 Mihail Geshoski
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
/**
* Content bank files repository data generator class
*
* @package repository_contentbank
* @category test
* @copyright 2020 Mihail Geshoski
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class repository_contentbank_generator extends testing_repository_generator {
}
@@ -0,0 +1,246 @@
<?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/>.
/**
* Content bank repository search unit tests.
*
* @package repository_contentbank
* @copyright 2020 Mihail Geshoski <mihail@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace repository_contentbank\search;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once("$CFG->dirroot/repository/lib.php");
/**
* Tests for the content bank search class.
*
* @package repository_contentbank
* @copyright 2020 Mihail Geshoski <mihail@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class search_test extends \advanced_testcase {
/**
* Test get_search_contents() by searching through some existing content using different search terms.
*
* @dataProvider get_search_contents_provider
* @param array $contentnames The array containing the names of the content that needs to be generated
* @param string $search The search string
* @param array $expected The array containing the expected content names that should be returned by the search
*/
public function test_get_search_contents(array $contentnames, string $search, array $expected): void {
$this->resetAfterTest();
$admin = get_admin();
$systemcontext = \context_system::instance();
// Add some content to the content bank.
$generator = $this->getDataGenerator()->get_plugin_generator('core_contentbank');
foreach ($contentnames as $contentname) {
$generator->generate_contentbank_data('contenttype_h5p', 1, $admin->id,
$systemcontext, true, 'file.h5p', $contentname);
}
// Log in as admin.
$this->setUser($admin);
// Search for content bank content items which have the search pattern within the name.
$searchcontentnodes = \repository_contentbank\contentbank_search::get_search_contents($search);
// Get the content name of the each content returned after performing the search.
$actual = array_map(function($searchcontentnode) {
return $searchcontentnode['shorttitle'];
}, $searchcontentnodes);
$this->assertEqualsCanonicalizing($expected, $actual);
}
/**
* Data provider for test_get_search_contents().
*
* @return array
*/
public function get_search_contents_provider(): array {
return [
'Search for existing pattern found within the name of content items' => [
[
'systemcontentfile1',
'systemcontentfile2',
'somesystemfile'
],
'content',
[
'systemcontentfile1',
'systemcontentfile2'
]
],
'Search for existing pattern found at the beginning of the name of content items' => [
[
'systemcontentfile1',
'systemcontentfile2',
'somesystemfile'
],
'some',
[
'somesystemfile',
]
],
'Search for existing pattern found at the end of the name of content items' => [
[
'systemcontentfile1',
'systemcontentfile2',
'somesystemfile'
],
'file2',
[
'systemcontentfile2',
]
],
'Search for a pattern which does not exist within the name of any content item' => [
[
'systemcontentfile1',
'somesystemfile'
],
'somefile',
[]
],
'Case-insensitive search for a pattern which exists within the name of content items' => [
[
'systemcontentfile1',
'systemcontentfile2',
'somesystemfile'
],
'CONTENT',
[
'systemcontentfile1',
'systemcontentfile2'
]
]
];
}
/**
* Test get_search_contents() by searching for content with users that have capability to access/view
* all existing content bank content. By default, admins, managers should be able to view every existing content
* that matches the search criteria.
*/
public function test_get_search_contents_user_can_access_all_content(): void {
$this->resetAfterTest(true);
// Create a course in default category by default.
$course = $this->getDataGenerator()->create_course();
$coursecontext = \context_course::instance($course->id);
// Create a course category without a course.
$category = $this->getDataGenerator()->create_category();
$categorycontext = \context_coursecat::instance($category->id);
$admin = get_admin();
// Add some content to the content bank in different contexts.
$generator = $this->getDataGenerator()->get_plugin_generator('core_contentbank');
// Add a content bank file in the category context.
$categorycontents = $generator->generate_contentbank_data('contenttype_h5p', 1, $admin->id,
$categorycontext, true, 'file.h5p', 'categorycontentfile');
$categorycontent = reset($categorycontents);
// Add a content bank file in the course context.
$coursecontents = $generator->generate_contentbank_data('contenttype_h5p', 1, $admin->id,
$coursecontext, true, 'file.h5p', 'coursecontentfile');
$coursecontent = reset($coursecontents);
// Log in as admin.
$this->setUser($admin);
// Search for content bank content items which have the pattern 'contentfile' within the name.
$search = 'contentfile';
$searchcontentnodes = \repository_contentbank\contentbank_search::get_search_contents($search);
// All content files which name matches the search criteria should be available to the admin user.
// The search should return 2 file nodes.
$this->assertCount(2, $searchcontentnodes);
$expected = [
\repository_contentbank\helper::create_contentbank_content_node($categorycontent),
\repository_contentbank\helper::create_contentbank_content_node($coursecontent),
];
$this->assertEqualsCanonicalizing($expected, $searchcontentnodes);
}
/**
* Test get_search_contents() by searching for content with users that have capability to access/view only
* certain existing content bank content. By default, editing teachers should be able to view content that matches
* the search criteria AND is in the courses they are enrolled, course categories of the enrolled courses
* and system content. Other authenticated users should be able to access only the system content.
*/
public function test_get_search_contents_user_can_access_certain_content(): void {
global $CFG;
$this->resetAfterTest(true);
$systemcontext = \context_system::instance();
// Create course1.
$course1 = $this->getDataGenerator()->create_course();
$course1context = \context_course::instance($course1->id);
// Create course2.
$course2 = $this->getDataGenerator()->create_course();
$course2context = \context_course::instance($course2->id);
$admin = get_admin();
// Create and enrol an editing teacher in course1.
$editingteacher = $this->getDataGenerator()->create_and_enrol($course1, 'editingteacher');
// Create and enrol a teacher in course2.
$teacher = $this->getDataGenerator()->create_and_enrol($course2, 'teacher');
// Add some content to the content bank in different contexts.
$generator = $this->getDataGenerator()->get_plugin_generator('core_contentbank');
// Add a content bank file in the system context.
$filepath = $CFG->dirroot . '/h5p/tests/fixtures/ipsums.h5p';
$systemcontents = $generator->generate_contentbank_data('contenttype_h5p', 1, $admin->id,
$systemcontext, true, $filepath, 'systemcontentfile');
$systemcontent = reset($systemcontents);
// Add a content bank file in the course1 context.
$course1contents = $generator->generate_contentbank_data('contenttype_h5p', 1, $admin->id,
$course1context, true, $filepath, 'coursecontentfile1');
$course1content = reset($course1contents);
// Add a content bank file in the course2 context.
$generator->generate_contentbank_data('contenttype_h5p', 1, $admin->id,
$course2context, true, $filepath, 'coursecontentfile2');
// Log in as an editing teacher.
$this->setUser($editingteacher);
// Search for content bank content items which have the pattern 'contentfile' within the name.
$search = 'contentfile';
$searchcontentnodes = \repository_contentbank\contentbank_search::get_search_contents($search);
// The search should return 2 file nodes. The editing teacher does not have access to the content of course2
// and therefore, the course2 content should be skipped.
$this->assertCount(2, $searchcontentnodes);
$expected = [
\repository_contentbank\helper::create_contentbank_content_node($systemcontent),
\repository_contentbank\helper::create_contentbank_content_node($course1content),
];
$this->assertEqualsCanonicalizing($expected, $searchcontentnodes);
// Log in as a teacher.
$this->setUser($teacher);
// Search for content bank content items which have the pattern 'contentfile' within the name.
$search = 'contentfile';
$searchcontentnodes = \repository_contentbank\contentbank_search::get_search_contents($search);
// The search should return 1 file node. The teacher should only be able to view system content.
$this->assertCount(1, $searchcontentnodes);
$expected = [
\repository_contentbank\helper::create_contentbank_content_node($systemcontent),
];
$this->assertEqualsCanonicalizing($expected, $searchcontentnodes);
}
}
+30
View File
@@ -0,0 +1,30 @@
<?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 repository_contentbank
* @copyright 2020 Mihail Geshoski
* @author Mihail Geshoski <mihail@moodle.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 = 'repository_contentbank'; // Full name of the plugin (used for diagnostics).