Файловый менеджер - Редактировать - /home/clickysoft/public_html/jmapi5.clickysoft.net/spatie.zip
Назад
PK �>�Zg�I % laravel-sluggable/.github/FUNDING.ymlnu �[��� github: spatie PK �>�Z !� � � = laravel-sluggable/.github/workflows/dependabot-auto-merge.ymlnu �[��� name: dependabot-auto-merge on: pull_request_target permissions: pull-requests: write contents: write jobs: dependabot: runs-on: ubuntu-latest if: ${{ github.actor == 'dependabot[bot]' }} steps: - name: Dependabot metadata id: metadata uses: dependabot/fetch-metadata@v1.6.0 with: github-token: "${{ secrets.GITHUB_TOKEN }}" compat-lookup: true - name: Auto-merge Dependabot PRs for semver-minor updates if: ${{steps.metadata.outputs.update-type == 'version-update:semver-minor'}} run: gh pr merge --auto --merge "$PR_URL" env: PR_URL: ${{github.event.pull_request.html_url}} GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} - name: Auto-merge Dependabot PRs for semver-patch updates if: ${{steps.metadata.outputs.update-type == 'version-update:semver-patch'}} run: gh pr merge --auto --merge "$PR_URL" env: PR_URL: ${{github.event.pull_request.html_url}} GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} - name: Auto-merge Dependabot PRs for Action major versions when compatibility is higher than 90% if: ${{steps.metadata.outputs.package-ecosystem == 'github_actions' && steps.metadata.outputs.update-type == 'version-update:semver-major' && steps.metadata.outputs.compatibility-score >= 90}} run: gh pr merge --auto --merge "$PR_URL" env: PR_URL: ${{github.event.pull_request.html_url}} GH_TOKEN: ${{secrets.GITHUB_TOKEN}} PK �>�Z�tAw 4 laravel-sluggable/.github/workflows/php-cs-fixer.ymlnu �[��� name: Check & fix styling on: [push] jobs: php-cs-fixer: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 with: ref: ${{ github.head_ref }} - name: Run PHP CS Fixer uses: docker://oskarstark/php-cs-fixer-ga with: args: --config=.php-cs-fixer.dist.php --allow-risky=yes - name: Commit changes uses: stefanzweifel/git-auto-commit-action@v4 with: commit_message: Fix styling PK �>�Z���2� � 8 laravel-sluggable/.github/workflows/update-changelog.ymlnu �[��� name: "Update Changelog" on: release: types: [released] jobs: update: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 with: ref: main - 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 with: branch: main commit_message: Update CHANGELOG file_pattern: CHANGELOG.md PK �>�Z,�X� � 1 laravel-sluggable/.github/workflows/run-tests.ymlnu �[��� name: run-tests on: [push, pull_request] jobs: test: runs-on: ${{ matrix.os }} strategy: fail-fast: true matrix: os: [ubuntu-latest] php: [8.3, 8.2, 8.1, 8.0] laravel: [11.*, 10.*, 9.*, 8.*] stability: [prefer-stable] include: - laravel: 11.* testbench: 9.* - laravel: 10.* testbench: 8.* - laravel: 9.* testbench: 7.* - laravel: 8.* testbench: 6.23 exclude: - laravel: 11.* php: 8.1 - laravel: 11.* php: 8.0 - laravel: 10.* php: 8.0 name: P${{ matrix.php }} - L${{ matrix.laravel }} - ${{ matrix.stability }} - ${{ matrix.os }} steps: - name: Checkout code uses: actions/checkout@v4 - name: Setup PHP uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php }} extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, bcmath, soap, intl, gd, exif, iconv, imagick coverage: none - name: Setup problem matchers run: | echo "::add-matcher::${{ runner.tool_cache }}/php.json" echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json" - name: Install dependencies run: | composer require "laravel/framework:${{ matrix.laravel }}" "orchestra/testbench:${{ matrix.testbench }}" --no-interaction --no-update composer update --${{ matrix.stability }} --prefer-dist --no-interaction - name: Execute tests run: vendor/bin/pest PK �>�Z/sB x x ( laravel-sluggable/.github/dependabot.ymlnu �[��� version: 2 updates: - package-ecosystem: "github-actions" directory: "/" schedule: interval: "weekly" PK �>�Zn��� laravel-sluggable/composer.jsonnu �[��� { "name": "spatie/laravel-sluggable", "description": "Generate slugs when saving Eloquent models", "license": "MIT", "keywords": [ "spatie", "laravel-sluggable" ], "authors": [ { "name": "Freek Van der Herten", "email": "freek@spatie.be", "homepage": "https://spatie.be", "role": "Developer" } ], "homepage": "https://github.com/spatie/laravel-sluggable", "require": { "php": "^8.0", "illuminate/database": "^8.0|^9.0|^10.0|^11.0", "illuminate/support": "^8.0|^9.0|^10.0|^11.0" }, "require-dev": { "orchestra/testbench": "^6.23|^7.0|^8.0|^9.0", "pestphp/pest": "^1.20|^2.0", "spatie/laravel-translatable": "^5.0|^6.0" }, "minimum-stability": "dev", "prefer-stable": true, "autoload": { "psr-4": { "Spatie\\Sluggable\\": "src" } }, "autoload-dev": { "psr-4": { "Spatie\\Sluggable\\Tests\\": "tests" } }, "config": { "allow-plugins": { "pestphp/pest-plugin": true } }, "scripts": { "format": "vendor/bin/php-cs-fixer fix --allow-risky=yes", "test": "vendor/bin/pest" } } PK �>�Z���k� � ( laravel-sluggable/.php-cs-fixer.dist.phpnu �[��� <?php $finder = Symfony\Component\Finder\Finder::create() ->notPath('bootstrap/*') ->notPath('storage/*') ->notPath('storage/*') ->notPath('resources/view/mail/*') ->in([ __DIR__ . '/src', __DIR__ . '/tests', ]) ->name('*.php') ->notName('*.blade.php') ->ignoreDotFiles(true) ->ignoreVCS(true); return (new PhpCsFixer\Config) ->setRules([ '@PSR12' => true, 'array_syntax' => ['syntax' => 'short'], 'ordered_imports' => ['sort_algorithm' => 'alpha'], 'no_unused_imports' => true, 'not_operator_with_successor_space' => true, 'trailing_comma_in_multiline' => true, 'phpdoc_scalar' => true, 'unary_operator_spaces' => true, 'binary_operator_spaces' => true, 'blank_line_before_statement' => [ 'statements' => ['break', 'continue', 'declare', 'return', 'throw', 'try'], ], 'phpdoc_single_line_var_spacing' => true, 'phpdoc_var_without_name' => true, 'method_argument_space' => [ 'on_multiline' => 'ensure_fully_multiline', 'keep_multiple_spaces_after_comma' => true, ] ]) ->setFinder($finder); PK �>�Z%.��8 8 laravel-sluggable/.editorconfignu �[��� ; This file is for unifying the coding style for different editors and IDEs. ; More information at http://editorconfig.org root = true [*] charset = utf-8 indent_size = 4 indent_style = space end_of_line = lf insert_final_newline = true trim_trailing_whitespace = true [*.md] trim_trailing_whitespace = false PK �>�Z�(G� � laravel-sluggable/CHANGELOG.mdnu ȯ�� # Changelog All notable changes to `laravel-sluggable` will be documented in this file ## 3.5.0 - 2023-05-29 ### What's Changed - Bump dependabot/fetch-metadata from 1.3.5 to 1.3.6 by @dependabot in https://github.com/spatie/laravel-sluggable/pull/250 - Fix badge with `build` status in `README.md` by @gomzyakov in https://github.com/spatie/laravel-sluggable/pull/252 - Bump dependabot/fetch-metadata from 1.3.6 to 1.4.0 by @dependabot in https://github.com/spatie/laravel-sluggable/pull/255 - feat: add findBySlug alias by @IsraelOrtuno in https://github.com/spatie/laravel-sluggable/pull/256 ### New Contributors - @gomzyakov made their first contribution in https://github.com/spatie/laravel-sluggable/pull/252 - @IsraelOrtuno made their first contribution in https://github.com/spatie/laravel-sluggable/pull/256 **Full Changelog**: https://github.com/spatie/laravel-sluggable/compare/3.4.2...3.5.0 ## 3.4.2 - 2023-01-23 - update for Laravel 10 ## 3.4.1 - 2022-12-07 ### What's Changed - Update README.md by @furiouskj in https://github.com/spatie/laravel-sluggable/pull/240 - composer allow-plugins config by @hotsaucejake in https://github.com/spatie/laravel-sluggable/pull/241 - Normalize composer.json by @patinthehat in https://github.com/spatie/laravel-sluggable/pull/247 - Add Dependabot Automation by @patinthehat in https://github.com/spatie/laravel-sluggable/pull/246 - Add PHP 8.2 Support by @patinthehat in https://github.com/spatie/laravel-sluggable/pull/245 - Bump actions/checkout from 2 to 3 by @dependabot in https://github.com/spatie/laravel-sluggable/pull/248 - Allow set slug suffix starting number by @Vediovis in https://github.com/spatie/laravel-sluggable/pull/249 ### New Contributors - @furiouskj made their first contribution in https://github.com/spatie/laravel-sluggable/pull/240 - @hotsaucejake made their first contribution in https://github.com/spatie/laravel-sluggable/pull/241 - @dependabot made their first contribution in https://github.com/spatie/laravel-sluggable/pull/248 - @Vediovis made their first contribution in https://github.com/spatie/laravel-sluggable/pull/249 **Full Changelog**: https://github.com/spatie/laravel-sluggable/compare/3.4.0...3.4.1 ## 3.4.0 - 2022-03-28 ## What's Changed - Converts Test cases to Pest tests by @marvin-wtt in https://github.com/spatie/laravel-sluggable/pull/223 - Add ability to skip the slug generation by a condition by @masterix21 in https://github.com/spatie/laravel-sluggable/pull/227 ## New Contributors - @masterix21 made their first contribution in https://github.com/spatie/laravel-sluggable/pull/227 **Full Changelog**: https://github.com/spatie/laravel-sluggable/compare/3.3.1...3.4.0 ## 3.3.1 - 2022-03-09 ## What's Changed - Add support for spatie/laravel-translatable:^6.0 by @mziraki in https://github.com/spatie/laravel-sluggable/pull/224 ## New Contributors - @mziraki made their first contribution in https://github.com/spatie/laravel-sluggable/pull/224 **Full Changelog**: https://github.com/spatie/laravel-sluggable/compare/3.3.0...3.3.1 ## 3.3.0 - 2022-01-13 - support Laravel 9 ## 3.2.0 - 2021-12-15 ## What's Changed - Adds support for implicit route model binding with translated slugs by @marvin-wtt in https://github.com/spatie/laravel-sluggable/pull/213 ## New Contributors - @marvin-wtt made their first contribution in https://github.com/spatie/laravel-sluggable/pull/213 **Full Changelog**: https://github.com/spatie/laravel-sluggable/compare/3.1.1...3.2.0 ## 3.1.1 - 2021-12-13 ## What's Changed - Migrate to PHP-CS-Fixer 3.x by @shuvroroy in https://github.com/spatie/laravel-sluggable/pull/203 - Adds test case for replicate method by @eduarguz in https://github.com/spatie/laravel-sluggable/pull/212 - Fix Deprecation: currentSlug is null by @phh in https://github.com/spatie/laravel-sluggable/pull/218 ## New Contributors - @shuvroroy made their first contribution in https://github.com/spatie/laravel-sluggable/pull/203 - @eduarguz made their first contribution in https://github.com/spatie/laravel-sluggable/pull/212 - @phh made their first contribution in https://github.com/spatie/laravel-sluggable/pull/218 **Full Changelog**: https://github.com/spatie/laravel-sluggable/compare/3.1.0...3.1.1 ## 3.1.0 - 2021-06-04 - add extra scope callback option (#201) ## 3.0.2 - 2021-05-07 - bugfix for updating slugs generated from a callback (#200) ## 3.0.1 - 2021-04-22 - update slug on non unique names (#195) ## 3.0.0 - 2021-03-01 - require PHP 8+ - drop support for PHP 7.x - convert syntax to PHP 8 - move Exceptions to `Exceptions` folder to match structure of other packages ## 2.6.2 - 2021-03-20 - Added translatable slug overriding (#190) ## 2.6.1 - 2020-01-31 - fix Eloquent model checking (#186) ## 2.6.0 - 2020-10-28 - add `preventOverwrite` - add support for PHP 8 ## 2.5.2 - 2020-10-01 - fixed an incompatibility bug with postgresql uuid column (#173) ## 2.5.1 - 2020-09-07 - add support for Laravel 8 ## 2.5.0 - 2020-06-15 - add helper trait to integrate with `laravel-translatable` #155 ## 2.4.2 - 2020-04-20 - fix bug that causes empty slugs when dealing with multi-bytes chars (#152) ## 2.4.1 - 2020-04-09 - use method for retrieving incrementing status of the model (#151) ## 2.4.0 - 2020-03-03 - add support for Laravel 7, drop support for Laravel 6 ## 2.3.0 - 2019-12-06 - drop support for anything below PHP 7.4 and Laravel 6 ## 2.2.1 - 2019-09-16 - Changed: Updated Laravel 6 compatibility for future versions ## 2.2.0 - 2019-09-04 - Drop support for PHP 7.1 - Add support for Laravel 6.0 ## 2.1.8 - 2019-06-08 - ensure slugs are unique when using soft deletes ## 2.1.7 - 2019-02-26 - Add support for Laravel 5.8 ## 2.1.6 - 2018-02-14 - performance improvements ## 2.1.5 - 2018-01-10 - improve compatibility with json fields ## 2.1.4 - 2018-08-28 - add support for Laravel 5.7 ## 2.1.3 - 2018-02-15 - fix for models with non incrementing primary keys ## 2.1.2 - 2018-02-08 - Support Laravel 5.6 ## 2.1.1 - 2017-01-28 - improve compatibility with Lumen ## 2.1.0 - 2017-09-13 - add `usingLanguage` ## 2.0.0 - 2017-08-31 - add support for Laravel 5.5, drop support for all older versions of the framework ## 1.5.2 - 2018-05-08 - make compatible with PHP 7.2 ## 1.5.1 - 2017-08-19 - fix bugs when using a custom separator ## 1.5.0 - 2017-04-13 - add `usingSeparator()` ## 1.4.1 - 2017-04-11 - ignore global scopes when determining a unique slug ## 1.4.0 - 2017-01-24 - add support for Laravel 5.4 ## 1.3.0 - 2016-11-14 - add `doNotGenerateSlugsOnCreate` and `doNotGenerateSlugsOnUpdate` ## 1.2.0 - 2016-06-13 - Added the ability to generate slugs from a callable ## 1.1.0 - 2016-01-24 - Allow custom slugs ## 1.0.2 - 2016-01-12 - Fix bug when creating slugs from null values ## 1.0.1 - 2015-12-27 - Fix Postgres bug ## 1.0.0 - 2015-12-24 - Initial release PK �>�Z`;�9B B laravel-sluggable/LICENSE.mdnu �[��� The MIT License (MIT) Copyright (c) Spatie bvba <info@spatie.be> 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. PK �>�ZCE� ! laravel-sluggable/src/HasSlug.phpnu �[��� <?php namespace Spatie\Sluggable; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Str; use Spatie\Sluggable\Exceptions\InvalidOption; trait HasSlug { protected SlugOptions $slugOptions; abstract public function getSlugOptions(): SlugOptions; protected static function bootHasSlug(): void { static::creating(function (Model $model) { $model->generateSlugOnCreate(); }); static::updating(function (Model $model) { $model->generateSlugOnUpdate(); }); } protected function generateSlugOnCreate(): void { $this->slugOptions = $this->getSlugOptions(); if ($this->slugOptions->skipGenerate) { return; } if (! $this->slugOptions->generateSlugsOnCreate) { return; } if ($this->slugOptions->preventOverwrite) { if ($this->{$this->slugOptions->slugField} !== null) { return; } } $this->addSlug(); } protected function generateSlugOnUpdate(): void { $this->slugOptions = $this->getSlugOptions(); if ($this->slugOptions->skipGenerate) { return; } if (! $this->slugOptions->generateSlugsOnUpdate) { return; } if ($this->slugOptions->preventOverwrite) { if ($this->{$this->slugOptions->slugField} !== null) { return; } } $this->addSlug(); } public function generateSlug(): void { $this->slugOptions = $this->getSlugOptions(); $this->addSlug(); } protected function addSlug(): void { $this->ensureValidSlugOptions(); $slug = $this->generateNonUniqueSlug(); if ($this->slugOptions->generateUniqueSlugs) { $slug = $this->makeSlugUnique($slug); } $slugField = $this->slugOptions->slugField; $this->$slugField = $slug; } protected function generateNonUniqueSlug(): string { $slugField = $this->slugOptions->slugField; if ($this->hasCustomSlugBeenUsed() && ! empty($this->$slugField)) { return $this->$slugField; } return Str::slug($this->getSlugSourceString(), $this->slugOptions->slugSeparator, $this->slugOptions->slugLanguage); } protected function hasCustomSlugBeenUsed(): bool { $slugField = $this->slugOptions->slugField; return $this->getOriginal($slugField) != $this->$slugField; } protected function getSlugSourceString(): string { if (is_callable($this->slugOptions->generateSlugFrom)) { $slugSourceString = $this->getSlugSourceStringFromCallable(); return $this->generateSubstring($slugSourceString); } $slugSourceString = collect($this->slugOptions->generateSlugFrom) ->map(fn (string $fieldName): string => data_get($this, $fieldName, '')) ->implode($this->slugOptions->slugSeparator); return $this->generateSubstring($slugSourceString); } protected function getSlugSourceStringFromCallable(): string { return call_user_func($this->slugOptions->generateSlugFrom, $this); } protected function makeSlugUnique(string $slug): string { $originalSlug = $slug; $i = $this->slugOptions->startSlugSuffixFrom; while ($this->otherRecordExistsWithSlug($slug) || $slug === '') { $slug = $originalSlug.$this->slugOptions->slugSeparator.$i++; } return $slug; } protected function otherRecordExistsWithSlug(string $slug): bool { $query = static::where($this->slugOptions->slugField, $slug) ->withoutGlobalScopes(); if ($this->slugOptions->extraScopeCallback) { $query->where($this->slugOptions->extraScopeCallback); } if ($this->exists) { $query->where($this->getKeyName(), '!=', $this->getKey()); } if ($this->usesSoftDeletes()) { $query->withTrashed(); } return $query->exists(); } protected function usesSoftDeletes(): bool { return in_array('Illuminate\Database\Eloquent\SoftDeletes', class_uses($this), true); } protected function ensureValidSlugOptions(): void { if (is_array($this->slugOptions->generateSlugFrom) && ! count($this->slugOptions->generateSlugFrom)) { throw InvalidOption::missingFromField(); } if (! strlen($this->slugOptions->slugField)) { throw InvalidOption::missingSlugField(); } if ($this->slugOptions->maximumLength <= 0) { throw InvalidOption::invalidMaximumLength(); } } /** * Helper function to handle multi-bytes strings if the module mb_substr is present, * default to substr otherwise. */ protected function generateSubstring($slugSourceString) { if (function_exists('mb_substr')) { return mb_substr($slugSourceString, 0, $this->slugOptions->maximumLength); } return substr($slugSourceString, 0, $this->slugOptions->maximumLength); } public static function findBySlug(string $slug, array $columns = ['*']) { $modelInstance = new static(); $field = $modelInstance->getSlugOptions()->slugField; $field = in_array(HasTranslatableSlug::class, class_uses_recursive(static::class)) ? "{$field}->{$modelInstance->getLocale()}" : $field; return static::where($field, $slug)->first($columns); } } PK �>�ZR��� � - laravel-sluggable/src/HasTranslatableSlug.phpnu �[��� <?php namespace Spatie\Sluggable; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Relations\Relation; use Illuminate\Support\Collection; use Illuminate\Support\Str; use Illuminate\Support\Traits\Localizable; trait HasTranslatableSlug { use HasSlug; use Localizable; protected function getLocalesForSlug(): Collection { $generateSlugFrom = $this->slugOptions->generateSlugFrom; if (is_callable($generateSlugFrom)) { // returns a collection of locales that were given to the SlugOptions object // when it was instantiated with the 'createWithLocales' method. return Collection::make($this->slugOptions->translatableLocales); } // collects all locales for all translatable fields return Collection::wrap($generateSlugFrom) ->filter(fn ($fieldName) => $this->isTranslatableAttribute($fieldName)) ->flatMap(fn ($fieldName) => $this->getTranslatedLocales($fieldName)); } protected function addSlug(): void { $this->ensureValidSlugOptions(); $this->getLocalesForSlug()->unique()->each(function ($locale) { $this->withLocale($locale, function () use ($locale) { $slug = $this->generateNonUniqueSlug(); $slugField = $this->slugOptions->slugField; if ($this->slugOptions->generateUniqueSlugs) { // temporarly change the 'slugField' of the SlugOptions // so the 'otherRecordExistsWithSlug' method queries // the locale JSON column instead of the 'slugField'. $this->slugOptions->saveSlugsTo("{$slugField}->{$locale}"); $slug = $this->makeSlugUnique($slug); // revert the change for the next iteration $this->slugOptions->saveSlugsTo($slugField); } $this->setTranslation($slugField, $locale, $slug); }); }); } protected function generateNonUniqueSlug(): string { $slugField = $this->slugOptions->slugField; $slugString = $this->getSlugSourceString(); $slug = $this->getTranslations($slugField)[$this->getLocale()] ?? null; $slugGeneratedFromCallable = is_callable($this->slugOptions->generateSlugFrom); $hasCustomSlug = $this->hasCustomSlugBeenUsed() && ! empty($slug); $hasNonChangedCustomSlug = ! $slugGeneratedFromCallable && ! empty($slug) && ! $this->slugIsBasedOnTitle(); if ($hasCustomSlug || $hasNonChangedCustomSlug) { $slugString = $slug; } return Str::slug($slugString, $this->slugOptions->slugSeparator, $this->slugOptions->slugLanguage); } protected function getSlugSourceStringFromCallable(): string { return call_user_func($this->slugOptions->generateSlugFrom, $this, $this->getLocale()); } protected function slugIsBasedOnTitle(): bool { $slugField = $this->slugOptions->slugField; $titleSlug = Str::slug($this->getOriginalSourceString(), $this->slugOptions->slugSeparator, $this->slugOptions->slugLanguage); $currentSlug = $this->getTranslations($slugField)[$this->getLocale()] ?? null; if (! str_starts_with($currentSlug, $titleSlug) || $titleSlug === '') { return false; } if ($titleSlug === $currentSlug) { return true; } $slugSeparator = $currentSlug[strlen($titleSlug)]; $slugIdentifier = substr($currentSlug, strlen($titleSlug) + 1); return $slugSeparator === $this->slugOptions->slugSeparator && is_numeric($slugIdentifier); } protected function getOriginalSourceString(): string { if (is_callable($this->slugOptions->generateSlugFrom)) { $slugSourceString = $this->getSlugSourceStringFromCallable(); return $this->generateSubstring($slugSourceString); } $slugSourceString = collect($this->slugOptions->generateSlugFrom) ->map(fn (string $fieldName): string => $this->getOriginal($fieldName)[$this->getLocale()] ?? '') ->implode($this->slugOptions->slugSeparator); return $this->generateSubstring($slugSourceString); } protected function hasCustomSlugBeenUsed(): bool { $slugField = $this->slugOptions->slugField; $originalSlug = $this->getOriginal($slugField)[$this->getLocale()] ?? null; $newSlug = $this->getTranslations($slugField)[$this->getLocale()] ?? null; return $originalSlug !== $newSlug; } public function resolveRouteBindingQuery($query, $value, $field = null): Builder|Relation { $field = $field ?? $this->getRouteKeyName(); if ($field !== $this->getSlugOptions()->slugField) { return parent::resolveRouteBindingQuery($query, $value, $field); } return $query->where("{$field}->{$this->getLocale()}", $value); } } PK �>�Zj]Ժ, , 2 laravel-sluggable/src/Exceptions/InvalidOption.phpnu �[��� <?php namespace Spatie\Sluggable\Exceptions; use Exception; class InvalidOption extends Exception { public static function missingFromField(): static { return new static('Could not determine which fields should be sluggified'); } public static function missingSlugField(): static { return new static('Could not determine in which field the slug should be saved'); } public static function invalidMaximumLength(): static { return new static('Maximum length should be greater than zero'); } } PK �>�Z�+0� � % laravel-sluggable/src/SlugOptions.phpnu �[��� <?php namespace Spatie\Sluggable; class SlugOptions { /** @var array|callable */ public $generateSlugFrom; /** @var callable */ public $extraScopeCallback; public string $slugField; public bool $generateUniqueSlugs = true; public int $maximumLength = 250; public bool $skipGenerate = false; public bool $generateSlugsOnCreate = true; public bool $generateSlugsOnUpdate = true; public bool $preventOverwrite = false; public string $slugSeparator = '-'; public string $slugLanguage = 'en'; public array $translatableLocales = []; public int $startSlugSuffixFrom = 1; public static function create(): static { return new static(); } public static function createWithLocales(array $locales): static { $slugOptions = static::create(); $slugOptions->translatableLocales = $locales; return $slugOptions; } public function generateSlugsFrom(string | array | callable $fieldName): self { if (is_string($fieldName)) { $fieldName = [$fieldName]; } $this->generateSlugFrom = $fieldName; return $this; } public function saveSlugsTo(string $fieldName): self { $this->slugField = $fieldName; return $this; } public function allowDuplicateSlugs(): self { $this->generateUniqueSlugs = false; return $this; } public function slugsShouldBeNoLongerThan(int $maximumLength): self { $this->maximumLength = $maximumLength; return $this; } public function skipGenerateWhen(callable $callable): self { $this->skipGenerate = $callable() === true; return $this; } public function doNotGenerateSlugsOnCreate(): self { $this->generateSlugsOnCreate = false; return $this; } public function doNotGenerateSlugsOnUpdate(): self { $this->generateSlugsOnUpdate = false; return $this; } public function preventOverwrite(): self { $this->preventOverwrite = true; return $this; } public function usingSeparator(string $separator): self { $this->slugSeparator = $separator; return $this; } public function usingLanguage(string $language): self { $this->slugLanguage = $language; return $this; } public function extraScope(callable $callbackMethod): self { $this->extraScopeCallback = $callbackMethod; return $this; } public function startSlugSuffixFrom(int $startSlugSuffixFrom): self { $this->startSlugSuffixFrom = max(1, $startSlugSuffixFrom); return $this; } } PK �>�Zr�lqC2 C2 laravel-sluggable/README.mdnu �[��� # Generate slugs when saving Eloquent models [](https://packagist.org/packages/spatie/laravel-sluggable) [](LICENSE.md) [](https://github.com/spatie/laravel-sluggable/actions) [](https://packagist.org/packages/spatie/laravel-sluggable) This package provides a trait that will generate a unique slug when saving any Eloquent model. ```php $model = new EloquentModel(); $model->name = 'activerecord is awesome'; $model->save(); echo $model->slug; // outputs "activerecord-is-awesome" ``` The slugs are generated with Laravels `Str::slug` method, whereby spaces are converted to '-'. Spatie is a webdesign agency based in Antwerp, Belgium. You'll find an overview of all our open source projects [on our website](https://spatie.be/opensource). ## Support us [<img src="https://github-ads.s3.eu-central-1.amazonaws.com/laravel-sluggable.jpg?t=1" width="419px" />](https://spatie.be/github-ad-click/laravel-sluggable) We invest a lot of resources into creating [best in class open source packages](https://spatie.be/open-source). You can support us by [buying one of our paid products](https://spatie.be/open-source/support-us). We highly appreciate you sending us a postcard from your hometown, mentioning which of our package(s) you are using. You'll find our address on [our contact page](https://spatie.be/about-us). We publish all received postcards on [our virtual postcard wall](https://spatie.be/open-source/postcards). ## Installation You can install the package via composer: ``` bash composer require spatie/laravel-sluggable ``` ## Usage Your Eloquent models should use the `Spatie\Sluggable\HasSlug` trait and the `Spatie\Sluggable\SlugOptions` class. The trait contains an abstract method `getSlugOptions()` that you must implement yourself. Your models' migrations should have a field to save the generated slug to. Here's an example of how to implement the trait: ```php namespace App; use Spatie\Sluggable\HasSlug; use Spatie\Sluggable\SlugOptions; use Illuminate\Database\Eloquent\Model; class YourEloquentModel extends Model { use HasSlug; /** * Get the options for generating the slug. */ public function getSlugOptions() : SlugOptions { return SlugOptions::create() ->generateSlugsFrom('name') ->saveSlugsTo('slug'); } } ``` With its migration: ```php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; class CreateYourEloquentModelTable extends Migration { public function up() { Schema::create('your_eloquent_models', function (Blueprint $table) { $table->increments('id'); $table->string('slug'); // Field name same as your `saveSlugsTo` $table->string('name'); $table->timestamps(); }); } } ``` ### Using slugs in routes To use the generated slug in routes, remember to use Laravel's [implicit route model binding](https://laravel.com/docs/5.8/routing#implicit-binding): ```php namespace App; use Spatie\Sluggable\HasSlug; use Spatie\Sluggable\SlugOptions; use Illuminate\Database\Eloquent\Model; class YourEloquentModel extends Model { use HasSlug; /** * Get the options for generating the slug. */ public function getSlugOptions() : SlugOptions { return SlugOptions::create() ->generateSlugsFrom('name') ->saveSlugsTo('slug'); } /** * Get the route key for the model. * * @return string */ public function getRouteKeyName() { return 'slug'; } } ``` ### Using multiple fields to create the slug Want to use multiple field as the basis for a slug? No problem! ```php public function getSlugOptions() : SlugOptions { return SlugOptions::create() ->generateSlugsFrom(['first_name', 'last_name']) ->saveSlugsTo('slug'); } ``` ### Customizing slug generation You can also pass a `callable` to `generateSlugsFrom`. By default the package will generate unique slugs by appending '-' and a number, to a slug that already exists. You can disable this behaviour by calling `allowDuplicateSlugs`. ```php public function getSlugOptions() : SlugOptions { return SlugOptions::create() ->generateSlugsFrom('name') ->saveSlugsTo('slug') ->allowDuplicateSlugs(); } ``` ### Limiting the length of a slug You can also put a maximum size limit on the created slug: ```php public function getSlugOptions() : SlugOptions { return SlugOptions::create() ->generateSlugsFrom('name') ->saveSlugsTo('slug') ->slugsShouldBeNoLongerThan(50); } ``` The slug may be slightly longer than the value specified, due to the suffix which is added to make it unique. You can also use a custom separator by calling `usingSeparator` ```php public function getSlugOptions() : SlugOptions { return SlugOptions::create() ->generateSlugsFrom('name') ->saveSlugsTo('slug') ->usingSeparator('_'); } ``` ### Setting the slug language To set the language used by `Str::slug` you may call `usingLanguage` ```php public function getSlugOptions() : SlugOptions { return SlugOptions::create() ->generateSlugsFrom('name') ->saveSlugsTo('slug') ->usingLanguage('nl'); } ``` ### Overriding slugs You can also override the generated slug just by setting it to another value than the generated slug. ```php $model = EloquentModel::create(['name' => 'my name']); //slug is now "my-name"; $model->slug = 'my-custom-url'; $model->save(); //slug is now "my-custom-url"; ``` ## Prevents slugs from being generated on some conditions If you don't want to create the slug when the model has a state, you can use the `skipGenerateWhen` function. ```php public function getSlugOptions() : SlugOptions { return SlugOptions::create() ->generateSlugsFrom('name') ->saveSlugsTo('slug') ->skipGenerateWhen(fn () => $this->state === 'draft'); } ``` ### Prevent slugs from being generated on creation If you don't want to create the slug when the model is initially created you can set use the `doNotGenerateSlugsOnCreate()` function. ```php public function getSlugOptions() : SlugOptions { return SlugOptions::create() ->generateSlugsFrom('name') ->saveSlugsTo('slug') ->doNotGenerateSlugsOnCreate(); } ``` ### Prevent slug updates Similarly, if you want to prevent the slug from being updated on model updates, call `doNotGenerateSlugsOnUpdate()`. ```php public function getSlugOptions() : SlugOptions { return SlugOptions::create() ->generateSlugsFrom('name') ->saveSlugsTo('slug') ->doNotGenerateSlugsOnUpdate(); } ``` This can be helpful for creating permalinks that don't change until you explicitly want it to. ```php $model = EloquentModel::create(['name' => 'my name']); //slug is now "my-name"; $model->save(); $model->name = 'changed name'; $model->save(); //slug stays "my-name" ``` ### Regenerating slugs If you want to explicitly update the slug on the model you can call `generateSlug()` on your model at any time to make the slug according to your other options. Don't forget to `save()` the model to persist the update to your database. ### Preventing overwrites You can prevent slugs from being overwritten. ```php public function getSlugOptions() : SlugOptions { return SlugOptions::create() ->generateSlugsFrom('name') ->saveSlugsTo('slug') ->preventOverwrite(); } ``` ### Using scopes If you have a global scope that should be taken into account, you can define this as well with `extraScope`. For example if you have a pages table containing pages of multiple websites and every website has it's own unique slugs. ```php public function getSlugOptions() : SlugOptions { return SlugOptions::create() ->generateSlugsFrom('name') ->saveSlugsTo('slug') ->extraScope(fn ($builder) => $builder->where('scope_id', $this->scope_id)); } ``` ### Setting the slug suffix starting index By default, suffix index starts from 1, you can set starting number. ```php public function getSlugOptions() : SlugOptions { return SlugOptions::create() ->generateSlugsFrom('name') ->saveSlugsTo('slug') ->startSlugSuffixFrom(2); } ``` ### Integration with laravel-translatable You can use this package along with [laravel-translatable](https://github.com/spatie/laravel-translatable) to generate a slug for each locale. Instead of using the `HasSlug` trait, you must use the `HasTranslatableSlug` trait, and add the name of the slug field to the `$translatable` array. For slugs that are generated from a single field _or_ multiple fields, you don't have to change anything else. ```php namespace App; use Spatie\Sluggable\HasTranslatableSlug; use Spatie\Sluggable\SlugOptions; use Spatie\Translatable\HasTranslations; use Illuminate\Database\Eloquent\Model; class YourEloquentModel extends Model { use HasTranslations, HasTranslatableSlug; public $translatable = ['name', 'slug']; /** * Get the options for generating the slug. */ public function getSlugOptions() : SlugOptions { return SlugOptions::create() ->generateSlugsFrom('name') ->saveSlugsTo('slug'); } } ``` For slugs that are generated from a callable, you need to instantiate the `SlugOptions` with the `createWithLocales` method. The callable now takes two arguments instead of one. Both the `$model` and the `$locale` are available to generate a slug from. ```php namespace App; use Spatie\Sluggable\HasTranslatableSlug; use Spatie\Sluggable\SlugOptions; use Spatie\Translatable\HasTranslations; use Illuminate\Database\Eloquent\Model; class YourEloquentModel extends Model { use HasTranslations, HasTranslatableSlug; public $translatable = ['name', 'slug']; /** * Get the options for generating the slug. */ public function getSlugOptions() : SlugOptions { return SlugOptions::createWithLocales(['en', 'nl']) ->generateSlugsFrom(function($model, $locale) { return "{$locale} {$model->id}"; }) ->saveSlugsTo('slug'); } } ``` #### Implicit route model binding You can also use Laravels [implicit route model binding](https://laravel.com/docs/8.x/routing#implicit-binding) inside your controller to automatically resolve the model. To use this feature, make sure that the slug column matches the `routeNameKey`. Currently, only some database types support JSON operations. Further information about which databases support JSON can be found in the [Laravel docs](https://laravel.com/docs/8.x/queries#json-where-clauses). ```php namespace App; use Spatie\Sluggable\HasSlug; use Spatie\Sluggable\SlugOptions; use Illuminate\Database\Eloquent\Model; class YourEloquentModel extends Model { use HasTranslations, HasTranslatableSlug; public $translatable = ['name', 'slug']; /** * Get the options for generating the slug. */ public function getSlugOptions() : SlugOptions { return SlugOptions::create() ->generateSlugsFrom('name') ->saveSlugsTo('slug'); } /** * Get the route key for the model. * * @return string */ public function getRouteKeyName() { return 'slug'; } } ``` ### Find models by slug For convenience, you can use the alias `findBySlug` to retrieve a model. The query will compare against the field passed to `saveSlugsTo` when defining the `SlugOptions`. ```php $model = Article::findBySlug('my-article'); ``` `findBySlug` also accepts a second parameter `$columns` just like the default Eloquent `find` method. ## Changelog Please see [CHANGELOG](CHANGELOG.md) for more information what has changed recently. ## Testing ``` bash composer test ``` ## Contributing Please see [CONTRIBUTING](https://github.com/spatie/.github/blob/main/CONTRIBUTING.md) for details. ## Security If you've found a bug regarding security please mail [security@spatie.be](mailto:security@spatie.be) instead of using the issue tracker. ## Credits - [Freek Van der Herten](https://github.com/freekmurze) - [All Contributors](../../contributors) ## License The MIT License (MIT). Please see [License File](LICENSE.md) for more information. PK �>�Zv?��/ / image/composer.jsonnu �[��� { "name": "spatie/image", "description": "Manipulate images with an expressive API", "keywords": [ "spatie", "image" ], "homepage": "https://github.com/spatie/image", "license": "MIT", "authors": [ { "name": "Freek Van der Herten", "email": "freek@spatie.be", "homepage": "https://spatie.be", "role": "Developer" } ], "require": { "php": "^8.0", "ext-exif": "*", "ext-mbstring": "*", "ext-json": "*", "league/glide": "^2.2.2", "spatie/image-optimizer": "^1.7", "spatie/temporary-directory": "^1.0|^2.0", "symfony/process": "^3.0|^4.0|^5.0|^6.0" }, "require-dev": { "pestphp/pest": "^1.22", "phpunit/phpunit": "^9.5", "symfony/var-dumper": "^4.0|^5.0|^6.0", "vimeo/psalm": "^4.6" }, "autoload": { "psr-4": { "Spatie\\Image\\": "src" } }, "autoload-dev": { "psr-4": { "Spatie\\Image\\Test\\": "tests" } }, "scripts": { "psalm": "vendor/bin/psalm", "test": "vendor/bin/pest" }, "config": { "sort-packages": true, "allow-plugins": { "pestphp/pest-plugin": true } } } PK �>�ZR��� � image/CHANGELOG.mdnu �[��� # Changelog All notable changes to `image` will be documented in this file ## 2.2.6 - 2023-05-06 ### What's Changed - Bump dependabot/fetch-metadata from 1.3.5 to 1.3.6 by @dependabot in https://github.com/spatie/image/pull/185 - Bump dependabot/fetch-metadata from 1.3.6 to 1.4.0 by @dependabot in https://github.com/spatie/image/pull/188 - Fit with only width or height by @gdebrauwer in https://github.com/spatie/image/pull/190 ### New Contributors - @dependabot made their first contribution in https://github.com/spatie/image/pull/185 - @gdebrauwer made their first contribution in https://github.com/spatie/image/pull/190 **Full Changelog**: https://github.com/spatie/image/compare/2.2.5...2.2.6 ## 2.2.5 - 2023-01-19 ### What's Changed - Refactor tests to pest by @AyoobMH in https://github.com/spatie/image/pull/176 - Add Dependabot Automation by @patinthehat in https://github.com/spatie/image/pull/177 - Add PHP 8.2 Support by @patinthehat in https://github.com/spatie/image/pull/180 - Update Dependabot Automation by @patinthehat in https://github.com/spatie/image/pull/181 - Add fill-max fit mode by @Tofandel in https://github.com/spatie/image/pull/183 ### New Contributors - @AyoobMH made their first contribution in https://github.com/spatie/image/pull/176 - @patinthehat made their first contribution in https://github.com/spatie/image/pull/177 - @Tofandel made their first contribution in https://github.com/spatie/image/pull/183 **Full Changelog**: https://github.com/spatie/image/compare/2.2.4...2.2.5 ## 2.2.4 - 2022-08-09 ### What's Changed - Add zero orientation support ignoring EXIF by @danielcastrobalbi in https://github.com/spatie/image/pull/171 ### New Contributors - @danielcastrobalbi made their first contribution in https://github.com/spatie/image/pull/171 **Full Changelog**: https://github.com/spatie/image/compare/2.2.3...2.2.4 ## 2.2.3 - 2022-05-21 ## What's Changed - Fix permission issue with temporary directory by @sebastianpopp in https://github.com/spatie/image/pull/163 ## New Contributors - @sebastianpopp made their first contribution in https://github.com/spatie/image/pull/163 **Full Changelog**: https://github.com/spatie/image/compare/2.2.2...2.2.3 ## 2.2.2 - 2022-02-22 - add TIFF support ## 1.11.0 - 2022-02-21 ## What's Changed - Fix docs link by @pascalbaljet in https://github.com/spatie/image/pull/154 - Update .gitattributes by @PaolaRuby in https://github.com/spatie/image/pull/158 - Add TIFF support by @Synchro in https://github.com/spatie/image/pull/159 ## New Contributors - @PaolaRuby made their first contribution in https://github.com/spatie/image/pull/158 **Full Changelog**: https://github.com/spatie/image/compare/2.2.1...1.11.0 ## 2.2.1 - 2021-12-17 ## What's Changed - Use match expression in convertToGlideParameter method by @mohprilaksono in https://github.com/spatie/image/pull/149 - [REF] updated fit docs description by @JeremyRed in https://github.com/spatie/image/pull/150 - Adding compatibility to Symfony 6 by @spackmat in https://github.com/spatie/image/pull/152 ## New Contributors - @mohprilaksono made their first contribution in https://github.com/spatie/image/pull/149 - @JeremyRed made their first contribution in https://github.com/spatie/image/pull/150 - @spackmat made their first contribution in https://github.com/spatie/image/pull/152 **Full Changelog**: https://github.com/spatie/image/compare/2.2.0...2.2.1 ## 2.2.0 - 2021-10-31 - add avif support (#148) ## 2.1.0 - 2021-07-15 - Drop support for PHP 7 - Make codebase more strict with type hinting ## 2.0.0 - 2021-07-15 - Bump league/glide to v2 [#134](https://github.com/spatie/image/pull/134) ## 1.10.4 - 2021-04-07 - Allow spatie/temporary-directory v2 ## 1.10.3 - 2021-03-10 - Bump league/glide to 2.0 [#123](https://github.com/spatie/image/pull/123) ## 1.10.2 - 2020-01-26 - change condition to delete $conversionResultDirectory (#118) ## 1.10.1 - 2020-12-27 - adds zoom option to focalCrop (#112) ## 1.9.0 - 2020-11-13 - allow usage of a custom `OptimizerChain` #110 ## 1.8.1 - 2020-11-12 - revert changes from 1.8.0 ## 1.8.0 - 2020-11-12 - allow usage of a custom `OptimizerChain` (#108) ## 1.7.7 - 2020-11-12 - add support for PHP 8 ## 1.7.6 - 2020-01-26 - change uppercase function to mb_strtoupper instead of strtoupper (#99) ## 1.7.5 - 2019-11-23 - allow symfony 5 components ## 1.7.4 - 2019-08-28 - do not export docs ## 1.7.3 - 2019-08-03 - fix duplicated files (fixes #84) ## 1.7.2 - 2019-05-13 - fixes `optimize()` when used with `apply()` (#78) ## 1.7.1 - 2019-04-17 - change GlideConversion sequence (#76) ## 1.7.0 - 2019-02-22 - add support for `webp` ## 1.6.0 - 2019-01-27 - add `setTemporaryDirectory` ## 1.5.3 - 2019-01-10 - update lower deps ## 1.5.2 - 2018-05-05 - fix exception message ## 1.5.1 - 2018-04-18 - Prevent error when trying to remove `/tmp` ## 1.5.0 - 2018-04-13 - add `flip` ## 1.4.2 - 2018-04-11 - Use the correct driver for getting widths and height of images. ## 1.4.1 - 2018-02-08 - Support symfony ^4.0 - Support phpunit ^7.0 ## 1.4.0 - 2017-12-05 - add `getWidth` and `getHeight` ## 1.3.5 - 2017-12-04 - fix for problems when creating directories in the temporary directory ## 1.3.4 - 2017-07-25 - fix `optimize` docblock ## 1.3.3 - 2017-07-11 - make `optimize` method fluent ## 1.3.2 - 2017-07-05 - swap out underlying optimization package ## 1.3.1 - 2017-07-02 - internally treat `optimize` as a manipulation ## 1.3.0 - 2017-07-02 - add `optimize` method ## 1.2.1 - 2017-06-29 - add methods to determine emptyness to `Manipulations` and `ManipulationSequence` ## 1.2.0 - 2017-04-17 - allow `Manipulations` to be constructed with an array of arrays ## 1.1.3 - 2017-04-07 - improve support for multi-volume systems ## 1.1.2 - 2017-04-04 - remove conversion directory after converting image ## 1.1.1 - 2017-03-17 - avoid processing empty manipulations groups ## 1.1.0 - 2017-02-06 - added support for watermarks ## 1.0.0 - 2017-02-06 - initial release PK �>�Z`;�9B B image/LICENSE.mdnu �[��� The MIT License (MIT) Copyright (c) Spatie bvba <info@spatie.be> 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. PK �>�Z�If� � image/src/Image.phpnu �[��� <?php namespace Spatie\Image; use BadMethodCallException; use Intervention\Image\ImageManagerStatic as InterventionImage; use Spatie\Image\Exceptions\InvalidImageDriver; use Spatie\ImageOptimizer\OptimizerChain; use Spatie\ImageOptimizer\OptimizerChainFactory; use Spatie\ImageOptimizer\Optimizers\BaseOptimizer; /** @mixin \Spatie\Image\Manipulations */ class Image { protected Manipulations $manipulations; protected string $imageDriver = 'gd'; protected ?string $temporaryDirectory = null; protected ?OptimizerChain $optimizerChain = null; public function __construct(protected string $pathToImage) { $this->manipulations = new Manipulations(); } public static function load(string $pathToImage): static { return new static($pathToImage); } public function setTemporaryDirectory($tempDir): static { $this->temporaryDirectory = $tempDir; return $this; } public function setOptimizeChain(OptimizerChain $optimizerChain): static { $this->optimizerChain = $optimizerChain; return $this; } /** * @param string $imageDriver * @return $this * @throws InvalidImageDriver */ public function useImageDriver(string $imageDriver): static { if (! in_array($imageDriver, ['gd', 'imagick'])) { throw InvalidImageDriver::driver($imageDriver); } $this->imageDriver = $imageDriver; InterventionImage::configure([ 'driver' => $this->imageDriver, ]); return $this; } public function manipulate(callable | Manipulations $manipulations): static { if (is_callable($manipulations)) { $manipulations($this->manipulations); } if ($manipulations instanceof Manipulations) { $this->manipulations->mergeManipulations($manipulations); } return $this; } public function __call($name, $arguments): static { if (! method_exists($this->manipulations, $name)) { throw new BadMethodCallException("Manipulation `{$name}` does not exist"); } $this->manipulations->$name(...$arguments); return $this; } public function getWidth(): int { return InterventionImage::make($this->pathToImage)->width(); } public function getHeight(): int { return InterventionImage::make($this->pathToImage)->height(); } public function getManipulationSequence(): ManipulationSequence { return $this->manipulations->getManipulationSequence(); } public function save(string $outputPath = ''): void { if ($outputPath === '') { $outputPath = $this->pathToImage; } $this->addFormatManipulation($outputPath); $glideConversion = GlideConversion::create($this->pathToImage)->useImageDriver($this->imageDriver); if (! is_null($this->temporaryDirectory)) { $glideConversion->setTemporaryDirectory($this->temporaryDirectory); } $glideConversion->performManipulations($this->manipulations); $glideConversion->save($outputPath); if ($this->shouldOptimize()) { $optimizerChainConfiguration = $this->manipulations->getFirstManipulationArgument('optimize'); $optimizerChainConfiguration = json_decode($optimizerChainConfiguration, true); $this->performOptimization($outputPath, $optimizerChainConfiguration); } } protected function shouldOptimize(): bool { return ! is_null($this->manipulations->getFirstManipulationArgument('optimize')); } protected function performOptimization($path, array $optimizerChainConfiguration): void { $optimizerChain = $this->optimizerChain ?? OptimizerChainFactory::create(); if (count($optimizerChainConfiguration)) { $existingOptimizers = $optimizerChain->getOptimizers(); $optimizers = array_map(function (array $optimizerOptions, string $optimizerClassName) use ($existingOptimizers) { $optimizer = array_values(array_filter($existingOptimizers, function ($optimizer) use ($optimizerClassName) { return $optimizer::class === $optimizerClassName; })); $optimizer = isset($optimizer[0]) && $optimizer[0] instanceof BaseOptimizer ? $optimizer[0] : new $optimizerClassName(); return $optimizer->setOptions($optimizerOptions)->setBinaryPath($optimizer->binaryPath); }, $optimizerChainConfiguration, array_keys($optimizerChainConfiguration)); $optimizerChain->setOptimizers($optimizers); } $optimizerChain->optimize($path); } protected function addFormatManipulation($outputPath): void { if ($this->manipulations->hasManipulation('format')) { return; } $inputExtension = strtolower(pathinfo($this->pathToImage, PATHINFO_EXTENSION)); $outputExtension = strtolower(pathinfo($outputPath, PATHINFO_EXTENSION)); if ($inputExtension === $outputExtension) { return; } $supportedFormats = [ Manipulations::FORMAT_JPG, Manipulations::FORMAT_PJPG, Manipulations::FORMAT_PNG, Manipulations::FORMAT_GIF, Manipulations::FORMAT_WEBP, Manipulations::FORMAT_AVIF, ]; //gd driver doesn't support TIFF if ($this->imageDriver === 'imagick') { $supportedFormats[] = Manipulations::FORMAT_TIFF; } if (in_array($outputExtension, $supportedFormats)) { $this->manipulations->format($outputExtension); } } } PK �>�Z��C� "