diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..1c4b2b4 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,15 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +indent_style = tab +indent_size = 4 +trim_trailing_whitespace = true + +[*.md] +trim_trailing_whitespace = false + +[*.{yml,yaml,json}] +indent_size = 2 \ No newline at end of file diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..81ad3f0 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,8 @@ +# Ignore all test and documentation with "export-ignore". +/.gitattributes export-ignore +/.github export-ignore +/.gitignore export-ignore +/phpunit.xml.dist export-ignore +/phpcs.xml export-ignore +/tests export-ignore +/.editorconfig export-ignore diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..aa990a0 --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,42 @@ +name: tests + +on: + push: + pull_request: + +jobs: + test: + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.repository + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + php: [8.2, 8.1, 8.0] + laravel: ["^10.0", "^9.0"] + dependency-version: [prefer-lowest, prefer-stable] + exclude: + - laravel: "^10.0" + php: 8.0 + name: P${{ matrix.php }} - L${{ matrix.laravel }} - ${{ matrix.dependency-version }} + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Cache dependencies + uses: actions/cache@v4 + with: + path: ~/.composer/cache/files + key: dependencies-laravel-${{ matrix.laravel }}-php-${{ matrix.php }}-composer-${{ hashFiles('composer.json') }} + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, mysql, mysqli, pdo_mysql, bcmath, soap, intl, gd, exif, iconv, imagick, fileinfo + coverage: none + + - name: Install dependencies + uses: ramsey/composer-install@v2 + + - name: Execute tests + run: composer test \ No newline at end of file diff --git a/.github/workflows/update-changelog.yml b/.github/workflows/update-changelog.yml new file mode 100644 index 0000000..298072a --- /dev/null +++ b/.github/workflows/update-changelog.yml @@ -0,0 +1,28 @@ +name: "Update Changelog" + +on: + release: + types: [released] + +jobs: + update: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v3 + with: + ref: master + + - name: Update Changelog + uses: stefanzweifel/changelog-updater-action@v1 + with: + latest-version: ${{ github.event.release.name }} + release-notes: ${{ github.event.release.body }} + + - name: Commit updated CHANGELOG + uses: stefanzweifel/git-auto-commit-action@v4.15.4 + with: + branch: master + commit_message: Update CHANGELOG + file_pattern: CHANGELOG.md \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fdb5924 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +vendor +.idea +composer.lock \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..d4cca36 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,7 @@ +# Changelog + +All notable changes to `syberisle/laravel-castable-archive` will be documented in this file + +## 0.0.0 - 2024-03-17 + +Initial Release diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..368890b --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,17 @@ +# Contributing + +Contributions are **welcome** and will be fully **credited**. + +We accept contributions via Pull Requests on [Github](https://github.com/syberisle/laravel-castable-archive). + +## Pull Requests + +- **[SyberIsle Coding Standard](https://github.com/SyberIsle/coding-standards)** - The easiest way to apply the conventions is to install [PHP Code Sniffer](http://pear.php.net/package/PHP_CodeSniffer). + +- **Document any change in behaviour** - Make sure the `README.md` and any other relevant documentation are kept up-to-date. + +- **Consider our release cycle** - We try to follow [SemVer v2.0.0](https://semver.org/). + +- **Create feature branches** - Don't ask us to pull from your master branch. + +- **One pull request per feature** - If you want to do more than one thing, send multiple pull requests. diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..246be92 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2024 SyberIsle, LLC. + +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. diff --git a/README.md b/README.md new file mode 100644 index 0000000..e97c709 --- /dev/null +++ b/README.md @@ -0,0 +1,49 @@ +# Laravel Model attribute to de/compress the value + +[![Latest Version on Packagist](https://img.shields.io/packagist/v/syberisle/laravel-castable-archive.svg?style=flat-square)](https://packagist.org/packages/syberisle/laravel-castable-archive) +[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/syberisle/laravel-castable-archive/run-tests.yml?branch=main&label=Tests)](https://github.com/syberisle/laravel-castable-archive/actions/workflows/tests.yml) +[![Total Downloads](https://img.shields.io/packagist/dt/syberisle/laravel-castable-archive.svg?style=flat-square)](https://packagist.org/packages/syberisle/laravel-castable-archive) + +This package allows you to cast a model attribute as a compressed value using either gzip or bzip. + +Available Casts: +- `SyberIsle\Laravel\Cast\Archive\BzArchive` +- `SyberIsle\Laravel\Cast\Archive\GzArchive` + +## Installation + +```shell +composer install syberisle/laravel-castable-archive +``` + +## Usage + +```php +use SyberIsle\Laravel\Cast\Archive; + +class MyModel +{ + protected $casts = [ + 'field_name' => Archive\GzArchive::class + ]; +} + +$model->field_name = 'kakaw' // raw attribute = b"ËNÌN,\x07\x00" +$value = $model->field_name; // = 'kakaw' +``` + +## Changelog + +Please see [CHANGELOG](CHANGELOG.md) for more information about recent changes. + +## Contributing + +Please see [CONTRIBUTING](CONTRIBUTING.md) for details. + +## Security + +If you've found a bug regarding security please report it via the security tab of this repository. + +## License + +The MIT License (MIT). Please see [License File](LICENSE.md) for more information. \ No newline at end of file diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..40a0675 --- /dev/null +++ b/composer.json @@ -0,0 +1,53 @@ +{ + "name": "syberisle/laravel-castable-archive", + "description": "Tool for casting a model field as bzip or gzip", + "license": "MIT", + "keywords": [ + "laravel", + "model cast", + "gzip", + "bzip" + ], + "authors": [ + { + "name": "David Lundgren", + "email": "dlundgren@syberisle.com", + "role": "Developer" + } + ], + "homepage": "https://github.com/syberisle/laravel-castable-archive", + "require": { + "php": "^8.0", + "ext-bz2": "*", + "ext-zlib": "*", + "illuminate/contracts": "^9.28 || ^10.0 || ^11.0" + }, + "require-dev": { + "nunomaduro/collision": "^6.2", + "orchestra/testbench": "^7.7 || ^8.0", + "phpstan/phpstan": "^1.8", + "phpunit/phpunit": "^9.5.24", + "squizlabs/php_codesniffer": "^3.9", + "syberisle/coding-standards": "^2.0" + }, + "minimum-stability": "dev", + "prefer-stable": true, + "autoload": { + "psr-4": { + "SyberIsle\\Laravel\\Cast\\Archive\\": "src" + } + }, + "autoload-dev": { + "psr-4": { + "SyberIsle\\Laravel\\Cast\\Archive\\Test\\": "tests" + } + }, + "config": { + "sort-packages": true + }, + "scripts": { + "sniff": "@php vendor/bin/phpcs", + "stan": "vendor/bin/phpstan analyse --level 6 src", + "test": "vendor/bin/testbench package:test" + } +} diff --git a/phpcs.xml b/phpcs.xml new file mode 100644 index 0000000..3a4f4ae --- /dev/null +++ b/phpcs.xml @@ -0,0 +1,15 @@ + + + Coding standard for this project + + + + src + tests + + + + + + + \ No newline at end of file diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 0000000..c13d1b4 --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,20 @@ + + + + + ./tests + + + + + ./app + ./src + + + \ No newline at end of file diff --git a/src/BzArchive.php b/src/BzArchive.php new file mode 100644 index 0000000..e782780 --- /dev/null +++ b/src/BzArchive.php @@ -0,0 +1,41 @@ + + */ +class BzArchive + implements CastsAttributes +{ + /** + * @param Model $model + * @param string $key + * @param mixed $value + * @param mixed[] $attributes + * + * @return false|string|null + */ + public function get($model, string $key, $value, array $attributes): mixed + { + return bzdecompress($value); + } + + /** + * @param Model $model + * @param string $key + * @param mixed $value + * @param mixed[] $attributes + * + * @return false|string|null + */ + public function set($model, string $key, $value, array $attributes) + { + return bzcompress($value); + } +} \ No newline at end of file diff --git a/src/GzArchive.php b/src/GzArchive.php new file mode 100644 index 0000000..73bf638 --- /dev/null +++ b/src/GzArchive.php @@ -0,0 +1,41 @@ + + */ +class GzArchive + implements CastsAttributes +{ + /** + * @param Model $model + * @param string $key + * @param mixed $value + * @param mixed[] $attributes + * + * @return false|string|null + */ + public function get($model, string $key, $value, array $attributes): mixed + { + return gzinflate($value); + } + + /** + * @param Model $model + * @param string $key + * @param mixed $value + * @param mixed[] $attributes + * + * @return false|string|null + */ + public function set($model, string $key, $value, array $attributes): mixed + { + return gzdeflate($value); + } +} \ No newline at end of file diff --git a/tests/BzArchiveTest.php b/tests/BzArchiveTest.php new file mode 100644 index 0000000..e062126 --- /dev/null +++ b/tests/BzArchiveTest.php @@ -0,0 +1,42 @@ + BzArchive::class + ]; + + public function getRawAttribute(string $key): mixed + { + return $this->attributes[$key]; + } + }; + } + + public function testGetDecompresses() + { + $model = $this->buildModel(); + $model->setRawAttributes(['test' => bzcompress('kakaw')]); + + self::assertEquals('kakaw', $model->test); + } + + public function testSetCompresses() + { + $model = $this->buildModel(); + $model->test = 'kakaw'; + + self::assertEquals($model->getRawAttribute('test'), bzcompress('kakaw')); + } +} \ No newline at end of file diff --git a/tests/GzArchiveTest.php b/tests/GzArchiveTest.php new file mode 100644 index 0000000..f9bfe63 --- /dev/null +++ b/tests/GzArchiveTest.php @@ -0,0 +1,42 @@ + GzArchive::class + ]; + + public function getRawAttribute(string $key): mixed + { + return $this->attributes[$key]; + } + }; + } + + public function testGetDecompresses() + { + $model = $this->buildModel(); + $model->setRawAttributes(['test' => gzdeflate('kakaw')]); + + self::assertEquals('kakaw', $model->test); + } + + public function testSetCompresses() + { + $model = $this->buildModel(); + $model->test = 'kakaw'; + + self::assertEquals($model->getRawAttribute('test'), gzdeflate('kakaw')); + } +} \ No newline at end of file