Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
| Total | |
39.44% |
28 / 71 |
|
25.93% |
7 / 27 |
CRAP | |
0.00% |
0 / 1 |
| core_kernel_classes_Class | |
39.44% |
28 / 71 |
|
25.93% |
7 / 27 |
358.77 | |
0.00% |
0 / 1 |
| getImplementation | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| getSubClasses | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| isSubClassOf | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| getParentClasses | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| getProperties | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| getInstances | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| getInstanceCollection | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| setInstance | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| setSubClassOf | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| setProperty | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| createInstance | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
1 | |||
| createSubClass | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
1 | |||
| retrieveSubClassByLabel | |
100.00% |
5 / 5 |
|
100.00% |
1 / 1 |
3 | |||
| retrieveOrCreateSubClassByLabel | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
2 | |||
| createSubClassPathByLabel | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
2 | |||
| createProperty | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| getMethodes | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| searchInstances | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| countInstances | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| getInstancesPropertyValues | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
2 | |||
| unsetProperty | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| createInstanceWithProperties | |
47.06% |
8 / 17 |
|
0.00% |
0 / 1 |
14.27 | |||
| deleteInstances | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| delete | |
0.00% |
0 / 11 |
|
0.00% |
0 / 1 |
6 | |||
| exists | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| getClassRepository | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| updateUri | |
0.00% |
0 / 1 |
|
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) 2002-2008 (original work) Public Research Centre Henri Tudor & University of Luxembourg |
| 19 | * (under the project TAO & TAO2); |
| 20 | * 2008-2010 (update and modification) Deutsche Institut für Internationale Pädagogische Forschung |
| 21 | * (under the project TAO-TRANSFER); |
| 22 | * 2009-2012 (update and modification) Public Research Centre Henri Tudor |
| 23 | * (under the project TAO-SUSTAIN & TAO-DEV); |
| 24 | * 2017-2021 (update and modification) Open Assessment Technologies SA. |
| 25 | */ |
| 26 | |
| 27 | use oat\generis\model\OntologyRdf; |
| 28 | use oat\oatbox\event\EventManager; |
| 29 | use oat\oatbox\event\EventManagerAwareTrait; |
| 30 | use oat\generis\model\data\event\ResourceCreated; |
| 31 | use oat\generis\model\resource\ResourceCollection; |
| 32 | use oat\generis\model\resource\Repository\ClassRepository; |
| 33 | use oat\generis\model\resource\Context\ResourceRepositoryContext; |
| 34 | use oat\generis\model\resource\Contract\ResourceRepositoryInterface; |
| 35 | |
| 36 | /** |
| 37 | * The class of rdfs:classes. It implements basic tests like isSubClassOf(Class |
| 38 | * instances, properties and subclasses retrieval, but also enable to edit it |
| 39 | * setSubClassOf setProperty, etc. |
| 40 | * |
| 41 | * @author patrick.plichart@tudor.lu |
| 42 | * |
| 43 | * @see http://www.w3.org/RDF/ |
| 44 | * @see http://www.w3.org/TR/rdf-schema/ |
| 45 | */ |
| 46 | class core_kernel_classes_Class extends core_kernel_classes_Resource |
| 47 | { |
| 48 | use EventManagerAwareTrait; |
| 49 | |
| 50 | /** |
| 51 | * |
| 52 | * @return core_kernel_persistence_ClassInterface |
| 53 | */ |
| 54 | protected function getImplementation() |
| 55 | { |
| 56 | return $this->getModel()->getRdfsInterface()->getClassImplementation(); |
| 57 | } |
| 58 | |
| 59 | |
| 60 | /** |
| 61 | * returns the collection of direct subClasses (see getIndirectSubClassesOf |
| 62 | * a complete list of subclasses) |
| 63 | * |
| 64 | * @access public |
| 65 | * @author patrick.plichart@tudor.lu |
| 66 | * @param boolean recursive |
| 67 | * @return \core_kernel_classes_Class[] |
| 68 | * @see http://www.w3.org/TR/rdf-schema/ |
| 69 | */ |
| 70 | public function getSubClasses($recursive = false) |
| 71 | { |
| 72 | return (array) $this->getImplementation()->getSubClasses($this, $recursive); |
| 73 | } |
| 74 | |
| 75 | /** |
| 76 | * returns true if this is a rdfs:subClassOf $parentClass |
| 77 | * |
| 78 | * @access public |
| 79 | * @author patrick.plichart@tudor.lu |
| 80 | * @param \core_kernel_classes_Class parentClass |
| 81 | * @return boolean |
| 82 | */ |
| 83 | public function isSubClassOf(core_kernel_classes_Class $parentClass) |
| 84 | { |
| 85 | return (bool) $this->getImplementation()->isSubClassOf($this, $parentClass); |
| 86 | } |
| 87 | |
| 88 | /** |
| 89 | * returns all parent classes as a collection |
| 90 | * |
| 91 | * @access public |
| 92 | * @author patrick.plichart@tudor.lu |
| 93 | * @param boolean recursive |
| 94 | * @return \core_kernel_classes_Class[] |
| 95 | */ |
| 96 | public function getParentClasses($recursive = false) |
| 97 | { |
| 98 | return (array) $this->getImplementation()->getParentClasses($this, $recursive); |
| 99 | } |
| 100 | |
| 101 | /** |
| 102 | * Returns the Properties bound to the Class. If the $recursive parameter is |
| 103 | * to true, the whole class hierarchy will be inspected from the current |
| 104 | * to the top one to retrieve tall its properties. |
| 105 | * |
| 106 | * @access public |
| 107 | * @author patrick.plichart@tudor.lu |
| 108 | * @param boolean recursive Recursive Properties retrieval accross the Class hierarchy. |
| 109 | * @return \core_kernel_classes_Property[] |
| 110 | */ |
| 111 | public function getProperties($recursive = false) |
| 112 | { |
| 113 | return (array) $this->getImplementation()->getProperties($this, $recursive); |
| 114 | } |
| 115 | |
| 116 | /** |
| 117 | * return direct instances of this class as a collection |
| 118 | * |
| 119 | * @access public |
| 120 | * @author patrick.plichart@tudor.lu |
| 121 | * @param boolean recursive |
| 122 | * @param array params |
| 123 | * @return \core_kernel_classes_Resource[] |
| 124 | */ |
| 125 | public function getInstances($recursive = false, $params = []) |
| 126 | { |
| 127 | return (array) $this->getImplementation()->getInstances($this, $recursive, $params); |
| 128 | } |
| 129 | |
| 130 | /** |
| 131 | * return direct instances of this class as a collection |
| 132 | * |
| 133 | * @param boolean recursive |
| 134 | * @param array params |
| 135 | * @return ResourceCollection |
| 136 | */ |
| 137 | public function getInstanceCollection() |
| 138 | { |
| 139 | return new ResourceCollection($this); |
| 140 | } |
| 141 | |
| 142 | /** |
| 143 | * creates a new instance of the class todo : different from the method |
| 144 | * which simply link the previously created ressource with this class |
| 145 | * |
| 146 | * @access public |
| 147 | * @author Jerome Bogaerts, <jerome.bogaerts@tudor.lu> |
| 148 | * @param \core_kernel_classes_Resource instance |
| 149 | * @return core_kernel_classes_Resource |
| 150 | * @deprecated |
| 151 | */ |
| 152 | public function setInstance(core_kernel_classes_Resource $instance) |
| 153 | { |
| 154 | return $this->getImplementation()->setInstance($this, $instance); |
| 155 | } |
| 156 | |
| 157 | /** |
| 158 | * alias to setPropertyValues using rdfs: subClassOf, uriClass must be a |
| 159 | * Class otherwise it returns false |
| 160 | * |
| 161 | * @access public |
| 162 | * @author patrick.plichart@tudor.lu |
| 163 | * @param \core_kernel_classes_Class iClass |
| 164 | * @return boolean |
| 165 | */ |
| 166 | public function setSubClassOf(core_kernel_classes_Class $iClass) |
| 167 | { |
| 168 | return (bool) $this->getImplementation()->setSubClassOf($this, $iClass); |
| 169 | } |
| 170 | |
| 171 | /** |
| 172 | * add a property to the class, uriProperty must be a valid property |
| 173 | * the method returns false |
| 174 | * |
| 175 | * @access public |
| 176 | * @author patrick.plichart@tudor.lu |
| 177 | * @param \core_kernel_classes_Property property |
| 178 | * @return boolean |
| 179 | * @deprecated |
| 180 | */ |
| 181 | public function setProperty(core_kernel_classes_Property $property) |
| 182 | { |
| 183 | return (bool) $this->getImplementation()->setProperty($this, $property); |
| 184 | } |
| 185 | |
| 186 | /** |
| 187 | * Should not be called by application code, please use |
| 188 | * core_kernel_classes_ResourceFactory::create() instead |
| 189 | * |
| 190 | * @access public |
| 191 | * @author Jerome Bogaerts, <jerome.bogaerts@tudor.lu> |
| 192 | * @param string label |
| 193 | * @param string comment |
| 194 | * @param string uri |
| 195 | * @return \core_kernel_classes_Resource |
| 196 | */ |
| 197 | public function createInstance($label = '', $comment = '', $uri = '') |
| 198 | { |
| 199 | $returnValue = $this->getImplementation()->createInstance($this, $label, $comment, $uri); |
| 200 | $eventManager = $this->getServiceManager()->get(EventManager::SERVICE_ID); |
| 201 | $eventManager->trigger(new ResourceCreated($returnValue)); |
| 202 | return $returnValue; |
| 203 | } |
| 204 | |
| 205 | /** |
| 206 | * Short description of method createSubClass |
| 207 | * |
| 208 | * @access public |
| 209 | * @author Jerome Bogaerts, <jerome.bogaerts@tudor.lu> |
| 210 | * @param string label |
| 211 | * @param string comment |
| 212 | * @param string uri |
| 213 | * @return core_kernel_classes_Class |
| 214 | */ |
| 215 | public function createSubClass($label = '', $comment = '', $uri = "") |
| 216 | { |
| 217 | $returnValue = $this->getImplementation()->createSubClass($this, $label, $comment, $uri); |
| 218 | $eventManager = $this->getServiceManager()->get(EventManager::SERVICE_ID); |
| 219 | $eventManager->trigger(new ResourceCreated($returnValue)); |
| 220 | return $returnValue; |
| 221 | } |
| 222 | |
| 223 | /** |
| 224 | * Retrieves a direct subclass by label. |
| 225 | * |
| 226 | * @param string label |
| 227 | * @return core_kernel_classes_Class|null |
| 228 | */ |
| 229 | public function retrieveSubClassByLabel($label) |
| 230 | { |
| 231 | $subClasses = $this->getSubClasses(); |
| 232 | foreach ($subClasses as $subclass) { |
| 233 | if ($subclass->getLabel() === $label) { |
| 234 | return $subclass; |
| 235 | } |
| 236 | } |
| 237 | |
| 238 | return null; |
| 239 | } |
| 240 | |
| 241 | /** |
| 242 | * Retrieves a direct subclass by label or creates it if not existent. |
| 243 | * |
| 244 | * @param string label |
| 245 | * @return core_kernel_classes_Class |
| 246 | */ |
| 247 | public function retrieveOrCreateSubClassByLabel($label) |
| 248 | { |
| 249 | return $this->retrieveSubClassByLabel($label) ?: $this->createSubClass($label); |
| 250 | } |
| 251 | |
| 252 | /** |
| 253 | * Creates a path of subclasses from an array of labels, URIs and comments. |
| 254 | * |
| 255 | * @param array $labels indexed array of labels ordered from root to leaf class |
| 256 | * @return core_kernel_classes_Class The last class created |
| 257 | */ |
| 258 | public function createSubClassPathByLabel(array $labels) |
| 259 | { |
| 260 | $currentClass = $this; |
| 261 | |
| 262 | foreach ($labels as $label) { |
| 263 | $currentClass = $currentClass->retrieveOrCreateSubClassByLabel($label); |
| 264 | } |
| 265 | |
| 266 | return $currentClass; |
| 267 | } |
| 268 | |
| 269 | /** |
| 270 | * Short description of method createProperty |
| 271 | * |
| 272 | * @access public |
| 273 | * @author Jerome Bogaerts, <jerome.bogaerts@tudor.lu> |
| 274 | * @param string label |
| 275 | * @param string comment |
| 276 | * @param boolean isLgDependent |
| 277 | * @return core_kernel_classes_Property |
| 278 | */ |
| 279 | public function createProperty($label = '', $comment = '', $isLgDependent = false) |
| 280 | { |
| 281 | return $this->getImplementation()->createProperty($this, $label, $comment, $isLgDependent); |
| 282 | } |
| 283 | |
| 284 | /** |
| 285 | * Retrieve available methods on class |
| 286 | * |
| 287 | * @access public |
| 288 | * @author Jerome Bogaerts, <jerome.bogaerts@tudor.lu> |
| 289 | * @return array |
| 290 | */ |
| 291 | public function getMethodes() |
| 292 | { |
| 293 | return [ 'instanciate' => true , 'addSubclass' => true , 'addPropery' => true]; |
| 294 | } |
| 295 | |
| 296 | /** |
| 297 | * Search for a specific instances according to filters and options |
| 298 | * |
| 299 | * options lists: |
| 300 | * like : (bool) true/false (default: true) |
| 301 | * chaining : (string) 'or'/'and' (default: 'and') |
| 302 | * recursive : (bool) search in subvlasses(default: false) |
| 303 | * lang : (string) e.g. 'en-US', 'fr-FR' (default: '') for all properties! |
| 304 | * offset : default 0 |
| 305 | * limit : default select all |
| 306 | * order : property to order by |
| 307 | * orderdir : direction of order (default: 'ASC') |
| 308 | * |
| 309 | * @access public |
| 310 | * @author Jerome Bogaerts, <jerome.bogaerts@tudor.lu> |
| 311 | * @param array propertyFilters |
| 312 | * @param array options |
| 313 | * @return \core_kernel_classes_Resource[] |
| 314 | */ |
| 315 | public function searchInstances($propertyFilters = [], $options = []) |
| 316 | { |
| 317 | return (array) $this->getImplementation()->searchInstances($this, $propertyFilters, $options); |
| 318 | } |
| 319 | |
| 320 | /** |
| 321 | * Short description of method countInstances |
| 322 | * |
| 323 | * @access public |
| 324 | * @author Jerome Bogaerts, <jerome.bogaerts@tudor.lu> |
| 325 | * @param array propertyFilters |
| 326 | * @param array options |
| 327 | * @return integer |
| 328 | */ |
| 329 | public function countInstances($propertyFilters = [], $options = []) |
| 330 | { |
| 331 | return $this->getImplementation()->countInstances($this, $propertyFilters, $options); |
| 332 | } |
| 333 | |
| 334 | /** |
| 335 | * Get instances' property values. |
| 336 | * The instances can be filtered. |
| 337 | * |
| 338 | * @access public |
| 339 | * @author Jerome Bogaerts, <jerome.bogaerts@tudor.lu> |
| 340 | * @param core_kernel_classes_Property property |
| 341 | * @param array propertyFilters |
| 342 | * @param array options |
| 343 | * @return \core_kernel_classes_Resource[] |
| 344 | */ |
| 345 | public function getInstancesPropertyValues( |
| 346 | core_kernel_classes_Property $property, |
| 347 | $propertyFilters = [], |
| 348 | $options = [] |
| 349 | ) { |
| 350 | return (array) $this->getImplementation()->getInstancesPropertyValues( |
| 351 | $this, |
| 352 | $property, |
| 353 | $propertyFilters, |
| 354 | $options |
| 355 | ); |
| 356 | } |
| 357 | |
| 358 | /** |
| 359 | * Unset the domain of the property related to the class |
| 360 | * |
| 361 | * @access public |
| 362 | * @author Jerome Bogaerts, <jerome.bogaerts@tudor.lu> |
| 363 | * @param core_kernel_classes_Property property |
| 364 | * @deprecated |
| 365 | */ |
| 366 | public function unsetProperty(core_kernel_classes_Property $property) |
| 367 | { |
| 368 | $this->getImplementation()->unsetProperty($this, $property); |
| 369 | } |
| 370 | |
| 371 | /** |
| 372 | * please use core_kernel_classes_ResourceFactory::create() |
| 373 | * instead of this function whenever possible |
| 374 | * |
| 375 | * Creates a new instance using the properties provided. |
| 376 | * |
| 377 | * @access public |
| 378 | * @author Jerome Bogaerts, <jerome.bogaerts@tudor.lu> |
| 379 | * @param array properties May contain additional types |
| 380 | * @return core_kernel_classes_Resource |
| 381 | * @see core_kernel_classes_ResourceFactory |
| 382 | */ |
| 383 | public function createInstanceWithProperties($properties) |
| 384 | { |
| 385 | $returnValue = null; |
| 386 | // remove the additional types, because they might be implemented differently |
| 387 | |
| 388 | $additionalTypes = []; |
| 389 | if (isset($properties[OntologyRdf::RDF_TYPE])) { |
| 390 | $types = is_array($properties[OntologyRdf::RDF_TYPE]) |
| 391 | ? $properties[OntologyRdf::RDF_TYPE] |
| 392 | : [$properties[OntologyRdf::RDF_TYPE]]; |
| 393 | foreach ($types as $type) { |
| 394 | $uri = is_object($type) ? $type->getUri() : $type; |
| 395 | if ($uri != $this->getUri()) { |
| 396 | $additionalTypes[] = $this->getClass($uri); |
| 397 | } |
| 398 | } |
| 399 | unset($properties[OntologyRdf::RDF_TYPE]); |
| 400 | } |
| 401 | // create the instance |
| 402 | $returnValue = $this->getImplementation()->createInstanceWithProperties($this, $properties); |
| 403 | foreach ($additionalTypes as $type) { |
| 404 | $returnValue->setType($type); |
| 405 | } |
| 406 | $eventManager = $this->getServiceManager()->get(EventManager::CONFIG_ID); |
| 407 | $eventManager->trigger(new ResourceCreated($returnValue)); |
| 408 | return $returnValue; |
| 409 | } |
| 410 | |
| 411 | /** |
| 412 | * Delete instances of a Class from the database. |
| 413 | * |
| 414 | * @access public |
| 415 | * @author Jerome Bogaerts, <jerome.bogaerts@tudor.lu> |
| 416 | * @param array $resources An array of core_kernel_classes_Resource or URIs. |
| 417 | * @param boolean $deleteReference If set to true, references about the resources will also be deleted from the |
| 418 | * database. |
| 419 | * @return boolean |
| 420 | */ |
| 421 | public function deleteInstances($resources, $deleteReference = false) |
| 422 | { |
| 423 | return (bool) $this->getImplementation()->deleteInstances($this, $resources, $deleteReference); |
| 424 | } |
| 425 | |
| 426 | /** |
| 427 | * @deprecated Use \oat\generis\model\resource\Repository\ClassRepository::delete() instead |
| 428 | * |
| 429 | * @author Jerome Bogaerts, <jerome.bogaerts@tudor.lu> |
| 430 | * |
| 431 | * @param bool deleteReference |
| 432 | * |
| 433 | * @return bool |
| 434 | */ |
| 435 | public function delete($deleteReference = false) |
| 436 | { |
| 437 | try { |
| 438 | $this->getClassRepository()->delete( |
| 439 | new ResourceRepositoryContext( |
| 440 | [ |
| 441 | ResourceRepositoryContext::PARAM_CLASS => $this, |
| 442 | ResourceRepositoryContext::PARAM_DELETE_REFERENCE => $deleteReference, |
| 443 | ] |
| 444 | ) |
| 445 | ); |
| 446 | |
| 447 | return true; |
| 448 | } catch (Throwable $exception) { |
| 449 | return false; |
| 450 | } |
| 451 | } |
| 452 | |
| 453 | /** |
| 454 | * States if the Class exists or not in persistent memory. The rule is |
| 455 | * if the Class has parent classes, it exists. It works even for the |
| 456 | * class because it inherits itself. |
| 457 | * |
| 458 | * @access public |
| 459 | * @author Jerome Bogaerts, <jerome.bogaerts@tudor.lu> |
| 460 | * @return boolean |
| 461 | */ |
| 462 | public function exists() |
| 463 | { |
| 464 | // If the Class has one or more direct parent classes (this rdfs:isSubClassOf C), |
| 465 | // we know that the class exists. |
| 466 | return (bool) (count($this->getParentClasses(false)) > 0); |
| 467 | } |
| 468 | |
| 469 | private function getClassRepository(): ResourceRepositoryInterface |
| 470 | { |
| 471 | return $this->getServiceManager()->getContainer()->get(ClassRepository::class); |
| 472 | } |
| 473 | |
| 474 | public function updateUri(string $newUri) |
| 475 | { |
| 476 | return $this->getImplementation()->updateUri($this, $newUri); |
| 477 | } |
| 478 | } |