ILIAS  trunk Revision v13.0_alpha-62-g3b72d83f2e5
ActionDBRepository.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
21namespace ILIAS\WOPI\Discovery;
22
24
29{
33 private const TABLE_NAME = 'wopi_action';
34 private array $edit_actions = [ActionTarget::EDIT, ActionTarget::EMBED_EDIT];
35
43 private array $view_actions = [ActionTarget::EMBED_VIEW, ActionTarget::VIEW];
44
45 public function __construct(
46 private \ilDBInterface $db
47 ) {
48 }
49
50 private function implodeTargets(ActionTarget ...$targets): string
51 {
52 return implode(
53 ', ',
54 array_map(
55 fn(ActionTarget $target): string => $this->db->quote($target->value, 'text'),
56 $targets
57 )
58 );
59 }
60
61 public function hasActionForSuffix(
62 string $suffix,
63 ActionTarget ...$action_target
64 ): bool {
65 static $cache = [];
66
67 $implode_targets = $this->implodeTargets(...$action_target);
68
69 if (isset($cache[$suffix][$implode_targets])) {
70 return $cache[$suffix][$implode_targets];
71 }
72
73 $query = 'SELECT * FROM '
74 . self::TABLE_NAME
75 . ' WHERE ext = %s AND name IN(' . $implode_targets . ')';
76
77 $result = $this->db->queryF(
78 $query,
79 ['text'],
80 [strtolower($suffix)]
81 );
82 return $cache[$suffix][$implode_targets] = $result->numRows() > 0;
83 }
84
85 public function hasEditActionForSuffix(string $suffix): bool
86 {
87 return $this->hasActionForSuffix($suffix, ...$this->edit_actions);
88 }
89
90 public function hasViewActionForSuffix(string $suffix): bool
91 {
92 return $this->hasActionForSuffix($suffix, ...$this->view_actions);
93 }
94
95 public function getActionForSuffix(
96 string $suffix,
97 ActionTarget $action_target
98 ): ?Action {
99 if (!$this->hasActionForSuffix($suffix, $action_target)) {
100 return null;
101 }
102
103 $query = 'SELECT * FROM '
104 . self::TABLE_NAME
105 . ' WHERE ext = %s AND name = %s';
106
107 $result = $this->db->queryF($query, ['text', 'text'], [strtolower($suffix), $action_target->value]);
108 $row = $this->db->fetchAssoc($result);
109 return $this->fromDBRow($row);
110 }
111
112 public function getEditActionForSuffix(string $suffix): ?Action
113 {
114 foreach ($this->edit_actions as $action_target) {
115 $action = $this->getActionForSuffix($suffix, $action_target);
116 if ($action !== null) {
117 return $action;
118 }
119 }
120 return null;
121 }
122
123 public function getViewActionForSuffix(string $suffix): ?Action
124 {
125 foreach ($this->view_actions as $action_target) {
126 $action = $this->getActionForSuffix($suffix, $action_target);
127 if ($action !== null) {
128 return $action;
129 }
130 }
131 return null;
132 }
133
134 public function getActions(): array
135 {
136 $actions = [];
137 $query = 'SELECT * FROM ' . self::TABLE_NAME;
138 $result = $this->db->query($query);
139 while ($row = $this->db->fetchAssoc($result)) {
140 $actions[] = $this->fromDBRow($row);
141 }
142 return $actions;
143 }
144
145 public function getActionsForTarget(ActionTarget $action_target): array
146 {
147 $query = 'SELECT * FROM ' . self::TABLE_NAME . ' WHERE name = %s';
148 $result = $this->db->queryF($query, ['text'], [$action_target->value]);
149 $actions = [];
150 while ($row = $this->db->fetchAssoc($result)) {
151 $actions[] = $this->fromDBRow($row);
152 }
153 return $actions;
154 }
155
156 public function getActionsForTargets(ActionTarget ...$action_target): array
157 {
158 $actions = [];
159 foreach ($action_target as $target) {
160 $actions[] = $this->getActionsForTarget($target);
161 }
162 return array_merge(...$actions);
163 }
164
165 public function getSupportedSuffixes(ActionTarget ...$action_target): array
166 {
167 $query = 'SELECT ext FROM '
168 . self::TABLE_NAME
169 . ' WHERE name IN (' . $this->implodeTargets(...$action_target) . ')';
170 $result = $this->db->query($query);
171 $suffixes = [];
172 while ($row = $this->db->fetchAssoc($result)) {
173 $suffixes[] = $row['ext'];
174 }
175 return $suffixes;
176 }
177
182 public function getCreatableSuffixes(bool $with_templates = false): array
183 {
184 $suffixes = array_keys($this->getCreatableFormats($with_templates));
185 sort($suffixes);
186
187 return $suffixes;
188 }
189
190 public function getCreatableFormats(bool $with_templates = false): array
191 {
192 $formats = [];
193 foreach ($this->getEditNewFormats() as $suffix => $format) {
194 if ($with_templates || !$format['template']) {
195 $formats[$suffix] = $format['app'];
196 }
197 }
198 uksort(
199 $formats,
200 static fn(string $a, string $b): int => strnatcasecmp($formats[$a] . ' ' . $a, $formats[$b] . ' ' . $b)
201 );
202
203 return $formats;
204 }
205
206 public function getTemplateSuffixes(): array
207 {
208 $suffixes = array_keys(
209 array_filter(
210 $this->getEditNewFormats(),
211 static fn(array $format): bool => $format['template']
212 )
213 );
214 sort($suffixes);
215
216 return $suffixes;
217 }
218
223 private function getEditNewFormats(): array
224 {
225 $query = 'SELECT a.ext, a.target_ext, p.name app_name FROM ' . self::TABLE_NAME . ' a'
226 . ' LEFT JOIN wopi_app p ON p.id = a.app_id'
227 . ' WHERE a.name = %s';
228 $result = $this->db->queryF($query, ['text'], [ActionTarget::EDIT_NEW->value]);
229
230 $formats = [];
231 while ($row = $this->db->fetchAssoc($result)) {
232 $suffix = strtolower((string) $row['ext']);
233 $target = empty($row['target_ext']) ? null : strtolower((string) $row['target_ext']);
234 $template = $target !== null && $target !== $suffix;
235 if (isset($formats[$suffix]) && ($template || !$formats[$suffix]['template'])) {
236 continue;
237 }
238 $formats[$suffix] = [
239 'app' => (string) ($row['app_name'] ?? ''),
240 'template' => $template,
241 ];
242 }
243
244 return $formats;
245 }
246
247 public function getActionsForApp(App $app): array
248 {
249 $actions = [];
250 $query = 'SELECT * FROM ' . self::TABLE_NAME . ' WHERE app_id = %s';
251 $result = $this->db->queryF($query, ['integer'], [$app->getId()]);
252 while ($row = $this->db->fetchAssoc($result)) {
253 $actions[] = $this->fromDBRow($row);
254 }
255 return $actions;
256 }
257
258 private function fromDBRow(array $row): Action
259 {
260 return new Action(
261 (int) $row['id'],
262 (string) $row['name'],
263 (string) $row['ext'],
264 new URI((string) $row['urlsrc']),
265 empty($row['url_appendix']) ? null : (string) $row['url_appendix'],
266 empty($row['target_ext']) ? null : (string) $row['target_ext']
267 );
268 }
269
270 public function clear(): void
271 {
272 $query = 'DELETE FROM ' . self::TABLE_NAME;
273 $this->db->manipulate($query);
274 }
275
276 public function clearSuperfluous(Action ...$actions): void
277 {
278 $collected_ids = array_map(
279 static fn(Action $act): int => $act->getId(),
280 $actions
281 );
282 $query = 'DELETE FROM ' . self::TABLE_NAME . ' WHERE ' . $this->db->in('id', $collected_ids, true, 'integer');
283 $this->db->manipulate($query);
284 }
285
286 public function store(Action $action, App $for_app): void
287 {
288 // store only actions with extensions
289 if (empty($action->getExtension())) {
290 return;
291 }
292
293 // check for existing action to update them
294 // most actions have no target extension, "target_ext = NULL" would never match them
295 $query = 'SELECT * FROM ' . self::TABLE_NAME . ' WHERE name = %s AND ext = %s';
296 $types = ['text', 'text'];
297 $values = [$action->getName(), strtolower($action->getExtension())];
298 if ($action->getTargetExtension() === null) {
299 $query .= ' AND target_ext IS NULL';
300 } else {
301 $query .= ' AND target_ext = %s';
302 $types[] = 'text';
303 $values[] = $action->getTargetExtension();
304 }
305 $result = $this->db->queryF($query, $types, $values);
306
307 if ($this->db->numRows($result) > 0) {
308 $row = $this->db->fetchAssoc($result);
309 $action = $action->withId((int) $row['id']);
310 }
311
312 if ($this->db->queryF(
313 'SELECT * FROM ' . self::TABLE_NAME . ' WHERE id = %s',
314 ['integer'],
315 [$action->getId()]
316 )->numRows() === 0) {
317 $next_id = $this->db->nextId(self::TABLE_NAME);
318 $this->db->insert(self::TABLE_NAME, [
319 'id' => ['integer', $next_id],
320 'name' => ['text', $action->getName()],
321 'ext' => ['text', strtolower($action->getExtension())],
322 'urlsrc' => ['text', $action->getLauncherUrl()],
323 'app_id' => ['integer', $for_app->getId()],
324 'url_appendix' => ['text', $action->getUrlAppendix()],
325 'target_ext' => ['text', $action->getTargetExtension()],
326 ]);
327 $action = $action->withId($next_id);
328 } else {
329 $this->db->update(self::TABLE_NAME, [
330 'name' => ['text', $action->getName()],
331 'ext' => ['text', strtolower($action->getExtension())],
332 'urlsrc' => ['text', $action->getLauncherUrl()],
333 'app_id' => ['integer', $for_app->getId()],
334 'url_appendix' => ['text', $action->getUrlAppendix()],
335 'target_ext' => ['text', $action->getTargetExtension()],
336 ], [
337 'id' => ['integer', $action->getId()],
338 ]);
339 }
340 }
341}
The scope of this class is split ilias-conform URI's into components.
Definition: URI.php:35
getActionForSuffix(string $suffix, ActionTarget $action_target)
getCreatableSuffixes(bool $with_templates=false)
Templates such as dotx are left out unless asked for: the editnew action of a template creates a file...
getActionsForTarget(ActionTarget $action_target)
array $view_actions
The order is the preference order of getViewActionForSuffix().
hasActionForSuffix(string $suffix, ActionTarget ... $action_target)
__construct(private \ilDBInterface $db)
implodeTargets(ActionTarget ... $targets)
getCreatableFormats(bool $with_templates=false)
getActionsForTargets(ActionTarget ... $action_target)
getSupportedSuffixes(ActionTarget ... $action_target)
Interface ilDBInterface.
ActionTarget
Officialy supported action targets, see https://learn.microsoft.com/en-us/openspecs/office_protocols/...
$a
thx to https://mlocati.github.io/php-cs-fixer-configurator for the examples
if(!file_exists('../ilias.ini.php'))