*/ class MediaService extends ConfigurableService { use ClassServiceTrait; use GenerisServiceTrait; use LoggerAwareTrait; public const ROOT_CLASS_URI = 'http://www.tao.lu/Ontologies/TAOMedia.rdf#Media'; public const PROPERTY_LINK = 'http://www.tao.lu/Ontologies/TAOMedia.rdf#Link'; public const PROPERTY_LANGUAGE = 'http://www.tao.lu/Ontologies/TAOMedia.rdf#Language'; public const PROPERTY_ALT_TEXT = 'http://www.tao.lu/Ontologies/TAOMedia.rdf#AltText'; public const PROPERTY_MD5 = 'http://www.tao.lu/Ontologies/TAOMedia.rdf#md5'; public const PROPERTY_MIME_TYPE = 'http://www.tao.lu/Ontologies/TAOMedia.rdf#mimeType'; public const SHARED_STIMULUS_MIME_TYPE = 'application/qti+xml'; /** * @deprecated */ public static function singleton() { return ServiceManager::getServiceManager()->get(self::class); } /** * (non-PHPdoc) * @see \tao_models_classes_ClassService::getRootClass() */ public function getRootClass() { return $this->getClass(self::ROOT_CLASS_URI); } /** * Create a media instance from a file, and define its class and language * * @param string|File $fileSource path to the file to create instance from * @param string $classUri parent to add the instance to * @param string $language language of the content * @param string $label label of the instance * @param string $mimeType mimeType of the file * @param string|null $userId owner of the resource * @return string | bool $instanceUri or false on error */ public function createMediaInstance( $fileSource, $classUri, $language, $label = null, $mimeType = null, $userId = null ) { $link = $this->getFileManager()->storeFile($fileSource, $label); if ($link === false) { return false; } $clazz = $this->getClass($classUri); //create media instance if (is_null($label)) { $label = $fileSource instanceof File ? $fileSource->getBasename() : basename($fileSource); } $content = $fileSource instanceof File ? $fileSource->read() : file_get_contents($fileSource); if (is_null($mimeType)) { $mimeType = $fileSource instanceof File ? $fileSource->getMimeType() : tao_helpers_File::getMimeType( $fileSource ); } $properties = [ OntologyRdfs::RDFS_LABEL => $label, self::PROPERTY_LINK => $link, self::PROPERTY_LANGUAGE => $language, self::PROPERTY_MD5 => md5($content), self::PROPERTY_MIME_TYPE => $mimeType, self::PROPERTY_ALT_TEXT => $label ]; $instance = $clazz->createInstanceWithProperties($properties); $id = $instance->getUri(); $this->getMediaSavedEventDispatcher()->dispatchFromContent($id, $mimeType, $content); // @todo: move taoRevision stuff under a listener of MediaSavedEvent if ($this->getServiceLocator()->get(common_ext_ExtensionsManager::SERVICE_ID)->isEnabled('taoRevision')) { $this->logInfo('Auto generating initial revision'); $this->getRepositoryService()->commit($instance, __('Initial import'), null, $userId); } return $id; } public function createSharedStimulusInstance( string $link, string $classUri, string $language, string $userId = null ): string { $content = $this->getFileManager()->getFileStream($link)->getContents(); $clazz = $this->getClass($classUri); $label = basename($link); $properties = [ OntologyRdfs::RDFS_LABEL => $label, self::PROPERTY_LINK => $link, self::PROPERTY_LANGUAGE => $language, self::PROPERTY_MD5 => md5($content), self::PROPERTY_MIME_TYPE => self::SHARED_STIMULUS_MIME_TYPE, self::PROPERTY_ALT_TEXT => $label, ]; $instance = $clazz->createInstanceWithProperties($properties); $id = $instance->getUri(); $this->getMediaSavedEventDispatcher()->dispatchFromContent($id, self::SHARED_STIMULUS_MIME_TYPE, $content); if ($this->getServiceLocator()->get(common_ext_ExtensionsManager::SERVICE_ID)->isEnabled('taoRevision')) { $this->logInfo('Auto generating initial revision'); $this->getRepositoryService()->commit($instance, __('Initial import'), null, $userId); } return $id; } /** * Edit a media instance with a new file and/or a new language * * @param string|File $fileSource */ public function editMediaInstance( $fileSource, string $id, string $language = null, string $userId = null ): bool { $instance = $this->getResource($id); $link = $this->getLink($instance); $fileManager = $this->getFileManager(); $fileManager->deleteFile($link); $link = $fileManager->storeFile($fileSource, $instance->getLabel()); if ($link !== false) { $md5 = $fileSource instanceof File ? md5($fileSource->read()) : md5_file($fileSource); $instance->editPropertyValues($this->getProperty(self::PROPERTY_LINK), $link); $instance->editPropertyValues($this->getProperty(self::PROPERTY_MD5), $md5); if ($language) { $instance->editPropertyValues($this->getProperty(self::PROPERTY_LANGUAGE), $language); } $this->getMediaSavedEventDispatcher() ->dispatchFromFile($id, $fileSource, $this->getResourceMimeType($instance)); // @todo: move taoRevision stuff under a listener of MediaSavedEvent if ($this->getServiceLocator()->get(common_ext_ExtensionsManager::SERVICE_ID)->isEnabled('taoRevision')) { $this->logInfo('Auto generating revision'); $this->getRepositoryService()->commit($instance, __('Imported new file'), null, $userId); } } return $link !== false; } public function deleteResource(RdfResource $resource) { $link = $this->getLink($resource); if ($this->removeFromFilesystem($link) && $resource->delete()) { $this->getEventManager() ->trigger(new MediaRemovedEvent($resource->getUri())); return true; } return false; } private function removeFromFilesystem($link): bool { $directory = dirname($link); if ($directory !== '.') { return $this->getFileManager()->deleteDirectory($directory); } return $this->getFileManager()->deleteFile($link); } private function getLink(RdfResource $resource): string { $instance = $resource->getUniquePropertyValue($this->getProperty(self::PROPERTY_LINK)); $link = $instance instanceof RdfResource ? $instance->getUri() : (string)$instance; return $this->getFileSourceUnserializer()->unserialize($link); } private function getMediaSavedEventDispatcher(): MediaSavedEventDispatcher { return $this->getServiceLocator()->get(MediaSavedEventDispatcher::class); } private function getFileManager(): FileManagement { return $this->getServiceLocator()->get(FileManagement::SERVICE_ID); } private function getRepositoryService(): RepositoryInterface { return $this->getServiceLocator()->get(RepositoryInterface::SERVICE_ID); } private function getEventManager(): EventManager { return $this->getServiceLocator()->get(EventManager::SERVICE_ID); } private function getResourceMimeType(RdfResource $resource): ?string { $container = $resource->getUniquePropertyValue($resource->getProperty(MediaService::PROPERTY_MIME_TYPE)); if ($container instanceof core_kernel_classes_Literal) { $mimeType = (string)$container; return $mimeType === MediaService::SHARED_STIMULUS_MIME_TYPE ? $mimeType : null; } return null; } private function getFileSourceUnserializer(): FileSourceUnserializer { return $this->getServiceLocator()->get(FileSourceUnserializer::class); } }