adapter = $adapter; $this->cache = $cache; $this->cache->load(); } /** * Get the underlying Adapter implementation. * * @return AdapterInterface */ public function getAdapter() { return $this->adapter; } /** * Get the used Cache implementation. * * @return CacheInterface */ public function getCache() { return $this->cache; } /** * {@inheritdoc} */ public function write($path, $contents, Config $config) { $result = $this->adapter->write($path, $contents, $config); if ($result !== false) { $result['type'] = 'file'; $this->cache->updateObject($path, $result + compact('path', 'contents'), true); } return $result; } /** * {@inheritdoc} */ public function writeStream($path, $resource, Config $config) { $result = $this->adapter->writeStream($path, $resource, $config); if ($result !== false) { $result['type'] = 'file'; $contents = false; $this->cache->updateObject($path, $result + compact('path', 'contents'), true); } return $result; } /** * {@inheritdoc} */ public function update($path, $contents, Config $config) { $result = $this->adapter->update($path, $contents, $config); if ($result !== false) { $result['type'] = 'file'; $this->cache->updateObject($path, $result + compact('path', 'contents'), true); } return $result; } /** * {@inheritdoc} */ public function updateStream($path, $resource, Config $config) { $result = $this->adapter->updateStream($path, $resource, $config); if ($result !== false) { $result['type'] = 'file'; $contents = false; $this->cache->updateObject($path, $result + compact('path', 'contents'), true); } return $result; } /** * {@inheritdoc} */ public function rename($path, $newPath) { $result = $this->adapter->rename($path, $newPath); if ($result !== false) { $this->cache->rename($path, $newPath); } return $result; } /** * {@inheritdoc} */ public function copy($path, $newpath) { $result = $this->adapter->copy($path, $newpath); if ($result !== false) { $this->cache->copy($path, $newpath); } return $result; } /** * {@inheritdoc} */ public function delete($path) { $result = $this->adapter->delete($path); if ($result !== false) { $this->cache->delete($path); } return $result; } /** * {@inheritdoc} */ public function deleteDir($dirname) { $result = $this->adapter->deleteDir($dirname); if ($result !== false) { $this->cache->deleteDir($dirname); } return $result; } /** * {@inheritdoc} */ public function createDir($dirname, Config $config) { $result = $this->adapter->createDir($dirname, $config); if ($result !== false) { $type = 'dir'; $path = $dirname; $this->cache->updateObject($dirname, compact('path', 'type'), true); } return $result; } /** * {@inheritdoc} */ public function setVisibility($path, $visibility) { $result = $this->adapter->setVisibility($path, $visibility); if ($result !== false) { $this->cache->updateObject($path, compact('path', 'visibility'), true); } return $result; } /** * {@inheritdoc} */ public function has($path) { $cacheHas = $this->cache->has($path); if ($cacheHas !== null) { return $cacheHas; } $adapterResponse = $this->adapter->has($path); if (! $adapterResponse) { $this->cache->storeMiss($path); } else { $cacheEntry = is_array($adapterResponse) ? $adapterResponse : compact('path'); $this->cache->updateObject($path, $cacheEntry, true); } return $adapterResponse; } /** * {@inheritdoc} */ public function read($path) { return $this->callWithFallback('contents', $path, 'read'); } /** * {@inheritdoc} */ public function readStream($path) { return $this->adapter->readStream($path); } /** * Get the path prefix. * * @return string|null path prefix or null if pathPrefix is empty */ public function getPathPrefix() { return $this->adapter->getPathPrefix(); } /** * Prefix a path. * * @param string $path * * @return string prefixed path */ public function applyPathPrefix($path) { return $this->adapter->applyPathPrefix($path); } /** * {@inheritdoc} */ public function listContents($directory = '', $recursive = false) { if ($this->cache->isComplete($directory, $recursive)) { return $this->cache->listContents($directory, $recursive); } $result = $this->adapter->listContents($directory, $recursive); if ($result !== false) { $this->cache->storeContents($directory, $result, $recursive); } return $result; } /** * {@inheritdoc} */ public function getMetadata($path) { return $this->callWithFallback(null, $path, 'getMetadata'); } /** * {@inheritdoc} */ public function getSize($path) { return $this->callWithFallback('size', $path, 'getSize'); } /** * {@inheritdoc} */ public function getMimetype($path) { return $this->callWithFallback('mimetype', $path, 'getMimetype'); } /** * {@inheritdoc} */ public function getTimestamp($path) { return $this->callWithFallback('timestamp', $path, 'getTimestamp'); } /** * {@inheritdoc} */ public function getVisibility($path) { return $this->callWithFallback('visibility', $path, 'getVisibility'); } /** * Call a method and cache the response. * * @param string $property * @param string $path * @param string $method * * @return mixed */ protected function callWithFallback($property, $path, $method) { $result = $this->cache->{$method}($path); if ($result !== false && ($property === null || array_key_exists($property, $result))) { return $result; } $result = $this->adapter->{$method}($path); if ($result) { $object = $result + compact('path'); $this->cache->updateObject($path, $object, true); } return $result; } }