Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.2.x will end 22 April 2024 (12 months).
  • Bug fixes for security issues in 4.2.x will end 7 October 2024 (18 months).
  • PHP version: minimum PHP 8.0.0 Note: minimum PHP version has increased since Moodle 4.1. PHP 8.1.x is supported too.
<?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 manager class
 *
 * @package    core_contentbank
 * @copyright  2020 Amaia Anabitarte <amaia@moodle.com>
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 */

namespace core_contentbank;

use core_text;
use stored_file;
use stdClass;
use coding_exception;
> use context;
use moodle_url; use core\event\contentbank_content_updated; /** * Content manager class * * @package core_contentbank * @copyright 2020 Amaia Anabitarte <amaia@moodle.com> * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ abstract class content {
> /** > * @var int Visibility value. Public content is visible to all users with access to the content bank of the /** @var stdClass $content The content of the current instance. **/ > * appropriate context. protected $content = null; > */ > public const VISIBILITY_PUBLIC = 1; /** > * Content bank constructor > /** * > * @var int Visibility value. Unlisted content is only visible to the author and to users with * @param stdClass $record A contentbank_content record. > * moodle/contentbank:viewunlistedcontent capability. * @throws coding_exception If content type is not right. > */ */ > public const VISIBILITY_UNLISTED = 2;
public function __construct(stdClass $record) { // Content type should exist and be linked to plugin classname. $classname = $record->contenttype.'\\content'; if (get_class($this) != $classname) { throw new coding_exception(get_string('contenttypenotfound', 'error', $record->contenttype)); } $typeclass = $record->contenttype.'\\contenttype'; if (!class_exists($typeclass)) { throw new coding_exception(get_string('contenttypenotfound', 'error', $record->contenttype)); } // A record with the id must exist in 'contentbank_content' table. // To improve performance, we are only checking the id is set, but no querying the database. if (!isset($record->id)) { throw new coding_exception(get_string('invalidcontentid', 'error')); } $this->content = $record; } /** * Returns $this->content. * * @return stdClass $this->content. */ public function get_content(): stdClass { return $this->content; } /** * Returns $this->content->contenttype. * * @return string $this->content->contenttype. */ public function get_content_type(): string { return $this->content->contenttype; } /**
> * Return the contenttype instance of this content. * Returns $this->content->timemodified. > * * > * @return contenttype The content type instance * @return int $this->content->timemodified. > */ */ > public function get_content_type_instance(): contenttype { public function get_timemodified(): int { > $context = context::instance_by_id($this->content->contextid); return $this->content->timemodified; > $contenttypeclass = "\\{$this->content->contenttype}\\contenttype"; } > return new $contenttypeclass($context); > } /** > * Updates content_bank table with information in $this->content. > /**
* * @return boolean True if the content has been succesfully updated. False otherwise. * @throws \coding_exception if not loaded. */ public function update_content(): bool { global $USER, $DB; // A record with the id must exist in 'contentbank_content' table. // To improve performance, we are only checking the id is set, but no querying the database. if (!isset($this->content->id)) { throw new coding_exception(get_string('invalidcontentid', 'error')); } $this->content->usermodified = $USER->id; $this->content->timemodified = time(); $result = $DB->update_record('contentbank_content', $this->content); if ($result) { // Trigger an event for updating this content. $event = contentbank_content_updated::create_from_record($this->content); $event->trigger(); } return $result; } /** * Set a new name to the content. * * @param string $name The name of the content. * @return bool True if the content has been succesfully updated. False otherwise. * @throws \coding_exception if not loaded. */ public function set_name(string $name): bool { $name = trim($name); if ($name === '') { return false; } // Clean name. $name = clean_param($name, PARAM_TEXT); if (core_text::strlen($name) > 255) { $name = core_text::substr($name, 0, 255); } $oldname = $this->content->name; $this->content->name = $name; $updated = $this->update_content(); if (!$updated) { $this->content->name = $oldname; } return $updated; } /** * Returns the name of the content. * * @return string The name of the content. */ public function get_name(): string { return $this->content->name; } /** * Set a new contextid to the content. * * @param int $contextid The new contextid of the content. * @return bool True if the content has been succesfully updated. False otherwise. */ public function set_contextid(int $contextid): bool { if ($this->content->contextid == $contextid) { return true; } $oldcontextid = $this->content->contextid; $this->content->contextid = $contextid; $updated = $this->update_content(); if ($updated) { // Move files to new context $fs = get_file_storage(); $fs->move_area_files_to_new_context($oldcontextid, $contextid, 'contentbank', 'public', $this->content->id); } else { $this->content->contextid = $oldcontextid; } return $updated; } /** * Returns the contextid of the content. * * @return int The id of the content context. */ public function get_contextid(): string { return $this->content->contextid; } /** * Returns the content ID. * * @return int The content ID. */ public function get_id(): int { return $this->content->id; } /** * Change the content instanceid value. * * @param int $instanceid New instanceid for this content * @return boolean True if the instanceid has been succesfully updated. False otherwise. */ public function set_instanceid(int $instanceid): bool { $this->content->instanceid = $instanceid; return $this->update_content(); } /** * Returns the $instanceid of this content. * * @return int contentbank instanceid */ public function get_instanceid(): int { return $this->content->instanceid; } /** * Change the content config values. * * @param string $configdata New config information for this content * @return boolean True if the configdata has been succesfully updated. False otherwise. */ public function set_configdata(string $configdata): bool { $this->content->configdata = $configdata; return $this->update_content(); } /** * Return the content config values. * * @return mixed Config information for this content (json decoded) */ public function get_configdata() { return $this->content->configdata; } /**
> * Sets a new content visibility and saves it to database. * Import a file as a valid content. > * * > * @param int $visibility Must be self::PUBLIC or self::UNLISTED * By default, all content has a public file area to interact with the content bank > * @return bool * repository. This method should be overridden by contentypes which does not simply > * @throws coding_exception * upload to the public file area. > */ * > public function set_visibility(int $visibility): bool { * If any, the method will return the final stored_file. This way it can be invoked > if (!in_array($visibility, [self::VISIBILITY_PUBLIC, self::VISIBILITY_UNLISTED])) { * as parent::import_file in case any plugin want to store the file in the public area > return false; * and also parse it. > } * > $this->content->visibility = $visibility; * @throws file_exception If file operations fail > return $this->update_content(); * @param stored_file $file File to store in the content file area. > } * @return stored_file|null the stored content file or null if the file is discarted. > */ > /** public function import_file(stored_file $file): ?stored_file { > * Return true if the content may be shown to other users in the content bank. $originalfile = $this->get_file(); > * if ($originalfile) { > * @return boolean $originalfile->replace_file_with($file); > */ return $originalfile; > public function get_visibility(): int { } else { > return $this->content->visibility; $itemid = $this->get_id(); > } $fs = get_file_storage(); > $filerecord = [ > /**
'contextid' => $this->get_contextid(), 'component' => 'contentbank', 'filearea' => 'public', 'itemid' => $this->get_id(), 'filepath' => '/', 'filename' => $file->get_filename(), 'timecreated' => time(), ]; return $fs->create_file_from_storedfile($filerecord, $file); } } /** * Returns the $file related to this content. * * @return stored_file File stored in content bank area related to the given itemid. * @throws \coding_exception if not loaded. */ public function get_file(): ?stored_file { $itemid = $this->get_id(); $fs = get_file_storage(); $files = $fs->get_area_files( $this->content->contextid, 'contentbank', 'public', $itemid, 'itemid, filepath, filename', false ); if (!empty($files)) { $file = reset($files); return $file; } return null; } /**
> * Returns the places where the file associated to this content is used or an empty array if the content has no file. * Returns the file url related to this content. > * * > * @return array of stored_file where current file content is used or empty array if it hasn't any file. * @return string URL of the file stored in content bank area related to the given itemid. > * @since 3.11 * @throws \coding_exception if not loaded. > */ */ > public function get_uses(): ?array { public function get_file_url(): string { > $references = []; if (!$file = $this->get_file()) { > return ''; > $file = $this->get_file(); } > if ($file != null) { $fileurl = moodle_url::make_pluginfile_url( > $fs = get_file_storage(); $this->content->contextid, > $references = $fs->get_references_by_storedfile($file); 'contentbank', > } 'public', > $file->get_itemid(), > return $references; $file->get_filepath(), > } $file->get_filename() > ); > /**
return $fileurl; } /** * Returns user has access permission for the content itself (based on what plugin needs). * * @return bool True if content could be accessed. False otherwise. */ public function is_view_allowed(): bool {
< // There's no capability at content level to check, < // but plugins can overwrite this method in case they want to check something related to content properties. < return true;
> // Plugins can overwrite this method in case they want to check something related to content properties. > global $USER; > $context = \context::instance_by_id($this->get_contextid()); > > return $USER->id == $this->content->usercreated || > $this->get_visibility() == self::VISIBILITY_PUBLIC || > has_capability('moodle/contentbank:viewunlistedcontent', $context);
} }