See Release Notes
Long Term Support Release
Differences Between: [Versions 39 and 310] [Versions 39 and 311] [Versions 39 and 400] [Versions 39 and 401] [Versions 39 and 402] [Versions 39 and 403]
1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 /** 18 * Content manager class 19 * 20 * @package core_contentbank 21 * @copyright 2020 Amaia Anabitarte <amaia@moodle.com> 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24 25 namespace core_contentbank; 26 27 use core_text; 28 use stored_file; 29 use stdClass; 30 use coding_exception; 31 use moodle_url; 32 use core\event\contentbank_content_updated; 33 34 /** 35 * Content manager class 36 * 37 * @package core_contentbank 38 * @copyright 2020 Amaia Anabitarte <amaia@moodle.com> 39 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 40 */ 41 abstract class content { 42 43 /** @var stdClass $content The content of the current instance. **/ 44 protected $content = null; 45 46 /** 47 * Content bank constructor 48 * 49 * @param stdClass $record A contentbank_content record. 50 * @throws coding_exception If content type is not right. 51 */ 52 public function __construct(stdClass $record) { 53 // Content type should exist and be linked to plugin classname. 54 $classname = $record->contenttype.'\\content'; 55 if (get_class($this) != $classname) { 56 throw new coding_exception(get_string('contenttypenotfound', 'error', $record->contenttype)); 57 } 58 $typeclass = $record->contenttype.'\\contenttype'; 59 if (!class_exists($typeclass)) { 60 throw new coding_exception(get_string('contenttypenotfound', 'error', $record->contenttype)); 61 } 62 // A record with the id must exist in 'contentbank_content' table. 63 // To improve performance, we are only checking the id is set, but no querying the database. 64 if (!isset($record->id)) { 65 throw new coding_exception(get_string('invalidcontentid', 'error')); 66 } 67 $this->content = $record; 68 } 69 70 /** 71 * Returns $this->content. 72 * 73 * @return stdClass $this->content. 74 */ 75 public function get_content(): stdClass { 76 return $this->content; 77 } 78 79 /** 80 * Returns $this->content->contenttype. 81 * 82 * @return string $this->content->contenttype. 83 */ 84 public function get_content_type(): string { 85 return $this->content->contenttype; 86 } 87 88 /** 89 * Returns $this->content->timemodified. 90 * 91 * @return int $this->content->timemodified. 92 */ 93 public function get_timemodified(): int { 94 return $this->content->timemodified; 95 } 96 97 /** 98 * Updates content_bank table with information in $this->content. 99 * 100 * @return boolean True if the content has been succesfully updated. False otherwise. 101 * @throws \coding_exception if not loaded. 102 */ 103 public function update_content(): bool { 104 global $USER, $DB; 105 106 // A record with the id must exist in 'contentbank_content' table. 107 // To improve performance, we are only checking the id is set, but no querying the database. 108 if (!isset($this->content->id)) { 109 throw new coding_exception(get_string('invalidcontentid', 'error')); 110 } 111 $this->content->usermodified = $USER->id; 112 $this->content->timemodified = time(); 113 $result = $DB->update_record('contentbank_content', $this->content); 114 if ($result) { 115 // Trigger an event for updating this content. 116 $event = contentbank_content_updated::create_from_record($this->content); 117 $event->trigger(); 118 } 119 return $result; 120 } 121 122 /** 123 * Set a new name to the content. 124 * 125 * @param string $name The name of the content. 126 * @return bool True if the content has been succesfully updated. False otherwise. 127 * @throws \coding_exception if not loaded. 128 */ 129 public function set_name(string $name): bool { 130 $name = trim($name); 131 if ($name === '') { 132 return false; 133 } 134 135 // Clean name. 136 $name = clean_param($name, PARAM_TEXT); 137 if (core_text::strlen($name) > 255) { 138 $name = core_text::substr($name, 0, 255); 139 } 140 141 $oldname = $this->content->name; 142 $this->content->name = $name; 143 $updated = $this->update_content(); 144 if (!$updated) { 145 $this->content->name = $oldname; 146 } 147 return $updated; 148 } 149 150 /** 151 * Returns the name of the content. 152 * 153 * @return string The name of the content. 154 */ 155 public function get_name(): string { 156 return $this->content->name; 157 } 158 159 /** 160 * Set a new contextid to the content. 161 * 162 * @param int $contextid The new contextid of the content. 163 * @return bool True if the content has been succesfully updated. False otherwise. 164 */ 165 public function set_contextid(int $contextid): bool { 166 if ($this->content->contextid == $contextid) { 167 return true; 168 } 169 170 $oldcontextid = $this->content->contextid; 171 $this->content->contextid = $contextid; 172 $updated = $this->update_content(); 173 if ($updated) { 174 // Move files to new context 175 $fs = get_file_storage(); 176 $fs->move_area_files_to_new_context($oldcontextid, $contextid, 'contentbank', 'public', $this->content->id); 177 } else { 178 $this->content->contextid = $oldcontextid; 179 } 180 return $updated; 181 } 182 183 /** 184 * Returns the contextid of the content. 185 * 186 * @return int The id of the content context. 187 */ 188 public function get_contextid(): string { 189 return $this->content->contextid; 190 } 191 192 /** 193 * Returns the content ID. 194 * 195 * @return int The content ID. 196 */ 197 public function get_id(): int { 198 return $this->content->id; 199 } 200 201 /** 202 * Change the content instanceid value. 203 * 204 * @param int $instanceid New instanceid for this content 205 * @return boolean True if the instanceid has been succesfully updated. False otherwise. 206 */ 207 public function set_instanceid(int $instanceid): bool { 208 $this->content->instanceid = $instanceid; 209 return $this->update_content(); 210 } 211 212 /** 213 * Returns the $instanceid of this content. 214 * 215 * @return int contentbank instanceid 216 */ 217 public function get_instanceid(): int { 218 return $this->content->instanceid; 219 } 220 221 /** 222 * Change the content config values. 223 * 224 * @param string $configdata New config information for this content 225 * @return boolean True if the configdata has been succesfully updated. False otherwise. 226 */ 227 public function set_configdata(string $configdata): bool { 228 $this->content->configdata = $configdata; 229 return $this->update_content(); 230 } 231 232 /** 233 * Return the content config values. 234 * 235 * @return mixed Config information for this content (json decoded) 236 */ 237 public function get_configdata() { 238 return $this->content->configdata; 239 } 240 241 /** 242 * Import a file as a valid content. 243 * 244 * By default, all content has a public file area to interact with the content bank 245 * repository. This method should be overridden by contentypes which does not simply 246 * upload to the public file area. 247 * 248 * If any, the method will return the final stored_file. This way it can be invoked 249 * as parent::import_file in case any plugin want to store the file in the public area 250 * and also parse it. 251 * 252 * @throws file_exception If file operations fail 253 * @param stored_file $file File to store in the content file area. 254 * @return stored_file|null the stored content file or null if the file is discarted. 255 */ 256 public function import_file(stored_file $file): ?stored_file { 257 $originalfile = $this->get_file(); 258 if ($originalfile) { 259 $originalfile->replace_file_with($file); 260 return $originalfile; 261 } else { 262 $itemid = $this->get_id(); 263 $fs = get_file_storage(); 264 $filerecord = [ 265 'contextid' => $this->get_contextid(), 266 'component' => 'contentbank', 267 'filearea' => 'public', 268 'itemid' => $this->get_id(), 269 'filepath' => '/', 270 'filename' => $file->get_filename(), 271 'timecreated' => time(), 272 ]; 273 return $fs->create_file_from_storedfile($filerecord, $file); 274 } 275 } 276 277 /** 278 * Returns the $file related to this content. 279 * 280 * @return stored_file File stored in content bank area related to the given itemid. 281 * @throws \coding_exception if not loaded. 282 */ 283 public function get_file(): ?stored_file { 284 $itemid = $this->get_id(); 285 $fs = get_file_storage(); 286 $files = $fs->get_area_files( 287 $this->content->contextid, 288 'contentbank', 289 'public', 290 $itemid, 291 'itemid, filepath, filename', 292 false 293 ); 294 if (!empty($files)) { 295 $file = reset($files); 296 return $file; 297 } 298 return null; 299 } 300 301 /** 302 * Returns the file url related to this content. 303 * 304 * @return string URL of the file stored in content bank area related to the given itemid. 305 * @throws \coding_exception if not loaded. 306 */ 307 public function get_file_url(): string { 308 if (!$file = $this->get_file()) { 309 return ''; 310 } 311 $fileurl = moodle_url::make_pluginfile_url( 312 $this->content->contextid, 313 'contentbank', 314 'public', 315 $file->get_itemid(), 316 $file->get_filepath(), 317 $file->get_filename() 318 ); 319 320 return $fileurl; 321 } 322 323 /** 324 * Returns user has access permission for the content itself (based on what plugin needs). 325 * 326 * @return bool True if content could be accessed. False otherwise. 327 */ 328 public function is_view_allowed(): bool { 329 // There's no capability at content level to check, 330 // but plugins can overwrite this method in case they want to check something related to content properties. 331 return true; 332 } 333 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body