1<?php 2declare(strict_types=1); 3 4namespace ILIAS\Filesystem\Provider\FlySystem; 5 6use ILIAS\Filesystem\FilesystemFacade; 7use ILIAS\Filesystem\Filesystem; 8use ILIAS\Filesystem\Provider\Configuration\LocalConfig; 9use League\Flysystem\Adapter\Local; 10 11/** 12 * Class FlySystemLocalFilesystemFactory 13 * 14 * The local fly system filesystem factory creates instances of the local filesystem adapter which is provided by 15 * the phpleague. 16 * 17 * @author Nicolas Schäfli <ns@studer-raimann.ch> 18 * @since 5.3 19 */ 20final class FlySystemLocalFilesystemFactory 21{ 22 const PRIVATE_ACCESS_KEY = 'private'; 23 const PUBLIC_ACCESS_KEY = 'public'; 24 const FILE_ACCESS_KEY = 'file'; 25 const DIRECTORY_ACCESS_KEY = 'dir'; 26 27 /** 28 * Creates a new instance of the local filesystem adapter used by fly system. 29 * 30 * @param LocalConfig $config The configuration which should be used to initialise the adapter. 31 * 32 * @return Filesystem 33 */ 34 public function getInstance(LocalConfig $config) 35 { 36 $this->validateFileLockMode($config->getLockMode()); 37 38 $adapter = new Local( 39 $config->getRootPath(), 40 $config->getLockMode(), 41 $this->mapConfigLinkToLocalLinks($config->getLinkBehaviour()), 42 [ 43 self::FILE_ACCESS_KEY => [ 44 self::PRIVATE_ACCESS_KEY => $config->getFileAccessPrivate(), 45 self::PUBLIC_ACCESS_KEY => $config->getFileAccessPublic() 46 ], 47 self::DIRECTORY_ACCESS_KEY => [ 48 self::PRIVATE_ACCESS_KEY => $config->getDirectoryAccessPrivate(), 49 self::PUBLIC_ACCESS_KEY => $config->getDirectoryAccessPublic() 50 ] 51 ] 52 ); 53 54 //switch the path separator to a forward slash, see Mantis 0022554 55 $reflection = new \ReflectionObject($adapter); 56 $property = $reflection->getProperty("pathSeparator"); 57 $property->setAccessible(true); 58 $property->setValue($adapter, '/'); 59 60 /* set new path separator in path prefix, the library will replace the old path ending 61 while setting the path prefix. 62 */ 63 $adapter->setPathPrefix($adapter->getPathPrefix()); 64 65 66 $filesystem = new \League\Flysystem\Filesystem($adapter); 67 $fileAccess = new FlySystemFileAccess($filesystem); 68 $facade = new FilesystemFacade( 69 new FlySystemFileStreamAccess($filesystem), 70 $fileAccess, 71 new FlySystemDirectoryAccess($filesystem, $fileAccess) 72 ); 73 74 return $facade; 75 } 76 77 78 /** 79 * Maps a constant of the LocalConfig class into a constant of the Local class. 80 * 81 * Example: 82 * 83 * @param int $configLinkBehaviour The code of the config link behaviour constant. 84 * 85 * @return int The mapped code of the Local filesystem adapter. 86 */ 87 private function mapConfigLinkToLocalLinks($configLinkBehaviour) 88 { 89 switch ($configLinkBehaviour) { 90 case LocalConfig::DISALLOW_LINKS: 91 return Local::DISALLOW_LINKS; 92 case LocalConfig::SKIP_LINKS: 93 return Local::SKIP_LINKS; 94 default: 95 throw new \InvalidArgumentException("The supplied value \"$configLinkBehaviour\" is not a valid LocalConfig link behaviour constant."); 96 } 97 } 98 99 100 /** 101 * Checks if the supplied file lock mode is valid. 102 * Valid values are LOCK_SH and LOCK_EX. 103 * 104 * LOCK_SH -> shared lock (read is possible for others) 105 * LOCK_EX -> no access for other processes 106 * 107 * @param int $code The code of the file lock mode which should be checked. 108 * 109 * @see LOCK_SH 110 * @see LOCK_EX 111 */ 112 private function validateFileLockMode($code) 113 { 114 if ($code === LOCK_EX || $code === LOCK_SH) { 115 return; 116 } 117 118 throw new \InvalidArgumentException("The supplied value \"$code\" is not a valid file lock mode please check your local file storage configurations."); 119 } 120} 121