CachedAdapter.php 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. <?php
  2. namespace League\Flysystem\Cached;
  3. use League\Flysystem\AdapterInterface;
  4. use League\Flysystem\Config;
  5. class CachedAdapter implements AdapterInterface
  6. {
  7. /**
  8. * @var AdapterInterface
  9. */
  10. private $adapter;
  11. /**
  12. * @var CacheInterface
  13. */
  14. private $cache;
  15. /**
  16. * Constructor.
  17. *
  18. * @param AdapterInterface $adapter
  19. * @param CacheInterface $cache
  20. */
  21. public function __construct(AdapterInterface $adapter, CacheInterface $cache)
  22. {
  23. $this->adapter = $adapter;
  24. $this->cache = $cache;
  25. $this->cache->load();
  26. }
  27. /**
  28. * Get the underlying Adapter implementation.
  29. *
  30. * @return AdapterInterface
  31. */
  32. public function getAdapter()
  33. {
  34. return $this->adapter;
  35. }
  36. /**
  37. * Get the used Cache implementation.
  38. *
  39. * @return CacheInterface
  40. */
  41. public function getCache()
  42. {
  43. return $this->cache;
  44. }
  45. /**
  46. * {@inheritdoc}
  47. */
  48. public function write($path, $contents, Config $config)
  49. {
  50. $result = $this->adapter->write($path, $contents, $config);
  51. if ($result !== false) {
  52. $result['type'] = 'file';
  53. $this->cache->updateObject($path, $result + compact('path', 'contents'), true);
  54. }
  55. return $result;
  56. }
  57. /**
  58. * {@inheritdoc}
  59. */
  60. public function writeStream($path, $resource, Config $config)
  61. {
  62. $result = $this->adapter->writeStream($path, $resource, $config);
  63. if ($result !== false) {
  64. $result['type'] = 'file';
  65. $contents = false;
  66. $this->cache->updateObject($path, $result + compact('path', 'contents'), true);
  67. }
  68. return $result;
  69. }
  70. /**
  71. * {@inheritdoc}
  72. */
  73. public function update($path, $contents, Config $config)
  74. {
  75. $result = $this->adapter->update($path, $contents, $config);
  76. if ($result !== false) {
  77. $result['type'] = 'file';
  78. $this->cache->updateObject($path, $result + compact('path', 'contents'), true);
  79. }
  80. return $result;
  81. }
  82. /**
  83. * {@inheritdoc}
  84. */
  85. public function updateStream($path, $resource, Config $config)
  86. {
  87. $result = $this->adapter->updateStream($path, $resource, $config);
  88. if ($result !== false) {
  89. $result['type'] = 'file';
  90. $contents = false;
  91. $this->cache->updateObject($path, $result + compact('path', 'contents'), true);
  92. }
  93. return $result;
  94. }
  95. /**
  96. * {@inheritdoc}
  97. */
  98. public function rename($path, $newPath)
  99. {
  100. $result = $this->adapter->rename($path, $newPath);
  101. if ($result !== false) {
  102. $this->cache->rename($path, $newPath);
  103. }
  104. return $result;
  105. }
  106. /**
  107. * {@inheritdoc}
  108. */
  109. public function copy($path, $newpath)
  110. {
  111. $result = $this->adapter->copy($path, $newpath);
  112. if ($result !== false) {
  113. $this->cache->copy($path, $newpath);
  114. }
  115. return $result;
  116. }
  117. /**
  118. * {@inheritdoc}
  119. */
  120. public function delete($path)
  121. {
  122. $result = $this->adapter->delete($path);
  123. if ($result !== false) {
  124. $this->cache->delete($path);
  125. }
  126. return $result;
  127. }
  128. /**
  129. * {@inheritdoc}
  130. */
  131. public function deleteDir($dirname)
  132. {
  133. $result = $this->adapter->deleteDir($dirname);
  134. if ($result !== false) {
  135. $this->cache->deleteDir($dirname);
  136. }
  137. return $result;
  138. }
  139. /**
  140. * {@inheritdoc}
  141. */
  142. public function createDir($dirname, Config $config)
  143. {
  144. $result = $this->adapter->createDir($dirname, $config);
  145. if ($result !== false) {
  146. $type = 'dir';
  147. $path = $dirname;
  148. $this->cache->updateObject($dirname, compact('path', 'type'), true);
  149. }
  150. return $result;
  151. }
  152. /**
  153. * {@inheritdoc}
  154. */
  155. public function setVisibility($path, $visibility)
  156. {
  157. $result = $this->adapter->setVisibility($path, $visibility);
  158. if ($result !== false) {
  159. $this->cache->updateObject($path, compact('path', 'visibility'), true);
  160. }
  161. return $result;
  162. }
  163. /**
  164. * {@inheritdoc}
  165. */
  166. public function has($path)
  167. {
  168. $cacheHas = $this->cache->has($path);
  169. if ($cacheHas !== null) {
  170. return $cacheHas;
  171. }
  172. $adapterResponse = $this->adapter->has($path);
  173. if (! $adapterResponse) {
  174. $this->cache->storeMiss($path);
  175. } else {
  176. $cacheEntry = is_array($adapterResponse) ? $adapterResponse : compact('path');
  177. $this->cache->updateObject($path, $cacheEntry, true);
  178. }
  179. return $adapterResponse;
  180. }
  181. /**
  182. * {@inheritdoc}
  183. */
  184. public function read($path)
  185. {
  186. return $this->callWithFallback('contents', $path, 'read');
  187. }
  188. /**
  189. * {@inheritdoc}
  190. */
  191. public function readStream($path)
  192. {
  193. return $this->adapter->readStream($path);
  194. }
  195. /**
  196. * {@inheritdoc}
  197. */
  198. public function listContents($directory = '', $recursive = false)
  199. {
  200. if ($this->cache->isComplete($directory, $recursive)) {
  201. return $this->cache->listContents($directory, $recursive);
  202. }
  203. $result = $this->adapter->listContents($directory, $recursive);
  204. if ($result !== false) {
  205. $this->cache->storeContents($directory, $result, $recursive);
  206. }
  207. return $result;
  208. }
  209. /**
  210. * {@inheritdoc}
  211. */
  212. public function getMetadata($path)
  213. {
  214. return $this->callWithFallback(null, $path, 'getMetadata');
  215. }
  216. /**
  217. * {@inheritdoc}
  218. */
  219. public function getSize($path)
  220. {
  221. return $this->callWithFallback('size', $path, 'getSize');
  222. }
  223. /**
  224. * {@inheritdoc}
  225. */
  226. public function getMimetype($path)
  227. {
  228. return $this->callWithFallback('mimetype', $path, 'getMimetype');
  229. }
  230. /**
  231. * {@inheritdoc}
  232. */
  233. public function getTimestamp($path)
  234. {
  235. return $this->callWithFallback('timestamp', $path, 'getTimestamp');
  236. }
  237. /**
  238. * {@inheritdoc}
  239. */
  240. public function getVisibility($path)
  241. {
  242. return $this->callWithFallback('visibility', $path, 'getVisibility');
  243. }
  244. /**
  245. * Call a method and cache the response.
  246. *
  247. * @param string $property
  248. * @param string $path
  249. * @param string $method
  250. *
  251. * @return mixed
  252. */
  253. protected function callWithFallback($property, $path, $method)
  254. {
  255. $result = $this->cache->{$method}($path);
  256. if ($result !== false && ($property === null || array_key_exists($property, $result))) {
  257. return $result;
  258. }
  259. $result = $this->adapter->{$method}($path);
  260. if ($result) {
  261. $object = $result + compact('path');
  262. $this->cache->updateObject($path, $object, true);
  263. }
  264. return $result;
  265. }
  266. }