directory = rtrim($directory); $this->indexFile = $this->directory . DS . 'index.fwstorage'; // If the index does not exist yet, load it if (!file_exists($this->indexFile)) { if (!$this->write_file($this->indexFile, serialize(['index' => []]))) throw new ObjectStorageException("Could not load FileProvider ObjectStorage. Could not write index."); chmod($this->indexFile, 0640); } // And finally, load the index $this->index = unserialize(file_get_contents($this->indexFile))['index']; return true; } public function getIndex(): array { return $this->index; } public function getItem(string $key): ?array { // Convert the key $file = $this->directory . DS . crc32($key) . '.fwstorage'; // If the key could not be found in the index, return null if (!isset($this->index[$key])) return null; // Check if the file exists. If not, delete the indexed value if (!file_exists($file)) { $this->deleteItem($key); return null; } // Otherwise try and load the metaData and contents $meta = $this->index[$key]['meta']; $data = unserialize(file_get_contents($file)); // Return the combined data return ['meta' => $meta, 'data' => $data]; } public function getItemMeta(string $key): ?array { // If the key could not be found in the index, return null if (!isset($this->index[$key])) return null; // Otherwise return the meta data return $this->index[$key]['meta']; } public function getItems(array $keys = []): array { $output = []; foreach ($keys as $key) $output[$key] = $this->getItem($key); return $output; } public function hasItem(string $key): bool { return isset($this->index[$key]); } public function clear(): bool { $keys = array_keys($this->index); return $this->deleteItems($keys); } public function deleteItem(string $key): bool { // Convert the key $file = $this->directory . DS . crc32($key) . '.fwstorage'; // Remove the file first if (file_exists($file)) unlink($file); // And remove it from the index if (isset($this->index[$key])) unset($this->index[$key]); // And commit the index return $this->commitIndex(); } public function deleteItems(array $keys): bool { foreach ($keys as $key) $this->deleteItem($key); return true; } public function save(string $key, $value, array $metaData = []): bool { // Convert the key $file = $this->directory . DS . crc32($key) . '.fwstorage'; // Remove the file if it already exists if (file_exists($file)) unlink($file); // Write everything to the index $this->index[$key] = ['meta' => $metaData]; $this->commitIndex(); // And write the contents if ($this->write_file($file, serialize($value))) { chmod($file, 0640); return true; } return false; } public function commit(): bool { // TODO: Implement commit() method. } public function revert(): bool { // TODO: Implement revert() method. } private function commitIndex(): bool { if ($this->write_file($this->indexFile, serialize(['index' => $this->index]))) { chmod($this->indexFile, 0640); return true; } return false; } /** * Write File * * Writes data to the file specified in the path. * Creates a new file if non-existent. * * @param string $path File path * @param string $data Data to write * @param string $mode fopen() mode (default: 'wb') * @return bool */ private function write_file(string $path, string $data, string $mode = 'wb'): bool { if ( ! $fp = @fopen($path, $mode)) return false; flock($fp, LOCK_EX); for ($result = $written = 0, $length = strlen($data); $written < $length; $written += $result) if (($result = fwrite($fp, substr($data, $written))) === false) break; flock($fp, LOCK_UN); fclose($fp); return is_int($result); } }