Filesystem.php 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408
  1. <?php
  2. namespace League\Flysystem;
  3. use InvalidArgumentException;
  4. use League\Flysystem\Adapter\CanOverwriteFiles;
  5. use League\Flysystem\Plugin\PluggableTrait;
  6. use League\Flysystem\Util\ContentListingFormatter;
  7. /**
  8. * @method array getWithMetadata(string $path, array $metadata)
  9. * @method bool forceCopy(string $path, string $newpath)
  10. * @method bool forceRename(string $path, string $newpath)
  11. * @method array listFiles(string $path = '', boolean $recursive = false)
  12. * @method array listPaths(string $path = '', boolean $recursive = false)
  13. * @method array listWith(array $keys = [], $directory = '', $recursive = false)
  14. */
  15. class Filesystem implements FilesystemInterface
  16. {
  17. use PluggableTrait;
  18. use ConfigAwareTrait;
  19. /**
  20. * @var AdapterInterface
  21. */
  22. protected $adapter;
  23. /**
  24. * Constructor.
  25. *
  26. * @param AdapterInterface $adapter
  27. * @param Config|array $config
  28. */
  29. public function __construct(AdapterInterface $adapter, $config = null)
  30. {
  31. $this->adapter = $adapter;
  32. $this->setConfig($config);
  33. }
  34. /**
  35. * Get the Adapter.
  36. *
  37. * @return AdapterInterface adapter
  38. */
  39. public function getAdapter()
  40. {
  41. return $this->adapter;
  42. }
  43. /**
  44. * @inheritdoc
  45. */
  46. public function has($path)
  47. {
  48. $path = Util::normalizePath($path);
  49. return strlen($path) === 0 ? false : (bool) $this->getAdapter()->has($path);
  50. }
  51. /**
  52. * @inheritdoc
  53. */
  54. public function write($path, $contents, array $config = [])
  55. {
  56. $path = Util::normalizePath($path);
  57. $this->assertAbsent($path);
  58. $config = $this->prepareConfig($config);
  59. return (bool) $this->getAdapter()->write($path, $contents, $config);
  60. }
  61. /**
  62. * @inheritdoc
  63. */
  64. public function writeStream($path, $resource, array $config = [])
  65. {
  66. if ( ! is_resource($resource)) {
  67. throw new InvalidArgumentException(__METHOD__ . ' expects argument #2 to be a valid resource.');
  68. }
  69. $path = Util::normalizePath($path);
  70. $this->assertAbsent($path);
  71. $config = $this->prepareConfig($config);
  72. Util::rewindStream($resource);
  73. return (bool) $this->getAdapter()->writeStream($path, $resource, $config);
  74. }
  75. /**
  76. * @inheritdoc
  77. */
  78. public function put($path, $contents, array $config = [])
  79. {
  80. $path = Util::normalizePath($path);
  81. $config = $this->prepareConfig($config);
  82. if ( ! $this->getAdapter() instanceof CanOverwriteFiles && $this->has($path)) {
  83. return (bool) $this->getAdapter()->update($path, $contents, $config);
  84. }
  85. return (bool) $this->getAdapter()->write($path, $contents, $config);
  86. }
  87. /**
  88. * @inheritdoc
  89. */
  90. public function putStream($path, $resource, array $config = [])
  91. {
  92. if ( ! is_resource($resource)) {
  93. throw new InvalidArgumentException(__METHOD__ . ' expects argument #2 to be a valid resource.');
  94. }
  95. $path = Util::normalizePath($path);
  96. $config = $this->prepareConfig($config);
  97. Util::rewindStream($resource);
  98. if ( ! $this->getAdapter() instanceof CanOverwriteFiles && $this->has($path)) {
  99. return (bool) $this->getAdapter()->updateStream($path, $resource, $config);
  100. }
  101. return (bool) $this->getAdapter()->writeStream($path, $resource, $config);
  102. }
  103. /**
  104. * @inheritdoc
  105. */
  106. public function readAndDelete($path)
  107. {
  108. $path = Util::normalizePath($path);
  109. $this->assertPresent($path);
  110. $contents = $this->read($path);
  111. if ($contents === false) {
  112. return false;
  113. }
  114. $this->delete($path);
  115. return $contents;
  116. }
  117. /**
  118. * @inheritdoc
  119. */
  120. public function update($path, $contents, array $config = [])
  121. {
  122. $path = Util::normalizePath($path);
  123. $config = $this->prepareConfig($config);
  124. $this->assertPresent($path);
  125. return (bool) $this->getAdapter()->update($path, $contents, $config);
  126. }
  127. /**
  128. * @inheritdoc
  129. */
  130. public function updateStream($path, $resource, array $config = [])
  131. {
  132. if ( ! is_resource($resource)) {
  133. throw new InvalidArgumentException(__METHOD__ . ' expects argument #2 to be a valid resource.');
  134. }
  135. $path = Util::normalizePath($path);
  136. $config = $this->prepareConfig($config);
  137. $this->assertPresent($path);
  138. Util::rewindStream($resource);
  139. return (bool) $this->getAdapter()->updateStream($path, $resource, $config);
  140. }
  141. /**
  142. * @inheritdoc
  143. */
  144. public function read($path)
  145. {
  146. $path = Util::normalizePath($path);
  147. $this->assertPresent($path);
  148. if ( ! ($object = $this->getAdapter()->read($path))) {
  149. return false;
  150. }
  151. return $object['contents'];
  152. }
  153. /**
  154. * @inheritdoc
  155. */
  156. public function readStream($path)
  157. {
  158. $path = Util::normalizePath($path);
  159. $this->assertPresent($path);
  160. if ( ! $object = $this->getAdapter()->readStream($path)) {
  161. return false;
  162. }
  163. return $object['stream'];
  164. }
  165. /**
  166. * @inheritdoc
  167. */
  168. public function rename($path, $newpath)
  169. {
  170. $path = Util::normalizePath($path);
  171. $newpath = Util::normalizePath($newpath);
  172. $this->assertPresent($path);
  173. $this->assertAbsent($newpath);
  174. return (bool) $this->getAdapter()->rename($path, $newpath);
  175. }
  176. /**
  177. * @inheritdoc
  178. */
  179. public function copy($path, $newpath)
  180. {
  181. $path = Util::normalizePath($path);
  182. $newpath = Util::normalizePath($newpath);
  183. $this->assertPresent($path);
  184. $this->assertAbsent($newpath);
  185. return $this->getAdapter()->copy($path, $newpath);
  186. }
  187. /**
  188. * @inheritdoc
  189. */
  190. public function delete($path)
  191. {
  192. $path = Util::normalizePath($path);
  193. $this->assertPresent($path);
  194. return $this->getAdapter()->delete($path);
  195. }
  196. /**
  197. * @inheritdoc
  198. */
  199. public function deleteDir($dirname)
  200. {
  201. $dirname = Util::normalizePath($dirname);
  202. if ($dirname === '') {
  203. throw new RootViolationException('Root directories can not be deleted.');
  204. }
  205. return (bool) $this->getAdapter()->deleteDir($dirname);
  206. }
  207. /**
  208. * @inheritdoc
  209. */
  210. public function createDir($dirname, array $config = [])
  211. {
  212. $dirname = Util::normalizePath($dirname);
  213. $config = $this->prepareConfig($config);
  214. return (bool) $this->getAdapter()->createDir($dirname, $config);
  215. }
  216. /**
  217. * @inheritdoc
  218. */
  219. public function listContents($directory = '', $recursive = false)
  220. {
  221. $directory = Util::normalizePath($directory);
  222. $contents = $this->getAdapter()->listContents($directory, $recursive);
  223. return (new ContentListingFormatter($directory, $recursive, $this->config->get('case_sensitive', true)))
  224. ->formatListing($contents);
  225. }
  226. /**
  227. * @inheritdoc
  228. */
  229. public function getMimetype($path)
  230. {
  231. $path = Util::normalizePath($path);
  232. $this->assertPresent($path);
  233. if (( ! $object = $this->getAdapter()->getMimetype($path)) || ! array_key_exists('mimetype', $object)) {
  234. return false;
  235. }
  236. return $object['mimetype'];
  237. }
  238. /**
  239. * @inheritdoc
  240. */
  241. public function getTimestamp($path)
  242. {
  243. $path = Util::normalizePath($path);
  244. $this->assertPresent($path);
  245. if (( ! $object = $this->getAdapter()->getTimestamp($path)) || ! array_key_exists('timestamp', $object)) {
  246. return false;
  247. }
  248. return $object['timestamp'];
  249. }
  250. /**
  251. * @inheritdoc
  252. */
  253. public function getVisibility($path)
  254. {
  255. $path = Util::normalizePath($path);
  256. $this->assertPresent($path);
  257. if (( ! $object = $this->getAdapter()->getVisibility($path)) || ! array_key_exists('visibility', $object)) {
  258. return false;
  259. }
  260. return $object['visibility'];
  261. }
  262. /**
  263. * @inheritdoc
  264. */
  265. public function getSize($path)
  266. {
  267. $path = Util::normalizePath($path);
  268. $this->assertPresent($path);
  269. if (( ! $object = $this->getAdapter()->getSize($path)) || ! array_key_exists('size', $object)) {
  270. return false;
  271. }
  272. return (int) $object['size'];
  273. }
  274. /**
  275. * @inheritdoc
  276. */
  277. public function setVisibility($path, $visibility)
  278. {
  279. $path = Util::normalizePath($path);
  280. $this->assertPresent($path);
  281. return (bool) $this->getAdapter()->setVisibility($path, $visibility);
  282. }
  283. /**
  284. * @inheritdoc
  285. */
  286. public function getMetadata($path)
  287. {
  288. $path = Util::normalizePath($path);
  289. $this->assertPresent($path);
  290. return $this->getAdapter()->getMetadata($path);
  291. }
  292. /**
  293. * @inheritdoc
  294. */
  295. public function get($path, Handler $handler = null)
  296. {
  297. $path = Util::normalizePath($path);
  298. if ( ! $handler) {
  299. $metadata = $this->getMetadata($path);
  300. $handler = $metadata['type'] === 'file' ? new File($this, $path) : new Directory($this, $path);
  301. }
  302. $handler->setPath($path);
  303. $handler->setFilesystem($this);
  304. return $handler;
  305. }
  306. /**
  307. * Assert a file is present.
  308. *
  309. * @param string $path path to file
  310. *
  311. * @throws FileNotFoundException
  312. *
  313. * @return void
  314. */
  315. public function assertPresent($path)
  316. {
  317. if ($this->config->get('disable_asserts', false) === false && ! $this->has($path)) {
  318. throw new FileNotFoundException($path);
  319. }
  320. }
  321. /**
  322. * Assert a file is absent.
  323. *
  324. * @param string $path path to file
  325. *
  326. * @throws FileExistsException
  327. *
  328. * @return void
  329. */
  330. public function assertAbsent($path)
  331. {
  332. if ($this->config->get('disable_asserts', false) === false && $this->has($path)) {
  333. throw new FileExistsException($path);
  334. }
  335. }
  336. }