MDL-67795 contentbank: delete content UI
[moodle.git] / contentbank / classes / contenttype.php
CommitLineData
33b8ca26
AA
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 type 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
25namespace core_contentbank;
26
27use coding_exception;
28use moodle_url;
29
30/**
31 * Content type manager class
32 *
33 * @package core_contentbank
34 * @copyright 2020 Amaia Anabitarte <amaia@moodle.com>
35 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
36 */
37abstract class contenttype {
38
39 /** Plugin implements uploading feature */
40 const CAN_UPLOAD = 'upload';
41
42 /** @var context This content's context. **/
43 protected $context = null;
44
45 /**
46 * Content type constructor
47 *
48 * @param \context $context Optional context to check (default null)
49 */
50 public function __construct(\context $context = null) {
51 if (empty($context)) {
52 $context = \context_system::instance();
53 }
54 $this->context = $context;
55 }
56
57 /**
58 * Fills content_bank table with appropiate information.
59 *
60 * @param stdClass $content An optional content record compatible object (default null)
61 * @return content Object with content bank information.
62 */
63 public function create_content(\stdClass $content = null): ?content {
64 global $USER, $DB;
65
66 $record = new \stdClass();
67 $record->contenttype = $this->get_contenttype_name();
68 $record->contextid = $this->context->id;
69 $record->name = $content->name ?? '';
70 $record->usercreated = $content->usercreated ?? $USER->id;
71 $record->timecreated = time();
72 $record->usermodified = $record->usercreated;
73 $record->timemodified = $record->timecreated;
74 $record->configdata = $content->configdata ?? '';
75 $record->id = $DB->insert_record('contentbank_content', $record);
76 if ($record->id) {
77 $classname = '\\'.$record->contenttype.'\\content';
78 return new $classname($record);
79 }
80 return null;
81 }
82
c0d615e8
SA
83 /**
84 * Delete this content from the content_bank.
85 * This method can be overwritten by the plugins if they need to delete specific information.
86 *
87 * @param content $content The content to delete.
88 * @return boolean true if the content has been deleted; false otherwise.
89 */
90 public function delete_content(content $content): bool {
91 global $DB;
92
93 // Delete the file if it exists.
94 if ($file = $content->get_file()) {
95 $file->delete();
96 }
97
98 // Delete the contentbank DB entry.
99 return $DB->delete_records('contentbank_content', ['id' => $content->get_id()]);
100 }
101
33b8ca26
AA
102 /**
103 * Returns the contenttype name of this content.
104 *
105 * @return string Content type of the current instance
106 */
107 public function get_contenttype_name(): string {
108 $classname = get_class($this);
109 $contenttype = explode('\\', $classname);
110 return array_shift($contenttype);
111 }
112
113 /**
114 * Returns the plugin name of the current instance.
115 *
116 * @return string Plugin name of the current instance
117 */
118 public function get_plugin_name(): string {
119 $contenttype = $this->get_contenttype_name();
120 $plugin = explode('_', $contenttype);
121 return array_pop($plugin);
122 }
123
124 /**
125 * Returns the URL where the content will be visualized.
126 *
127 * @param stdClass $record Th content to be displayed.
128 * @return string URL where to visualize the given content.
129 */
130 public function get_view_url(\stdClass $record): string {
131 return new moodle_url('/contentbank/view.php', ['id' => $record->id]);
132 }
133
134 /**
135 * Returns the HTML content to add to view.php visualizer.
136 *
137 * @param stdClass $record Th content to be displayed.
138 * @return string HTML code to include in view.php.
139 */
140 public function get_view_content(\stdClass $record): string {
141 // Main contenttype class can visualize the content, but plugins could overwrite visualization.
142 return '';
143 }
144
145 /**
146 * Returns the HTML code to render the icon for content bank contents.
147 *
148 * @param string $contentname The contentname to add as alt value to the icon.
149 * @return string HTML code to render the icon
150 */
151 public function get_icon(string $contentname): string {
152 global $OUTPUT;
153 return $OUTPUT->pix_icon('f/unknown-64', $contentname, 'moodle', ['class' => 'iconsize-big']);
154 }
155
156 /**
157 * Returns user has access capability for the main content bank and the content itself (base on is_access_allowed from plugin).
158 *
159 * @return bool True if content could be accessed. False otherwise.
160 */
161 final public function can_access(): bool {
162 $classname = 'contenttype/'.$this->get_plugin_name();
163 $capability = $classname.":access";
164 $hascapabilities = has_capability('moodle/contentbank:access', $this->context)
165 && has_capability($capability, $this->context);
166 return $hascapabilities && $this->is_access_allowed();
167 }
168
169 /**
170 * Returns user has access capability for the content itself.
171 *
172 * @return bool True if content could be accessed. False otherwise.
173 */
174 protected function is_access_allowed(): bool {
175 // Plugins can overwrite this function to add any check they need.
176 return true;
177 }
178
179 /**
180 * Returns the user has permission to upload new content.
181 *
182 * @return bool True if content could be uploaded. False otherwise.
183 */
184 final public function can_upload(): bool {
185 if (!$this->is_feature_supported(self::CAN_UPLOAD)) {
186 return false;
187 }
188 if (!$this->can_access()) {
189 return false;
190 }
191
192 $classname = 'contenttype/'.$this->get_plugin_name();
193 $uploadcap = $classname.':upload';
194 $hascapabilities = has_capability('moodle/contentbank:upload', $this->context)
195 && has_capability($uploadcap, $this->context);
196 return $hascapabilities && $this->is_upload_allowed();
197 }
198
199 /**
200 * Returns plugin allows uploading.
201 *
202 * @return bool True if plugin allows uploading. False otherwise.
203 */
204 protected function is_upload_allowed(): bool {
205 // Plugins can overwrite this function to add any check they need.
206 return true;
207 }
208
c0d615e8
SA
209 /**
210 * Check if the user can delete this content.
211 *
212 * @param content $content The content to be deleted.
213 * @return bool True if content could be uploaded. False otherwise.
214 */
215 final public function can_delete(content $content): bool {
216 global $USER;
217
218 if ($this->context->id != $content->get_content()->contextid) {
219 // The content has to have exactly the same context as this contenttype.
220 return false;
221 }
222
223 $hascapability = has_capability('moodle/contentbank:deleteanycontent', $this->context);
224 if ($content->get_content()->usercreated == $USER->id) {
225 // This content has been created by the current user; check if she can delete her content.
226 $hascapability = $hascapability || has_capability('moodle/contentbank:deleteowncontent', $this->context);
227 }
228
229 return $hascapability && $this->is_delete_allowed($content);
230 }
231
232 /**
233 * Returns if content allows deleting.
234 *
235 * @param content $content The content to be deleted.
236 * @return bool True if content allows uploading. False otherwise.
237 */
238 protected function is_delete_allowed(content $content): bool {
239 // Plugins can overwrite this function to add any check they need.
240 return true;
241 }
242
33b8ca26
AA
243 /**
244 * Returns the plugin supports the feature.
245 *
246 * @param string $feature Feature code e.g CAN_UPLOAD
247 * @return bool True if content could be uploaded. False otherwise.
248 */
249 final public function is_feature_supported(string $feature): bool {
250 return in_array($feature, $this->get_implemented_features());
251 }
252
253 /**
254 * Return an array of implemented features by the plugins.
255 *
256 * @return array
257 */
258 abstract protected function get_implemented_features(): array;
259
260 /**
261 * Return an array of extensions the plugins could manage.
262 *
263 * @return array
264 */
265 abstract public function get_manageable_extensions(): array;
266}