From 8f3a2ba8268d2464d38d090fe16651f40123d46f Mon Sep 17 00:00:00 2001 From: Abel Hoogeveen Date: Thu, 26 Nov 2020 22:02:36 +0100 Subject: [PATCH] Initial commit --- .drone.yml | 0 .gitattributes | 4 + .gitignore | 6 + LICENSE | 21 ++ composer.json | 28 ++ config.storage.php | 36 +++ .../Exception/ObjectStorageException.php | 40 +++ .../ObjectStorage/ObjectStorageComponent.php | 69 +++++ .../ObjectStorage/Provider/FileProvider.php | 268 ++++++++++++++++++ .../ObjectStorage/iObjectStorageProvider.php | 56 ++++ test/bootstrap.php | 57 ++++ test/temp/placeholder | 0 12 files changed, 585 insertions(+) create mode 100644 .drone.yml create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 composer.json create mode 100644 config.storage.php create mode 100644 src/FuzeWorks/ObjectStorage/Exception/ObjectStorageException.php create mode 100644 src/FuzeWorks/ObjectStorage/ObjectStorageComponent.php create mode 100644 src/FuzeWorks/ObjectStorage/Provider/FileProvider.php create mode 100644 src/FuzeWorks/ObjectStorage/iObjectStorageProvider.php create mode 100644 test/bootstrap.php create mode 100644 test/temp/placeholder diff --git a/.drone.yml b/.drone.yml new file mode 100644 index 0000000..e69de29 diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..d6966d7 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,4 @@ +.gitattributes export-ignore +.gitignore export-ignore +.drone.yml export-ignore +test/ export-ignore \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c6f4d6e --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +composer.lock +composer.phar +.idea/ +build/ +test/temp/ +vendor/ \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..a325d0e --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2013-2020 i15 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..ee1b843 --- /dev/null +++ b/composer.json @@ -0,0 +1,28 @@ +{ + "name": "fuzeworks/objectstorage", + "minimum-stability": "stable", + "license": ["MIT"], + "authors": [ + { + "name": "Abel Hoogeveen", + "email": "abel@i15.nl" + } + ], + "require": { + "php": ">=7.4.0", + "fuzeworks/core": "~1.2", + "psr/cache": "~1.0" + }, + "suggest": { + "ext-redis": "1" + }, + "require-dev": { + "phpunit/phpunit": "^9", + "fuzeworks/tracycomponent": "~1.2" + }, + "autoload": { + "psr-4": { + "FuzeWorks\\ObjectStorage\\": "src/FuzeWorks/ObjectStorage/" + } + } +} \ No newline at end of file diff --git a/config.storage.php b/config.storage.php new file mode 100644 index 0000000..8c2d911 --- /dev/null +++ b/config.storage.php @@ -0,0 +1,36 @@ + $this]; + } + + public function onAddComponent(Configurator $configurator) + { + } + + public function onCreateContainer(Factory $container) + { + } +} \ No newline at end of file diff --git a/src/FuzeWorks/ObjectStorage/Provider/FileProvider.php b/src/FuzeWorks/ObjectStorage/Provider/FileProvider.php new file mode 100644 index 0000000..0dd287d --- /dev/null +++ b/src/FuzeWorks/ObjectStorage/Provider/FileProvider.php @@ -0,0 +1,268 @@ +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); + } +} \ No newline at end of file diff --git a/src/FuzeWorks/ObjectStorage/iObjectStorageProvider.php b/src/FuzeWorks/ObjectStorage/iObjectStorageProvider.php new file mode 100644 index 0000000..8000a0f --- /dev/null +++ b/src/FuzeWorks/ObjectStorage/iObjectStorageProvider.php @@ -0,0 +1,56 @@ +setTempDirectory(__DIR__ . '/temp'); +$configurator->setLogDirectory(__DIR__ . '/temp'); + +// Other values +$configurator->setTimeZone('Europe/Amsterdam'); + +// Add TracyComponent +\FuzeWorks\TracyComponent::enableTracy(); +$configurator->addComponent(new \FuzeWorks\TracyComponent()); + +// And the star of the show: ObjectStorageComponent +$configurator->addComponent(new \FuzeWorks\ObjectStorage\ObjectStorageComponent()); + +// Debug related +$configurator->enableDebugMode(); +$configurator->setDebugAddress('ALL'); + +return $configurator->createContainer(); \ No newline at end of file diff --git a/test/temp/placeholder b/test/temp/placeholder new file mode 100644 index 0000000..e69de29