diff --git a/.travis.yml b/.travis.yml index 95bc4269..11f120d3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,15 +1,35 @@ -language: php +dist: focal -php: -- 8.0 -- nightly +arch: + - amd64 + +os: linux + +language: shell notifications: email: - - team@appwrite.io + - team@appwrite.io + +before_script: docker run --rm --interactive --tty --volume "$(pwd)":/app composer update --ignore-platform-reqs --optimize-autoloader --no-plugins --no-scripts --prefer-dist + +before_install: + - curl -fsSL https://get.docker.com | sh + - echo '{"experimental":"enabled"}' | sudo tee /etc/docker/daemon.json + - mkdir -p $HOME/.docker + - echo '{"experimental":"enabled"}' | sudo tee $HOME/.docker/config.json + - sudo service docker start + - > + if [ ! -z "${DOCKERHUB_PULL_USERNAME:-}" ]; then + echo "${DOCKERHUB_PULL_PASSWORD}" | docker login --username "${DOCKERHUB_PULL_USERNAME}" --password-stdin + fi + - docker --version -before_script: composer install --ignore-platform-reqs +install: + - docker-compose up -d + - sleep 10 script: -- vendor/bin/phpunit --configuration phpunit.xml -- vendor/bin/psalm --show-info=true \ No newline at end of file + - docker ps + - docker-compose exec tests vendor/bin/phpunit --configuration phpunit.xml + - docker-compose exec tests vendor/bin/psalm --show-info=true \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100755 index 00000000..47fbced9 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,55 @@ +FROM composer:2.0 as composer + +ARG TESTING=false +ENV TESTING=$TESTING + +WORKDIR /usr/local/src/ + +COPY composer.lock /usr/local/src/ +COPY composer.json /usr/local/src/ + +RUN composer update \ + --ignore-platform-reqs \ + --optimize-autoloader \ + --no-plugins \ + --no-scripts \ + --prefer-dist + +FROM php:8.0-cli-alpine as compile + +ENV PHP_ZSTD_VERSION="master" + +RUN apk add --no-cache \ + git \ + autoconf \ + make \ + g++ \ + zstd-dev + +## Zstandard Extension +FROM compile AS zstd +RUN git clone --recursive --depth 1 --branch $PHP_ZSTD_VERSION https://github.com/kjdev/php-ext-zstd.git \ + && cd php-ext-zstd \ + && phpize \ + && ./configure --with-libzstd \ + && make && make install + +FROM compile as final + +LABEL maintainer="team@appwrite.io" + +WORKDIR /usr/src/code + +RUN echo extension=zstd.so >> /usr/local/etc/php/conf.d/zstd.ini + +RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini" \ + && echo "opcache.enable_cli=1" >> $PHP_INI_DIR/php.ini \ + && echo "memory_limit=1024M" >> $PHP_INI_DIR/php.ini + +COPY --from=composer /usr/local/src/vendor /usr/src/code/vendor +COPY --from=zstd /usr/local/lib/php/extensions/no-debug-non-zts-20200930/zstd.so /usr/local/lib/php/extensions/no-debug-non-zts-20200930/ + +# Add Source Code +COPY . /usr/src/code + +CMD [ "tail", "-f", "/dev/null" ] diff --git a/README.md b/README.md index fa6456a0..6723ba5c 100644 --- a/README.md +++ b/README.md @@ -26,14 +26,14 @@ use Utopia\Storage\Device\Local use Utopia\Storage\Device\S3 use Utopia\Storage\Device\DOSpaces -// instiantiating local storage +// Instantiating local storage Storage::setDevice('files', new Local('path')); -//or you can use s3 storage -Storage::setDevice('files', new S3('path',AWS_ACCESS_KEY, AWS_SECRET_KEY,AWS_BUCKET_NAME, AWS_REGION, AWS_ACL_FLAG)); +// Or you can use AWS S3 storage +Storage::setDevice('files', new S3('path', AWS_ACCESS_KEY, AWS_SECRET_KEY,AWS_BUCKET_NAME, AWS_REGION, AWS_ACL_FLAG)); -//or you can use Digitalocean spaces storage -Storage::setDevice('files', new DOSpaces('path',DO_SPACES_ACCESS_KEY, DO_SPACES_SECRET_KEY,DO_SPACES_BUCKET_NAME, DO_SPACES_REGION, AWS_ACL_FLAG)); +// Or you can use DigitalOcean Spaces storage +Storage::setDevice('files', new DOSpaces('path', DO_SPACES_ACCESS_KEY, DO_SPACES_SECRET_KEY, DO_SPACES_BUCKET_NAME, DO_SPACES_REGION, AWS_ACL_FLAG)); $device = Storage::getDevice('files'); diff --git a/composer.json b/composer.json index 4b48008b..5635eb96 100644 --- a/composer.json +++ b/composer.json @@ -17,6 +17,9 @@ "psr-4": {"Utopia\\Tests\\":"tests/Storage"} }, "require": { + "ext-fileinfo": "*", + "ext-zlib": "*", + "ext-zstd": "*", "php": ">=8.0", "utopia-php/framework": "0.*.*" }, diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 00000000..e6af4bb2 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,20 @@ +version: '3.1' + +services: + tests: + container_name: tests + build: + context: . + volumes: + - ./:/usr/src/code + environment: + - S3_ACCESS_KEY + - S3_SECRET + - DO_ACCESS_KEY + - DO_SECRET + - LINODE_ACCESS_KEY + - LINODE_SECRET + - BACKBLAZE_ACCESS_KEY + - BACKBLAZE_SECRET + - WASABI_ACCESS_KEY + - WASABI_SECRET \ No newline at end of file diff --git a/phpunit.xml b/phpunit.xml index ec39a7ed..e45a8aee 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -6,8 +6,7 @@ convertNoticesToExceptions="true" convertWarningsToExceptions="true" processIsolation="false" - stopOnFailure="false" - > + stopOnFailure="false"> ./tests/ diff --git a/src/Storage/Compression/Algorithms/Zstd.php b/src/Storage/Compression/Algorithms/Zstd.php new file mode 100644 index 00000000..98451af0 --- /dev/null +++ b/src/Storage/Compression/Algorithms/Zstd.php @@ -0,0 +1,81 @@ += 20 should be used with caution, as they require more memory. + * + * Default value is 3. + */ + protected int $level = 3; + + public function __construct(int $level = 3) + { + $this->level = $level; + } + + /** + * Get the compression level. + * + * @return int + */ + public function getLevel(): int + { + return $this->level; + } + + /** + * Set the compression level. + * + * Allow values from 1 up to a current max of 22. + * + * @param int $level + * @return void + */ + public function setLevel(int $level): void + { + if ($level < 1 || $level > 22) { + throw new \InvalidArgumentException('Level must be between 1 and 22'); + } + $this->level = $level; + } + + /** + * Get the name of the algorithm. + * + * @return string + */ + public function getName(): string + { + return 'zstd'; + } + + /** + * Compress. + * + * @param string $data + * + * @return string + */ + public function compress(string $data): string + { + return \zstd_compress($data, $this->level); + } + + /** + * Decompress. + * + * @param string $data + * + * @return string + */ + public function decompress(string $data): string + { + return \zstd_uncompress($data); + } +} diff --git a/tests/Storage/Compression/Algorithms/ZstdTest.php b/tests/Storage/Compression/Algorithms/ZstdTest.php new file mode 100644 index 00000000..b1bec685 --- /dev/null +++ b/tests/Storage/Compression/Algorithms/ZstdTest.php @@ -0,0 +1,77 @@ +object = new Zstd(); + } + + public function tearDown(): void + { + } + + public function testName() + { + $this->assertEquals($this->object->getName(), 'zstd'); + } + + public function testCompressDecompressWithText() + { + $demo = 'This is a demo string'; + $demoSize = \mb_strlen($demo, '8bit'); + + $data = $this->object->compress($demo); + $dataSize = \mb_strlen($data, '8bit'); + + $this->assertEquals(21, $demoSize); + $this->assertEquals(30, $dataSize); + + $this->assertEquals($demo, $this->object->decompress($data)); + } + + public function testCompressDecompressWithJPGImage() + { + $demo = \file_get_contents(__DIR__ . '/../../../resources/disk-a/kitten-1.jpg'); + $demoSize = \mb_strlen($demo, '8bit'); + + $data = $this->object->compress($demo); + $dataSize = \mb_strlen($data, '8bit'); + + $this->assertEquals(599639, $demoSize); + $this->assertEquals(599663, $dataSize); + + $this->assertGreaterThan($demoSize, $dataSize); + + $data = $this->object->decompress($data); + $dataSize = \mb_strlen($data, '8bit'); + + $this->assertEquals(599639, $dataSize); + } + + public function testCompressDecompressWithPNGImage() + { + $demo = \file_get_contents(__DIR__ . '/../../../resources/disk-b/kitten-1.png'); + $demoSize = \mb_strlen($demo, '8bit'); + + $data = $this->object->compress($demo); + $dataSize = \mb_strlen($data, '8bit'); + + $this->assertEquals(3038056, $demoSize); + $this->assertEquals(3038138, $dataSize); + + $this->assertGreaterThan($demoSize, $dataSize); + + $data = $this->object->decompress($data); + $dataSize = \mb_strlen($data, '8bit'); + + $this->assertEquals(3038056, $dataSize); + } +} diff --git a/tests/Storage/Device/WasabiTest.php b/tests/Storage/Device/WasabiTest.php index 7d24d28a..4cf40653 100644 --- a/tests/Storage/Device/WasabiTest.php +++ b/tests/Storage/Device/WasabiTest.php @@ -12,10 +12,9 @@ protected function init(): void $this->root = 'root'; $key = $_SERVER['WASABI_ACCESS_KEY'] ?? ''; $secret = $_SERVER['WASABI_SECRET'] ?? ''; - $bucket = 'utopia-tests'; + $bucket = 'utopia-php-storage-tests'; $this->object = new Wasabi($this->root, $key, $secret, $bucket, Wasabi::EU_CENTRAL_1, WASABI::ACL_PRIVATE); - } protected function getAdapterName(): string