storage === null) { $this->storage = $this->getSubService(self::OPTION_STORAGE); } return $this->storage; } /** * * @return FileSystem */ protected function getFileSystem() { if ($this->fileSystem === null) { $this->fileSystem = $this->getServiceLocator()->get(FileSystemService::SERVICE_ID)->getFileSystem( $this->getOption(self::OPTION_FILE_SYSTEM) ); } return $this->fileSystem; } /** * @return TriplesManagerService */ public function getTriplesManagerService() { return $this->getServiceLocator()->get(TriplesManagerService::SERVICE_ID); } /** * @param string $resourceId * * @return Revision[] * @throws InvalidService * @throws InvalidServiceManagerException */ public function getAllRevisions(string $resourceId) { return $this->getStorage()->getAllRevisions($resourceId); } /** * @param string $resourceId * @param int $version * * @return Revision * @throws InvalidService * @throws InvalidServiceManagerException */ public function getRevision(string $resourceId, int $version) { return $this->getStorage()->getRevision($resourceId, $version); } /** * @param Resource $resource * @param string $message * @param int|null $version * @param string|null $author * * @return Revision * @throws InvalidService * @throws InvalidServiceManagerException * @throws common_Exception * @throws common_exception_Error */ public function commit(Resource $resource, string $message, int $version = null, string $author = null) { $triplesManager = $this->getTriplesManagerService(); if ($author === null) { $user = common_session_SessionManager::getSession()->getUser(); if ($user !== null) { $author = $user->getIdentifier(); } if ($author === null) { $author = ''; } } $version = $version ?? $this->getNextVersion($resource->getUri()); $triples = $resource->getRdfTriples(); $fileSystemMap = array_fill_keys( array_keys($triplesManager->getPropertyStorageMap($triples)), $this->getFileSystem()->getId() ); $revision = new Revision($resource->getUri(), $version, time(), $author, $message); $clonedTriples = $triplesManager->cloneTriples($triples, $fileSystemMap); return $this->getStorage()->addRevision($revision, $clonedTriples); } /** * @param Revision $revision * * @return bool * @throws common_Exception */ public function restore(Revision $revision) { $triplesManager = $this->getTriplesManagerService(); $data = $this->getStorage()->getData($revision); $resource = $this->getResource($revision->getResourceId()); $originFilesystemMap = $this->getTriplesManagerService()->getPropertyStorageMap($resource->getRdfTriples()); $triplesManager->deleteTriplesFor($resource); $clonedTriples = $triplesManager->cloneTriples($data, $originFilesystemMap); foreach ($clonedTriples as $triple) { $this->getModel()->getRdfInterface()->add($triple); } $this->updateItemsRelations($originFilesystemMap, $resource); return true; } /** * @param string $query * * @param array $options * @return Resource[] * @throws InvalidService * @throws InvalidServiceManagerException * @todo Fix usage in the NEC project */ public function searchRevisionResources(string $query, array $options = []) { return $this->getStorage()->getResourcesDataByQuery($query, $options); } /** * Helper to determine suitable next version * * @param string $resourceId * * @return int * @throws InvalidService * @throws InvalidServiceManagerException */ protected function getNextVersion(string $resourceId): int { $candidate = 0; foreach ($this->getAllRevisions($resourceId) as $revision) { $version = $revision->getVersion(); if (is_numeric($version) && $version > $candidate) { $candidate = $version; } } return $candidate + 1; } private function getUpdatedItemEventDispatcher(): UpdatedItemEventDispatcher { return $this->getServiceLocator()->get(UpdatedItemEventDispatcher::class); } private function getQtiService(): Service { return $this->getServiceLocator()->get(Service::class); } /** * @throws common_Exception */ private function updateItemsRelations(array $originFilesystemMap, Resource $resource): void { if (key($originFilesystemMap) === CreatorItems::PROPERTY_ITEM_CONTENT_URI) { $item = $this->getQtiService()->getDataItemByRdfItem($resource); $this->getUpdatedItemEventDispatcher()->dispatch($item, $resource); } } }