PageRenderTime 46ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/vendor/league/flysystem/src/Adapter/Local.php

https://gitlab.com/riandy_db/self-monitoring
PHP | 512 lines | 325 code | 74 blank | 113 comment | 22 complexity | 3a3e39bddadd727aef7b69415c188b04 MD5 | raw file
  1. <?php
  2. namespace League\Flysystem\Adapter;
  3. use DirectoryIterator;
  4. use FilesystemIterator;
  5. use finfo as Finfo;
  6. use League\Flysystem\AdapterInterface;
  7. use League\Flysystem\Config;
  8. use League\Flysystem\Exception;
  9. use League\Flysystem\NotSupportedException;
  10. use League\Flysystem\UnreadableFileException;
  11. use League\Flysystem\Util;
  12. use LogicException;
  13. use RecursiveDirectoryIterator;
  14. use RecursiveIteratorIterator;
  15. use SplFileInfo;
  16. class Local extends AbstractAdapter
  17. {
  18. /**
  19. * @var int
  20. */
  21. const SKIP_LINKS = 0001;
  22. /**
  23. * @var int
  24. */
  25. const DISALLOW_LINKS = 0002;
  26. /**
  27. * @var array
  28. */
  29. protected static $permissions = [
  30. 'file' => [
  31. 'public' => 0644,
  32. 'private' => 0600,
  33. ],
  34. 'dir' => [
  35. 'public' => 0755,
  36. 'private' => 0700,
  37. ]
  38. ];
  39. /**
  40. * @var string
  41. */
  42. protected $pathSeparator = DIRECTORY_SEPARATOR;
  43. /**
  44. * @var array
  45. */
  46. protected $permissionMap;
  47. /**
  48. * @var int
  49. */
  50. protected $writeFlags;
  51. /**
  52. * @var int
  53. */
  54. private $linkHandling;
  55. /**
  56. * Constructor.
  57. *
  58. * @param string $root
  59. * @param int $writeFlags
  60. * @param int $linkHandling
  61. * @param array $permissions
  62. */
  63. public function __construct($root, $writeFlags = LOCK_EX, $linkHandling = self::DISALLOW_LINKS, array $permissions = [])
  64. {
  65. $root = is_link($root) ? realpath($root) : $root;
  66. $this->permissionMap = array_replace_recursive(static::$permissions, $permissions);
  67. $this->ensureDirectory($root);
  68. if ( ! is_dir($root) || ! is_readable($root)) {
  69. throw new LogicException('The root path ' . $root . ' is not readable.');
  70. }
  71. $this->setPathPrefix($root);
  72. $this->writeFlags = $writeFlags;
  73. $this->linkHandling = $linkHandling;
  74. }
  75. /**
  76. * Ensure the root directory exists.
  77. *
  78. * @param string $root root directory path
  79. *
  80. * @return void
  81. *
  82. * @throws Exception in case the root directory can not be created
  83. */
  84. protected function ensureDirectory($root)
  85. {
  86. if ( ! is_dir($root)) {
  87. $umask = umask(0);
  88. @mkdir($root, $this->permissionMap['dir']['public'], true);
  89. umask($umask);
  90. if ( ! is_dir($root)) {
  91. throw new Exception(sprintf('Impossible to create the root directory "%s".', $root));
  92. }
  93. }
  94. }
  95. /**
  96. * @inheritdoc
  97. */
  98. public function has($path)
  99. {
  100. $location = $this->applyPathPrefix($path);
  101. return file_exists($location);
  102. }
  103. /**
  104. * @inheritdoc
  105. */
  106. public function write($path, $contents, Config $config)
  107. {
  108. $location = $this->applyPathPrefix($path);
  109. $this->ensureDirectory(dirname($location));
  110. if (($size = file_put_contents($location, $contents, $this->writeFlags)) === false) {
  111. return false;
  112. }
  113. $type = 'file';
  114. $result = compact('contents', 'type', 'size', 'path');
  115. if ($visibility = $config->get('visibility')) {
  116. $result['visibility'] = $visibility;
  117. $this->setVisibility($path, $visibility);
  118. }
  119. return $result;
  120. }
  121. /**
  122. * @inheritdoc
  123. */
  124. public function writeStream($path, $resource, Config $config)
  125. {
  126. $location = $this->applyPathPrefix($path);
  127. $this->ensureDirectory(dirname($location));
  128. $stream = fopen($location, 'w+b');
  129. if ( ! $stream) {
  130. return false;
  131. }
  132. stream_copy_to_stream($resource, $stream);
  133. if ( ! fclose($stream)) {
  134. return false;
  135. }
  136. if ($visibility = $config->get('visibility')) {
  137. $this->setVisibility($path, $visibility);
  138. }
  139. return compact('path', 'visibility');
  140. }
  141. /**
  142. * @inheritdoc
  143. */
  144. public function readStream($path)
  145. {
  146. $location = $this->applyPathPrefix($path);
  147. $stream = fopen($location, 'rb');
  148. return compact('stream', 'path');
  149. }
  150. /**
  151. * @inheritdoc
  152. */
  153. public function updateStream($path, $resource, Config $config)
  154. {
  155. return $this->writeStream($path, $resource, $config);
  156. }
  157. /**
  158. * @inheritdoc
  159. */
  160. public function update($path, $contents, Config $config)
  161. {
  162. $location = $this->applyPathPrefix($path);
  163. $mimetype = Util::guessMimeType($path, $contents);
  164. $size = file_put_contents($location, $contents, $this->writeFlags);
  165. if ($size === false) {
  166. return false;
  167. }
  168. return compact('path', 'size', 'contents', 'mimetype');
  169. }
  170. /**
  171. * @inheritdoc
  172. */
  173. public function read($path)
  174. {
  175. $location = $this->applyPathPrefix($path);
  176. $contents = file_get_contents($location);
  177. if ($contents === false) {
  178. return false;
  179. }
  180. return compact('contents', 'path');
  181. }
  182. /**
  183. * @inheritdoc
  184. */
  185. public function rename($path, $newpath)
  186. {
  187. $location = $this->applyPathPrefix($path);
  188. $destination = $this->applyPathPrefix($newpath);
  189. $parentDirectory = $this->applyPathPrefix(Util::dirname($newpath));
  190. $this->ensureDirectory($parentDirectory);
  191. return rename($location, $destination);
  192. }
  193. /**
  194. * @inheritdoc
  195. */
  196. public function copy($path, $newpath)
  197. {
  198. $location = $this->applyPathPrefix($path);
  199. $destination = $this->applyPathPrefix($newpath);
  200. $this->ensureDirectory(dirname($destination));
  201. return copy($location, $destination);
  202. }
  203. /**
  204. * @inheritdoc
  205. */
  206. public function delete($path)
  207. {
  208. $location = $this->applyPathPrefix($path);
  209. return unlink($location);
  210. }
  211. /**
  212. * @inheritdoc
  213. */
  214. public function listContents($directory = '', $recursive = false)
  215. {
  216. $result = [];
  217. $location = $this->applyPathPrefix($directory);
  218. if ( ! is_dir($location)) {
  219. return [];
  220. }
  221. $iterator = $recursive ? $this->getRecursiveDirectoryIterator($location) : $this->getDirectoryIterator($location);
  222. foreach ($iterator as $file) {
  223. $path = $this->getFilePath($file);
  224. if (preg_match('#(^|/|\\\\)\.{1,2}$#', $path)) {
  225. continue;
  226. }
  227. $result[] = $this->normalizeFileInfo($file);
  228. }
  229. return array_filter($result);
  230. }
  231. /**
  232. * @inheritdoc
  233. */
  234. public function getMetadata($path)
  235. {
  236. $location = $this->applyPathPrefix($path);
  237. $info = new SplFileInfo($location);
  238. return $this->normalizeFileInfo($info);
  239. }
  240. /**
  241. * @inheritdoc
  242. */
  243. public function getSize($path)
  244. {
  245. return $this->getMetadata($path);
  246. }
  247. /**
  248. * @inheritdoc
  249. */
  250. public function getMimetype($path)
  251. {
  252. $location = $this->applyPathPrefix($path);
  253. $finfo = new Finfo(FILEINFO_MIME_TYPE);
  254. $mimetype = $finfo->file($location);
  255. if (in_array($mimetype, ['application/octet-stream', 'inode/x-empty'])) {
  256. $mimetype = Util\MimeType::detectByFilename($location);
  257. }
  258. return ['mimetype' => $mimetype];
  259. }
  260. /**
  261. * @inheritdoc
  262. */
  263. public function getTimestamp($path)
  264. {
  265. return $this->getMetadata($path);
  266. }
  267. /**
  268. * @inheritdoc
  269. */
  270. public function getVisibility($path)
  271. {
  272. $location = $this->applyPathPrefix($path);
  273. clearstatcache(false, $location);
  274. $permissions = octdec(substr(sprintf('%o', fileperms($location)), -4));
  275. $visibility = $permissions & 0044 ? AdapterInterface::VISIBILITY_PUBLIC : AdapterInterface::VISIBILITY_PRIVATE;
  276. return compact('visibility');
  277. }
  278. /**
  279. * @inheritdoc
  280. */
  281. public function setVisibility($path, $visibility)
  282. {
  283. $location = $this->applyPathPrefix($path);
  284. $type = is_dir($location) ? 'dir' : 'file';
  285. $success = chmod($location, $this->permissionMap[$type][$visibility]);
  286. if ($success === false) {
  287. return false;
  288. }
  289. return compact('visibility');
  290. }
  291. /**
  292. * @inheritdoc
  293. */
  294. public function createDir($dirname, Config $config)
  295. {
  296. $location = $this->applyPathPrefix($dirname);
  297. $umask = umask(0);
  298. $visibility = $config->get('visibility', 'public');
  299. if ( ! is_dir($location) && ! mkdir($location, $this->permissionMap['dir'][$visibility], true)) {
  300. $return = false;
  301. } else {
  302. $return = ['path' => $dirname, 'type' => 'dir'];
  303. }
  304. umask($umask);
  305. return $return;
  306. }
  307. /**
  308. * @inheritdoc
  309. */
  310. public function deleteDir($dirname)
  311. {
  312. $location = $this->applyPathPrefix($dirname);
  313. if ( ! is_dir($location)) {
  314. return false;
  315. }
  316. $contents = $this->getRecursiveDirectoryIterator($location, RecursiveIteratorIterator::CHILD_FIRST);
  317. /** @var SplFileInfo $file */
  318. foreach ($contents as $file) {
  319. $this->guardAgainstUnreadableFileInfo($file);
  320. $this->deleteFileInfoObject($file);
  321. }
  322. return rmdir($location);
  323. }
  324. /**
  325. * @param SplFileInfo $file
  326. */
  327. protected function deleteFileInfoObject(SplFileInfo $file)
  328. {
  329. switch ($file->getType()) {
  330. case 'dir':
  331. rmdir($file->getRealPath());
  332. break;
  333. case 'link':
  334. unlink($file->getPathname());
  335. break;
  336. default:
  337. unlink($file->getRealPath());
  338. }
  339. }
  340. /**
  341. * Normalize the file info.
  342. *
  343. * @param SplFileInfo $file
  344. *
  345. * @return array
  346. */
  347. protected function normalizeFileInfo(SplFileInfo $file)
  348. {
  349. if ( ! $file->isLink()) {
  350. return $this->mapFileInfo($file);
  351. }
  352. if ($this->linkHandling & self::DISALLOW_LINKS) {
  353. throw NotSupportedException::forLink($file);
  354. }
  355. }
  356. /**
  357. * Get the normalized path from a SplFileInfo object.
  358. *
  359. * @param SplFileInfo $file
  360. *
  361. * @return string
  362. */
  363. protected function getFilePath(SplFileInfo $file)
  364. {
  365. $location = $file->getPathname();
  366. $path = $this->removePathPrefix($location);
  367. return trim(str_replace('\\', '/', $path), '/');
  368. }
  369. /**
  370. * @param string $path
  371. * @param int $mode
  372. *
  373. * @return RecursiveIteratorIterator
  374. */
  375. protected function getRecursiveDirectoryIterator($path, $mode = RecursiveIteratorIterator::SELF_FIRST)
  376. {
  377. return new RecursiveIteratorIterator(
  378. new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS),
  379. $mode
  380. );
  381. }
  382. /**
  383. * @param string $path
  384. *
  385. * @return DirectoryIterator
  386. */
  387. protected function getDirectoryIterator($path)
  388. {
  389. $iterator = new DirectoryIterator($path);
  390. return $iterator;
  391. }
  392. /**
  393. * @param SplFileInfo $file
  394. *
  395. * @return array
  396. */
  397. protected function mapFileInfo(SplFileInfo $file)
  398. {
  399. $normalized = [
  400. 'type' => $file->getType(),
  401. 'path' => $this->getFilePath($file),
  402. ];
  403. $normalized['timestamp'] = $file->getMTime();
  404. if ($normalized['type'] === 'file') {
  405. $normalized['size'] = $file->getSize();
  406. }
  407. return $normalized;
  408. }
  409. /**
  410. * @inheritdoc
  411. */
  412. public function applyPathPrefix($path)
  413. {
  414. $prefixedPath = parent::applyPathPrefix($path);
  415. return str_replace('/', DIRECTORY_SEPARATOR, $prefixedPath);
  416. }
  417. /**
  418. * @param SplFileInfo $file
  419. *
  420. * @throws UnreadableFileException
  421. */
  422. protected function guardAgainstUnreadableFileInfo(SplFileInfo $file)
  423. {
  424. if ( ! $file->isReadable()) {
  425. throw UnreadableFileException::forFileInfo($file);
  426. }
  427. }
  428. }