Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 53
0.00% covered (danger)
0.00%
0 / 11
CRAP
0.00% covered (danger)
0.00%
0 / 1
RdfLtiPlatformRepository
0.00% covered (danger)
0.00%
0 / 53
0.00% covered (danger)
0.00%
0 / 11
506
0.00% covered (danger)
0.00%
0 / 1
 getRootClass
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 count
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 findAll
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 searchByLabel
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getPlatforms
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
6
 queryResources
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
20
 getLtiPlatformFromResource
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 searchById
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
12
 searchByClientId
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
12
 searchByIssuer
0.00% covered (danger)
0.00%
0 / 15
0.00% covered (danger)
0.00%
0 / 1
20
 getLtiPlatformFactory
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
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) 2021 (original work) Open Assessment Technologies SA
19 */
20
21namespace oat\taoLti\models\classes\Platform\Repository;
22
23use core_kernel_classes_Class;
24use oat\generis\model\kernel\persistence\smoothsql\search\ComplexSearchService;
25use oat\generis\model\OntologyRdfs;
26use oat\tao\model\OntologyClassService;
27use oat\taoLti\models\classes\Platform\LtiPlatformRegistration;
28use common_exception_Error as ErrorException;
29use core_kernel_classes_Resource as RdfResource;
30
31/**
32 * Service methods to manage the LTI 1.3 platform business objects using the RDF API.
33 *
34 * @package taoLti
35 */
36class RdfLtiPlatformRepository extends OntologyClassService implements LtiPlatformRepositoryInterface
37{
38    public const CLASS_URI = 'http://www.tao.lu/Ontologies/TAOLTI.rdf#Platform';
39
40    public const LTI_PLATFORM_CLIENT_ID = 'http://www.tao.lu/Ontologies/TAOLTI.rdf#PlatformClientId';
41    public const LTI_PLATFORM_DEPLOYMENT_ID = 'http://www.tao.lu/Ontologies/TAOLTI.rdf#PlatformDeploymentId';
42    public const LTI_PLATFORM_AUDIENCE = 'http://www.tao.lu/Ontologies/TAOLTI.rdf#PlatformAudience';
43    public const LTI_PLATFORM_OAUTH2_ACCESS_TOKEN_URL =
44        'http://www.tao.lu/Ontologies/TAOLTI.rdf#PlatformOuath2AccessTokenUrl';
45    public const LTI_PLATFORM_OIDC_URL = 'http://www.tao.lu/Ontologies/TAOLTI.rdf#PlatformOidcAuthenticationUrl';
46    public const LTI_PLATFORM_JWKS_URL = 'http://www.tao.lu/Ontologies/TAOLTI.rdf#PlatformJwksUrl';
47
48    /**
49     * return the group top level class
50     *
51     * @return core_kernel_classes_Class
52     */
53    public function getRootClass()
54    {
55        return $this->getClass(self::CLASS_URI);
56    }
57
58    /**
59     * @return int
60     */
61    public function count()
62    {
63        return $this->queryResources([], 'count', 0);
64    }
65
66    /**
67     * @inheritdoc
68     */
69    public function findAll(): array
70    {
71        return $this->getPlatforms();
72    }
73
74    /**
75     * @inheritdoc
76     */
77    public function searchByLabel(string $queryString): array
78    {
79        return $this->getPlatforms([OntologyRdfs::RDFS_LABEL => $queryString]);
80    }
81
82    /**
83     * Retrieves LTI platforms from RDF store corresponding to the given criteria.
84     *
85     * @return LtiPlatformRegistration[]
86     */
87    private function getPlatforms(array $criteria = []): array
88    {
89        $resources = $this->queryResources($criteria, 'search', []);
90        $ltiPlatforms = [];
91
92        foreach ($resources as $resource) {
93            $ltiPlatforms[] = $this->getLtiPlatformFromResource($resource);
94        }
95
96        return $ltiPlatforms;
97    }
98
99    /**
100     * Retrieves resources from rdf store corresponding to the given criteria,
101     * hydrate the result with the $hydration method
102     * or returns $default on failure
103     *
104     * @param array $criteria
105     * @param string $hydration Hydration method ("search" for actual results, "count" for counting results)
106     * @param array|int $default default value to return on failure
107     *
108     * @return mixed
109     */
110    private function queryResources(array $criteria, $hydration, $default)
111    {
112        try {
113            /** @var ComplexSearchService $searchService */
114            $searchService = $this->getServiceLocator()->get(ComplexSearchService::SERVICE_ID);
115            $queryBuilder = $searchService->query();
116            $query = $searchService->searchType($queryBuilder, self::CLASS_URI, true);
117            if (count($criteria)) {
118                foreach ($criteria as $property => $value) {
119                    $query->add($property)->contains($value);
120                }
121            }
122            $queryBuilder->setCriteria($query);
123
124            return $searchService->getGateway()->$hydration($queryBuilder);
125        } catch (ErrorException $e) {
126            $this->logError('Unable to retrieve platforms: ' . $e->getMessage());
127
128            return $default;
129        }
130    }
131
132    private function getLtiPlatformFromResource(RdfResource $resource): LtiPlatformRegistration
133    {
134        return $this->getLtiPlatformFactory()->createFromResource($resource);
135    }
136
137    public function searchById(string $id): ?LtiPlatformRegistration
138    {
139        $resource = $this->getResource($id);
140
141        if (!$resource->exists()) {
142            return null;
143        }
144
145        $types = $resource->getTypes();
146        $type = reset($types);
147
148        if ($type->getUri() !== self::CLASS_URI) {
149            return null;
150        }
151
152        return $this->getLtiPlatformFromResource($this->getResource($id));
153    }
154
155    public function searchByClientId(string $clientId): ?LtiPlatformRegistration
156    {
157        $platforms = $this->getPlatforms([self::LTI_PLATFORM_CLIENT_ID => $clientId]);
158        $count = count($platforms);
159        if ($count === 0) {
160            return null;
161        }
162        if ($count > 1) {
163            $this->logWarning(sprintf('Found %d LTI platforms with the same clientId: %s', $count, $clientId));
164        }
165        return reset($platforms);
166    }
167
168    public function searchByIssuer(string $issuer, string $clientId = null): ?LtiPlatformRegistration
169    {
170        $criteria = [self::LTI_PLATFORM_AUDIENCE => $issuer];
171        if ($clientId !== null) {
172            $criteria[self::LTI_PLATFORM_CLIENT_ID] = $clientId;
173        }
174        $platforms = $this->getPlatforms($criteria);
175        $count = count($platforms);
176        if ($count === 0) {
177            return null;
178        }
179        if ($count > 1) {
180            $this->logWarning(sprintf(
181                'Found %d LTI platforms with the same clientId: %s and audience: %s',
182                $count,
183                $clientId,
184                $issuer
185            ));
186        }
187        return reset($platforms);
188    }
189
190    private function getLtiPlatformFactory(): LtiPlatformFactory
191    {
192        return $this->getServiceLocator()->get(LtiPlatformFactory::class);
193    }
194}