Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
93.10% covered (success)
93.10%
27 / 29
80.00% covered (warning)
80.00%
4 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
InstanceMover
93.10% covered (success)
93.10%
27 / 29
80.00% covered (warning)
80.00%
4 / 5
14.06
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 withPermissionCopier
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 withPermissionCopiers
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
6
 transfer
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
1 / 1
4
 assertInSameRootClass
100.00% covered (success)
100.00%
12 / 12
100.00% covered (success)
100.00%
1 / 1
6
1<?php
2
3/**
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; under version 2
7 * of the License (non-upgradable).
8 *
9 * This program 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 this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17 *
18 * Copyright (c) 2023 (original work) Open Assessment Technologies SA.
19 */
20
21declare(strict_types=1);
22
23namespace oat\tao\model\resources\Service;
24
25use core_kernel_classes_Class;
26use core_kernel_classes_Resource;
27use InvalidArgumentException;
28use oat\generis\model\data\Ontology;
29use oat\tao\model\resources\Command\ResourceTransferCommand;
30use oat\tao\model\resources\Contract\PermissionCopierInterface;
31use oat\tao\model\resources\Contract\ResourceTransferInterface;
32use oat\tao\model\resources\Contract\RootClassesListServiceInterface;
33use oat\tao\model\resources\ResourceTransferResult;
34use oat\tao\model\Translation\Service\TranslationMoveService;
35
36class InstanceMover implements ResourceTransferInterface
37{
38    private Ontology $ontology;
39    private RootClassesListServiceInterface $rootClassesListService;
40    private TranslationMoveService $translationMoveService;
41
42    public function __construct(
43        Ontology $ontology,
44        RootClassesListServiceInterface $rootClassesListService,
45        TranslationMoveService $translationMoveService
46    ) {
47        $this->ontology = $ontology;
48        $this->rootClassesListService = $rootClassesListService;
49        $this->translationMoveService = $translationMoveService;
50    }
51
52    public function withPermissionCopier(PermissionCopierInterface $permissionCopier): void
53    {
54        $this->permissionCopier = $permissionCopier;
55    }
56
57    /**
58     * This method is to be used with tagged_iterator() from service providers
59     * (but only the last copier from the iterable is effectively applied).
60     */
61    public function withPermissionCopiers(iterable $permissionCopiers): void
62    {
63        foreach ($permissionCopiers as $copier) {
64            $this->withPermissionCopier($copier);
65        }
66    }
67
68    public function transfer(ResourceTransferCommand $command): ResourceTransferResult
69    {
70        $from = $this->ontology->getResource($command->getFrom());
71        $to = $this->ontology->getClass($command->getTo());
72
73        $fromClasses = $from->getTypes();
74
75        $this->assertInSameRootClass($from, current($fromClasses), $to);
76
77        foreach ($fromClasses as $fromClass) {
78            $from->removeType($fromClass);
79        }
80
81        $from->setType($to);
82
83        if (isset($this->permissionCopier) && $command->useDestinationAcl()) {
84            $this->permissionCopier->copy($to, $from);
85        }
86
87        $this->translationMoveService->moveTranslations($command);
88
89        return new ResourceTransferResult($from->getUri());
90    }
91
92    private function assertInSameRootClass(
93        core_kernel_classes_Resource $fromInstance,
94        core_kernel_classes_Class $fromClass,
95        core_kernel_classes_Class $toClass
96    ): void {
97        foreach ($this->rootClassesListService->list() as $rootClass) {
98            if (
99                ($fromClass->equals($rootClass) || $fromClass->isSubClassOf($rootClass))
100                && !$toClass->equals($rootClass)
101                && !$toClass->isSubClassOf($rootClass)
102            ) {
103                throw new InvalidArgumentException(
104                    sprintf(
105                        'Selected instance (%s) and destination class (%s) must be in the same root class (%s).',
106                        $fromInstance->getUri(),
107                        $toClass->getUri(),
108                        $rootClass->getUri()
109                    )
110                );
111            }
112        }
113    }
114}