Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
28.32% |
81 / 286 |
|
20.83% |
5 / 24 |
CRAP | |
0.00% |
0 / 1 |
WorkspaceDAO | |
28.32% |
81 / 286 |
|
20.83% |
5 / 24 |
1008.86 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
1 | |||
getWorkspaceId | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getWorkspaceName | |
100.00% |
7 / 7 |
|
100.00% |
1 / 1 |
2 | |||
getGlobalIds | |
100.00% |
10 / 10 |
|
100.00% |
1 / 1 |
2 | |||
updateLoginSource | n/a |
0 / 0 |
n/a |
0 / 0 |
1 | |||||
addLoginSource | |
100.00% |
30 / 30 |
|
100.00% |
1 / 1 |
4 | |||
deleteLoginSource | n/a |
0 / 0 |
n/a |
0 / 0 |
1 | |||||
storeFile | |
100.00% |
23 / 23 |
|
100.00% |
1 / 1 |
2 | |||
deleteFile | n/a |
0 / 0 |
n/a |
0 / 0 |
1 | |||||
getFileById | |
0.00% |
0 / 10 |
|
0.00% |
0 / 1 |
6 | |||
updateUnitDefsAttachments | |
0.00% |
0 / 18 |
|
0.00% |
0 / 1 |
6 | |||
getAllFiles | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
2 | |||
getFilesByNames | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
2 | |||
getAllFilesWhere | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
6 | |||
getFileRelations | |
0.00% |
0 / 17 |
|
0.00% |
0 / 1 |
2 | |||
getFiles | |
0.00% |
0 / 14 |
|
0.00% |
0 / 1 |
30 | |||
fetchFiles | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
12 | |||
resultRow2File | |
0.00% |
0 / 23 |
|
0.00% |
0 / 1 |
2 | |||
getBlockedFiles | |
0.00% |
0 / 25 |
|
0.00% |
0 / 1 |
12 | |||
storeRelations | |
0.00% |
0 / 21 |
|
0.00% |
0 / 1 |
20 | |||
getBookletResourcePaths | |
0.00% |
0 / 10 |
|
0.00% |
0 / 1 |
2 | |||
getWorkspaceHash | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
2 | |||
setWorkspaceHash | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
2 | |||
setSysCheckModeAccordingToTT | |
80.00% |
8 / 10 |
|
0.00% |
0 / 1 |
3.07 | |||
setSysCheckMode | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
2 | |||
fetchDependenciesForFile | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
2 | |||
getDependentFilesByTypes | |
0.00% |
0 / 15 |
|
0.00% |
0 / 1 |
12 |
1 | <?php |
2 | /** @noinspection PhpUnhandledExceptionInspection */ |
3 | declare(strict_types=1); |
4 | |
5 | class WorkspaceDAO extends DAO { |
6 | private int $workspaceId; |
7 | private string $workspacePath; |
8 | |
9 | public function __construct(int $workspaceId, string $workspacePath) { |
10 | parent::__construct(); |
11 | $this->workspaceId = $workspaceId; |
12 | $this->workspacePath = $workspacePath; |
13 | } |
14 | |
15 | public function getWorkspaceId(): int |
16 | { |
17 | return $this->workspaceId; |
18 | } |
19 | |
20 | public function getWorkspaceName(): string { |
21 | $workspace = $this->_( |
22 | 'select workspaces.name |
23 | from workspaces |
24 | where workspaces.id=:workspace_id', |
25 | [':workspace_id' => $this->workspaceId] |
26 | ); |
27 | |
28 | if ($workspace == null) { |
29 | throw new HttpError("Workspace `$this->workspaceId` not found", 404); // @codeCoverageIgnore |
30 | } |
31 | |
32 | return $workspace['name']; |
33 | } |
34 | |
35 | public function getGlobalIds(): array { |
36 | $globalIds = $this->_(" |
37 | select |
38 | globalIds.id as id, |
39 | source, |
40 | workspace_id, |
41 | workspaces.name as workspace_name, |
42 | globalIds.type as type |
43 | from ( |
44 | select name as id, source, workspace_id, 'login' as type from logins |
45 | union |
46 | select group_name as id, source, workspace_id, 'group' as type from logins group by group_name, source, workspace_id |
47 | ) as globalIds |
48 | left join workspaces on workspace_id |
49 | ", |
50 | [], |
51 | true |
52 | ); |
53 | |
54 | $arr = []; |
55 | |
56 | foreach ($globalIds as $globalId) { |
57 | $arr[$globalId['workspace_id']][$globalId['source']][$globalId['type']][] = $globalId['id']; |
58 | $arr[$globalId['workspace_id']]['/name/'] = $globalId['workspace_name']; |
59 | } |
60 | |
61 | return $arr; |
62 | } |
63 | |
64 | /** |
65 | * @codeCoverageIgnore |
66 | */ |
67 | public function updateLoginSource(string $source, LoginArray $logins): array { |
68 | $deleted = $this->deleteLoginSource($source); |
69 | $added = $this->addLoginSource($source, $logins); |
70 | return [$deleted, $added]; |
71 | } |
72 | |
73 | |
74 | // TODO unit-test |
75 | public function addLoginSource(string $source, LoginArray $logins): int { |
76 | |
77 | // one source could contain 10ks of logins. For the sake of performance we use one statement to insert them all |
78 | // and plain foreach and string-concatenation to build the query. |
79 | |
80 | $sql = 'insert into logins ( |
81 | name, |
82 | mode, |
83 | workspace_id, |
84 | codes_to_booklets, |
85 | group_name, |
86 | group_label, |
87 | custom_texts, |
88 | password, |
89 | source, |
90 | valid_from, |
91 | valid_to, |
92 | valid_for, |
93 | monitors |
94 | ) values'; |
95 | |
96 | foreach ($logins as $login) { |
97 | /* @var $login Login */ |
98 | $loginValues = array_map( |
99 | function (string|int|null $v): string|int { |
100 | if ($v == null) return 'null'; |
101 | if (is_string($v)) return $this->pdoDBhandle->quote($v); |
102 | return $v; |
103 | }, |
104 | [ |
105 | $login->getName(), |
106 | $login->getMode(), |
107 | $this->workspaceId, |
108 | json_encode($login->getBooklets()), |
109 | $login->getGroupName(), |
110 | $login->getGroupLabel(), |
111 | json_encode($login->getCustomTexts()), |
112 | Password::encrypt($login->getPassword(), 't', true), |
113 | $source, |
114 | TimeStamp::toSQLFormat($login->getValidFrom()), |
115 | TimeStamp::toSQLFormat($login->getValidTo()), |
116 | $login->getValidForMinutes(), |
117 | json_encode($login->getProfiles()) |
118 | ] |
119 | ); |
120 | $sql .= '(' . implode(', ', $loginValues) . '),'; |
121 | } |
122 | $sql = rtrim($sql, ","); |
123 | |
124 | $this->_($sql, [], true); |
125 | |
126 | $this->setSysCheckModeAccordingToTT($logins); |
127 | |
128 | return count($logins->asArray()); |
129 | } |
130 | |
131 | /** |
132 | * @codeCoverageIgnore |
133 | */ |
134 | public function deleteLoginSource(string $source): int { |
135 | $this->_( |
136 | 'delete from logins where source = :source and workspace_id = :ws_id', |
137 | [ |
138 | ':source' => $source, |
139 | ':ws_id' => $this->workspaceId |
140 | ] |
141 | ); |
142 | return $this->lastAffectedRows; |
143 | } |
144 | |
145 | public function storeFile(File $file): void { |
146 | $this->_("replace into files ( |
147 | workspace_id, |
148 | name, |
149 | id, |
150 | version_mayor, |
151 | version_minor, |
152 | version_patch, |
153 | version_label, |
154 | label, |
155 | description, |
156 | type, |
157 | verona_module_type, |
158 | verona_version, |
159 | verona_module_id, |
160 | is_valid, |
161 | validation_report, |
162 | size, |
163 | modification_ts, |
164 | context_data |
165 | ) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);", |
166 | [ |
167 | $this->workspaceId, |
168 | $file->getName(), |
169 | $file->getId(), |
170 | $file->getVersionMayor(), |
171 | $file->getVersionMinor(), |
172 | $file->getVersionPatch(), |
173 | $file->getVersionLabel(), |
174 | $file->getLabel(), |
175 | $file->getDescription(), |
176 | $file->getType(), |
177 | $file->getVeronaModuleType(), |
178 | $file->getVeronaVersion(), |
179 | $file->getVeronaModuleId(), |
180 | $file->isValid() ? 1 : 0, |
181 | serialize($file->getValidationReport()), |
182 | $file->getSize(), |
183 | TimeStamp::toSQLFormat($file->getModificationTime()), |
184 | serialize($file->getContextData()) |
185 | ] |
186 | ); |
187 | } |
188 | |
189 | /** |
190 | * @codeCoverageIgnore |
191 | */ |
192 | public function deleteFile(File $file): void { |
193 | $this->_("delete from files where workspace_id = ? and name = ? and type = ?", [$this->workspaceId, $file->getName(), $file->getType()]); |
194 | } |
195 | |
196 | public function getFileById(string $fileId, string $type): ?File { |
197 | $fileData = $this->_( |
198 | "select |
199 | name, |
200 | id, |
201 | label, |
202 | type, |
203 | description, |
204 | is_valid, |
205 | validation_report, |
206 | size, |
207 | modification_ts, |
208 | version_mayor, |
209 | version_minor, |
210 | version_patch, |
211 | version_label, |
212 | verona_module_id, |
213 | verona_module_type, |
214 | verona_version, |
215 | context_data |
216 | from |
217 | files |
218 | where |
219 | workspace_id = ? and id = ? and type = ?", |
220 | [ |
221 | $this->workspaceId, |
222 | $fileId, |
223 | $type |
224 | ] |
225 | ); |
226 | |
227 | return $fileData ? $this->resultRow2File($fileData, []) : null; |
228 | } |
229 | |
230 | public function updateUnitDefsAttachments(string $bookletName, array $attachments): void { |
231 | $this->_( |
232 | 'delete from unit_defs_attachments where workspace_id = :workspace_id and booklet_name = :booklet_name;', |
233 | [ |
234 | ':workspace_id' => $this->workspaceId, |
235 | ':booklet_name' => $bookletName |
236 | ] |
237 | ); |
238 | |
239 | foreach ($attachments as $requestedAttachment) { |
240 | /* @var RequestedAttachment $requestedAttachment */ |
241 | |
242 | $this->_( |
243 | 'replace into unit_defs_attachments(workspace_id, booklet_name, unit_name, variable_id, attachment_type) |
244 | values(:workspace_id, :booklet_name, :unit_name, :variable_id, :attachment_type)', |
245 | [ |
246 | ':workspace_id' => $this->workspaceId, |
247 | ':booklet_name' => $bookletName, |
248 | ':unit_name' => $requestedAttachment->unitName, |
249 | ':variable_id' => $requestedAttachment->variableId, |
250 | ':attachment_type' => $requestedAttachment->attachmentType |
251 | ]); |
252 | } |
253 | } |
254 | |
255 | public function getAllFiles(): array { |
256 | $sql = " |
257 | select |
258 | name, |
259 | type, |
260 | id, |
261 | label, |
262 | description, |
263 | is_valid, |
264 | validation_report, |
265 | size, |
266 | modification_ts, |
267 | version_mayor, |
268 | version_minor, |
269 | version_patch, |
270 | version_label, |
271 | verona_module_id, |
272 | verona_module_type, |
273 | verona_version, |
274 | context_data |
275 | from files |
276 | where workspace_id = ?"; |
277 | $replacements = [$this->workspaceId]; |
278 | |
279 | return $this->fetchFiles($sql, $replacements); |
280 | } |
281 | |
282 | public function getFilesByNames(array $names): array { |
283 | $sql = " |
284 | select |
285 | name, |
286 | type, |
287 | id, |
288 | label, |
289 | description, |
290 | is_valid, |
291 | validation_report, |
292 | size, |
293 | modification_ts, |
294 | version_mayor, |
295 | version_minor, |
296 | version_patch, |
297 | version_label, |
298 | verona_module_id, |
299 | verona_module_type, |
300 | verona_version, |
301 | context_data |
302 | from files |
303 | where workspace_id = ? and |
304 | name in (" . implode(',', array_map(fn ($name) => '?', $names)) . ')'; |
305 | |
306 | $replacements = [ |
307 | $this->workspaceId, |
308 | ...$names |
309 | ]; |
310 | |
311 | return $this->fetchFiles($sql, $replacements, true); |
312 | } |
313 | |
314 | /** @param array $conditions list('column' => value) |
315 | * @return array ['filetype' => File[]]*/ |
316 | public function getAllFilesWhere(array $conditions): array { |
317 | $sql = " |
318 | select |
319 | name, |
320 | type, |
321 | id, |
322 | label, |
323 | description, |
324 | is_valid, |
325 | validation_report, |
326 | size, |
327 | modification_ts, |
328 | version_mayor, |
329 | version_minor, |
330 | version_patch, |
331 | version_label, |
332 | verona_module_id, |
333 | verona_module_type, |
334 | verona_version, |
335 | context_data |
336 | from files |
337 | where workspace_id = ?"; |
338 | $replacements = [$this->workspaceId]; |
339 | |
340 | foreach ($conditions as $condition => $value) { |
341 | $sql .= " and $condition = ?"; |
342 | $replacements[] = $value; |
343 | } |
344 | |
345 | return $this->fetchFiles($sql, $replacements); |
346 | } |
347 | |
348 | public function getFileRelations(string $name, string $type): array { |
349 | $relations = $this->_(" |
350 | select |
351 | object_type, |
352 | object_name, |
353 | relationship_type, |
354 | id as object_id |
355 | from |
356 | file_relations |
357 | left join files |
358 | on file_relations.workspace_id = files.workspace_id |
359 | and file_relations.object_name = files.name |
360 | and file_relations.object_type = files.type |
361 | where |
362 | files.workspace_id = ? |
363 | and subject_name = ? |
364 | and subject_type = ?", |
365 | [$this->workspaceId, $name, $type], |
366 | true |
367 | ); |
368 | |
369 | return array_map( |
370 | function(array $r): FileRelation { |
371 | return new FileRelation( |
372 | $r['object_type'], |
373 | $r['object_name'], |
374 | constant("FileRelationshipType::{$r['relationship_type']}"), |
375 | null, |
376 | $r['object_id'] |
377 | ); |
378 | }, |
379 | $relations |
380 | ); |
381 | } |
382 | |
383 | public function getFiles(array $localPaths, bool $includeInvalid = false): array { |
384 | $replacements = [$this->workspaceId]; |
385 | $validFilePaths = 0; |
386 | |
387 | foreach ($localPaths as $fileLocalPath) { |
388 | $partParts = explode('/', $fileLocalPath, 2); |
389 | if (count($partParts) == 2) { |
390 | list($replacements[], $replacements[]) = $partParts; |
391 | $validFilePaths++; |
392 | } |
393 | } |
394 | |
395 | $filePathCondition = implode(' or ', array_fill(0, $validFilePaths, '(type = ? and name = ?)')); |
396 | $filePathCondition = $filePathCondition ? "and ($filePathCondition)" : ''; |
397 | |
398 | $andIsValid = $includeInvalid ? '' : ' and files.is_valid'; |
399 | |
400 | $sql = "select distinct |
401 | name, |
402 | type, |
403 | id, |
404 | label, |
405 | description, |
406 | is_valid, |
407 | validation_report, |
408 | size, |
409 | modification_ts, |
410 | version_mayor, |
411 | version_minor, |
412 | version_patch, |
413 | version_label, |
414 | verona_module_id, |
415 | verona_module_type, |
416 | verona_version, |
417 | context_data |
418 | from files |
419 | where |
420 | files.workspace_id = ? |
421 | $andIsValid |
422 | $filePathCondition"; |
423 | |
424 | return $this->fetchFiles($sql, $replacements); |
425 | } |
426 | |
427 | private function fetchFiles($sql, $replacements, bool $getDependencies = false): array { |
428 | $files = []; |
429 | foreach ($this->_($sql, $replacements, true) as $row) { |
430 | $files[$row['type']] ??= []; |
431 | // $relations = $this->getFileRelations($workspaceId, $row['name'], $row['type']); |
432 | if ($getDependencies) { |
433 | $dependencies = $this->fetchDependenciesForFile($row['name']); |
434 | } |
435 | $files[$row['type']][$row['name']] = $this->resultRow2File($row, $dependencies ?? []); |
436 | } |
437 | return $files; |
438 | } |
439 | |
440 | private function resultRow2File(array $row, array $relations): ?File { |
441 | return File::get( |
442 | new FileData( |
443 | "$this->workspacePath/{$row['type']}/{$row['name']}", |
444 | $row['type'], |
445 | $row['id'], |
446 | $row['label'], |
447 | $row['description'], |
448 | !!$row['is_valid'], |
449 | unserialize($row['validation_report']), |
450 | $relations, |
451 | TimeStamp::fromSQLFormat($row['modification_ts']), |
452 | $row['size'], |
453 | unserialize($row['context_data']), |
454 | $row['verona_module_type'], |
455 | $row['verona_module_id'], |
456 | $row['version_mayor'], |
457 | $row['version_minor'], |
458 | $row['version_patch'], |
459 | $row['version_label'], |
460 | $row['verona_version'] |
461 | ), |
462 | $row['type'] |
463 | ); |
464 | } |
465 | |
466 | public function getBlockedFiles(array $files): array { |
467 | if (!count($files)) { |
468 | return []; |
469 | } |
470 | |
471 | $replacements = [ |
472 | ':ws_id' => $this->workspaceId |
473 | ]; |
474 | $conditions = []; |
475 | $i = 0; |
476 | foreach ($files as $file) { |
477 | $i++; |
478 | $replacements[":type_$i"] = $file->getType(); |
479 | $replacements[":name_$i"] = $file->getName(); |
480 | $conditions[] = "(object_type = :type_$i and object_name = :name_$i)"; |
481 | } |
482 | |
483 | $selectedFilesConditions = implode(' or ', $conditions); |
484 | |
485 | $sql = "with recursive affected_files as ( |
486 | -- base/first case that initializes the recursion |
487 | select |
488 | subject_type as object_type, |
489 | subject_name as object_name, |
490 | object_type || '/' || object_name as ancestor |
491 | from file_relations |
492 | where |
493 | workspace_id = :ws_id and ($selectedFilesConditions) |
494 | |
495 | union all |
496 | |
497 | -- recursive case |
498 | select |
499 | file_relations.subject_type as object_type, |
500 | file_relations.subject_name as object_name, |
501 | affected_files.ancestor |
502 | from affected_files |
503 | join file_relations |
504 | on affected_files.object_name = file_relations.object_name |
505 | and affected_files.object_type = file_relations.object_type |
506 | and file_relations.workspace_id = :ws_id |
507 | ) |
508 | select distinct |
509 | affected_files.ancestor as file_local_path, |
510 | object_type || '/' || object_name as blocked_by |
511 | from affected_files |
512 | where |
513 | not ($selectedFilesConditions)"; |
514 | |
515 | $result = $this->_($sql, $replacements, true); |
516 | |
517 | return array_reduce( |
518 | $result, |
519 | function(array $agg, array $row) { |
520 | $agg[$row['file_local_path']] = $row['blocked_by']; |
521 | return $agg; |
522 | }, |
523 | [] |
524 | ); |
525 | } |
526 | |
527 | public function storeRelations(File $file): array { |
528 | $unresolvedRelations = []; |
529 | $updatedRelations = []; |
530 | |
531 | foreach ($file->getRelations() as $relation) { |
532 | /* @var $relation FileRelation */ |
533 | |
534 | $relatedFile = $relation->getTarget(); |
535 | |
536 | if (!$relatedFile) { |
537 | $unresolvedRelations++; |
538 | } |
539 | |
540 | $this->_( |
541 | "replace into file_relations (workspace_id, subject_name, subject_type, relationship_type, object_type, object_name) |
542 | values (?, ?, ?, ?, ?, ?);", |
543 | [ |
544 | $this->workspaceId, |
545 | $file->getName(), |
546 | $file->getType(), |
547 | $relation->getRelationshipType()->name, |
548 | $relation->getTargetType(), |
549 | $relatedFile->getName() |
550 | ] |
551 | ); |
552 | |
553 | if ($this->lastAffectedRows != 1) { |
554 | $updatedRelations[] = $relation; |
555 | } |
556 | } |
557 | |
558 | return [$unresolvedRelations, $updatedRelations]; |
559 | } |
560 | |
561 | public function getBookletResourcePaths(string $bookletFileName): array { |
562 | return |
563 | $this->_( |
564 | "select distinct |
565 | unitFiles.id, |
566 | resourceFiles.type, |
567 | resourceFiles.name, |
568 | unitNeedsResource.relationship_type |
569 | from file_relations as bookletContainsUnit |
570 | left join file_relations as unitNeedsResource |
571 | on bookletContainsUnit.workspace_id = unitNeedsResource.workspace_id |
572 | and bookletContainsUnit.object_name = unitNeedsResource.subject_name |
573 | and bookletContainsUnit.object_type = unitNeedsResource.subject_type |
574 | -- and unitNeedsResource.relationship_type in('isDefinedBy', 'usesPlayer') |
575 | and unitNeedsResource.object_type = 'Resource' |
576 | and bookletContainsUnit.relationship_type = 'containsUnit' |
577 | left join files as resourceFiles |
578 | on resourceFiles.type = unitNeedsResource.object_type |
579 | and resourceFiles.name = unitNeedsResource.object_name |
580 | and resourceFiles.workspace_id = unitNeedsResource.workspace_id |
581 | left join files as unitFiles |
582 | on unitFiles.type = unitNeedsResource.subject_type |
583 | and unitFiles.name = unitNeedsResource.subject_name |
584 | and unitFiles.workspace_id = unitNeedsResource.workspace_id |
585 | where |
586 | bookletContainsUnit.subject_name = :booklet_file_name |
587 | and resourceFiles.workspace_id = :ws_id |
588 | and resourceFiles.is_valid = 1", |
589 | [ |
590 | ':ws_id' => $this->workspaceId, |
591 | ':booklet_file_name' => $bookletFileName |
592 | ], |
593 | true |
594 | ); |
595 | } |
596 | |
597 | public function getWorkspaceHash(): string |
598 | { |
599 | return $this->_( |
600 | "select workspace_hash from workspaces where id = :ws_id", |
601 | [':ws_id' => $this->workspaceId] |
602 | )['workspace_hash']; |
603 | } |
604 | |
605 | public function setWorkspaceHash(string $hash): void |
606 | { |
607 | $this->_( |
608 | "update workspaces set workspace_hash = :hash where id = :ws_id", |
609 | [':hash' => $hash, ':ws_id' => $this->workspaceId] |
610 | ); |
611 | } |
612 | |
613 | private function setSysCheckModeAccordingToTT(LoginArray $logins) { |
614 | $enableSysCheckMode = SysCheckMode::TEST; |
615 | /** @var Login $login */ |
616 | foreach ($logins as $login) { |
617 | if ($login->getMode() == 'sys-check-login') { |
618 | $enableSysCheckMode = SysCheckMode::SYSCHECK; |
619 | break; |
620 | } |
621 | } |
622 | $this->_( |
623 | "update workspaces set content_type = '$enableSysCheckMode->value' where id = :ws_id", |
624 | [':ws_id' => $this->workspaceId], |
625 | true |
626 | ); |
627 | } |
628 | |
629 | public function setSysCheckMode(string $mode): void { |
630 | $this->_( |
631 | "update workspaces set content_type = :mode where id = :ws_id", |
632 | [ |
633 | ':mode' => $mode, |
634 | ':ws_id' => $this->workspaceId |
635 | ], |
636 | true |
637 | ); |
638 | } |
639 | |
640 | public function fetchDependenciesForFile(string $name): ?array { |
641 | return $this->_( |
642 | " |
643 | -- base case that starts the recursion |
644 | with recursive dependencies as ( |
645 | select subject_name, object_name, relationship_type |
646 | from file_relations |
647 | where subject_name = :name |
648 | |
649 | union all |
650 | |
651 | -- recursive case |
652 | select fr.subject_name, fr.object_name, fr.relationship_type |
653 | from file_relations fr |
654 | inner join dependencies dep |
655 | on fr.subject_name = dep.object_name |
656 | ) |
657 | select distinct object_name, relationship_type |
658 | from dependencies;", |
659 | [ |
660 | ':name' => $name, |
661 | ], |
662 | true |
663 | ); |
664 | } |
665 | |
666 | public function getDependentFilesByTypes(File $file, array $types = []): array { |
667 | $sql = "select |
668 | files.name, |
669 | files.type, |
670 | files.id, |
671 | files.label, |
672 | files.description, |
673 | files.is_valid, |
674 | files.validation_report, |
675 | files.size, |
676 | files.modification_ts, |
677 | files.version_mayor, |
678 | files.version_minor, |
679 | files.version_patch, |
680 | files.version_label, |
681 | files.verona_module_id, |
682 | files.verona_module_type, |
683 | files.verona_version, |
684 | files.context_data |
685 | from file_relations |
686 | left join files |
687 | on file_relations.workspace_id = files.workspace_id |
688 | and file_relations.subject_name = files.name |
689 | and file_relations.subject_type = files.type |
690 | where |
691 | files.workspace_id = :ws_id |
692 | and object_type = :file_type and object_name= :file_name"; |
693 | |
694 | $replacements = [ |
695 | ':ws_id' => $this->workspaceId, |
696 | ':file_type' => $file->getType(), |
697 | ':file_name' => $file->getName() |
698 | ]; |
699 | |
700 | // add more conditions |
701 | if (!empty($types)) { |
702 | $conditions = []; |
703 | foreach ($types as $index => $type) { |
704 | $conditions[] = "files.type = :type$index"; |
705 | $replacements[":type$index"] = $type; |
706 | } |
707 | $addCondition = ' and (' . implode(' or ', $conditions) . ')'; |
708 | $sql .= $addCondition; |
709 | } |
710 | |
711 | return $this->fetchFiles($sql, $replacements); |
712 | } |
713 | } |