item = (isset($data['item'])) ? $data['item'] : null; $this->lang = (isset($data['lang'])) ? $data['lang'] : ''; } /** * @return \core_kernel_classes_Resource */ public function getItem() { return $this->item; } /** * @throws \common_Exception * @throws \tao_models_classes_FileNotFoundException * @throws common_exception_Error */ public function getDirectories(DirectorySearchQuery $params): array { return $this->searchDirectories( $params->getParentLink(), $params->getFilter(), $params->getDepth(), $params->getChildrenLimit() ); } /** * Get a array representing the tree of directory * @deprecated in favor of MediaBrowser::getDirectories * @throws \common_Exception * @throws \tao_models_classes_FileNotFoundException * @throws common_exception_Error */ public function getDirectory($parentLink = '', $acceptableMime = [], $depth = 1) { return $this->searchDirectories($parentLink, $acceptableMime, $depth, 0); } /** * Return file info regarding a file * * @see \oat\tao\model\media\MediaBrowser::getFileInfo * @param string $link * @return array * @throws \tao_models_classes_FileNotFoundException * @throws common_exception_Error */ public function getFileInfo($link) { return $this->getInfoFromFile($this->getFile($link)); } /** * Method should be used only after uploading local file, when metadata like file size and mime type * of remote uploaded file are not critical. To get more precise info about remote file use getInfoFromFile(). * * In case of using S3 Flysystem adapter there might be latency and file cannot be accessed right after upload. * * @param File $file * @param string $sourceFile * @return array * @throws \common_Exception * @throws \tao_models_classes_FileNotFoundException */ protected function getInfoFromSource(File $file, string $sourceFile): array { if (file_exists($sourceFile)) { $link = $this->getItemDirectory()->getRelPath($file); return [ 'name' => $file->getBasename(), 'uri' => $link, 'mime' => tao_helpers_File::getMimeType($sourceFile), 'filePath' => $link, 'size' => filesize($sourceFile), ]; } else { return $this->getInfoFromFile($file); } } protected function getInfoFromFile(File $file) { $link = $this->getItemDirectory()->getRelPath($file); return [ 'name' => $file->getBasename(), 'uri' => $link, 'mime' => $file->getMimeType(), 'filePath' => $link, 'size' => $file->getSize(), ]; } /** * Copy file content to temp file. Path is return to be downloaded * * @see \oat\tao\model\media\MediaBrowser::download * @param string $link * @return string * @throws \common_Exception * @throws \tao_models_classes_FileNotFoundException * @throws common_exception_Error */ public function download($link) { $file = $this->getFile($link); $relPath = $this->getItemDirectory()->getRelPath($file); $tmpDir = rtrim(\tao_helpers_File::createTempDir(), '/'); $tmpFile = $tmpDir . $relPath; if (! is_dir(dirname($tmpFile))) { mkdir(dirname($tmpFile), 0755, true); } if (($resource = fopen($tmpFile, 'w')) !== false) { stream_copy_to_stream($file->readStream(), $resource); fclose($resource); return $tmpFile; } throw new \common_Exception('Unable to write "' . $link . '" into tmp folder("' . $tmpFile . '").'); } /** * Return filename of given path * * @see \oat\tao\model\media\MediaBrowser::getBaseName * @param string $link * @return string */ public function getBaseName($link) { return basename($link); } /** * Add content to file * * @see \oat\tao\model\media\MediaManagement::add * @param string $source * @param string $fileName * @param string $parent * @return array * @throws \common_Exception * @throws \tao_models_classes_FileNotFoundException */ public function add($source, $fileName, $parent) { if (! \tao_helpers_File::securityCheck($fileName, true)) { throw new \common_Exception('Unsecured filename "' . $fileName . '"'); } if (($resource = fopen($source, 'r')) === false) { throw new \common_Exception('Unable to read content of file ("' . $source . '")'); } $file = $this->getItemDirectory()->getDirectory($parent)->getFile($fileName); $writeSuccess = $file->put($resource); if (is_resource($resource)) { fclose($resource); } if (! $writeSuccess) { throw new \common_Exception('Unable to write file ("' . $fileName . '")'); } return $this->getInfoFromSource($file, $source); } /** * Delete the file located at $link * * @see \oat\tao\model\media\MediaManagement::delete * @param $link * @return bool * @throws \tao_models_classes_FileNotFoundException * @throws common_exception_Error */ public function delete($link) { return $this->getFile($link)->delete(); } /** * Return file stream of file located at $link * * @see tao/models/classes/media/MediaBrowser.php:getFileStream * @param string $link * @return StreamInterface * @throws \tao_models_classes_FileNotFoundException * @throws common_exception_Error */ public function getFileStream($link) { return $this->getFile($link)->readPsrStream(); } /** * Get file object associated to $link, search in main item directory or specific item directory * * @param $link * @return File * @throws \common_Exception * @throws \tao_models_classes_FileNotFoundException * @throws common_exception_Error */ private function getFile($link) { if (!tao_helpers_File::securityCheck($link)) { throw new common_exception_Error(__('Your path contains error')); } $file = $this->getItemDirectory()->getFile($link); if ($file->exists()) { return $file; } throw new \tao_models_classes_FileNotFoundException($link); } /** * Get item directory based on $this->item & $this->lang * * @return Directory * @throws \common_Exception */ protected function getItemDirectory() { if (! $this->itemService) { $this->itemService = taoItems_models_classes_ItemsService::singleton(); } return $this->itemService->getItemDirectory($this->item, $this->lang); } /** * @throws \common_Exception * @throws \tao_models_classes_FileNotFoundException * @throws common_exception_Error */ private function searchDirectories( string $parentLink, array $acceptableMime, int $depth, int $childrenLimit ): array { if (!tao_helpers_File::securityCheck($parentLink)) { throw new common_exception_Error(__('Your path contains error')); } $label = rtrim($parentLink, '/'); if (strrpos($parentLink, '/') !== false && substr($parentLink, -1) !== '/') { $label = substr($parentLink, strrpos($parentLink, '/') + 1); $parentLink = $parentLink . '/'; } if (in_array($parentLink, ['', '/'])) { $label = $this->getItem()->getLabel(); $parentLink = '/'; } $data = [ 'path' => $parentLink, 'label' => $label, 'childrenLimit' => $childrenLimit, 'total' => 0, ]; if ($depth <= 0) { $data['parent'] = $parentLink; return $data; } $children = []; /** @var Directory $directory */ $itemDirectory = $this->getItemDirectory(); if ($parentLink != '/') { $directory = $itemDirectory->getDirectory($parentLink); } else { $directory = $itemDirectory; } $iterator = $directory->getFlyIterator(); $total = 0; foreach ($iterator as $content) { if ($content instanceof Directory) { $children[] = $this->searchDirectories( $itemDirectory->getRelPath($content), $acceptableMime, $depth - 1, $childrenLimit ); continue; } $fileInfo = $this->getInfoFromFile($content); if (empty($acceptableMime) || in_array($fileInfo['mime'], $acceptableMime)) { $children[] = $fileInfo; $total++; } } $data['children'] = $children; $data['total'] = $total; return $data; } }