[增添]添加了datasource的setting数据库以及默认值
This commit is contained in:
15
vendor/spatie/color/.editorconfig
vendored
Normal file
15
vendor/spatie/color/.editorconfig
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
; 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
|
||||
3
vendor/spatie/color/.github/FUNDING.yml
vendored
Normal file
3
vendor/spatie/color/.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: spatie
|
||||
24
vendor/spatie/color/.github/workflows/php-cs-fixer.yml
vendored
Normal file
24
vendor/spatie/color/.github/workflows/php-cs-fixer.yml
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
name: Check & fix styling
|
||||
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
php-cs-fixer:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
ref: ${{ github.head_ref }}
|
||||
|
||||
- name: Run PHP CS Fixer
|
||||
uses: docker://oskarstark/php-cs-fixer-ga
|
||||
with:
|
||||
args: --config=.php_cs.dist.php --allow-risky=yes
|
||||
|
||||
- name: Commit changes
|
||||
uses: stefanzweifel/git-auto-commit-action@v4
|
||||
with:
|
||||
commit_message: Fix styling
|
||||
|
||||
36
vendor/spatie/color/.github/workflows/run-tests.yml
vendored
Normal file
36
vendor/spatie/color/.github/workflows/run-tests.yml
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
name: Tests
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: true
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest]
|
||||
php: [8.2, 8.1, 8.0, 7.4, 7.3]
|
||||
stability: [prefer-lowest, prefer-stable]
|
||||
|
||||
name: P${{ matrix.php }} - ${{ matrix.stability }} - ${{ matrix.os }}
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- 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, fileinfo
|
||||
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 update --${{ matrix.stability }} --prefer-dist --no-interaction
|
||||
|
||||
- name: Execute tests
|
||||
run: vendor/bin/pest
|
||||
28
vendor/spatie/color/.github/workflows/update-changelog.yml
vendored
Normal file
28
vendor/spatie/color/.github/workflows/update-changelog.yml
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
name: "Update Changelog"
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [released]
|
||||
|
||||
jobs:
|
||||
update:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
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
|
||||
40
vendor/spatie/color/.php_cs.dist.php
vendored
Normal file
40
vendor/spatie/color/.php_cs.dist.php
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
$finder = Symfony\Component\Finder\Finder::create()
|
||||
->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,
|
||||
'class_attributes_separation' => [
|
||||
'elements' => [
|
||||
'method' => 'one',
|
||||
],
|
||||
],
|
||||
'method_argument_space' => [
|
||||
'on_multiline' => 'ensure_fully_multiline',
|
||||
'keep_multiple_spaces_after_comma' => true,
|
||||
],
|
||||
'single_trait_insert_per_statement' => true,
|
||||
])
|
||||
->setFinder($finder);
|
||||
87
vendor/spatie/color/CHANGELOG.md
vendored
Normal file
87
vendor/spatie/color/CHANGELOG.md
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to `color` will be documented in this file
|
||||
|
||||
## 1.5.2 - 2022-06-24
|
||||
|
||||
### What's Changed
|
||||
|
||||
- Add RegEx fix to Validate.php too... by @jcogs-design in https://github.com/spatie/color/pull/73
|
||||
- Fix typo in Distance::CIE76. by @Angel5a in https://github.com/spatie/color/pull/76
|
||||
|
||||
### New Contributors
|
||||
|
||||
- @jcogs-design made their first contribution in https://github.com/spatie/color/pull/73
|
||||
- @Angel5a made their first contribution in https://github.com/spatie/color/pull/76
|
||||
|
||||
**Full Changelog**: https://github.com/spatie/color/compare/1.5.1...1.5.2
|
||||
|
||||
## 1.5.1 - 2022-04-12
|
||||
|
||||
## What's Changed
|
||||
|
||||
- Fix rgba opacity by @AstroCorp in https://github.com/spatie/color/pull/67
|
||||
|
||||
## New Contributors
|
||||
|
||||
- @AstroCorp made their first contribution in https://github.com/spatie/color/pull/67
|
||||
|
||||
**Full Changelog**: https://github.com/spatie/color/compare/1.5.0...1.5.1
|
||||
|
||||
## 1.4.0 - 2022-01-05
|
||||
|
||||
- Added support for PHP 8
|
||||
- Added support for CMYK & HSB
|
||||
- Added support for HEX alpha channel
|
||||
- Added support for 3-digit HEX values
|
||||
|
||||
## 1.3.1 - 2021-09-09
|
||||
|
||||
- Fix HEX/HSL conversion bug
|
||||
|
||||
## 1.3.0 - 2021-09-06
|
||||
|
||||
- Added CIELab and XYZ color formats and `Distance` API
|
||||
- Added `Contrast` API
|
||||
|
||||
## 1.2.4 - 2021-02-18
|
||||
|
||||
- Fixed division by zero error on pure white/black convertions ([#42](https://github.com/spatie/color/pull/42))
|
||||
|
||||
## 1.2.3 - 2020-12-10
|
||||
|
||||
- Added support for PHP 8
|
||||
|
||||
## 1.2.2 - 2020-11-18
|
||||
|
||||
- Fix transform RGB value to HSL : division by zero (#38)
|
||||
|
||||
## 1.2.1 - 2020-07-17
|
||||
|
||||
- HSL to RGB fixes
|
||||
|
||||
## 1.2.0 - 2020-06-22
|
||||
|
||||
- Added HSL & HSLA support
|
||||
|
||||
## 1.1.1 - 2017-02-03
|
||||
|
||||
- Fixed validation when a color contained redundant characters at the beginning or end of the string
|
||||
|
||||
## 1.1.0 - 2017-01-13
|
||||
|
||||
- All color formats now implement a `Color` interface
|
||||
- Added a `Factory` class with a `fromString` static method to guess a format
|
||||
- `rgb` and `rgba` values can now contain spaces (e.g. `rgb(255, 255, 255)`)
|
||||
|
||||
## 1.0.2 - 2016-10-17
|
||||
|
||||
- `rgbChannelToHexChannel` now also accepts single single-digit hex values
|
||||
|
||||
## 1.0.1 - 2016-09-22
|
||||
|
||||
- Bugfix (breaking!): Alpha channel values are now a float between 0 and 1
|
||||
|
||||
## 1.0.0 - 2016-09-21
|
||||
|
||||
- First release
|
||||
21
vendor/spatie/color/LICENSE.md
vendored
Normal file
21
vendor/spatie/color/LICENSE.md
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
# 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.
|
||||
286
vendor/spatie/color/README.md
vendored
Normal file
286
vendor/spatie/color/README.md
vendored
Normal file
@@ -0,0 +1,286 @@
|
||||
|
||||
[<img src="https://github-ads.s3.eu-central-1.amazonaws.com/support-ukraine.svg?t=1" />](https://supportukrainenow.org)
|
||||
|
||||
# A little library to handle color conversions and comparisons
|
||||
|
||||
[](https://packagist.org/packages/spatie/color)
|
||||
[](LICENSE.md)
|
||||
[](https://travis-ci.org/spatie/color)
|
||||
[](https://scrutinizer-ci.com/g/spatie/color)
|
||||
[](https://packagist.org/packages/spatie/color)
|
||||

|
||||
|
||||
A little library to handle color conversions and comparisons. Currently supports rgb, rgba, hex, hsl, hsla, CIELab, and xyz color formats as well as CIE76, CIE94, and CIEDE2000 color comparison algorithms.
|
||||
|
||||
```php
|
||||
$rgb = Rgb::fromString('rgb(55,155,255)');
|
||||
|
||||
echo $rgb->red(); // 55
|
||||
echo $rgb->green(); // 155
|
||||
echo $rgb->blue(); // 255
|
||||
|
||||
echo $rgb; // rgb(55,155,255)
|
||||
|
||||
$rgba = $rgb->toRgba(); // `Spatie\Color\Rgba`
|
||||
$rgba->alpha(); // 1
|
||||
echo $rgba; // rgba(55,155,255,1)
|
||||
|
||||
$hex = $rgb->toHex(); // `Spatie\Color\Hex`
|
||||
$rgba->alpha(); // ff
|
||||
echo $hex; // #379bff
|
||||
|
||||
$cmyk = $rgb->toCmyk(); // `Spatie\Color\Cmyk`
|
||||
echo $cmyk; // cmyk(78,39,0,0)
|
||||
|
||||
$hsl = $rgb->toHsl(); // `Spatie\Color\Hsl`
|
||||
echo $hsl; // hsl(210,100%,100%)
|
||||
|
||||
$hsb = $rgb->toHsb(); // `Spatie\Color\Hsb`
|
||||
echo $hsb; // hsl(210,78.4%,100%)
|
||||
|
||||
$lab = $rgb->toCIELab();
|
||||
echo $lab; // CIELab(62.91,5.34,-57.73)
|
||||
|
||||
$xyz = $rgb->toXyz();
|
||||
echo $xyz; // xyz(31.3469,31.4749,99.0308)
|
||||
|
||||
$hex2 = Hex::fromString('#2d78c8');
|
||||
|
||||
$ratio = Contrast::ratio(Hex::fromString('#f0fff0'), Hex::fromString('#191970'));
|
||||
echo $ratio; // 15.0
|
||||
|
||||
$cie76_distance = Distance::CIE76($rgb, $hex2);
|
||||
$cie76_distance = Distance::CIE76('rgba(55,155,255,1)', '#2d78c8'); // Outputs the same thing, Factory is built-in to all comparison functions
|
||||
echo $cie76_distance; // 55.89468042667388
|
||||
|
||||
$cie94_distance = Distance::CIE94($rgb, $hex2);
|
||||
echo $cie94_distance; // 13.49091942790753
|
||||
|
||||
$cie94_textiles_distance = Distance::CIE94($rgb, $hex2, 1); // Third parameter optionally sets the application type (0 = Graphic Arts [Default], 1 = Textiles)
|
||||
echo $cie94_textiles_distance; // 7.0926538068477
|
||||
|
||||
$ciede2000_distance = Distance::CIEDE2000($rgb, $hex2);
|
||||
echo $ciede2000_distance; // 12.711957696300898
|
||||
```
|
||||
|
||||
## Support us
|
||||
|
||||
[<img src="https://github-ads.s3.eu-central-1.amazonaws.com/color.jpg?t=1" width="419px" />](https://spatie.be/github-ad-click/color)
|
||||
|
||||
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/color
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
The `Color` package contains a separate class per color format, which each implement a `Color` interface.
|
||||
|
||||
There are seven classes which implement the `Color` interface:
|
||||
|
||||
- `CIELab`
|
||||
- `Cmyk`
|
||||
- `Hex`
|
||||
- `Hsb`
|
||||
- `Hsl`
|
||||
- `Hsla`
|
||||
- `Rgb`
|
||||
- `Rgba`
|
||||
- `Xyz`
|
||||
|
||||
### `interface Spatie\Color\Color`
|
||||
|
||||
#### `fromString(): Color`
|
||||
|
||||
Parses a color string and returns a `Color` implementation, depending on the format of the input string.
|
||||
|
||||
```php
|
||||
Hex::fromString('#000000');
|
||||
Rgba::fromString('rgba(255, 255, 255, 1)');
|
||||
Hsla::fromString('hsla(360, 100%, 100%, 1)');
|
||||
```
|
||||
|
||||
Throws an `InvalidColorValue` exception if the string can't be parsed.
|
||||
|
||||
> `Rgb`, `Rgba`, `Hsl` and `Hsla` strings are allowed to have spaces. `rgb(0,0,0)` is just as valid as `rgb(0, 0, 0)`.
|
||||
|
||||
#### `red(): int|string`
|
||||
|
||||
Return the value of the `red` color channel.
|
||||
|
||||
```php
|
||||
Hex::fromString('#ff0000')->red(); // 'ff'
|
||||
Rgb::fromString('rgb(255, 0, 0)')->red(); // 255
|
||||
```
|
||||
|
||||
#### `green(): int|string`
|
||||
|
||||
Return the value of the `green` color channel.
|
||||
|
||||
```php
|
||||
Hex::fromString('#00ff00')->green(); // 'ff'
|
||||
Rgb::fromString('rgb(0, 255, 0)')->green(); // 255
|
||||
```
|
||||
|
||||
#### `blue(): int|string`
|
||||
|
||||
Return the value of the `blue` color channel.
|
||||
|
||||
```php
|
||||
Hex::fromString('#0000ff')->blue(); // 'ff'
|
||||
Rgb::fromString('rgb(0, 0, 255)')->blue(); // 255
|
||||
```
|
||||
|
||||
#### `toCmyk(): Cmyk`
|
||||
|
||||
Convert a color to a `Cmyk` color.
|
||||
|
||||
```php
|
||||
Rgb::fromString('rgb(0, 0, 255)')->toCmyk();
|
||||
// `Cmyk` instance; 'cmyk(100,100,0,0)'
|
||||
```
|
||||
|
||||
#### `toHex(): Hex`
|
||||
|
||||
Convert a color to a `Hex` color.
|
||||
|
||||
```php
|
||||
Rgb::fromString('rgb(0, 0, 255)')->toHex();
|
||||
// `Hex` instance; '#0000ff'
|
||||
```
|
||||
|
||||
When coming from a color format that doesn't support opacity, it can be added by passing it to the `$alpha` parameter.
|
||||
|
||||
|
||||
#### `toHsb(): Hsb`
|
||||
|
||||
Convert a color to a `Hsb` color.
|
||||
|
||||
```php
|
||||
Rgb::fromString('rgb(0, 0, 255)')->toHsb();
|
||||
// `Hsl` instance; 'hsb(240, 100%, 100%)'
|
||||
```
|
||||
|
||||
#### `toHsl(): Hsl`
|
||||
|
||||
Convert a color to a `Hsl` color.
|
||||
|
||||
```php
|
||||
Rgb::fromString('rgb(0, 0, 255)')->toHsl();
|
||||
// `Hsl` instance; 'hsl(240, 100%, 50%)'
|
||||
```
|
||||
|
||||
When coming from a color format that supports opacity, the opacity will simply be omitted.
|
||||
|
||||
```php
|
||||
Rgba::fromString('rgba(0, 0, 255, .5)')->toHsl();
|
||||
// `Hsl` instance; 'hsl(240, 100%, 50%)'
|
||||
```
|
||||
|
||||
#### `toHsla(float $alpha = 1): Hsla`
|
||||
|
||||
Convert a color to a `Hsla` color.
|
||||
|
||||
```php
|
||||
Rgb::fromString('rgb(0, 0, 255)')->toHsla();
|
||||
// `Hsla` instance; 'hsla(240, 100%, 50%, 1.0)'
|
||||
```
|
||||
|
||||
When coming from a color format that doesn't support opacity, it can be added by passing it to the `$alpha` parameter.
|
||||
|
||||
```php
|
||||
Rgb::fromString('rgb(0, 0, 255)')->toHsla(.5);
|
||||
// `Hsla` instance; 'hsla(240, 100%, 50%, 0.5)'
|
||||
```
|
||||
|
||||
#### `toRgb(): Rgb`
|
||||
|
||||
Convert a color to an `Rgb` color.
|
||||
|
||||
```php
|
||||
Hex::fromString('#0000ff')->toRgb();
|
||||
// `Rgb` instance; 'rgb(0, 0, 255)'
|
||||
```
|
||||
|
||||
When coming from a color format that supports opacity, the opacity will simply be omitted.
|
||||
|
||||
```php
|
||||
Rgba::fromString('rgb(0, 0, 255, .5)')->toRgb();
|
||||
// `Rgb` instance; 'rgb(0, 0, 255)'
|
||||
```
|
||||
|
||||
#### `toRgba(float $alpha = 1): Rgba`
|
||||
|
||||
Convert a color to a `Rgba` color.
|
||||
|
||||
```php
|
||||
Rgb::fromString('rgb(0, 0, 255)')->toRgba();
|
||||
// `Rgba` instance; 'rgba(0, 0, 255, 1)'
|
||||
```
|
||||
|
||||
When coming from a color format that doesn't support opacity, it can be added by passing it to the `$alpha` parameter.
|
||||
|
||||
```php
|
||||
Rgba::fromString('rgb(0, 0, 255)')->toRgba(.5);
|
||||
// `Rgba` instance; 'rgba(0, 0, 255, .5)'
|
||||
```
|
||||
|
||||
#### `__toString(): string`
|
||||
|
||||
Cast the color to a string.
|
||||
|
||||
```php
|
||||
(string) Rgb::fromString('rgb(0, 0, 255)'); // 'rgb(0,0,255)'
|
||||
(string) Rgba::fromString('rgb(0, 0, 255, .5)'); // 'rgb(0,0,255,0.5)'
|
||||
(string) Hex::fromString('#0000ff'); // '#0000ff'
|
||||
(string) Hsla::fromString('hsl(240, 100%, 50%)'); // 'hsl(240, 100%, 50%)'
|
||||
(string) Hsla::fromString('hsla(240, 100%, 50%, 1.0)'); // 'hsla(240, 100%, 50%, 1.0)'
|
||||
```
|
||||
|
||||
### `Factory::fromString(): Color`
|
||||
|
||||
With the `Factory` class, you can create a color instance from any string (it does an educated guess under the hood). If the string isn't a valid color string in any format, it throws an `InvalidColorValue` exception.
|
||||
|
||||
```php
|
||||
Factory::fromString('rgb(0, 0, 255)'); // `Rgb` instance
|
||||
Factory::fromString('#0000ff'); // `Hex` instance
|
||||
Factory::fromString('hsl(240, 100%, 50%)'); // `Hsl` instance
|
||||
Factory::fromString('Hello world!'); // `InvalidColorValue` exception
|
||||
```
|
||||
|
||||
## 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
|
||||
|
||||
- [Sebastian De Deyne](https://github.com/sebastiandedeyne)
|
||||
- [All Contributors](../../contributors)
|
||||
|
||||
## About Spatie
|
||||
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).
|
||||
|
||||
## License
|
||||
|
||||
The MIT License (MIT). Please see [License File](LICENSE.md) for more information.
|
||||
46
vendor/spatie/color/composer.json
vendored
Normal file
46
vendor/spatie/color/composer.json
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
{
|
||||
"name": "spatie/color",
|
||||
"description": "A little library to handle color conversions",
|
||||
"keywords": [
|
||||
"spatie",
|
||||
"color",
|
||||
"conversion",
|
||||
"rgb"
|
||||
],
|
||||
"homepage": "https://github.com/spatie/color",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Sebastian De Deyne",
|
||||
"email": "sebastian@spatie.be",
|
||||
"homepage": "https://spatie.be",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php" : "^7.3|^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"pestphp/pest": "^1.22",
|
||||
"phpunit/phpunit": "^6.5||^9.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Spatie\\Color\\": "src"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Spatie\\Color\\Test\\": "tests"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"test": "vendor/bin/pest"
|
||||
},
|
||||
"config": {
|
||||
"sort-packages": true,
|
||||
"allow-plugins": {
|
||||
"pestphp/pest-plugin": true
|
||||
}
|
||||
}
|
||||
}
|
||||
127
vendor/spatie/color/src/CIELab.php
vendored
Normal file
127
vendor/spatie/color/src/CIELab.php
vendored
Normal file
@@ -0,0 +1,127 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\Color;
|
||||
|
||||
class CIELab implements Color
|
||||
{
|
||||
/** @var float */
|
||||
protected $l;
|
||||
protected $a;
|
||||
protected $b;
|
||||
|
||||
public function __construct(float $l, float $a, float $b)
|
||||
{
|
||||
Validate::CIELabValue($l, 'l');
|
||||
Validate::CIELabValue($a, 'a');
|
||||
Validate::CIELabValue($b, 'b');
|
||||
|
||||
$this->l = $l;
|
||||
$this->a = $a;
|
||||
$this->b = $b;
|
||||
}
|
||||
|
||||
public static function fromString(string $string)
|
||||
{
|
||||
Validate::CIELabColorString($string);
|
||||
|
||||
$matches = null;
|
||||
preg_match('/CIELab\( *(\d{1,3}\.?\d* *, *-?\d{1,3}\.?\d* *, *-?\d{1,3}\.?\d*) *\)/i', $string, $matches);
|
||||
|
||||
$channels = explode(',', $matches[1]);
|
||||
[$l, $a, $b] = array_map('trim', $channels);
|
||||
|
||||
return new static($l, $a, $b);
|
||||
}
|
||||
|
||||
public function l(): float
|
||||
{
|
||||
return $this->l;
|
||||
}
|
||||
|
||||
public function a(): float
|
||||
{
|
||||
return $this->a;
|
||||
}
|
||||
|
||||
public function b(): float
|
||||
{
|
||||
return $this->b;
|
||||
}
|
||||
|
||||
public function red(): int
|
||||
{
|
||||
$rgb = $this->toRgb();
|
||||
|
||||
return $rgb->red();
|
||||
}
|
||||
|
||||
public function blue(): int
|
||||
{
|
||||
$rgb = $this->toRgb();
|
||||
|
||||
return $rgb->blue();
|
||||
}
|
||||
|
||||
public function green(): int
|
||||
{
|
||||
$rgb = $this->toRgb();
|
||||
|
||||
return $rgb->green();
|
||||
}
|
||||
|
||||
public function toCIELab(): self
|
||||
{
|
||||
return new self($this->l, $this->a, $this->b);
|
||||
}
|
||||
|
||||
public function toCmyk(): Cmyk
|
||||
{
|
||||
return $this->toRgb()->toCmyk();
|
||||
}
|
||||
|
||||
public function toHex(string $alpha = 'ff'): Hex
|
||||
{
|
||||
return $this->toRgb()->toHex($alpha);
|
||||
}
|
||||
|
||||
public function toHsb(): Hsb
|
||||
{
|
||||
return $this->toRgb()->toHsb();
|
||||
}
|
||||
|
||||
public function toHsl(): Hsl
|
||||
{
|
||||
return $this->toRgb()->toHSL();
|
||||
}
|
||||
|
||||
public function toHsla(float $alpha = 1): Hsla
|
||||
{
|
||||
return $this->toRgb()->toHsla($alpha);
|
||||
}
|
||||
|
||||
public function toRgb(): Rgb
|
||||
{
|
||||
return $this->toXyz()->toRgb();
|
||||
}
|
||||
|
||||
public function toRgba(float $alpha = 1): Rgba
|
||||
{
|
||||
return $this->toRgb()->toRgba($alpha);
|
||||
}
|
||||
|
||||
public function toXyz(): Xyz
|
||||
{
|
||||
[$x, $y, $z] = Convert::CIELabValueToXyz(
|
||||
$this->l,
|
||||
$this->a,
|
||||
$this->b
|
||||
);
|
||||
|
||||
return new Xyz($x, $y, $z);
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return "CIELab({$this->l},{$this->a},{$this->b})";
|
||||
}
|
||||
}
|
||||
132
vendor/spatie/color/src/Cmyk.php
vendored
Normal file
132
vendor/spatie/color/src/Cmyk.php
vendored
Normal file
@@ -0,0 +1,132 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\Color;
|
||||
|
||||
class Cmyk implements Color
|
||||
{
|
||||
/** @var float */
|
||||
protected $cyan;
|
||||
protected $magenta;
|
||||
protected $yellow;
|
||||
protected $key;
|
||||
|
||||
public function __construct(float $cyan, float $magenta, float $yellow, float $key)
|
||||
{
|
||||
Validate::cmykValue($cyan, 'cyan');
|
||||
Validate::cmykValue($magenta, 'magenta');
|
||||
Validate::cmykValue($yellow, 'yellow');
|
||||
Validate::cmykValue($key, 'key (black)');
|
||||
|
||||
$this->cyan = $cyan;
|
||||
$this->magenta = $magenta;
|
||||
$this->yellow = $yellow;
|
||||
$this->key = $key;
|
||||
}
|
||||
|
||||
public static function fromString(string $string)
|
||||
{
|
||||
Validate::cmykColorString($string);
|
||||
|
||||
$matches = null;
|
||||
preg_match('/cmyk\( *(\d{1,3})%? *, *(\d{1,3})%? *, *(\d{1,3})%? *, *(\d{1,3})%? *\)/i', $string, $matches);
|
||||
|
||||
return new static($matches[1] / 100, $matches[2] / 100, $matches[3] / 100, $matches[4] / 100);
|
||||
}
|
||||
|
||||
public function red(): int
|
||||
{
|
||||
return Convert::cmykValueToRgb($this->cyan, $this->magenta, $this->yellow, $this->key)[0];
|
||||
}
|
||||
|
||||
public function green(): int
|
||||
{
|
||||
return Convert::cmykValueToRgb($this->cyan, $this->magenta, $this->yellow, $this->key)[1];
|
||||
}
|
||||
|
||||
public function blue(): int
|
||||
{
|
||||
return Convert::cmykValueToRgb($this->cyan, $this->magenta, $this->yellow, $this->key)[2];
|
||||
}
|
||||
|
||||
public function cyan(): float
|
||||
{
|
||||
return $this->cyan;
|
||||
}
|
||||
|
||||
public function magenta(): float
|
||||
{
|
||||
return $this->magenta;
|
||||
}
|
||||
|
||||
public function yellow(): float
|
||||
{
|
||||
return $this->yellow;
|
||||
}
|
||||
|
||||
public function key(): float
|
||||
{
|
||||
return $this->key;
|
||||
}
|
||||
|
||||
public function black(): float
|
||||
{
|
||||
return $this->key;
|
||||
}
|
||||
|
||||
public function toCmyk(): Cmyk
|
||||
{
|
||||
return new self($this->cyan, $this->magenta, $this->yellow, $this->key);
|
||||
}
|
||||
|
||||
public function toCIELab(): CIELab
|
||||
{
|
||||
return $this->toRgb()->toCIELab();
|
||||
}
|
||||
|
||||
public function toHex(string $alpha = 'ff'): Hex
|
||||
{
|
||||
return $this->toRgb()->toHex($alpha);
|
||||
}
|
||||
|
||||
public function toHsb(): Hsb
|
||||
{
|
||||
return $this->toRgb()->toHsb();
|
||||
}
|
||||
|
||||
public function toHsl(): Hsl
|
||||
{
|
||||
return $this->toRgb()->toHsl();
|
||||
}
|
||||
|
||||
public function toHsla(float $alpha = 1): Hsla
|
||||
{
|
||||
return $this->toRgb()->toHsla($alpha);
|
||||
}
|
||||
|
||||
public function toRgb(): Rgb
|
||||
{
|
||||
list($red, $green, $blue) = Convert::cmykValueToRgb($this->cyan, $this->magenta, $this->yellow, $this->key);
|
||||
|
||||
return new Rgb($red, $green, $blue);
|
||||
}
|
||||
|
||||
public function toRgba(float $alpha = 1): Rgba
|
||||
{
|
||||
return $this->toRgb()->toRgba($alpha);
|
||||
}
|
||||
|
||||
public function toXyz(): Xyz
|
||||
{
|
||||
return $this->toRgba()->toXyz();
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
$cyan = round($this->cyan * 100);
|
||||
$magenta = round($this->magenta * 100);
|
||||
$yellow = round($this->yellow * 100);
|
||||
$key = round($this->key * 100);
|
||||
|
||||
return "cmyk({$cyan}%,{$magenta}%,{$yellow}%,{$key}%)";
|
||||
}
|
||||
}
|
||||
34
vendor/spatie/color/src/Color.php
vendored
Normal file
34
vendor/spatie/color/src/Color.php
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\Color;
|
||||
|
||||
interface Color
|
||||
{
|
||||
public static function fromString(string $string);
|
||||
|
||||
public function red();
|
||||
|
||||
public function green();
|
||||
|
||||
public function blue();
|
||||
|
||||
public function toCIELab(): CIELab;
|
||||
|
||||
public function toHex(string $alpha = 'ff'): Hex;
|
||||
|
||||
public function toHsb(): Hsb;
|
||||
|
||||
public function toHsl(): Hsl;
|
||||
|
||||
public function toHsla(float $alpha = 1): Hsla;
|
||||
|
||||
public function toRgb(): Rgb;
|
||||
|
||||
public function toRgba(float $alpha = 1): Rgba;
|
||||
|
||||
public function toXyz(): Xyz;
|
||||
|
||||
public function toCmyk(): Cmyk;
|
||||
|
||||
public function __toString(): string;
|
||||
}
|
||||
33
vendor/spatie/color/src/Contrast.php
vendored
Normal file
33
vendor/spatie/color/src/Contrast.php
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\Color;
|
||||
|
||||
class Contrast
|
||||
{
|
||||
public static function ratio(Color $a, Color $b): float
|
||||
{
|
||||
if (! $a instanceof Hex) {
|
||||
$a = $a->toHex();
|
||||
}
|
||||
|
||||
if (! $b instanceof Hex) {
|
||||
$b = $b->toHex();
|
||||
}
|
||||
|
||||
$l1 =
|
||||
0.2126 * pow(hexdec($a->red()) / 255, 2.2) +
|
||||
0.7152 * pow(hexdec($a->green()) / 255, 2.2) +
|
||||
0.0722 * pow(hexdec($a->blue()) / 255, 2.2);
|
||||
|
||||
$l2 =
|
||||
0.2126 * pow(hexdec($b->red()) / 255, 2.2) +
|
||||
0.7152 * pow(hexdec($b->green()) / 255, 2.2) +
|
||||
0.0722 * pow(hexdec($b->blue()) / 255, 2.2);
|
||||
|
||||
if ($l1 > $l2) {
|
||||
return (int) (($l1 + 0.05) / ($l2 + 0.05));
|
||||
} else {
|
||||
return (int) (($l2 + 0.05) / ($l1 + 0.05));
|
||||
}
|
||||
}
|
||||
}
|
||||
389
vendor/spatie/color/src/Convert.php
vendored
Normal file
389
vendor/spatie/color/src/Convert.php
vendored
Normal file
@@ -0,0 +1,389 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\Color;
|
||||
|
||||
class Convert
|
||||
{
|
||||
public static function CIELabValueToXyz(float $l, float $a, float $b): array
|
||||
{
|
||||
$y = ($l + 16) / 116;
|
||||
$x = $a / 500 + $y;
|
||||
$z = $y - $b / 200;
|
||||
|
||||
if (pow($y, 3) > 0.008856) {
|
||||
$y = pow($y, 3);
|
||||
} else {
|
||||
$y = ($y - 16 / 116) / 7.787;
|
||||
}
|
||||
|
||||
if (pow($x, 3) > 0.008856) {
|
||||
$x = pow($x, 3);
|
||||
} else {
|
||||
$x = ($x - 16 / 116) / 7.787;
|
||||
}
|
||||
|
||||
if (pow($z, 3) > 0.008856) {
|
||||
$z = pow($z, 3);
|
||||
} else {
|
||||
$z = ($z - 16 / 116) / 7.787;
|
||||
}
|
||||
|
||||
$x = round(95.047 * $x, 4);
|
||||
$y = round(100.000 * $y, 4);
|
||||
$z = round(108.883 * $z, 4);
|
||||
|
||||
if ($x > 95.047) {
|
||||
$x = 95.047;
|
||||
}
|
||||
if ($y > 100) {
|
||||
$y = 100;
|
||||
}
|
||||
if ($z > 108.883) {
|
||||
$z = 108.883;
|
||||
}
|
||||
|
||||
return [$x, $y, $z];
|
||||
}
|
||||
|
||||
public static function cmykValueToRgb(float $cyan, float $magenta, float $yellow, float $key): array
|
||||
{
|
||||
return [
|
||||
(int) (255 * (1 - $cyan) * (1 - $key)),
|
||||
(int) (255 * (1 - $magenta) * (1 - $key)),
|
||||
(int) (255 * (1 - $yellow) * (1 - $key)),
|
||||
];
|
||||
}
|
||||
|
||||
public static function rgbValueToCmyk($red, $green, $blue): array
|
||||
{
|
||||
$red /= 255;
|
||||
$green /= 255;
|
||||
$blue /= 255;
|
||||
|
||||
$black = 1 - max($red, $green, $blue);
|
||||
$keyNeg = (1 - $black);
|
||||
|
||||
return [
|
||||
(1 - $red - $black) / ($keyNeg ?: 1),
|
||||
(1 - $green - $black) / ($keyNeg ?: 1),
|
||||
(1 - $blue - $black) / ($keyNeg ?: 1),
|
||||
$black,
|
||||
];
|
||||
}
|
||||
|
||||
public static function hexChannelToRgbChannel(string $hexValue): int
|
||||
{
|
||||
return hexdec($hexValue);
|
||||
}
|
||||
|
||||
public static function rgbChannelToHexChannel(int $rgbValue): string
|
||||
{
|
||||
return str_pad(dechex($rgbValue), 2, '0', STR_PAD_LEFT);
|
||||
}
|
||||
|
||||
public static function hsbValueToRgb($hue, $saturation, $brightness)
|
||||
{
|
||||
while ($hue > 360) {
|
||||
$hue -= 360.0;
|
||||
}
|
||||
while ($hue < 0) {
|
||||
$hue += 360.0;
|
||||
}
|
||||
|
||||
$hue /= 360;
|
||||
$saturation /= 100;
|
||||
$brightness /= 100;
|
||||
|
||||
if ($saturation == 0) {
|
||||
$R = $G = $B = $brightness * 255;
|
||||
} else {
|
||||
$hue = $hue * 6;
|
||||
$i = floor($hue);
|
||||
$j = $brightness * (1 - $saturation);
|
||||
$k = $brightness * (1 - $saturation * ($hue - $i));
|
||||
$l = $brightness * (1 - $saturation * (1 - ($hue - $i)));
|
||||
|
||||
switch ($i) {
|
||||
case 0:
|
||||
$red = $brightness;
|
||||
$green = $l;
|
||||
$blue = $j;
|
||||
|
||||
break;
|
||||
|
||||
case 1:
|
||||
$red = $k;
|
||||
$green = $brightness;
|
||||
$blue = $j;
|
||||
|
||||
break;
|
||||
|
||||
case 2:
|
||||
$red = $j;
|
||||
$green = $brightness;
|
||||
$blue = $l;
|
||||
|
||||
break;
|
||||
|
||||
case 3:
|
||||
$red = $j;
|
||||
$green = $k;
|
||||
$blue = $brightness;
|
||||
|
||||
break;
|
||||
|
||||
case 4:
|
||||
$red = $l;
|
||||
$green = $j;
|
||||
$blue = $brightness;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
$red = $brightness;
|
||||
$green = $j;
|
||||
$blue = $k;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
$R = $red * 255;
|
||||
$G = $green * 255;
|
||||
$B = $blue * 255;
|
||||
}
|
||||
|
||||
return [round($R), round($G), round($B)];
|
||||
}
|
||||
|
||||
public static function hslValueToRgb(float $hue, float $saturation, float $lightness): array
|
||||
{
|
||||
$h = intval((360 + (intval($hue) % 360)) % 360); // hue values can be less than 0 and greater than 360. This normalises them into the range 0-360.
|
||||
|
||||
$c = (1 - abs(2 * ($lightness / 100) - 1)) * ($saturation / 100);
|
||||
$x = $c * (1 - abs(fmod($h / 60, 2) - 1));
|
||||
$m = ($lightness / 100) - ($c / 2);
|
||||
|
||||
if ($h >= 0 && $h <= 60) {
|
||||
return [round(($c + $m) * 255), round(($x + $m) * 255), round($m * 255)];
|
||||
}
|
||||
|
||||
if ($h > 60 && $h <= 120) {
|
||||
return [round(($x + $m) * 255), round(($c + $m) * 255), round($m * 255)];
|
||||
}
|
||||
|
||||
if ($h > 120 && $h <= 180) {
|
||||
return [round($m * 255), round(($c + $m) * 255), round(($x + $m) * 255)];
|
||||
}
|
||||
|
||||
if ($h > 180 && $h <= 240) {
|
||||
return [round($m * 255), round(($x + $m) * 255), round(($c + $m) * 255)];
|
||||
}
|
||||
|
||||
if ($h > 240 && $h <= 300) {
|
||||
return [round(($x + $m) * 255), round($m * 255), round(($c + $m) * 255)];
|
||||
}
|
||||
|
||||
if ($h > 300 && $h <= 360) {
|
||||
return [round(($c + $m) * 255), round($m * 255), round(($x + $m) * 255)];
|
||||
}
|
||||
}
|
||||
|
||||
public static function rgbValueToHsb($red, $green, $blue): array
|
||||
{
|
||||
$red /= 255;
|
||||
$green /= 255;
|
||||
$blue /= 255;
|
||||
|
||||
$min = min($red, $green, $blue);
|
||||
$max = max($red, $green, $blue);
|
||||
$delMax = $max - $min;
|
||||
|
||||
$brightness = $max;
|
||||
$hue = 0;
|
||||
|
||||
if ($delMax == 0) {
|
||||
$hue = 0;
|
||||
$saturation = 0;
|
||||
} else {
|
||||
$saturation = $delMax / $max;
|
||||
|
||||
$delR = ((($max - $red) / 6) + ($delMax / 2)) / $delMax;
|
||||
$delG = ((($max - $green) / 6) + ($delMax / 2)) / $delMax;
|
||||
$delB = ((($max - $blue) / 6) + ($delMax / 2)) / $delMax;
|
||||
|
||||
if ($red == $max) {
|
||||
$hue = $delB - $delG;
|
||||
} else {
|
||||
if ($green == $max) {
|
||||
$hue = (1 / 3) + $delR - $delB;
|
||||
} else {
|
||||
if ($blue == $max) {
|
||||
$hue = (2 / 3) + $delG - $delR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($hue < 0) {
|
||||
$hue++;
|
||||
}
|
||||
if ($hue > 1) {
|
||||
$hue--;
|
||||
}
|
||||
}
|
||||
|
||||
return [round($hue, 2) * 360, round($saturation, 2) * 100, round($brightness, 2) * 100];
|
||||
}
|
||||
|
||||
public static function rgbValueToHsl($red, $green, $blue): array
|
||||
{
|
||||
$r = $red / 255;
|
||||
$g = $green / 255;
|
||||
$b = $blue / 255;
|
||||
|
||||
$cmax = max($r, $g, $b);
|
||||
$cmin = min($r, $g, $b);
|
||||
$delta = $cmax - $cmin;
|
||||
|
||||
$hue = 0;
|
||||
if ($delta != 0) {
|
||||
if ($r === $cmax) {
|
||||
$hue = 60 * fmod(($g - $b) / $delta, 6);
|
||||
$hue = $hue < 0 ? $hue + 360 : $hue ;
|
||||
}
|
||||
|
||||
if ($g === $cmax) {
|
||||
$hue = 60 * ((($b - $r) / $delta) + 2);
|
||||
}
|
||||
|
||||
if ($b === $cmax) {
|
||||
$hue = 60 * ((($r - $g) / $delta) + 4);
|
||||
}
|
||||
}
|
||||
|
||||
$lightness = ($cmax + $cmin) / 2;
|
||||
|
||||
$saturation = 0;
|
||||
|
||||
if ($lightness > 0 && $lightness < 1) {
|
||||
$saturation = $delta / (1 - abs((2 * $lightness) - 1));
|
||||
}
|
||||
|
||||
return [$hue, min($saturation, 1) * 100, min($lightness, 1) * 100];
|
||||
}
|
||||
|
||||
public static function rgbValueToXyz($red, $green, $blue): array
|
||||
{
|
||||
$red = $red / 255;
|
||||
$green = $green / 255;
|
||||
$blue = $blue / 255;
|
||||
|
||||
if ($red > 0.04045) {
|
||||
$red = pow((($red + 0.055) / 1.055), 2.4);
|
||||
} else {
|
||||
$red = $red / 12.92;
|
||||
}
|
||||
|
||||
if ($green > 0.04045) {
|
||||
$green = pow((($green + 0.055) / 1.055), 2.4);
|
||||
} else {
|
||||
$green = $green / 12.92;
|
||||
}
|
||||
|
||||
if ($blue > 0.04045) {
|
||||
$blue = pow((($blue + 0.055) / 1.055), 2.4);
|
||||
} else {
|
||||
$blue = $blue / 12.92;
|
||||
}
|
||||
|
||||
$red = $red * 100;
|
||||
$green = $green * 100;
|
||||
$blue = $blue * 100;
|
||||
$x = round($red * 0.4124 + $green * 0.3576 + $blue * 0.1805, 4);
|
||||
$y = round($red * 0.2126 + $green * 0.7152 + $blue * 0.0722, 4);
|
||||
$z = round($red * 0.0193 + $green * 0.1192 + $blue * 0.9505, 4);
|
||||
|
||||
if ($x > 95.047) {
|
||||
$x = 95.047;
|
||||
}
|
||||
if ($y > 100) {
|
||||
$y = 100;
|
||||
}
|
||||
if ($z > 108.883) {
|
||||
$z = 108.883;
|
||||
}
|
||||
|
||||
return [$x, $y, $z];
|
||||
}
|
||||
|
||||
public static function xyzValueToCIELab(float $x, float $y, float $z): array
|
||||
{
|
||||
$x = $x / 95.047;
|
||||
$y = $y / 100.000;
|
||||
$z = $z / 108.883;
|
||||
|
||||
if ($x > 0.008856) {
|
||||
$x = pow($x, 1 / 3);
|
||||
} else {
|
||||
$x = (7.787 * $x) + (16 / 116);
|
||||
}
|
||||
|
||||
if ($y > 0.008856) {
|
||||
$y = pow($y, 1 / 3);
|
||||
} else {
|
||||
$y = (7.787 * $y) + (16 / 116);
|
||||
}
|
||||
|
||||
if ($y > 0.008856) {
|
||||
$l = (116 * $y) - 16;
|
||||
} else {
|
||||
$l = 903.3 * $y;
|
||||
}
|
||||
|
||||
if ($z > 0.008856) {
|
||||
$z = pow($z, 1 / 3);
|
||||
} else {
|
||||
$z = (7.787 * $z) + (16 / 116);
|
||||
}
|
||||
|
||||
$l = round($l, 2);
|
||||
$a = round(500 * ($x - $y), 2);
|
||||
$b = round(200 * ($y - $z), 2);
|
||||
|
||||
return [$l, $a, $b];
|
||||
}
|
||||
|
||||
public static function xyzValueToRgb(float $x, float $y, float $z): array
|
||||
{
|
||||
$x = $x / 100;
|
||||
$y = $y / 100;
|
||||
$z = $z / 100;
|
||||
|
||||
$r = $x * 3.2406 + $y * -1.5372 + $z * -0.4986;
|
||||
$g = $x * -0.9689 + $y * 1.8758 + $z * 0.0415;
|
||||
$b = $x * 0.0557 + $y * -0.2040 + $z * 1.0570;
|
||||
|
||||
if ($r > 0.0031308) {
|
||||
$r = 1.055 * pow($r, (1 / 2.4)) - 0.055;
|
||||
} else {
|
||||
$r = 12.92 * $r;
|
||||
}
|
||||
|
||||
if ($g > 0.0031308) {
|
||||
$g = 1.055 * pow($g, (1 / 2.4)) - 0.055;
|
||||
} else {
|
||||
$g = 12.92 * $g;
|
||||
}
|
||||
|
||||
if ($b > 0.0031308) {
|
||||
$b = 1.055 * pow($b, (1 / 2.4)) - 0.055;
|
||||
} else {
|
||||
$b = 12.92 * $b;
|
||||
}
|
||||
|
||||
$r = intval(max(0, min(255, $r * 255)));
|
||||
$g = intval(max(0, min(255, $g * 255)));
|
||||
$b = intval(max(0, min(255, $b * 255)));
|
||||
|
||||
return [$r, $g, $b];
|
||||
}
|
||||
}
|
||||
155
vendor/spatie/color/src/Distance.php
vendored
Normal file
155
vendor/spatie/color/src/Distance.php
vendored
Normal file
@@ -0,0 +1,155 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\Color;
|
||||
|
||||
class Distance
|
||||
{
|
||||
public static function CIE76($color1, $color2): float
|
||||
{
|
||||
if (gettype($color1) === 'string') {
|
||||
$color1 = Factory::fromString($color1);
|
||||
}
|
||||
|
||||
if (gettype($color2) === 'string') {
|
||||
$color2 = Factory::fromString($color2);
|
||||
}
|
||||
|
||||
$lab1 = $color1->toCIELab();
|
||||
$lab2 = $color2->toCIELab();
|
||||
|
||||
if (strval($lab1) === strval($lab2)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$sum = 0;
|
||||
$sum += pow($lab1->l() - $lab2->l(), 2);
|
||||
$sum += pow($lab1->a() - $lab2->a(), 2);
|
||||
$sum += pow($lab1->b() - $lab2->b(), 2);
|
||||
|
||||
return max(min(sqrt($sum), 100), 0);
|
||||
}
|
||||
|
||||
public static function CIE94($color1, $color2, $textiles = 0): float
|
||||
{
|
||||
if (gettype($color1) === 'string') {
|
||||
$color1 = Factory::fromString($color1);
|
||||
}
|
||||
|
||||
if (gettype($color2) === 'string') {
|
||||
$color2 = Factory::fromString($color2);
|
||||
}
|
||||
|
||||
$lab1 = $color1->toCIELab();
|
||||
$lab2 = $color2->toCIELab();
|
||||
|
||||
$l1 = $lab1->l();
|
||||
$a1 = $lab1->a();
|
||||
$b1 = $lab1->b();
|
||||
|
||||
$l2 = $lab2->l();
|
||||
$a2 = $lab2->a();
|
||||
$b2 = $lab2->b();
|
||||
|
||||
$delta_l = $l1 - $l2;
|
||||
$delta_a = $a1 - $a2;
|
||||
$delta_b = $b1 - $b2;
|
||||
|
||||
$c1 = sqrt(pow($a1, 2) + pow($b1, 2));
|
||||
$c2 = sqrt(pow($a2, 2) + pow($b2, 2));
|
||||
$delta_c = $c1 - $c2;
|
||||
|
||||
$delta_h = pow($delta_a, 2) + pow($delta_b, 2) - pow($delta_c, 2);
|
||||
$delta_h = $delta_h < 0 ? 0 : sqrt($delta_h);
|
||||
|
||||
if ($textiles) {
|
||||
$kl = 2.0;
|
||||
$k1 = .048;
|
||||
$k2 = .014;
|
||||
} else {
|
||||
$kl = 1.0;
|
||||
$k1 = .045;
|
||||
$k2 = .015;
|
||||
}
|
||||
|
||||
$sc = 1.0 + $k1 * $c1;
|
||||
$sh = 1.0 + $k2 * $c1;
|
||||
|
||||
$i = pow($delta_l / $kl, 2) + pow($delta_c / $sc, 2) + pow($delta_h / $sh, 2);
|
||||
|
||||
return $i < 0 ? 0 : sqrt($i);
|
||||
}
|
||||
|
||||
public static function CIEDE2000($color1, $color2): float
|
||||
{
|
||||
if (gettype($color1) === 'string') {
|
||||
$color1 = Factory::fromString($color1);
|
||||
}
|
||||
|
||||
if (gettype($color2) === 'string') {
|
||||
$color2 = Factory::fromString($color2);
|
||||
}
|
||||
|
||||
$lab1 = $color1->toCIELab();
|
||||
$lab2 = $color2->toCIELab();
|
||||
|
||||
$l1 = $lab1->l();
|
||||
$a1 = $lab1->a();
|
||||
$b1 = $lab1->b();
|
||||
|
||||
$l2 = $lab2->l();
|
||||
$a2 = $lab2->a();
|
||||
$b2 = $lab2->b();
|
||||
|
||||
$avg_lp = ($l1 + $l2) / 2;
|
||||
$c1 = sqrt(pow($a1, 2) + pow($b1, 2));
|
||||
$c2 = sqrt(pow($a2, 2) + pow($b2, 2));
|
||||
$avg_c = ($c1 + $c2) / 2;
|
||||
$g = (1 - sqrt(pow($avg_c, 7) / (pow($avg_c, 7) + pow(25, 7)))) / 2;
|
||||
$a1p = $a1 * (1 + $g);
|
||||
$a2p = $a2 * (1 + $g);
|
||||
$c1p = sqrt(pow($a1p, 2) + pow($b1, 2));
|
||||
$c2p = sqrt(pow($a2p, 2) + pow($b2, 2));
|
||||
$avg_cp = ($c1p + $c2p) / 2;
|
||||
$h1p = rad2deg(atan2($b1, $a1p));
|
||||
|
||||
if ($h1p < 0) {
|
||||
$h1p += 360;
|
||||
}
|
||||
|
||||
$h2p = rad2deg(atan2($b2, $a2p));
|
||||
|
||||
if ($h2p < 0) {
|
||||
$h2p += 360;
|
||||
}
|
||||
|
||||
$avg_hp = abs($h1p - $h2p) > 180 ? ($h1p + $h2p + 360) / 2 : ($h1p + $h2p) / 2;
|
||||
$t = 1 - 0.17 * cos(deg2rad($avg_hp - 30)) + 0.24 * cos(deg2rad(2 * $avg_hp)) + 0.32 * cos(deg2rad(3 * $avg_hp + 6)) - 0.2 * cos(deg2rad(4 * $avg_hp - 63));
|
||||
$delta_hp = $h2p - $h1p;
|
||||
|
||||
if (abs($delta_hp) > 180) {
|
||||
if ($h2p <= $h1p) {
|
||||
$delta_hp += 360;
|
||||
} else {
|
||||
$delta_hp -= 360;
|
||||
}
|
||||
}
|
||||
|
||||
$delta_lp = $l2 - $l1;
|
||||
$delta_cp = $c2p - $c1p;
|
||||
$delta_hp = 2 * sqrt($c1p * $c2p) * sin(deg2rad($delta_hp) / 2);
|
||||
|
||||
$s_l = 1 + ((0.015 * pow($avg_lp - 50, 2)) / sqrt(20 + pow($avg_lp - 50, 2)));
|
||||
$s_c = 1 + 0.045 * $avg_cp;
|
||||
$s_h = 1 + 0.015 * $avg_cp * $t;
|
||||
|
||||
$delta_ro = 30 * exp(-(pow(($avg_hp - 275) / 25, 2)));
|
||||
$r_c = 2 * sqrt(pow($avg_cp, 7) / (pow($avg_cp, 7) + pow(25, 7)));
|
||||
$r_t = -$r_c * sin(2 * deg2rad($delta_ro));
|
||||
|
||||
$kl = $kc = $kh = 1;
|
||||
|
||||
$delta_e = sqrt(pow($delta_lp / ($s_l * $kl), 2) + pow($delta_cp / ($s_c * $kc), 2) + pow($delta_hp / ($s_h * $kh), 2) + $r_t * ($delta_cp / ($s_c * $kc)) * ($delta_hp / ($s_h * $kh)));
|
||||
|
||||
return $delta_e;
|
||||
}
|
||||
}
|
||||
100
vendor/spatie/color/src/Exceptions/InvalidColorValue.php
vendored
Normal file
100
vendor/spatie/color/src/Exceptions/InvalidColorValue.php
vendored
Normal file
@@ -0,0 +1,100 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\Color\Exceptions;
|
||||
|
||||
use Exception;
|
||||
|
||||
class InvalidColorValue extends Exception
|
||||
{
|
||||
public static function CIELabValueNotInRange(float $value, string $name, float $min, float $max): self
|
||||
{
|
||||
return new static("CIELab value `{$name}` must be a number between $min and $max");
|
||||
}
|
||||
|
||||
public static function rgbChannelValueNotInRange(int $value, string $channel): self
|
||||
{
|
||||
return new static("An rgb values must be an integer between 0 and 255, `{$value}` provided for channel {$channel}.");
|
||||
}
|
||||
|
||||
public static function alphaChannelValueNotInRange(float $value): self
|
||||
{
|
||||
return new static("An alpha values must be a float between 0 and 1, `{$value}` provided.");
|
||||
}
|
||||
|
||||
public static function hexChannelValueHasInvalidLength(string $value): self
|
||||
{
|
||||
$length = strlen($value);
|
||||
|
||||
return new static("Hex values must contain exactly 2 characters, `{$value}` contains {$length} characters.");
|
||||
}
|
||||
|
||||
public static function malformedCIELabColorString(string $string): self
|
||||
{
|
||||
return new static("CIELab color string `{$string}` is malformed. A CIELab color contains 3 comma separated values, wrapped in `CIELab()`, e.g. `CIELab(62.91,5.34,-57.73)`.");
|
||||
}
|
||||
|
||||
public static function cmykValueNotInRange(float $value, string $name): self
|
||||
{
|
||||
return new static("Cmyk value `{$name}` must be a number between 0 and 1");
|
||||
}
|
||||
|
||||
public static function hexValueContainsInvalidCharacters(string $value): self
|
||||
{
|
||||
return new static("Hex values can only contain numbers or letters from A-F, `{$value}` contains invalid characters.");
|
||||
}
|
||||
|
||||
public static function hsbValueNotInRange(float $value, string $name): self
|
||||
{
|
||||
return new static("Hsb value `{$name}` must be a number between 0 and 100");
|
||||
}
|
||||
|
||||
public static function hslValueNotInRange(float $value, string $name): self
|
||||
{
|
||||
return new static("Hsl value `{$name}` must be a number between 0 and 100");
|
||||
}
|
||||
|
||||
public static function malformedCmykColorString(string $string): self
|
||||
{
|
||||
return new static("Cmyk color string `{$string}` is malformed. A cmyk color contains cyan, magenta, yellow and key (black) values, wrapped in `cmyk()`, e.g. `cmyk(100%,100%,100%,100%)`.");
|
||||
}
|
||||
|
||||
public static function malformedHexColorString(string $string): self
|
||||
{
|
||||
return new static("Hex color string `{$string}` is malformed. A hex color string starts with a `#` and contains exactly six characters, e.g. `#aabbcc`.");
|
||||
}
|
||||
|
||||
public static function malformedHslColorString(string $string): self
|
||||
{
|
||||
return new static("Hsl color string `{$string}` is malformed. An hsl color contains hue, saturation, and lightness values, wrapped in `hsl()`, e.g. `hsl(300,10%,50%)`.");
|
||||
}
|
||||
|
||||
public static function malformedHslaColorString(string $string): self
|
||||
{
|
||||
return new static("Hsla color string `{$string}` is malformed. An hsla color contains hue, saturation, lightness and alpha values, wrapped in `hsl()`, e.g. `hsl(300,10%,50%,0.25)`.");
|
||||
}
|
||||
|
||||
public static function malformedRgbColorString(string $string): self
|
||||
{
|
||||
return new static("Rgb color string `{$string}` is malformed. An rgb color contains 3 comma separated values between 0 and 255, wrapped in `rgb()`, e.g. `rgb(0,0,255)`.");
|
||||
}
|
||||
|
||||
public static function malformedRgbaColorString(string $string): self
|
||||
{
|
||||
return new static("Rgba color string `{$string}` is malformed. An rgba color contains 3 comma separated values between 0 and 255 with an alpha value between 0 and 1, wrapped in `rgba()`, e.g. `rgb(0,0,255,0.5)`.");
|
||||
}
|
||||
|
||||
public static function malformedColorString(string $string): self
|
||||
{
|
||||
return new static("Color string `{$string}` doesn't match any of the available colors.");
|
||||
}
|
||||
|
||||
public static function malformedXyzColorString(string $string): self
|
||||
{
|
||||
return new static("Xyz color string `{$string}` is malformed. An xyz color contains 3 comma separated values, wrapped in `xyz()`, e.g. `xyz(31.3469,31.4749,99.0308)`.");
|
||||
}
|
||||
|
||||
public static function xyzValueNotInRange(float $value, string $name, float $min, float $max): self
|
||||
{
|
||||
return new static("Xyz value `{$name}` must be a number between $min and $max");
|
||||
}
|
||||
}
|
||||
38
vendor/spatie/color/src/Factory.php
vendored
Normal file
38
vendor/spatie/color/src/Factory.php
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\Color;
|
||||
|
||||
use Spatie\Color\Exceptions\InvalidColorValue;
|
||||
|
||||
class Factory
|
||||
{
|
||||
public static function fromString(string $string): Color
|
||||
{
|
||||
$colorClasses = static::getColorClasses();
|
||||
|
||||
foreach ($colorClasses as $colorClass) {
|
||||
try {
|
||||
return $colorClass::fromString($string);
|
||||
} catch (InvalidColorValue $e) {
|
||||
// Catch the exception but never throw it.
|
||||
}
|
||||
}
|
||||
|
||||
throw InvalidColorValue::malformedColorString($string);
|
||||
}
|
||||
|
||||
protected static function getColorClasses(): array
|
||||
{
|
||||
return [
|
||||
CIELab::class,
|
||||
Cmyk::class,
|
||||
Hex::class,
|
||||
Hsb::class,
|
||||
Hsl::class,
|
||||
Hsla::class,
|
||||
Rgb::class,
|
||||
Rgba::class,
|
||||
Xyz::class,
|
||||
];
|
||||
}
|
||||
}
|
||||
152
vendor/spatie/color/src/Hex.php
vendored
Normal file
152
vendor/spatie/color/src/Hex.php
vendored
Normal file
@@ -0,0 +1,152 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\Color;
|
||||
|
||||
class Hex implements Color
|
||||
{
|
||||
/** @var string */
|
||||
protected $red;
|
||||
protected $green;
|
||||
protected $blue;
|
||||
protected $alpha = 'ff';
|
||||
|
||||
public function __construct(string $red, string $green, string $blue, string $alpha = 'ff')
|
||||
{
|
||||
Validate::hexChannelValue($red, 'red');
|
||||
Validate::hexChannelValue($green, 'green');
|
||||
Validate::hexChannelValue($blue, 'blue');
|
||||
Validate::hexChannelValue($alpha, 'alpha');
|
||||
|
||||
$this->red = strtolower($red);
|
||||
$this->green = strtolower($green);
|
||||
$this->blue = strtolower($blue);
|
||||
$this->alpha = strtolower($alpha);
|
||||
}
|
||||
|
||||
public static function fromString(string $string)
|
||||
{
|
||||
Validate::hexColorString($string);
|
||||
|
||||
$string = ltrim($string, '#');
|
||||
|
||||
switch (strlen($string)) {
|
||||
case 3:
|
||||
[$red, $green, $blue] = str_split($string);
|
||||
$red .= $red;
|
||||
$green .= $green;
|
||||
$blue .= $blue;
|
||||
$alpha = 'ff';
|
||||
|
||||
break;
|
||||
|
||||
case 4:
|
||||
[$red, $green, $blue, $alpha] = str_split($string);
|
||||
$red .= $red;
|
||||
$green .= $green;
|
||||
$blue .= $blue;
|
||||
$alpha .= $alpha;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
case 6:
|
||||
[$red, $green, $blue] = str_split($string, 2);
|
||||
$alpha = 'ff';
|
||||
|
||||
break;
|
||||
|
||||
case 8:
|
||||
[$red, $green, $blue, $alpha] = str_split($string, 2);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return new static($red, $green, $blue, $alpha);
|
||||
}
|
||||
|
||||
public function red(): string
|
||||
{
|
||||
return $this->red;
|
||||
}
|
||||
|
||||
public function green(): string
|
||||
{
|
||||
return $this->green;
|
||||
}
|
||||
|
||||
public function blue(): string
|
||||
{
|
||||
return $this->blue;
|
||||
}
|
||||
|
||||
public function alpha(): string
|
||||
{
|
||||
return $this->alpha;
|
||||
}
|
||||
|
||||
public function toCIELab(): CIELab
|
||||
{
|
||||
return $this->toRgb()->toCIELab();
|
||||
}
|
||||
|
||||
public function toCmyk(): Cmyk
|
||||
{
|
||||
return $this->toRgb()->toCmyk();
|
||||
}
|
||||
|
||||
public function toHex(string $alpha = 'ff'): self
|
||||
{
|
||||
return new self($this->red, $this->green, $this->blue, $alpha);
|
||||
}
|
||||
|
||||
public function toHsb(): Hsb
|
||||
{
|
||||
return $this->toRgb()->toHsb();
|
||||
}
|
||||
|
||||
public function toHsl(): Hsl
|
||||
{
|
||||
[$hue, $saturation, $lightness] = Convert::rgbValueToHsl(
|
||||
Convert::hexChannelToRgbChannel($this->red),
|
||||
Convert::hexChannelToRgbChannel($this->green),
|
||||
Convert::hexChannelToRgbChannel($this->blue)
|
||||
);
|
||||
|
||||
return new Hsl($hue, $saturation, $lightness);
|
||||
}
|
||||
|
||||
public function toHsla(float $alpha = 1): Hsla
|
||||
{
|
||||
[$hue, $saturation, $lightness] = Convert::rgbValueToHsl(
|
||||
Convert::hexChannelToRgbChannel($this->red),
|
||||
Convert::hexChannelToRgbChannel($this->green),
|
||||
Convert::hexChannelToRgbChannel($this->blue)
|
||||
);
|
||||
|
||||
return new Hsla($hue, $saturation, $lightness, $alpha);
|
||||
}
|
||||
|
||||
public function toRgb(): Rgb
|
||||
{
|
||||
return new Rgb(
|
||||
Convert::hexChannelToRgbChannel($this->red),
|
||||
Convert::hexChannelToRgbChannel($this->green),
|
||||
Convert::hexChannelToRgbChannel($this->blue)
|
||||
);
|
||||
}
|
||||
|
||||
public function toRgba(float $alpha = 1): Rgba
|
||||
{
|
||||
return $this->toRgb()->toRgba($alpha);
|
||||
}
|
||||
|
||||
public function toXyz(): Xyz
|
||||
{
|
||||
return $this->toRgb()->toXyz();
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return "#{$this->red}{$this->green}{$this->blue}" . ($this->alpha !== 'ff' ? $this->alpha : '');
|
||||
}
|
||||
}
|
||||
121
vendor/spatie/color/src/Hsb.php
vendored
Normal file
121
vendor/spatie/color/src/Hsb.php
vendored
Normal file
@@ -0,0 +1,121 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\Color;
|
||||
|
||||
class Hsb implements Color
|
||||
{
|
||||
/** @var float */
|
||||
protected $hue;
|
||||
protected $saturation;
|
||||
protected $brightness;
|
||||
|
||||
public function __construct(float $hue, float $saturation, float $brightness)
|
||||
{
|
||||
Validate::hsbValue($hue, 'hue');
|
||||
Validate::hsbValue($saturation, 'saturation');
|
||||
Validate::hsbValue($brightness, 'brightness');
|
||||
|
||||
$this->hue = $hue;
|
||||
$this->saturation = $saturation;
|
||||
$this->brightness = $brightness;
|
||||
}
|
||||
|
||||
public static function fromString(string $string)
|
||||
{
|
||||
Validate::hsbColorString($string);
|
||||
|
||||
$matches = null;
|
||||
preg_match('/hs[vb]\( *(-?\d{1,3}) *, *(\d{1,3})%? *, *(\d{1,3})%? *\)/i', $string, $matches);
|
||||
|
||||
return new static($matches[1], $matches[2], $matches[3]);
|
||||
}
|
||||
|
||||
public function hue(): float
|
||||
{
|
||||
return $this->hue;
|
||||
}
|
||||
|
||||
public function saturation(): float
|
||||
{
|
||||
return $this->saturation;
|
||||
}
|
||||
|
||||
public function brightness(): float
|
||||
{
|
||||
return $this->brightness;
|
||||
}
|
||||
|
||||
public function red(): int
|
||||
{
|
||||
return Convert::hsbValueToRgb($this->hue, $this->saturation, $this->brightness)[0];
|
||||
}
|
||||
|
||||
public function green(): int
|
||||
{
|
||||
return Convert::hsbValueToRgb($this->hue, $this->saturation, $this->brightness)[1];
|
||||
}
|
||||
|
||||
public function blue(): int
|
||||
{
|
||||
return Convert::hsbValueToRgb($this->hue, $this->saturation, $this->brightness)[2];
|
||||
}
|
||||
|
||||
public function toCIELab(): CIELab
|
||||
{
|
||||
return $this->toRgb()->toCIELab();
|
||||
}
|
||||
|
||||
public function toCmyk(): Cmyk
|
||||
{
|
||||
return $this->toRgb()->toCmyk();
|
||||
}
|
||||
|
||||
public function toHsb(): Hsb
|
||||
{
|
||||
return new self($this->hue, $this->saturation, $this->brightness);
|
||||
}
|
||||
|
||||
public function toHex(string $alpha = 'ff'): Hex
|
||||
{
|
||||
return new Hex(
|
||||
Convert::rgbChannelToHexChannel($this->red()),
|
||||
Convert::rgbChannelToHexChannel($this->green()),
|
||||
Convert::rgbChannelToHexChannel($this->blue()),
|
||||
$alpha
|
||||
);
|
||||
}
|
||||
|
||||
public function toHsl(): Hsl
|
||||
{
|
||||
return $this->toRgb()->toHsl();
|
||||
}
|
||||
|
||||
public function toHsla(float $alpha = 1): Hsla
|
||||
{
|
||||
return $this->toRgb()->toHsla($alpha);
|
||||
}
|
||||
|
||||
public function toRgb(): Rgb
|
||||
{
|
||||
return new Rgb($this->red(), $this->green(), $this->blue());
|
||||
}
|
||||
|
||||
public function toRgba(float $alpha = 1): Rgba
|
||||
{
|
||||
return new Rgba($this->red(), $this->green(), $this->blue(), $alpha);
|
||||
}
|
||||
|
||||
public function toXyz(): Xyz
|
||||
{
|
||||
return $this->toRgb()->toXyz();
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
$hue = round($this->hue);
|
||||
$saturation = round($this->saturation);
|
||||
$brightness = round($this->brightness);
|
||||
|
||||
return "hsb({$hue},{$saturation}%,{$brightness}%)";
|
||||
}
|
||||
}
|
||||
120
vendor/spatie/color/src/Hsl.php
vendored
Normal file
120
vendor/spatie/color/src/Hsl.php
vendored
Normal file
@@ -0,0 +1,120 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\Color;
|
||||
|
||||
class Hsl implements Color
|
||||
{
|
||||
/** @var float */
|
||||
protected $hue;
|
||||
protected $saturation;
|
||||
protected $lightness;
|
||||
|
||||
public function __construct(float $hue, float $saturation, float $lightness)
|
||||
{
|
||||
Validate::hslValue($saturation, 'saturation');
|
||||
Validate::hslValue($lightness, 'lightness');
|
||||
|
||||
$this->hue = $hue;
|
||||
$this->saturation = $saturation;
|
||||
$this->lightness = $lightness;
|
||||
}
|
||||
|
||||
public static function fromString(string $string)
|
||||
{
|
||||
Validate::hslColorString($string);
|
||||
|
||||
$matches = null;
|
||||
preg_match('/hsl\( *(-?\d{1,3}) *, *(\d{1,3})%? *, *(\d{1,3})%? *\)/i', $string, $matches);
|
||||
|
||||
return new static($matches[1], $matches[2], $matches[3]);
|
||||
}
|
||||
|
||||
public function hue(): float
|
||||
{
|
||||
return $this->hue;
|
||||
}
|
||||
|
||||
public function saturation(): float
|
||||
{
|
||||
return $this->saturation;
|
||||
}
|
||||
|
||||
public function lightness(): float
|
||||
{
|
||||
return $this->lightness;
|
||||
}
|
||||
|
||||
public function red(): int
|
||||
{
|
||||
return Convert::hslValueToRgb($this->hue, $this->saturation, $this->lightness)[0];
|
||||
}
|
||||
|
||||
public function green(): int
|
||||
{
|
||||
return Convert::hslValueToRgb($this->hue, $this->saturation, $this->lightness)[1];
|
||||
}
|
||||
|
||||
public function blue(): int
|
||||
{
|
||||
return Convert::hslValueToRgb($this->hue, $this->saturation, $this->lightness)[2];
|
||||
}
|
||||
|
||||
public function toCIELab(): CIELab
|
||||
{
|
||||
return $this->toRgb()->toCIELab();
|
||||
}
|
||||
|
||||
public function toCmyk(): Cmyk
|
||||
{
|
||||
return $this->toRgb()->toCmyk();
|
||||
}
|
||||
|
||||
public function toHex(string $alpha = 'ff'): Hex
|
||||
{
|
||||
return new Hex(
|
||||
Convert::rgbChannelToHexChannel($this->red()),
|
||||
Convert::rgbChannelToHexChannel($this->green()),
|
||||
Convert::rgbChannelToHexChannel($this->blue()),
|
||||
$alpha
|
||||
);
|
||||
}
|
||||
|
||||
public function toHsb(): Hsb
|
||||
{
|
||||
return $this->toRgb()->toHsb();
|
||||
}
|
||||
|
||||
public function toHsl(): self
|
||||
{
|
||||
return new self($this->hue(), $this->saturation(), $this->lightness());
|
||||
}
|
||||
|
||||
public function toHsla(float $alpha = 1): Hsla
|
||||
{
|
||||
return new Hsla($this->hue(), $this->saturation(), $this->lightness(), $alpha);
|
||||
}
|
||||
|
||||
public function toRgb(): Rgb
|
||||
{
|
||||
return new Rgb($this->red(), $this->green(), $this->blue());
|
||||
}
|
||||
|
||||
public function toRgba(float $alpha = 1): Rgba
|
||||
{
|
||||
return new Rgba($this->red(), $this->green(), $this->blue(), $alpha);
|
||||
}
|
||||
|
||||
public function toXyz(): Xyz
|
||||
{
|
||||
return $this->toRgb()->toXyz();
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
$hue = round($this->hue);
|
||||
$saturation = round($this->saturation);
|
||||
$lightness = round($this->lightness);
|
||||
|
||||
return "hsl({$hue},{$saturation}%,{$lightness}%)";
|
||||
}
|
||||
}
|
||||
134
vendor/spatie/color/src/Hsla.php
vendored
Normal file
134
vendor/spatie/color/src/Hsla.php
vendored
Normal file
@@ -0,0 +1,134 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\Color;
|
||||
|
||||
class Hsla implements Color
|
||||
{
|
||||
/** @var float */
|
||||
protected $hue;
|
||||
protected $saturation;
|
||||
protected $lightness;
|
||||
protected $alpha;
|
||||
|
||||
public function __construct(float $hue, float $saturation, float $lightness, float $alpha = 1.0)
|
||||
{
|
||||
Validate::hslValue($saturation, 'saturation');
|
||||
Validate::hslValue($lightness, 'lightness');
|
||||
Validate::alphaChannelValue($alpha);
|
||||
|
||||
$this->hue = $hue;
|
||||
$this->saturation = $saturation;
|
||||
$this->lightness = $lightness;
|
||||
$this->alpha = $alpha;
|
||||
}
|
||||
|
||||
public static function fromString(string $string)
|
||||
{
|
||||
Validate::hslaColorString($string);
|
||||
|
||||
$matches = null;
|
||||
preg_match('/hsla\( *(\d{1,3}) *, *(\d{1,3})%? *, *(\d{1,3})%? *, *([0-1](\.\d{1,2})?) *\)/i', $string, $matches);
|
||||
|
||||
return new static($matches[1], $matches[2], $matches[3], $matches[4]);
|
||||
}
|
||||
|
||||
public function hue(): float
|
||||
{
|
||||
return $this->hue;
|
||||
}
|
||||
|
||||
public function saturation(): float
|
||||
{
|
||||
return $this->saturation;
|
||||
}
|
||||
|
||||
public function lightness(): float
|
||||
{
|
||||
return $this->lightness;
|
||||
}
|
||||
|
||||
public function red(): int
|
||||
{
|
||||
return Convert::hslValueToRgb($this->hue, $this->saturation, $this->lightness)[0];
|
||||
}
|
||||
|
||||
public function green(): int
|
||||
{
|
||||
return Convert::hslValueToRgb($this->hue, $this->saturation, $this->lightness)[1];
|
||||
}
|
||||
|
||||
public function blue(): int
|
||||
{
|
||||
return Convert::hslValueToRgb($this->hue, $this->saturation, $this->lightness)[2];
|
||||
}
|
||||
|
||||
public function alpha(): float
|
||||
{
|
||||
return $this->alpha;
|
||||
}
|
||||
|
||||
public function contrast(): self
|
||||
{
|
||||
return Contrast::make($this->toHex())->toHsla($this->alpha());
|
||||
}
|
||||
|
||||
public function toCIELab(): CIELab
|
||||
{
|
||||
return $this->toRgb()->toCIELab();
|
||||
}
|
||||
|
||||
public function toCmyk(): Cmyk
|
||||
{
|
||||
return $this->toRgb()->toCmyk();
|
||||
}
|
||||
|
||||
public function toHex(string $alpha = 'ff'): Hex
|
||||
{
|
||||
return new Hex(
|
||||
Convert::rgbChannelToHexChannel($this->red()),
|
||||
Convert::rgbChannelToHexChannel($this->green()),
|
||||
Convert::rgbChannelToHexChannel($this->blue()),
|
||||
$alpha
|
||||
);
|
||||
}
|
||||
|
||||
public function toHsb(): Hsb
|
||||
{
|
||||
return $this->toRgb()->toHsb();
|
||||
}
|
||||
|
||||
public function toHsla(float $alpha = 1): self
|
||||
{
|
||||
return new self($this->hue(), $this->saturation(), $this->lightness(), $alpha);
|
||||
}
|
||||
|
||||
public function toHsl(): Hsl
|
||||
{
|
||||
return new Hsl($this->hue(), $this->saturation(), $this->lightness());
|
||||
}
|
||||
|
||||
public function toRgb(): Rgb
|
||||
{
|
||||
return new Rgb($this->red(), $this->green(), $this->blue());
|
||||
}
|
||||
|
||||
public function toRgba(float $alpha = 1): Rgba
|
||||
{
|
||||
return new Rgba($this->red(), $this->green(), $this->blue(), $alpha);
|
||||
}
|
||||
|
||||
public function toXyz(): Xyz
|
||||
{
|
||||
return $this->toRgb()->toXyz();
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
$hue = round($this->hue);
|
||||
$saturation = round($this->saturation);
|
||||
$lightness = round($this->lightness);
|
||||
$alpha = round($this->alpha, 2);
|
||||
|
||||
return "hsla({$hue},{$saturation}%,{$lightness}%,{$alpha})";
|
||||
}
|
||||
}
|
||||
127
vendor/spatie/color/src/Rgb.php
vendored
Normal file
127
vendor/spatie/color/src/Rgb.php
vendored
Normal file
@@ -0,0 +1,127 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\Color;
|
||||
|
||||
class Rgb implements Color
|
||||
{
|
||||
/** @var int */
|
||||
protected $red;
|
||||
protected $green;
|
||||
protected $blue;
|
||||
|
||||
public function __construct(int $red, int $green, int $blue)
|
||||
{
|
||||
Validate::rgbChannelValue($red, 'red');
|
||||
Validate::rgbChannelValue($green, 'green');
|
||||
Validate::rgbChannelValue($blue, 'blue');
|
||||
|
||||
$this->red = $red;
|
||||
$this->green = $green;
|
||||
$this->blue = $blue;
|
||||
}
|
||||
|
||||
public static function fromString(string $string)
|
||||
{
|
||||
Validate::rgbColorString($string);
|
||||
|
||||
$matches = null;
|
||||
preg_match('/rgb\( *(\d{1,3} *, *\d{1,3} *, *\d{1,3}) *\)/i', $string, $matches);
|
||||
|
||||
$channels = explode(',', $matches[1]);
|
||||
[$red, $green, $blue] = array_map('trim', $channels);
|
||||
|
||||
return new static($red, $green, $blue);
|
||||
}
|
||||
|
||||
public function red(): int
|
||||
{
|
||||
return $this->red;
|
||||
}
|
||||
|
||||
public function green(): int
|
||||
{
|
||||
return $this->green;
|
||||
}
|
||||
|
||||
public function blue(): int
|
||||
{
|
||||
return $this->blue;
|
||||
}
|
||||
|
||||
public function toCIELab(): CIELab
|
||||
{
|
||||
return $this->toXyz()->toCIELab();
|
||||
}
|
||||
|
||||
public function toCmyk(): Cmyk
|
||||
{
|
||||
list($cyan, $magenta, $yellow, $key) = Convert::rgbValueToCmyk($this->red, $this->green, $this->blue);
|
||||
|
||||
return new Cmyk($cyan, $magenta, $yellow, $key);
|
||||
}
|
||||
|
||||
public function toHex(string $alpha = 'ff'): Hex
|
||||
{
|
||||
return new Hex(
|
||||
Convert::rgbChannelToHexChannel($this->red),
|
||||
Convert::rgbChannelToHexChannel($this->green),
|
||||
Convert::rgbChannelToHexChannel($this->blue),
|
||||
$alpha
|
||||
);
|
||||
}
|
||||
|
||||
public function toHsb(): Hsb
|
||||
{
|
||||
list($hue, $saturation, $brightness) = Convert::rgbValueToHsb($this->red, $this->green, $this->blue);
|
||||
|
||||
return new Hsb($hue, $saturation, $brightness);
|
||||
}
|
||||
|
||||
public function toHsl(): Hsl
|
||||
{
|
||||
[$hue, $saturation, $lightness] = Convert::rgbValueToHsl(
|
||||
$this->red,
|
||||
$this->green,
|
||||
$this->blue
|
||||
);
|
||||
|
||||
return new Hsl($hue, $saturation, $lightness);
|
||||
}
|
||||
|
||||
public function toHsla(float $alpha = 1): Hsla
|
||||
{
|
||||
[$hue, $saturation, $lightness] = Convert::rgbValueToHsl(
|
||||
$this->red,
|
||||
$this->green,
|
||||
$this->blue
|
||||
);
|
||||
|
||||
return new Hsla($hue, $saturation, $lightness, $alpha);
|
||||
}
|
||||
|
||||
public function toRgb(): self
|
||||
{
|
||||
return new self($this->red, $this->green, $this->blue);
|
||||
}
|
||||
|
||||
public function toRgba(float $alpha = 1): Rgba
|
||||
{
|
||||
return new Rgba($this->red, $this->green, $this->blue, $alpha);
|
||||
}
|
||||
|
||||
public function toXyz(): Xyz
|
||||
{
|
||||
[$x, $y, $z] = Convert::rgbValueToXyz(
|
||||
$this->red,
|
||||
$this->green,
|
||||
$this->blue
|
||||
);
|
||||
|
||||
return new Xyz($x, $y, $z);
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return "rgb({$this->red},{$this->green},{$this->blue})";
|
||||
}
|
||||
}
|
||||
124
vendor/spatie/color/src/Rgba.php
vendored
Normal file
124
vendor/spatie/color/src/Rgba.php
vendored
Normal file
@@ -0,0 +1,124 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\Color;
|
||||
|
||||
class Rgba implements Color
|
||||
{
|
||||
/** @var int */
|
||||
protected $red;
|
||||
protected $green;
|
||||
protected $blue;
|
||||
|
||||
/** @var float */
|
||||
protected $alpha;
|
||||
|
||||
public function __construct(int $red, int $green, int $blue, float $alpha)
|
||||
{
|
||||
Validate::rgbChannelValue($red, 'red');
|
||||
Validate::rgbChannelValue($green, 'green');
|
||||
Validate::rgbChannelValue($blue, 'blue');
|
||||
Validate::alphaChannelValue($alpha);
|
||||
|
||||
$this->red = $red;
|
||||
$this->green = $green;
|
||||
$this->blue = $blue;
|
||||
$this->alpha = $alpha;
|
||||
}
|
||||
|
||||
public static function fromString(string $string)
|
||||
{
|
||||
Validate::rgbaColorString($string);
|
||||
|
||||
$matches = null;
|
||||
preg_match('/rgba\( *(\d{1,3} *, *\d{1,3} *, *\d{1,3} *, *[0-1]*(\.\d{1,})?) *\)/i', $string, $matches);
|
||||
|
||||
$channels = explode(',', $matches[1]);
|
||||
[$red, $green, $blue, $alpha] = array_map('trim', $channels);
|
||||
|
||||
return new static($red, $green, $blue, $alpha);
|
||||
}
|
||||
|
||||
public function red(): int
|
||||
{
|
||||
return $this->red;
|
||||
}
|
||||
|
||||
public function green(): int
|
||||
{
|
||||
return $this->green;
|
||||
}
|
||||
|
||||
public function blue(): int
|
||||
{
|
||||
return $this->blue;
|
||||
}
|
||||
|
||||
public function alpha(): float
|
||||
{
|
||||
return $this->alpha;
|
||||
}
|
||||
|
||||
public function toCIELab(): CIELab
|
||||
{
|
||||
return $this->toRgb()->toCIELab();
|
||||
}
|
||||
|
||||
public function toCmyk(): Cmyk
|
||||
{
|
||||
return $this->toRgb()->toCmyk();
|
||||
}
|
||||
|
||||
public function toHex(string $alpha = 'ff'): Hex
|
||||
{
|
||||
return $this->toRgb()->toHex($alpha);
|
||||
}
|
||||
|
||||
public function toHsb(): Hsb
|
||||
{
|
||||
return $this->toRgb()->toHsb();
|
||||
}
|
||||
|
||||
public function toHsl(): Hsl
|
||||
{
|
||||
[$hue, $saturation, $lightness] = Convert::rgbValueToHsl(
|
||||
$this->red,
|
||||
$this->green,
|
||||
$this->blue
|
||||
);
|
||||
|
||||
return new Hsl($hue, $saturation, $lightness);
|
||||
}
|
||||
|
||||
public function toHsla(float $alpha = 1): Hsla
|
||||
{
|
||||
[$hue, $saturation, $lightness] = Convert::rgbValueToHsl(
|
||||
$this->red,
|
||||
$this->green,
|
||||
$this->blue
|
||||
);
|
||||
|
||||
return new Hsla($hue, $saturation, $lightness, $alpha);
|
||||
}
|
||||
|
||||
public function toRgb(): Rgb
|
||||
{
|
||||
return new Rgb($this->red, $this->green, $this->blue);
|
||||
}
|
||||
|
||||
public function toRgba(float $alpha = 1): self
|
||||
{
|
||||
return new self($this->red, $this->green, $this->blue, $alpha);
|
||||
}
|
||||
|
||||
public function toXyz(): Xyz
|
||||
{
|
||||
return $this->toRgb()->toXyz();
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
$alpha = number_format($this->alpha, 2);
|
||||
|
||||
return "rgba({$this->red},{$this->green},{$this->blue},{$alpha})";
|
||||
}
|
||||
}
|
||||
155
vendor/spatie/color/src/Validate.php
vendored
Normal file
155
vendor/spatie/color/src/Validate.php
vendored
Normal file
@@ -0,0 +1,155 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\Color;
|
||||
|
||||
use Spatie\Color\Exceptions\InvalidColorValue;
|
||||
|
||||
class Validate
|
||||
{
|
||||
public static function CIELabValue(float $value, string $name): void
|
||||
{
|
||||
if ($name === 'l' && ($value < 0 || $value > 100)) {
|
||||
throw InvalidColorValue::CIELabValueNotInRange($value, $name, 0, 100);
|
||||
}
|
||||
|
||||
if (($name === 'a' || $name === 'b') && ($value < -110 || $value > 110)) {
|
||||
throw InvalidColorValue::CIELabValueNotInRange($value, $name, -110, 110);
|
||||
}
|
||||
}
|
||||
|
||||
public static function CIELabColorString($string): void
|
||||
{
|
||||
if (! preg_match('/^ *CIELab\( *\d{1,3}\.?\d* *, *-?\d{1,3}\.?\d* *, *-?\d{1,3}\.?\d* *\) *$/i', $string)) {
|
||||
throw InvalidColorValue::malformedCIELabColorString($string);
|
||||
}
|
||||
}
|
||||
|
||||
public static function cmykValue(float $value, string $name): void
|
||||
{
|
||||
if ($value < 0 || $value > 1) {
|
||||
throw InvalidColorValue::cmykValueNotInRange($value, $name);
|
||||
}
|
||||
}
|
||||
|
||||
public static function rgbChannelValue(int $value, string $channel): void
|
||||
{
|
||||
if ($value < 0 || $value > 255) {
|
||||
throw InvalidColorValue::rgbChannelValueNotInRange($value, $channel);
|
||||
}
|
||||
}
|
||||
|
||||
public static function alphaChannelValue(float $value): void
|
||||
{
|
||||
if ($value < 0 || $value > 1) {
|
||||
throw InvalidColorValue::alphaChannelValueNotInRange($value);
|
||||
}
|
||||
}
|
||||
|
||||
public static function hexChannelValue(string $value): void
|
||||
{
|
||||
if (strlen($value) !== 2) {
|
||||
throw InvalidColorValue::hexChannelValueHasInvalidLength($value);
|
||||
}
|
||||
|
||||
if (! preg_match('/[a-f0-9]{2}/i', $value)) {
|
||||
throw InvalidColorValue::hexValueContainsInvalidCharacters($value);
|
||||
}
|
||||
}
|
||||
|
||||
public static function hsbValue(float $value, string $name): void
|
||||
{
|
||||
switch ($name) {
|
||||
case 'hue':
|
||||
if ($value < 0 || $value > 360) {
|
||||
throw InvalidColorValue::hsbValueNotInRange($value, $name);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
if ($value < 0 || $value > 100) {
|
||||
throw InvalidColorValue::hsbValueNotInRange($value, $name);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public static function hslValue(float $value, string $name): void
|
||||
{
|
||||
if ($value < 0 || $value > 100) {
|
||||
throw InvalidColorValue::hslValueNotInRange($value, $name);
|
||||
}
|
||||
}
|
||||
|
||||
public static function cmykColorString($string): void
|
||||
{
|
||||
if (! preg_match('/^ *cmyk\( *(\d{1,3})%? *, *(\d{1,3})%? *, *(\d{1,3})%? *, *(\d{1,3})%? *\) *$/i', $string)) {
|
||||
throw InvalidColorValue::malformedCmykColorString($string);
|
||||
}
|
||||
}
|
||||
|
||||
public static function rgbColorString($string): void
|
||||
{
|
||||
if (! preg_match('/^ *rgb\( *\d{1,3} *, *\d{1,3} *, *\d{1,3} *\) *$/i', $string)) {
|
||||
throw InvalidColorValue::malformedRgbColorString($string);
|
||||
}
|
||||
}
|
||||
|
||||
public static function rgbaColorString($string): void
|
||||
{
|
||||
if (! preg_match('/^ *rgba\( *\d{1,3} *, *\d{1,3} *, *\d{1,3} *, *[0-1]*(\.\d{1,})? *\) *$/i', $string)) {
|
||||
throw InvalidColorValue::malformedRgbaColorString($string);
|
||||
}
|
||||
}
|
||||
|
||||
public static function hexColorString($string): void
|
||||
{
|
||||
if (! preg_match('/^#(?:[a-f0-9]{3}|[a-f0-9]{4}|[a-f0-9]{6}|[a-f0-9]{8})$/i', $string)) {
|
||||
throw InvalidColorValue::malformedHexColorString($string);
|
||||
}
|
||||
}
|
||||
|
||||
public static function hsbColorString($string): void
|
||||
{
|
||||
if (! preg_match('/^ *hs[vb]\( *-?\d{1,3} *, *\d{1,3}%? *, *\d{1,3}%? *\) *$/i', $string)) {
|
||||
throw InvalidColorValue::malformedHslColorString($string);
|
||||
}
|
||||
}
|
||||
|
||||
public static function hslColorString($string): void
|
||||
{
|
||||
if (! preg_match('/^ *hsl\( *-?\d{1,3} *, *\d{1,3}%? *, *\d{1,3}%? *\) *$/i', $string)) {
|
||||
throw InvalidColorValue::malformedHslColorString($string);
|
||||
}
|
||||
}
|
||||
|
||||
public static function hslaColorString($string): void
|
||||
{
|
||||
if (! preg_match('/^ *hsla\( *\d{1,3} *, *\d{1,3}%? *, *\d{1,3}%? *, *[0-1](\.\d{1,2})? *\) *$/i', $string)) {
|
||||
throw InvalidColorValue::malformedHslaColorString($string);
|
||||
}
|
||||
}
|
||||
|
||||
public static function xyzValue(float $value, string $name): void
|
||||
{
|
||||
if ($name === 'x' && ($value < 0 || $value > 95.047)) {
|
||||
throw InvalidColorValue::xyzValueNotInRange($value, $name, 0, 95.047);
|
||||
}
|
||||
|
||||
if ($name === 'y' && ($value < 0 || $value > 100)) {
|
||||
throw InvalidColorValue::xyzValueNotInRange($value, $name, 0, 100);
|
||||
}
|
||||
|
||||
if ($name === 'z' && ($value < 0 || $value > 108.883)) {
|
||||
throw InvalidColorValue::xyzValueNotInRange($value, $name, 0, 108.883);
|
||||
}
|
||||
}
|
||||
|
||||
public static function xyzColorString($string): void
|
||||
{
|
||||
if (! preg_match('/^ *xyz\( *\d{1,2}\.?\d+? *, *\d{1,3}\.?\d+? *, *\d{1,3}\.?\d+? *\) *$/i', $string)) {
|
||||
throw InvalidColorValue::malformedXyzColorString($string);
|
||||
}
|
||||
}
|
||||
}
|
||||
133
vendor/spatie/color/src/Xyz.php
vendored
Normal file
133
vendor/spatie/color/src/Xyz.php
vendored
Normal file
@@ -0,0 +1,133 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\Color;
|
||||
|
||||
class Xyz implements Color
|
||||
{
|
||||
/** @var float */
|
||||
protected $x;
|
||||
protected $y;
|
||||
protected $z;
|
||||
|
||||
public function __construct(float $x, float $y, float $z)
|
||||
{
|
||||
Validate::xyzValue($x, 'x');
|
||||
Validate::xyzValue($y, 'y');
|
||||
Validate::xyzValue($z, 'z');
|
||||
|
||||
$this->x = $x;
|
||||
$this->y = $y;
|
||||
$this->z = $z;
|
||||
}
|
||||
|
||||
public static function fromString(string $string)
|
||||
{
|
||||
Validate::xyzColorString($string);
|
||||
|
||||
$matches = null;
|
||||
preg_match('/xyz\( *(\d{1,2}\.?\d+? *, *\d{1,3}\.?\d+? *, *\d{1,3}\.?\d+?) *\)/i', $string, $matches);
|
||||
|
||||
$channels = explode(',', $matches[1]);
|
||||
[$x, $y, $z] = array_map('trim', $channels);
|
||||
|
||||
return new static($x, $y, $z);
|
||||
}
|
||||
|
||||
public function x(): float
|
||||
{
|
||||
return $this->x;
|
||||
}
|
||||
|
||||
public function y(): float
|
||||
{
|
||||
return $this->y;
|
||||
}
|
||||
|
||||
public function z(): float
|
||||
{
|
||||
return $this->z;
|
||||
}
|
||||
|
||||
public function red(): int
|
||||
{
|
||||
$rgb = $this->toRgb();
|
||||
|
||||
return $rgb->red();
|
||||
}
|
||||
|
||||
public function blue(): int
|
||||
{
|
||||
$rgb = $this->toRgb();
|
||||
|
||||
return $rgb->blue();
|
||||
}
|
||||
|
||||
public function green(): int
|
||||
{
|
||||
$rgb = $this->toRgb();
|
||||
|
||||
return $rgb->green();
|
||||
}
|
||||
|
||||
public function toCIELab(): CIELab
|
||||
{
|
||||
[$l, $a, $b] = Convert::xyzValueToCIELab(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z
|
||||
);
|
||||
|
||||
return new CIELab($l, $a, $b);
|
||||
}
|
||||
|
||||
public function toCmyk(): Cmyk
|
||||
{
|
||||
return $this->toRgb()->toCmyk();
|
||||
}
|
||||
|
||||
public function toHex(string $alpha = 'ff'): Hex
|
||||
{
|
||||
return $this->toRgb()->toHex($alpha);
|
||||
}
|
||||
|
||||
public function toHsb(): Hsb
|
||||
{
|
||||
return $this->toRgb()->toHsb();
|
||||
}
|
||||
|
||||
public function toHsl(): Hsl
|
||||
{
|
||||
return $this->toRgb()->toHSL();
|
||||
}
|
||||
|
||||
public function toHsla(float $alpha = 1): Hsla
|
||||
{
|
||||
return $this->toRgb()->toHsla($alpha);
|
||||
}
|
||||
|
||||
public function toRgb(): Rgb
|
||||
{
|
||||
[$red, $green, $blue] = Convert::xyzValueToRgb(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z
|
||||
);
|
||||
|
||||
return new Rgb($red, $green, $blue);
|
||||
}
|
||||
|
||||
public function toRgba(float $alpha = 1): Rgba
|
||||
{
|
||||
return $this->toRgb()->toRgba($alpha);
|
||||
}
|
||||
|
||||
public function toXyz(): self
|
||||
{
|
||||
return new self($this->x, $this->y, $this->z);
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return "xyz({$this->x},{$this->y},{$this->z})";
|
||||
}
|
||||
}
|
||||
96
vendor/spatie/invade/CHANGELOG.md
vendored
Normal file
96
vendor/spatie/invade/CHANGELOG.md
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to `invade` will be documented in this file.
|
||||
|
||||
## 2.0.0 - 2023-07-19
|
||||
|
||||
### What's Changed
|
||||
|
||||
- invade without reflection by @enricodelazzari in https://github.com/spatie/invade/pull/24
|
||||
|
||||
### New Contributors
|
||||
|
||||
- @enricodelazzari made their first contribution in https://github.com/spatie/invade/pull/24
|
||||
|
||||
**Full Changelog**: https://github.com/spatie/invade/compare/1.1.1...2.0.0
|
||||
|
||||
## 1.1.1 - 2022-07-05
|
||||
|
||||
### What's Changed
|
||||
|
||||
- Bump dependabot/fetch-metadata from 1.3.1 to 1.3.3 by @dependabot in https://github.com/spatie/invade/pull/13
|
||||
- Improve the PHPStan extension by @jrmajor in https://github.com/spatie/invade/pull/14
|
||||
|
||||
### New Contributors
|
||||
|
||||
- @jrmajor made their first contribution in https://github.com/spatie/invade/pull/14
|
||||
|
||||
**Full Changelog**: https://github.com/spatie/invade/compare/1.1.0...1.1.1
|
||||
|
||||
## 1.1.0 - 2022-07-02
|
||||
|
||||
### What's Changed
|
||||
|
||||
- Add phpstan support to not report access to private properties/methods by @tpetry in https://github.com/spatie/invade/pull/12
|
||||
|
||||
### New Contributors
|
||||
|
||||
- @tpetry made their first contribution in https://github.com/spatie/invade/pull/12
|
||||
|
||||
**Full Changelog**: https://github.com/spatie/invade/compare/1.0.3...1.1.0
|
||||
|
||||
## 1.0.3 - 2022-06-06
|
||||
|
||||
### What's Changed
|
||||
|
||||
- Bump dependabot/fetch-metadata from 1.2.0 to 1.2.1 by @dependabot in https://github.com/spatie/invade/pull/8
|
||||
- Bump dependabot/fetch-metadata from 1.2.1 to 1.3.0 by @dependabot in https://github.com/spatie/invade/pull/9
|
||||
- Bump dependabot/fetch-metadata from 1.3.0 to 1.3.1 by @dependabot in https://github.com/spatie/invade/pull/11
|
||||
- Add type checking via phpstan by @olivernybroe in https://github.com/spatie/invade/pull/5
|
||||
- Bump actions/checkout from 2 to 3 by @dependabot in https://github.com/spatie/invade/pull/10
|
||||
|
||||
### New Contributors
|
||||
|
||||
- @olivernybroe made their first contribution in https://github.com/spatie/invade/pull/5
|
||||
|
||||
**Full Changelog**: https://github.com/spatie/invade/compare/1.0.2...1.0.3
|
||||
|
||||
## 1.0.2 - 2022-02-21
|
||||
|
||||
## What's Changed
|
||||
|
||||
- Bump dependabot/fetch-metadata from 1.1.1 to 1.2.0 by @dependabot in https://github.com/spatie/invade/pull/6
|
||||
- Add brand new logo to the project by @caneco in https://github.com/spatie/invade/pull/7
|
||||
|
||||
## New Contributors
|
||||
|
||||
- @dependabot made their first contribution in https://github.com/spatie/invade/pull/6
|
||||
- @caneco made their first contribution in https://github.com/spatie/invade/pull/7
|
||||
|
||||
**Full Changelog**: https://github.com/spatie/invade/compare/1.0.1...1.0.2
|
||||
|
||||
## 1.0.1 - 2022-02-11
|
||||
|
||||
## What's Changed
|
||||
|
||||
- Invador -> Invader spelling by @danharrin in https://github.com/spatie/invade/pull/2
|
||||
- Only declare function if it does not already exist by @benjam-es in https://github.com/spatie/invade/pull/1
|
||||
|
||||
## New Contributors
|
||||
|
||||
- @danharrin made their first contribution in https://github.com/spatie/invade/pull/2
|
||||
- @benjam-es made their first contribution in https://github.com/spatie/invade/pull/1
|
||||
|
||||
**Full Changelog**: https://github.com/spatie/invade/compare/1.0.0...1.0.1
|
||||
|
||||
## 0.0.2 - 2022-02-11
|
||||
|
||||
- experimental release
|
||||
|
||||
## 0.0.1 - 2022-02-11
|
||||
|
||||
- experimental release
|
||||
|
||||
## 1.0.0 - 202X-XX-XX
|
||||
|
||||
- initial release
|
||||
21
vendor/spatie/invade/LICENSE.md
vendored
Normal file
21
vendor/spatie/invade/LICENSE.md
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) spatie <freek@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.
|
||||
127
vendor/spatie/invade/README.md
vendored
Normal file
127
vendor/spatie/invade/README.md
vendored
Normal file
@@ -0,0 +1,127 @@
|
||||
<p align="center"><img src="/art/socialcard.png" alt="Social Card of Invade"></p>
|
||||
|
||||
# A PHP function to access private properties and methods
|
||||
|
||||
[](https://packagist.org/packages/spatie/invade)
|
||||
[](https://github.com/spatie/invade/actions/workflows/run-tests.yml)
|
||||
[](https://packagist.org/packages/spatie/invade)
|
||||
|
||||
This package offers an `invade` function that will allow you to read/write private properties of an object. It will also allow you to call private methods.
|
||||
|
||||
## Support us
|
||||
|
||||
[<img src="https://github-ads.s3.eu-central-1.amazonaws.com/invade.jpg?t=1" width="419px" />](https://spatie.be/github-ad-click/invade)
|
||||
|
||||
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/invade
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
Imagine you have this class defined which has a private property and method.
|
||||
|
||||
```php
|
||||
class MyClass
|
||||
{
|
||||
private string $privateProperty = 'private value';
|
||||
|
||||
private function privateMethod(): string
|
||||
{
|
||||
return 'private return value';
|
||||
}
|
||||
}
|
||||
|
||||
$myClass = new Myclass();
|
||||
```
|
||||
|
||||
This is how you can get the value of the private property using the `invade` function.
|
||||
|
||||
```php
|
||||
invade($myClass)->privateProperty; // returns 'private value'
|
||||
```
|
||||
|
||||
The `invade` function also allows you to change private values.
|
||||
|
||||
```php
|
||||
invade($myClass)->privateProperty = 'changed value';
|
||||
invade($myClass)->privateProperty; // returns 'changed value
|
||||
```
|
||||
|
||||
Using `invade` you can also call private functions.
|
||||
|
||||
```php
|
||||
invade($myClass)->privateMethod(); // returns 'private return value'
|
||||
```
|
||||
|
||||
Further, you can also get and set private static class properties and call private static methods. Imagine having this class:
|
||||
|
||||
```php
|
||||
class MyClass
|
||||
{
|
||||
private static string $privateStaticProperty = 'privateValue';
|
||||
|
||||
private static function privateStaticMethod(string $string, int $int): string
|
||||
{
|
||||
return 'private return value ' . $string . ' ' . $int;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Here is how you get and set private class properties:
|
||||
|
||||
```php
|
||||
invade(MyClass::class)->get('privateStaticProperty'); // returns 'private value'
|
||||
|
||||
invade(MyClass::class)->set('privateStaticProperty', 'changedValue');
|
||||
|
||||
invade(MyClass::class)->get('privateStaticProperty'); // returns 'changedValue'
|
||||
```
|
||||
|
||||
And this is how you call private static methods:
|
||||
|
||||
```php
|
||||
invade(MyClass::class)
|
||||
->method('privateStaticMethod')
|
||||
->call('foo', 123);
|
||||
|
||||
// returns 'private return value foo 123'
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
```bash
|
||||
composer test
|
||||
```
|
||||
|
||||
## Changelog
|
||||
|
||||
Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.
|
||||
|
||||
## Contributing
|
||||
|
||||
Please see [CONTRIBUTING](https://github.com/spatie/.github/blob/main/CONTRIBUTING.md) for details.
|
||||
|
||||
## Security Vulnerabilities
|
||||
|
||||
Please review [our security policy](../../security/policy) on how to report security vulnerabilities.
|
||||
|
||||
## Credits
|
||||
|
||||
- [Freek Van der Herten](https://github.com/spatie)
|
||||
- [All Contributors](../../contributors)
|
||||
|
||||
And a special thanks to [Caneco](https://twitter.com/caneco) for the logo ✨
|
||||
|
||||
The [original idea](https://twitter.com/calebporzio/status/1492141967404371968) for the `invade` function came from [Caleb "string king" Porzio](https://twitter.com/calebporzio). We slightly polished the code that he created in [this commit on Livewire](https://github.com/livewire/livewire/pull/4649/files).
|
||||
|
||||
## License
|
||||
|
||||
The MIT License (MIT). Please see [License File](LICENSE.md) for more information.
|
||||
51
vendor/spatie/invade/composer.json
vendored
Normal file
51
vendor/spatie/invade/composer.json
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
{
|
||||
"name": "spatie/invade",
|
||||
"description": "A PHP function to work with private properties and methods",
|
||||
"keywords": [
|
||||
"spatie",
|
||||
"invade"
|
||||
],
|
||||
"homepage": "https://github.com/spatie/invade",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Freek Van der Herten",
|
||||
"email": "freek@spatie.be",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": "^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"pestphp/pest": "^1.20",
|
||||
"phpstan/phpstan": "^1.4",
|
||||
"spatie/ray": "^1.28"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Spatie\\Invade\\": "src"
|
||||
},
|
||||
"files": [
|
||||
"src/functions.php"
|
||||
]
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Spatie\\Invade\\Tests\\": "tests"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"analyse": "vendor/bin/phpstan analyse",
|
||||
"test": "vendor/bin/pest",
|
||||
"test-coverage": "vendor/bin/pest --coverage"
|
||||
},
|
||||
"config": {
|
||||
"sort-packages": true,
|
||||
"allow-plugins": {
|
||||
"pestphp/pest-plugin": true
|
||||
}
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
"prefer-stable": true
|
||||
}
|
||||
0
vendor/spatie/invade/phpstan-baseline.neon
vendored
Normal file
0
vendor/spatie/invade/phpstan-baseline.neon
vendored
Normal file
9
vendor/spatie/invade/phpstan.neon.dist
vendored
Normal file
9
vendor/spatie/invade/phpstan.neon.dist
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
includes:
|
||||
- phpstan-baseline.neon
|
||||
|
||||
parameters:
|
||||
level: 4
|
||||
paths:
|
||||
- src
|
||||
tmpDir: build/phpstan
|
||||
checkMissingIterableValueType: false
|
||||
33
vendor/spatie/invade/src/Invader.php
vendored
Normal file
33
vendor/spatie/invade/src/Invader.php
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\Invade;
|
||||
|
||||
/**
|
||||
* @template T of object
|
||||
* @mixin T
|
||||
*/
|
||||
class Invader
|
||||
{
|
||||
/**
|
||||
* @param T $obj
|
||||
*/
|
||||
public function __construct(
|
||||
public object $obj
|
||||
) {
|
||||
}
|
||||
|
||||
public function __get(string $name): mixed
|
||||
{
|
||||
return (fn () => $this->{$name})->call($this->obj);
|
||||
}
|
||||
|
||||
public function __set(string $name, mixed $value): void
|
||||
{
|
||||
(fn () => $this->{$name} = $value)->call($this->obj);
|
||||
}
|
||||
|
||||
public function __call(string $name, array $params = []): mixed
|
||||
{
|
||||
return (fn () => $this->{$name}(...$params))->call($this->obj);
|
||||
}
|
||||
}
|
||||
49
vendor/spatie/invade/src/StaticInvader.php
vendored
Normal file
49
vendor/spatie/invade/src/StaticInvader.php
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\Invade;
|
||||
|
||||
use Exception;
|
||||
|
||||
class StaticInvader
|
||||
{
|
||||
private ?string $method = null;
|
||||
|
||||
/**
|
||||
* @param class-string $className
|
||||
*/
|
||||
public function __construct(
|
||||
public string $className,
|
||||
) {
|
||||
}
|
||||
|
||||
public function get(string $name): mixed
|
||||
{
|
||||
return (fn () => static::${$name})->bindTo(null, $this->className)();
|
||||
}
|
||||
|
||||
public function set(string $name, mixed $value): void
|
||||
{
|
||||
(fn ($value) => static::${$name} = $value)->bindTo(null, $this->className)($value);
|
||||
}
|
||||
|
||||
public function method(string $name): self
|
||||
{
|
||||
$this->method = $name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function call(...$params): mixed
|
||||
{
|
||||
if ($this->method === null) {
|
||||
throw new Exception(
|
||||
'No method to be called. Use it like: invadeStatic(Foo::class)->method(\'bar\')->call()'
|
||||
);
|
||||
}
|
||||
|
||||
return (fn ($method) => static::{$method}(...$params))->bindTo(null, $this->className)($this->method);
|
||||
}
|
||||
}
|
||||
21
vendor/spatie/invade/src/functions.php
vendored
Normal file
21
vendor/spatie/invade/src/functions.php
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
use Spatie\Invade\Invader;
|
||||
use Spatie\Invade\StaticInvader;
|
||||
|
||||
if (! function_exists('invade')) {
|
||||
/**
|
||||
* @template T of object
|
||||
*
|
||||
* @param T|class-string $object
|
||||
* @return Invader<T>|StaticInvader
|
||||
*/
|
||||
function invade(object|string $object): Invader|StaticInvader
|
||||
{
|
||||
if (is_object($object)) {
|
||||
return new Invader($object);
|
||||
}
|
||||
|
||||
return new StaticInvader($object);
|
||||
}
|
||||
}
|
||||
21
vendor/spatie/laravel-package-tools/LICENSE.md
vendored
Normal file
21
vendor/spatie/laravel-package-tools/LICENSE.md
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) spatie <freek@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.
|
||||
553
vendor/spatie/laravel-package-tools/README.md
vendored
Normal file
553
vendor/spatie/laravel-package-tools/README.md
vendored
Normal file
@@ -0,0 +1,553 @@
|
||||
# Tools for creating Laravel packages
|
||||
|
||||
[](https://packagist.org/packages/spatie/laravel-package-tools)
|
||||

|
||||
[](https://packagist.org/packages/spatie/laravel-package-tools)
|
||||
|
||||
This package contains a `PackageServiceProvider` that you can use in your packages to easily register config files,
|
||||
migrations, and more.
|
||||
|
||||
Here's an example of how it can be used.
|
||||
|
||||
```php
|
||||
use Spatie\LaravelPackageTools\PackageServiceProvider;
|
||||
use Spatie\LaravelPackageTools\Package;
|
||||
use MyPackage\ViewComponents\Alert;
|
||||
use Spatie\LaravelPackageTools\Commands\InstallCommand;
|
||||
|
||||
class YourPackageServiceProvider extends PackageServiceProvider
|
||||
{
|
||||
public function configurePackage(Package $package): void
|
||||
{
|
||||
$package
|
||||
->name('your-package-name')
|
||||
->hasConfigFile()
|
||||
->hasViews()
|
||||
->hasViewComponent('spatie', Alert::class)
|
||||
->hasViewComposer('*', MyViewComposer::class)
|
||||
->sharesDataWithAllViews('downloads', 3)
|
||||
->hasTranslations()
|
||||
->hasAssets()
|
||||
->publishesServiceProvider('MyProviderName')
|
||||
->hasRoute('web')
|
||||
->hasMigration('create_package_tables')
|
||||
->hasCommand(YourCoolPackageCommand::class)
|
||||
->hasInstallCommand(function(InstallCommand $command) {
|
||||
$command
|
||||
->publishConfigFile()
|
||||
->publishAssets()
|
||||
->publishMigrations()
|
||||
->copyAndRegisterServiceProviderInApp()
|
||||
->askToStarRepoOnGitHub();
|
||||
});
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Under the hood it will do the necessary work to register the necessary things and make all sorts of files publishable.
|
||||
|
||||
## Support us
|
||||
|
||||
[<img src="https://github-ads.s3.eu-central-1.amazonaws.com/laravel-package-tools.jpg?t=1" width="419px" />](https://spatie.be/github-ad-click/laravel-package-tools)
|
||||
|
||||
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).
|
||||
|
||||
## Getting started
|
||||
|
||||
This package is opinionated on how you should structure your package. To get started easily, consider
|
||||
using [our package-skeleton repo](https://github.com/spatie/package-skeleton-laravel) to start your package. The
|
||||
skeleton is structured perfectly to work perfectly with the `PackageServiceProvider` in this package.
|
||||
|
||||
## Usage
|
||||
|
||||
In your package you should let your service provider extend `Spatie\LaravelPackageTools\PackageServiceProvider`.
|
||||
|
||||
```php
|
||||
use Spatie\LaravelPackageTools\PackageServiceProvider;
|
||||
use Spatie\LaravelPackageTools\Package;
|
||||
|
||||
class YourPackageServiceProvider extends PackageServiceProvider
|
||||
{
|
||||
public function configurePackage(Package $package) : void
|
||||
{
|
||||
$package->name('your-package-name');
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Passing the package name to `name` is mandatory.
|
||||
|
||||
### Working with a config file
|
||||
|
||||
To register a config file, you should create a php file with your package name in the `config` directory of your
|
||||
package. In this example it should be at `<package root>/config/your-package-name.php`.
|
||||
|
||||
If your package name starts with `laravel-`, we expect that your config file does not contain that prefix. So if your
|
||||
package name is `laravel-cool-package`, the config file should be named `cool-package.php`.
|
||||
|
||||
To register that config file, call `hasConfigFile()` on `$package` in the `configurePackage` method.
|
||||
|
||||
```php
|
||||
$package
|
||||
->name('your-package-name')
|
||||
->hasConfigFile();
|
||||
```
|
||||
|
||||
The `hasConfigFile` method will also make the config file publishable. Users of your package will be able to publish the
|
||||
config file with this command.
|
||||
|
||||
```bash
|
||||
php artisan vendor:publish --tag=your-package-name-config
|
||||
```
|
||||
|
||||
Should your package have multiple config files, you can pass their names as an array to `hasConfigFile`
|
||||
|
||||
```php
|
||||
$package
|
||||
->name('your-package-name')
|
||||
->hasConfigFile(['my-config-file', 'another-config-file']);
|
||||
```
|
||||
|
||||
### Working with views
|
||||
|
||||
Any views your package provides, should be placed in the `<package root>/resources/views` directory.
|
||||
|
||||
You can register these views with the `hasViews` command.
|
||||
|
||||
```php
|
||||
$package
|
||||
->name('your-package-name')
|
||||
->hasViews();
|
||||
```
|
||||
|
||||
This will register your views with Laravel.
|
||||
|
||||
If you have a view `<package root>/resources/views/myView.blade.php`, you can use it like
|
||||
this: `view('your-package-name::myView')`. Of course, you can also use subdirectories to organise your views. A view
|
||||
located at `<package root>/resources/views/subdirectory/myOtherView.blade.php` can be used
|
||||
with `view('your-package-name::subdirectory.myOtherView')`.
|
||||
|
||||
#### Using a custom view namespace
|
||||
|
||||
You can pass a custom view namespace to the `hasViews` method.
|
||||
|
||||
```php
|
||||
$package
|
||||
->name('your-package-name')
|
||||
->hasViews('custom-view-namespace');
|
||||
```
|
||||
|
||||
You can now use the views of the package like this:
|
||||
|
||||
```php
|
||||
view('custom-view-namespace::myView');
|
||||
```
|
||||
|
||||
#### Publishing the views
|
||||
|
||||
Calling `hasViews` will also make views publishable. Users of your package will be able to publish the views with this
|
||||
command:
|
||||
|
||||
```bash
|
||||
php artisan vendor:publish --tag=your-package-name-views
|
||||
```
|
||||
|
||||
> **Note:**
|
||||
>
|
||||
> If you use custom view namespace then you should change your publish command like this:
|
||||
```bash
|
||||
php artisan vendor:publish --tag=custom-view-namespace-views
|
||||
```
|
||||
|
||||
|
||||
### Sharing global data with views
|
||||
|
||||
You can share data with all views using the `sharesDataWithAllViews` method. This will make the shared variable
|
||||
available to all views.
|
||||
|
||||
```php
|
||||
$package
|
||||
->name('your-package-name')
|
||||
->sharesDataWithAllViews('companyName', 'Spatie');
|
||||
```
|
||||
|
||||
### Working with Blade view components
|
||||
|
||||
Any Blade view components that your package provides should be placed in the `<package root>/src/Components` directory.
|
||||
|
||||
You can register these views with the `hasViewComponents` command.
|
||||
|
||||
```php
|
||||
$package
|
||||
->name('your-package-name')
|
||||
->hasViewComponents('spatie', Alert::class);
|
||||
```
|
||||
|
||||
This will register your view components with Laravel. In the case of `Alert::class`, it can be referenced in views
|
||||
as `<x-spatie-alert />`, where `spatie` is the prefix you provided during registration.
|
||||
|
||||
Calling `hasViewComponents` will also make view components publishable, and will be published
|
||||
to `app/Views/Components/vendor/<package name>`.
|
||||
|
||||
Users of your package will be able to publish the view components with this command:
|
||||
|
||||
```bash
|
||||
php artisan vendor:publish --tag=your-package-name-components
|
||||
```
|
||||
|
||||
### Working with view composers
|
||||
|
||||
You can register any view composers that your project uses with the `hasViewComposers` method. You may also register a
|
||||
callback that receives a `$view` argument instead of a classname.
|
||||
|
||||
To register a view composer with all views, use an asterisk as the view name `'*'`.
|
||||
|
||||
```php
|
||||
$package
|
||||
->name('your-package-name')
|
||||
->hasViewComposer('viewName', MyViewComposer::class)
|
||||
->hasViewComposer('*', function($view) {
|
||||
$view->with('sharedVariable', 123);
|
||||
});
|
||||
```
|
||||
|
||||
### Working with inertia components
|
||||
|
||||
Any `.vue` or `.jsx` files your package provides, should be placed in the `<package root>/resources/js/Pages` directory.
|
||||
|
||||
You can register these components with the `hasInertiaComponents` command.
|
||||
|
||||
```php
|
||||
$package
|
||||
->name('your-package-name')
|
||||
->hasInertiaComponents();
|
||||
```
|
||||
|
||||
This will register your components with Laravel.
|
||||
|
||||
The user should publish the inertia components manually or using the [installer-command](#adding-an-installer-command) in order to use them.
|
||||
|
||||
If you have an inertia component `<package root>/resources/js/Pages/myComponent.vue`, you can use it like
|
||||
this: `Inertia::render('YourPackageName/myComponent')`. Of course, you can also use subdirectories to organise your components.
|
||||
|
||||
#### Publishing inertia components
|
||||
|
||||
Calling `hasInertiaComponents` will also make inertia components publishable. Users of your package will be able to publish the views with this
|
||||
command:
|
||||
|
||||
```bash
|
||||
php artisan vendor:publish --tag=your-package-name-inertia-components
|
||||
```
|
||||
|
||||
Also, the inertia components are available in a convenient way with your package [installer-command](#adding-an-installer-command)
|
||||
|
||||
### Working with translations
|
||||
|
||||
Any translations your package provides, should be placed in the `<package root>/resources/lang/<language-code>`
|
||||
directory.
|
||||
|
||||
You can register these translations with the `hasTranslations` command.
|
||||
|
||||
```php
|
||||
$package
|
||||
->name('your-package-name')
|
||||
->hasTranslations();
|
||||
```
|
||||
|
||||
This will register the translations with Laravel.
|
||||
|
||||
Assuming you save this translation file at `<package root>/resources/lang/en/translations.php`...
|
||||
|
||||
```php
|
||||
return [
|
||||
'translatable' => 'translation',
|
||||
];
|
||||
```
|
||||
|
||||
... your package and users will be able to retrieve the translation with:
|
||||
|
||||
```php
|
||||
trans('your-package-name::translations.translatable'); // returns 'translation'
|
||||
```
|
||||
|
||||
If your package name starts with `laravel-` then you should leave that off in the example above.
|
||||
|
||||
Coding with translation strings as keys, you should create JSON files
|
||||
in `<package root>/resources/lang/<language-code>.json`.
|
||||
|
||||
For example, creating `<package root>/resources/lang/it.json` file like so:
|
||||
|
||||
```json
|
||||
{
|
||||
"Hello!": "Ciao!"
|
||||
}
|
||||
```
|
||||
|
||||
...the output of...
|
||||
|
||||
```php
|
||||
trans('Hello!');
|
||||
```
|
||||
|
||||
...will be `Ciao!` if the application uses the Italian language.
|
||||
|
||||
Calling `hasTranslations` will also make translations publishable. Users of your package will be able to publish the
|
||||
translations with this command:
|
||||
|
||||
```bash
|
||||
php artisan vendor:publish --tag=your-package-name-translations
|
||||
```
|
||||
|
||||
### Working with assets
|
||||
|
||||
Any assets your package provides, should be placed in the `<package root>/resources/dist/` directory.
|
||||
|
||||
You can make these assets publishable the `hasAssets` method.
|
||||
|
||||
```php
|
||||
$package
|
||||
->name('your-package-name')
|
||||
->hasAssets();
|
||||
```
|
||||
|
||||
Users of your package will be able to publish the assets with this command:
|
||||
|
||||
```bash
|
||||
php artisan vendor:publish --tag=your-package-name-assets
|
||||
```
|
||||
|
||||
This will copy over the assets to the `public/vendor/<your-package-name>` directory in the app where your package is
|
||||
installed in.
|
||||
|
||||
### Working with migrations
|
||||
|
||||
The `PackageServiceProvider` assumes that any migrations are placed in this
|
||||
directory: `<package root>/database/migrations`. Inside that directory you can put any migrations.
|
||||
|
||||
To register your migration, you should pass its name without the extension to the `hasMigration` table.
|
||||
|
||||
If your migration file is called `create_my_package_tables.php.stub` you can register them like this:
|
||||
|
||||
```php
|
||||
$package
|
||||
->name('your-package-name')
|
||||
->hasMigration('create_my_package_tables');
|
||||
```
|
||||
|
||||
Should your package contain multiple migration files, you can just call `hasMigration` multiple times or
|
||||
use `hasMigrations`.
|
||||
|
||||
```php
|
||||
$package
|
||||
->name('your-package-name')
|
||||
->hasMigrations(['my_package_tables', 'some_other_migration']);
|
||||
```
|
||||
|
||||
Calling `hasMigration` will also make migrations publishable. Users of your package will be able to publish the
|
||||
migrations with this command:
|
||||
|
||||
```bash
|
||||
php artisan vendor:publish --tag=your-package-name-migrations
|
||||
```
|
||||
|
||||
Like you might expect, published migration files will be prefixed with the current datetime.
|
||||
|
||||
You can also enable the migrations to be registered without needing the users of your package to publish them:
|
||||
|
||||
```php
|
||||
$package
|
||||
->name('your-package-name')
|
||||
->hasMigrations(['my_package_tables', 'some_other_migration'])
|
||||
->runsMigrations();
|
||||
```
|
||||
|
||||
### Working with a publishable service provider
|
||||
|
||||
Some packages need an example service provider to be copied into the `app\Providers` directory of the Laravel app. Think
|
||||
of for instance, the `laravel/horizon` package that copies an `HorizonServiceProvider` into your app with some sensible
|
||||
defaults.
|
||||
|
||||
```php
|
||||
$package
|
||||
->name('your-package-name')
|
||||
->publishesServiceProvider($nameOfYourServiceProvider);
|
||||
```
|
||||
|
||||
The file that will be copied to the app should be stored in your package
|
||||
in `/resources/stubs/{$nameOfYourServiceProvider}.php.stub`.
|
||||
|
||||
When your package is installed into an app, running this command...
|
||||
|
||||
```bash
|
||||
php artisan vendor:publish --tag=your-package-name-provider
|
||||
```
|
||||
|
||||
... will copy `/resources/stubs/{$nameOfYourServiceProvider}.php.stub` in your package
|
||||
to `app/Providers/{$nameOfYourServiceProvider}.php` in the app of the user.
|
||||
|
||||
### Registering commands
|
||||
|
||||
You can register any command you package provides with the `hasCommand` function.
|
||||
|
||||
```php
|
||||
$package
|
||||
->name('your-package-name')
|
||||
->hasCommand(YourCoolPackageCommand::class);
|
||||
````
|
||||
|
||||
If your package provides multiple commands, you can either use `hasCommand` multiple times, or pass an array
|
||||
to `hasCommands`
|
||||
|
||||
```php
|
||||
$package
|
||||
->name('your-package-name')
|
||||
->hasCommands([
|
||||
YourCoolPackageCommand::class,
|
||||
YourOtherCoolPackageCommand::class,
|
||||
]);
|
||||
```
|
||||
|
||||
### Adding an installer command
|
||||
|
||||
Instead of letting your users manually publishing config files, migrations, and other files manually, you could opt to
|
||||
add an install command that does all this work in one go. Packages like Laravel Horizon and Livewire provide such
|
||||
commands.
|
||||
|
||||
When using Laravel Package Tools, you don't have to write an `InstallCommand` yourself. Instead, you can simply
|
||||
call, `hasInstallCommand` and configure it using a closure. Here's an example.
|
||||
|
||||
```php
|
||||
use Spatie\LaravelPackageTools\PackageServiceProvider;
|
||||
use Spatie\LaravelPackageTools\Package;
|
||||
use Spatie\LaravelPackageTools\Commands\InstallCommand;
|
||||
|
||||
class YourPackageServiceProvider extends PackageServiceProvider
|
||||
{
|
||||
public function configurePackage(Package $package): void
|
||||
{
|
||||
$package
|
||||
->name('your-package-name')
|
||||
->hasConfigFile()
|
||||
->hasMigration('create_package_tables')
|
||||
->publishesServiceProvider('MyServiceProviderName')
|
||||
->hasInstallCommand(function(InstallCommand $command) {
|
||||
$command
|
||||
->publishConfigFile()
|
||||
->publishAssets()
|
||||
->publishMigrations()
|
||||
->askToRunMigrations()
|
||||
->copyAndRegisterServiceProviderInApp()
|
||||
->askToStarRepoOnGitHub('your-vendor/your-repo-name')
|
||||
});
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
With this in place, the package user can call this command:
|
||||
|
||||
```bash
|
||||
php artisan your-package-name:install
|
||||
```
|
||||
|
||||
Using the code above, that command will:
|
||||
|
||||
- publish the config file
|
||||
- publish the assets
|
||||
- publish the migrations
|
||||
- copy the `/resources/stubs/MyProviderName.php.stub` from your package to `app/Providers/MyServiceProviderName.php`, and also register that
|
||||
provider in `config/app.php`
|
||||
- ask if migrations should be run now
|
||||
- prompt the user to open up `https://github.com/'your-vendor/your-repo-name'` in the browser in order to star it
|
||||
|
||||
You can also call `startWith` and `endWith` on the `InstallCommand`. They will respectively be executed at the start and
|
||||
end when running `php artisan your-package-name:install`. You can use this to perform extra work or display extra
|
||||
output.
|
||||
|
||||
```php
|
||||
use Spatie\LaravelPackageTools\Commands\InstallCommand;
|
||||
|
||||
public function configurePackage(Package $package): void
|
||||
{
|
||||
$package
|
||||
// ... configure package
|
||||
->hasInstallCommand(function(InstallCommand $command) {
|
||||
$command
|
||||
->startWith(function(InstallCommand $command) {
|
||||
$command->info('Hello, and welcome to my great new package!');
|
||||
})
|
||||
->publishConfigFile()
|
||||
->publishAssets()
|
||||
->publishMigrations()
|
||||
->askToRunMigrations()
|
||||
->copyAndRegisterServiceProviderInApp()
|
||||
->askToStarRepoOnGitHub('your-vendor/your-repo-name')
|
||||
->endWith(function(InstallCommand $command) {
|
||||
$command->info('Have a great day!');
|
||||
})
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
### Working with routes
|
||||
|
||||
The `PackageServiceProvider` assumes that any route files are placed in this directory: `<package root>/routes`. Inside
|
||||
that directory you can put any route files.
|
||||
|
||||
To register your route, you should pass its name without the extension to the `hasRoute` method.
|
||||
|
||||
If your route file is called `web.php` you can register them like this:
|
||||
|
||||
```php
|
||||
$package
|
||||
->name('your-package-name')
|
||||
->hasRoute('web');
|
||||
```
|
||||
|
||||
Should your package contain multiple route files, you can just call `hasRoute` multiple times or use `hasRoutes`.
|
||||
|
||||
```php
|
||||
$package
|
||||
->name('your-package-name')
|
||||
->hasRoutes(['web', 'admin']);
|
||||
```
|
||||
|
||||
### Using lifecycle hooks
|
||||
|
||||
You can put any custom logic your package needs while starting up in one of these methods:
|
||||
|
||||
- `registeringPackage`: will be called at the start of the `register` method of `PackageServiceProvider`
|
||||
- `packageRegistered`: will be called at the end of the `register` method of `PackageServiceProvider`
|
||||
- `bootingPackage`: will be called at the start of the `boot` method of `PackageServiceProvider`
|
||||
- `packageBooted`: will be called at the end of the `boot` method of `PackageServiceProvider`
|
||||
|
||||
## Testing
|
||||
|
||||
```bash
|
||||
composer test
|
||||
```
|
||||
|
||||
## Changelog
|
||||
|
||||
Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.
|
||||
|
||||
## Contributing
|
||||
|
||||
Please see [CONTRIBUTING](https://github.com/spatie/.github/blob/main/CONTRIBUTING.md) for details.
|
||||
|
||||
## Security Vulnerabilities
|
||||
|
||||
Please review [our security policy](../../security/policy) on how to report security vulnerabilities.
|
||||
|
||||
## 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.
|
||||
50
vendor/spatie/laravel-package-tools/composer.json
vendored
Normal file
50
vendor/spatie/laravel-package-tools/composer.json
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
{
|
||||
"name": "spatie/laravel-package-tools",
|
||||
"description": "Tools for creating Laravel packages",
|
||||
"keywords": [
|
||||
"spatie",
|
||||
"laravel-package-tools"
|
||||
],
|
||||
"homepage": "https://github.com/spatie/laravel-package-tools",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Freek Van der Herten",
|
||||
"email": "freek@spatie.be",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": "^8.0",
|
||||
"illuminate/contracts": "^9.28|^10.0|^11.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"mockery/mockery": "^1.5",
|
||||
"orchestra/testbench": "^7.7|^8.0",
|
||||
"pestphp/pest": "^1.22",
|
||||
"phpunit/phpunit": "^9.5.24",
|
||||
"spatie/pest-plugin-test-time": "^1.1"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Spatie\\LaravelPackageTools\\": "src"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Spatie\\LaravelPackageTools\\Tests\\": "tests"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"test": "vendor/bin/pest",
|
||||
"test-coverage": "vendor/bin/pest --coverage"
|
||||
},
|
||||
"config": {
|
||||
"sort-packages": true,
|
||||
"allow-plugins": {
|
||||
"pestphp/pest-plugin": true
|
||||
}
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
"prefer-stable": true
|
||||
}
|
||||
199
vendor/spatie/laravel-package-tools/src/Commands/InstallCommand.php
vendored
Normal file
199
vendor/spatie/laravel-package-tools/src/Commands/InstallCommand.php
vendored
Normal file
@@ -0,0 +1,199 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelPackageTools\Commands;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Str;
|
||||
use Spatie\LaravelPackageTools\Package;
|
||||
|
||||
class InstallCommand extends Command
|
||||
{
|
||||
protected Package $package;
|
||||
|
||||
public ?Closure $startWith = null;
|
||||
|
||||
protected array $publishes = [];
|
||||
|
||||
protected bool $askToRunMigrations = false;
|
||||
|
||||
protected bool $copyServiceProviderInApp = false;
|
||||
|
||||
protected ?string $starRepo = null;
|
||||
|
||||
public ?Closure $endWith = null;
|
||||
|
||||
public $hidden = true;
|
||||
|
||||
public function __construct(Package $package)
|
||||
{
|
||||
$this->signature = $package->shortName() . ':install';
|
||||
|
||||
$this->description = 'Install ' . $package->name;
|
||||
|
||||
$this->package = $package;
|
||||
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
public function handle()
|
||||
{
|
||||
if ($this->startWith) {
|
||||
($this->startWith)($this);
|
||||
}
|
||||
|
||||
foreach ($this->publishes as $tag) {
|
||||
$name = str_replace('-', ' ', $tag);
|
||||
$this->comment("Publishing {$name}...");
|
||||
|
||||
$this->callSilently("vendor:publish", [
|
||||
'--tag' => "{$this->package->shortName()}-{$tag}",
|
||||
]);
|
||||
}
|
||||
|
||||
if ($this->askToRunMigrations) {
|
||||
if ($this->confirm('Would you like to run the migrations now?')) {
|
||||
$this->comment('Running migrations...');
|
||||
|
||||
$this->call('migrate');
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->copyServiceProviderInApp) {
|
||||
$this->comment('Publishing service provider...');
|
||||
|
||||
$this->copyServiceProviderInApp();
|
||||
}
|
||||
|
||||
if ($this->starRepo) {
|
||||
if ($this->confirm('Would you like to star our repo on GitHub?')) {
|
||||
$repoUrl = "https://github.com/{$this->starRepo}";
|
||||
|
||||
if (PHP_OS_FAMILY == 'Darwin') {
|
||||
exec("open {$repoUrl}");
|
||||
}
|
||||
if (PHP_OS_FAMILY == 'Windows') {
|
||||
exec("start {$repoUrl}");
|
||||
}
|
||||
if (PHP_OS_FAMILY == 'Linux') {
|
||||
exec("xdg-open {$repoUrl}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->info("{$this->package->shortName()} has been installed!");
|
||||
|
||||
if ($this->endWith) {
|
||||
($this->endWith)($this);
|
||||
}
|
||||
}
|
||||
|
||||
public function publish(string ...$tag): self
|
||||
{
|
||||
$this->publishes = array_merge($this->publishes, $tag);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function publishConfigFile(): self
|
||||
{
|
||||
return $this->publish('config');
|
||||
}
|
||||
|
||||
public function publishAssets(): self
|
||||
{
|
||||
return $this->publish('assets');
|
||||
}
|
||||
|
||||
public function publishInertiaComponents(): self
|
||||
{
|
||||
return $this->publish('inertia-components');
|
||||
}
|
||||
|
||||
public function publishMigrations(): self
|
||||
{
|
||||
return $this->publish('migrations');
|
||||
}
|
||||
|
||||
public function askToRunMigrations(): self
|
||||
{
|
||||
$this->askToRunMigrations = true;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function copyAndRegisterServiceProviderInApp(): self
|
||||
{
|
||||
$this->copyServiceProviderInApp = true;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function askToStarRepoOnGitHub($vendorSlashRepoName): self
|
||||
{
|
||||
$this->starRepo = $vendorSlashRepoName;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function startWith($callable): self
|
||||
{
|
||||
$this->startWith = $callable;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function endWith($callable): self
|
||||
{
|
||||
$this->endWith = $callable;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function copyServiceProviderInApp(): self
|
||||
{
|
||||
$providerName = $this->package->publishableProviderName;
|
||||
|
||||
if (! $providerName) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$this->callSilent('vendor:publish', ['--tag' => $this->package->shortName() . '-provider']);
|
||||
|
||||
$namespace = Str::replaceLast('\\', '', $this->laravel->getNamespace());
|
||||
|
||||
if (intval(app()->version()) < 11 || ! file_exists(base_path('bootstrap/providers.php'))) {
|
||||
$appConfig = file_get_contents(config_path('app.php'));
|
||||
} else {
|
||||
$appConfig = file_get_contents(base_path('bootstrap/providers.php'));
|
||||
}
|
||||
|
||||
$class = '\\Providers\\' . $providerName . '::class';
|
||||
|
||||
if (Str::contains($appConfig, $namespace . $class)) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
if (intval(app()->version()) < 11 || ! file_exists(base_path('bootstrap/providers.php'))) {
|
||||
file_put_contents(config_path('app.php'), str_replace(
|
||||
"{$namespace}\\Providers\\BroadcastServiceProvider::class,",
|
||||
"{$namespace}\\Providers\\BroadcastServiceProvider::class," . PHP_EOL . " {$namespace}{$class},",
|
||||
$appConfig
|
||||
));
|
||||
} else {
|
||||
file_put_contents(base_path('bootstrap/providers.php'), str_replace(
|
||||
"{$namespace}\\Providers\\AppServiceProvider::class,",
|
||||
"{$namespace}\\Providers\\AppServiceProvider::class," . PHP_EOL . " {$namespace}{$class},",
|
||||
$appConfig
|
||||
));
|
||||
}
|
||||
|
||||
file_put_contents(app_path('Providers/' . $providerName . '.php'), str_replace(
|
||||
"namespace App\Providers;",
|
||||
"namespace {$namespace}\Providers;",
|
||||
file_get_contents(app_path('Providers/' . $providerName . '.php'))
|
||||
));
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
13
vendor/spatie/laravel-package-tools/src/Exceptions/InvalidPackage.php
vendored
Normal file
13
vendor/spatie/laravel-package-tools/src/Exceptions/InvalidPackage.php
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelPackageTools\Exceptions;
|
||||
|
||||
use Exception;
|
||||
|
||||
class InvalidPackage extends Exception
|
||||
{
|
||||
public static function nameIsRequired(): self
|
||||
{
|
||||
return new static('This package does not have a name. You can set one with `$package->name("yourName")`');
|
||||
}
|
||||
}
|
||||
241
vendor/spatie/laravel-package-tools/src/Package.php
vendored
Normal file
241
vendor/spatie/laravel-package-tools/src/Package.php
vendored
Normal file
@@ -0,0 +1,241 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelPackageTools;
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
use Spatie\LaravelPackageTools\Commands\InstallCommand;
|
||||
|
||||
class Package
|
||||
{
|
||||
public string $name;
|
||||
|
||||
public array $configFileNames = [];
|
||||
|
||||
public bool $hasViews = false;
|
||||
|
||||
public bool $hasInertiaComponents = false;
|
||||
|
||||
public ?string $viewNamespace = null;
|
||||
|
||||
public bool $hasTranslations = false;
|
||||
|
||||
public bool $hasAssets = false;
|
||||
|
||||
public bool $runsMigrations = false;
|
||||
|
||||
public array $migrationFileNames = [];
|
||||
|
||||
public array $routeFileNames = [];
|
||||
|
||||
public array $commands = [];
|
||||
|
||||
public array $consoleCommands = [];
|
||||
|
||||
public array $viewComponents = [];
|
||||
|
||||
public array $sharedViewData = [];
|
||||
|
||||
public array $viewComposers = [];
|
||||
|
||||
public string $basePath;
|
||||
|
||||
public ?string $publishableProviderName = null;
|
||||
|
||||
public function name(string $name): static
|
||||
{
|
||||
$this->name = $name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function hasConfigFile($configFileName = null): static
|
||||
{
|
||||
$configFileName ??= $this->shortName();
|
||||
|
||||
if (! is_array($configFileName)) {
|
||||
$configFileName = [$configFileName];
|
||||
}
|
||||
|
||||
$this->configFileNames = $configFileName;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function publishesServiceProvider(string $providerName): static
|
||||
{
|
||||
$this->publishableProviderName = $providerName;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function hasInstallCommand($callable): static
|
||||
{
|
||||
$installCommand = new InstallCommand($this);
|
||||
|
||||
$callable($installCommand);
|
||||
|
||||
$this->consoleCommands[] = $installCommand;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function shortName(): string
|
||||
{
|
||||
return Str::after($this->name, 'laravel-');
|
||||
}
|
||||
|
||||
public function hasViews(string $namespace = null): static
|
||||
{
|
||||
$this->hasViews = true;
|
||||
|
||||
$this->viewNamespace = $namespace;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function hasInertiaComponents(string $namespace = null): static
|
||||
{
|
||||
$this->hasInertiaComponents = true;
|
||||
|
||||
$this->viewNamespace = $namespace;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function hasViewComponent(string $prefix, string $viewComponentName): static
|
||||
{
|
||||
$this->viewComponents[$viewComponentName] = $prefix;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function hasViewComponents(string $prefix, ...$viewComponentNames): static
|
||||
{
|
||||
foreach ($viewComponentNames as $componentName) {
|
||||
$this->viewComponents[$componentName] = $prefix;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function sharesDataWithAllViews(string $name, $value): static
|
||||
{
|
||||
$this->sharedViewData[$name] = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function hasViewComposer($view, $viewComposer): static
|
||||
{
|
||||
if (! is_array($view)) {
|
||||
$view = [$view];
|
||||
}
|
||||
|
||||
foreach ($view as $viewName) {
|
||||
$this->viewComposers[$viewName] = $viewComposer;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function hasTranslations(): static
|
||||
{
|
||||
$this->hasTranslations = true;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function hasAssets(): static
|
||||
{
|
||||
$this->hasAssets = true;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function runsMigrations(bool $runsMigrations = true): static
|
||||
{
|
||||
$this->runsMigrations = $runsMigrations;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function hasMigration(string $migrationFileName): static
|
||||
{
|
||||
$this->migrationFileNames[] = $migrationFileName;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function hasMigrations(...$migrationFileNames): static
|
||||
{
|
||||
$this->migrationFileNames = array_merge(
|
||||
$this->migrationFileNames,
|
||||
collect($migrationFileNames)->flatten()->toArray()
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function hasCommand(string $commandClassName): static
|
||||
{
|
||||
$this->commands[] = $commandClassName;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function hasCommands(...$commandClassNames): static
|
||||
{
|
||||
$this->commands = array_merge($this->commands, collect($commandClassNames)->flatten()->toArray());
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function hasConsoleCommand(string $commandClassName): static
|
||||
{
|
||||
$this->consoleCommands[] = $commandClassName;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function hasConsoleCommands(...$commandClassNames): static
|
||||
{
|
||||
$this->consoleCommands = array_merge($this->consoleCommands, collect($commandClassNames)->flatten()->toArray());
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function hasRoute(string $routeFileName): static
|
||||
{
|
||||
$this->routeFileNames[] = $routeFileName;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function hasRoutes(...$routeFileNames): static
|
||||
{
|
||||
$this->routeFileNames = array_merge($this->routeFileNames, collect($routeFileNames)->flatten()->toArray());
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function basePath(string $directory = null): string
|
||||
{
|
||||
if ($directory === null) {
|
||||
return $this->basePath;
|
||||
}
|
||||
|
||||
return $this->basePath . DIRECTORY_SEPARATOR . ltrim($directory, DIRECTORY_SEPARATOR);
|
||||
}
|
||||
|
||||
public function viewNamespace(): string
|
||||
{
|
||||
return $this->viewNamespace ?? $this->shortName();
|
||||
}
|
||||
|
||||
public function setBasePath(string $path): static
|
||||
{
|
||||
$this->basePath = $path;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
216
vendor/spatie/laravel-package-tools/src/PackageServiceProvider.php
vendored
Normal file
216
vendor/spatie/laravel-package-tools/src/PackageServiceProvider.php
vendored
Normal file
@@ -0,0 +1,216 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelPackageTools;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Facades\View;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Illuminate\Support\Str;
|
||||
use ReflectionClass;
|
||||
use Spatie\LaravelPackageTools\Exceptions\InvalidPackage;
|
||||
|
||||
abstract class PackageServiceProvider extends ServiceProvider
|
||||
{
|
||||
protected Package $package;
|
||||
|
||||
abstract public function configurePackage(Package $package): void;
|
||||
|
||||
public function register()
|
||||
{
|
||||
$this->registeringPackage();
|
||||
|
||||
$this->package = $this->newPackage();
|
||||
|
||||
$this->package->setBasePath($this->getPackageBaseDir());
|
||||
|
||||
$this->configurePackage($this->package);
|
||||
|
||||
if (empty($this->package->name)) {
|
||||
throw InvalidPackage::nameIsRequired();
|
||||
}
|
||||
|
||||
foreach ($this->package->configFileNames as $configFileName) {
|
||||
$this->mergeConfigFrom($this->package->basePath("/../config/{$configFileName}.php"), $configFileName);
|
||||
}
|
||||
|
||||
$this->packageRegistered();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function newPackage(): Package
|
||||
{
|
||||
return new Package();
|
||||
}
|
||||
|
||||
public function boot()
|
||||
{
|
||||
$this->bootingPackage();
|
||||
|
||||
if ($this->package->hasTranslations) {
|
||||
$langPath = 'vendor/' . $this->package->shortName();
|
||||
|
||||
$langPath = (function_exists('lang_path'))
|
||||
? lang_path($langPath)
|
||||
: resource_path('lang/' . $langPath);
|
||||
}
|
||||
|
||||
if ($this->app->runningInConsole()) {
|
||||
foreach ($this->package->configFileNames as $configFileName) {
|
||||
$this->publishes([
|
||||
$this->package->basePath("/../config/{$configFileName}.php") => config_path("{$configFileName}.php"),
|
||||
], "{$this->package->shortName()}-config");
|
||||
}
|
||||
|
||||
if ($this->package->hasViews) {
|
||||
$this->publishes([
|
||||
$this->package->basePath('/../resources/views') => base_path("resources/views/vendor/{$this->packageView($this->package->viewNamespace)}"),
|
||||
], "{$this->packageView($this->package->viewNamespace)}-views");
|
||||
}
|
||||
|
||||
if ($this->package->hasInertiaComponents) {
|
||||
$packageDirectoryName = Str::of($this->packageView($this->package->viewNamespace))->studly()->remove('-')->value();
|
||||
|
||||
$this->publishes([
|
||||
$this->package->basePath('/../resources/js/Pages') => base_path("resources/js/Pages/{$packageDirectoryName}"),
|
||||
], "{$this->packageView($this->package->viewNamespace)}-inertia-components");
|
||||
}
|
||||
|
||||
$now = Carbon::now();
|
||||
foreach ($this->package->migrationFileNames as $migrationFileName) {
|
||||
$filePath = $this->package->basePath("/../database/migrations/{$migrationFileName}.php");
|
||||
if (! file_exists($filePath)) {
|
||||
// Support for the .stub file extension
|
||||
$filePath .= '.stub';
|
||||
}
|
||||
|
||||
$this->publishes([
|
||||
$filePath => $this->generateMigrationName(
|
||||
$migrationFileName,
|
||||
$now->addSecond()
|
||||
), ], "{$this->package->shortName()}-migrations");
|
||||
|
||||
if ($this->package->runsMigrations) {
|
||||
$this->loadMigrationsFrom($filePath);
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->package->hasTranslations) {
|
||||
$this->publishes([
|
||||
$this->package->basePath('/../resources/lang') => $langPath,
|
||||
], "{$this->package->shortName()}-translations");
|
||||
}
|
||||
|
||||
if ($this->package->hasAssets) {
|
||||
$this->publishes([
|
||||
$this->package->basePath('/../resources/dist') => public_path("vendor/{$this->package->shortName()}"),
|
||||
], "{$this->package->shortName()}-assets");
|
||||
}
|
||||
}
|
||||
|
||||
if (! empty($this->package->commands)) {
|
||||
$this->commands($this->package->commands);
|
||||
}
|
||||
|
||||
if (! empty($this->package->consoleCommands) && $this->app->runningInConsole()) {
|
||||
$this->commands($this->package->consoleCommands);
|
||||
}
|
||||
|
||||
if ($this->package->hasTranslations) {
|
||||
$this->loadTranslationsFrom(
|
||||
$this->package->basePath('/../resources/lang/'),
|
||||
$this->package->shortName()
|
||||
);
|
||||
|
||||
$this->loadJsonTranslationsFrom($this->package->basePath('/../resources/lang/'));
|
||||
|
||||
$this->loadJsonTranslationsFrom($langPath);
|
||||
}
|
||||
|
||||
if ($this->package->hasViews) {
|
||||
$this->loadViewsFrom($this->package->basePath('/../resources/views'), $this->package->viewNamespace());
|
||||
}
|
||||
|
||||
foreach ($this->package->viewComponents as $componentClass => $prefix) {
|
||||
$this->loadViewComponentsAs($prefix, [$componentClass]);
|
||||
}
|
||||
|
||||
if (count($this->package->viewComponents)) {
|
||||
$this->publishes([
|
||||
$this->package->basePath('/Components') => base_path("app/View/Components/vendor/{$this->package->shortName()}"),
|
||||
], "{$this->package->name}-components");
|
||||
}
|
||||
|
||||
if ($this->package->publishableProviderName) {
|
||||
$this->publishes([
|
||||
$this->package->basePath("/../resources/stubs/{$this->package->publishableProviderName}.php.stub") => base_path("app/Providers/{$this->package->publishableProviderName}.php"),
|
||||
], "{$this->package->shortName()}-provider");
|
||||
}
|
||||
|
||||
|
||||
foreach ($this->package->routeFileNames as $routeFileName) {
|
||||
$this->loadRoutesFrom("{$this->package->basePath('/../routes/')}{$routeFileName}.php");
|
||||
}
|
||||
|
||||
foreach ($this->package->sharedViewData as $name => $value) {
|
||||
View::share($name, $value);
|
||||
}
|
||||
|
||||
foreach ($this->package->viewComposers as $viewName => $viewComposer) {
|
||||
View::composer($viewName, $viewComposer);
|
||||
}
|
||||
|
||||
$this->packageBooted();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public static function generateMigrationName(string $migrationFileName, Carbon $now): string
|
||||
{
|
||||
$migrationsPath = 'migrations/' . dirname($migrationFileName) . '/';
|
||||
$migrationFileName = basename($migrationFileName);
|
||||
|
||||
$len = strlen($migrationFileName) + 4;
|
||||
|
||||
if (Str::contains($migrationFileName, '/')) {
|
||||
$migrationsPath .= Str::of($migrationFileName)->beforeLast('/')->finish('/');
|
||||
$migrationFileName = Str::of($migrationFileName)->afterLast('/');
|
||||
}
|
||||
|
||||
foreach (glob(database_path("{$migrationsPath}*.php")) as $filename) {
|
||||
if ((substr($filename, -$len) === $migrationFileName . '.php')) {
|
||||
return $filename;
|
||||
}
|
||||
}
|
||||
|
||||
return database_path($migrationsPath . $now->format('Y_m_d_His') . '_' . Str::of($migrationFileName)->snake()->finish('.php'));
|
||||
}
|
||||
|
||||
public function registeringPackage()
|
||||
{
|
||||
}
|
||||
|
||||
public function packageRegistered()
|
||||
{
|
||||
}
|
||||
|
||||
public function bootingPackage()
|
||||
{
|
||||
}
|
||||
|
||||
public function packageBooted()
|
||||
{
|
||||
}
|
||||
|
||||
protected function getPackageBaseDir(): string
|
||||
{
|
||||
$reflector = new ReflectionClass(get_class($this));
|
||||
|
||||
return dirname($reflector->getFileName());
|
||||
}
|
||||
|
||||
public function packageView(?string $namespace)
|
||||
{
|
||||
return is_null($namespace) ? $this->package->shortName() : $this->package->viewNamespace;
|
||||
}
|
||||
}
|
||||
262
vendor/spatie/laravel-settings/CHANGELOG.md
vendored
Normal file
262
vendor/spatie/laravel-settings/CHANGELOG.md
vendored
Normal file
@@ -0,0 +1,262 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to `laravel-settings` will be documented in this file
|
||||
|
||||
# Unreleased
|
||||
|
||||
- Make `spatie/data-transfer-object` dependency optional. (#160)
|
||||
|
||||
## 3.3.1 - 2024-03-13
|
||||
|
||||
### What's Changed
|
||||
|
||||
* fix when base path is app path by @mvenghaus in https://github.com/spatie/laravel-settings/pull/259
|
||||
|
||||
**Full Changelog**: https://github.com/spatie/laravel-settings/compare/3.3.0...3.3.1
|
||||
|
||||
## 3.3.0 - 2024-02-19
|
||||
|
||||
### What's Changed
|
||||
|
||||
* Update composer.json to use Larastan Org by @arnebr in https://github.com/spatie/laravel-settings/pull/252
|
||||
* Add support for laravel 11 by @shuvroroy in https://github.com/spatie/laravel-settings/pull/256
|
||||
* Added settings driven custom encoder/decoder by @naxvog in https://github.com/spatie/laravel-settings/pull/250
|
||||
|
||||
**Full Changelog**: https://github.com/spatie/laravel-settings/compare/3.2.3...3.3.0
|
||||
|
||||
## 3.2.3 - 2023-12-04
|
||||
|
||||
- Revert "Use Illuminate\Database\Eloquent\Casts\Json if possible" (#249)
|
||||
|
||||
## 3.2.2 - 2023-12-01
|
||||
|
||||
- Use Illuminate\Database\Eloquent\Casts\Json if possible (#241)
|
||||
|
||||
## 3.2.1 - 2023-09-15
|
||||
|
||||
- Change provider tag name for config (#233)
|
||||
|
||||
## 3.2.0 - 2023-07-05
|
||||
|
||||
- Add support for database-less fakes
|
||||
|
||||
## 3.1.0 - 2023-05-11
|
||||
|
||||
- Add support for nullable enum properties
|
||||
- Updates to the upgrade guide
|
||||
|
||||
## 3.0.0 - 2023-04-28
|
||||
|
||||
- Allow repositories to update multiple settings at once (#213 )
|
||||
- The default location where searching for settings happens is now `app_path('Settings')` instead of `app_path()`
|
||||
- The default `discovered_settings_cache_path` is changed
|
||||
|
||||
## 2.8.3 - 2023-03-30
|
||||
|
||||
- Remove doctrine as a dependency
|
||||
|
||||
## 2.8.2 - 2023-03-10
|
||||
|
||||
- Fix remigration problems with anonymous settings migrations
|
||||
|
||||
## 2.8.1 - 2023-03-02
|
||||
|
||||
- Show message and target path after setting migration created (#203)
|
||||
- Follow Laravel's namespace convention in MakeSettingCommand (#200)
|
||||
- Update MakeSettingsMigrationCommand.php (#205)
|
||||
- Revert "Add support for structure discoverer"( #207)
|
||||
|
||||
## 2.8.0 - 2023-02-10
|
||||
|
||||
- Drop Laravel 8 support
|
||||
- Drop PHP 8.0 support
|
||||
- Use spatie/structures-discoverer for finding settings
|
||||
|
||||
## 2.7.0 - 2023-02-01
|
||||
|
||||
- Add Laravel 10 Support (#192)
|
||||
- Update make:settings migration class as anonymous class (#189)
|
||||
- Use correct namespace in make:settings command (#190)
|
||||
|
||||
## 2.6.1 - 2023-01-06
|
||||
|
||||
- Add current date to the settings migration file (#178)
|
||||
- Add command to make new settings (#181)
|
||||
|
||||
## 1.6.1 - 2022-12-21
|
||||
|
||||
- create settings migration with current date (#179)
|
||||
|
||||
## 2.6.0 - 2022-11-24
|
||||
|
||||
- Add support for caching on repository level
|
||||
|
||||
## 2.5.0 - 2022-11-10
|
||||
|
||||
- Remove deprecated package
|
||||
- Add laravel data cast
|
||||
- Add support for PHP 8.2
|
||||
- Remove PHP 7.4 support
|
||||
- Remove dto cast from default config
|
||||
|
||||
## 2.4.5 - 2022-09-28
|
||||
|
||||
- Add deleteIfExists() method to migrator (#154)
|
||||
|
||||
## 2.4.4 - 2022-09-07
|
||||
|
||||
- cache encrypted settings
|
||||
|
||||
Please, be sure to clear your cache since settings classes with encrypted properties will crash due to the cached versions missing a proper encrypted version of the property. Clearing and caching again after installing this version resolves this problem and is something you probably should always do when deploying to production!
|
||||
|
||||
## 2.4.3 - 2022-08-10
|
||||
|
||||
- add rollback to migration
|
||||
|
||||
## 2.4.2 - 2022-06-17
|
||||
|
||||
- use Facade imports instead of aliases (#132)
|
||||
|
||||
## 2.4.1 - 2022-04-07
|
||||
|
||||
- Switch to using scoped instances instead of singletons (#129)
|
||||
|
||||
## 2.4.0 - 2022-03-22
|
||||
|
||||
## What's Changed
|
||||
|
||||
- Add TTL config for settings cache by @AlexVanderbist in https://github.com/spatie/laravel-settings/pull/122
|
||||
|
||||
## New Contributors
|
||||
|
||||
- @AlexVanderbist made their first contribution in https://github.com/spatie/laravel-settings/pull/122
|
||||
|
||||
**Full Changelog**: https://github.com/spatie/laravel-settings/compare/2.3.3...2.4.0
|
||||
|
||||
## 2.3.3 - 2022-03-18
|
||||
|
||||
- fix debug info method
|
||||
- convert PHPUnit to Pest (#118)
|
||||
|
||||
## 2.3.2 - 2022-02-25
|
||||
|
||||
- Allow migrations without a value (#113)
|
||||
|
||||
## 2.3.1 - 2022-02-04
|
||||
|
||||
- Add support for Laravel 9
|
||||
- Fix cache implementation with casts
|
||||
- Remove Psalm
|
||||
- Add PHPStan
|
||||
|
||||
## 2.2.0 - 2021-10-22
|
||||
|
||||
- add support for multiple migration paths (#92)
|
||||
|
||||
## 2.1.12 - 2021-10-14
|
||||
|
||||
- add possibility to check if setting is locked or unlocked (#89)
|
||||
|
||||
## 2.1.11 - 2021-08-23
|
||||
|
||||
- ignore abstract classes when discovering settings (#84)
|
||||
|
||||
## 2.1.10 - 2021-08-17
|
||||
|
||||
- add support for `null` in DateTime casts
|
||||
|
||||
## 2.1.9 - 2021-07-08
|
||||
|
||||
- fix `empty` call not working when properties weren't loaded
|
||||
|
||||
## 2.1.8 - 2021-06-21
|
||||
|
||||
- fix fake settings not working with `Arrayable`
|
||||
|
||||
## 2.1.7 - 2021-06-08
|
||||
|
||||
- add support for refreshing settings
|
||||
|
||||
## 2.1.6 - 2021-06-03
|
||||
|
||||
- add support for defining the database connection table
|
||||
|
||||
## 2.1.5 - 2021-05-21
|
||||
|
||||
- fix some casting problems
|
||||
- update php-cs-fixer
|
||||
|
||||
## 2.1.4 - 2021-04-28
|
||||
|
||||
- added fallback for settings.auto_discover_settings (#63)
|
||||
- add support for spatie/data-transfer-object v3 (#62)
|
||||
|
||||
## 2.1.3 - 2021-04-14
|
||||
|
||||
- add support for spatie/temporary-directory v2
|
||||
|
||||
## 2.1.2 - 2021-04-08
|
||||
|
||||
- skip classes with errors when discovering settings
|
||||
|
||||
## 2.1.1 - 2021-04-07
|
||||
|
||||
- add better support for nullable types in docblocks
|
||||
|
||||
## 2.1.0 - 2021-04-07
|
||||
|
||||
- add casts to migrations (#53)
|
||||
- add original properties to `SavingSettings` event (#57)
|
||||
|
||||
## 2.0.1 - 2021-03-05
|
||||
|
||||
- add support for lumen
|
||||
|
||||
## 2.0.0 - 2021-03-03
|
||||
|
||||
- settings classes:
|
||||
- properties won't be loaded when constructed but when requested
|
||||
- receive a `SettingsMapper` when constructed
|
||||
- faking settings will now only request non-given properties from the repository
|
||||
- rewritten `SettingsMapper` from scratch
|
||||
- removed `SettingsPropertyData` and `ettingsPropertyDataCollection`
|
||||
- changed signatures of `SavingSettings` and `LoadingSettings` events
|
||||
- added support for caching settings
|
||||
- renamed `cache_path` in settings.php to `discovered_settings_cache_path`
|
||||
|
||||
## 1.0.8 - 2021-03-03
|
||||
|
||||
- fix for properties without defined type
|
||||
|
||||
## 1.0.7 - 2021-02-19
|
||||
|
||||
- fix correct 'Event' facade (#30)
|
||||
|
||||
## 1.0.6 - 2021-02-05
|
||||
|
||||
- add support for restoring settings after a Laravel schema:dump
|
||||
|
||||
## 1.0.5 - 2021-01-29
|
||||
|
||||
- bump the `doctrine/dbal` dependency
|
||||
|
||||
## 1.0.4 - 2021-01-08
|
||||
|
||||
- add support for getting the locked settings
|
||||
|
||||
## 1.0.3 - 2020-11-26
|
||||
|
||||
- add PHP 8 support
|
||||
|
||||
## 1.0.2 - 2020-11-26
|
||||
|
||||
- fix package namespace within migrations (#9)
|
||||
|
||||
## 1.0.1 - 2020-11-18
|
||||
|
||||
- fix config file tag (#4)
|
||||
- fix database migration path exists (#7)
|
||||
|
||||
## 1.0.0 - 2020-11-09
|
||||
|
||||
- initial release
|
||||
21
vendor/spatie/laravel-settings/LICENSE.md
vendored
Normal file
21
vendor/spatie/laravel-settings/LICENSE.md
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
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.
|
||||
1134
vendor/spatie/laravel-settings/README.md
vendored
Normal file
1134
vendor/spatie/laravel-settings/README.md
vendored
Normal file
File diff suppressed because it is too large
Load Diff
50
vendor/spatie/laravel-settings/UPGRADING.md
vendored
Normal file
50
vendor/spatie/laravel-settings/UPGRADING.md
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
# Upgrading
|
||||
|
||||
Because there are many breaking changes an upgrade is not that easy. There are many edge cases this guide does not cover. We accept PRs to improve this guide.
|
||||
|
||||
## From v2 to v3
|
||||
|
||||
This should be a quick update:
|
||||
|
||||
- When creating a new project, the default search location for settings classes will be in the `app_path('Settings')` directory. If you want to keep the old location, then you can set the `auto_discover_settings` option to `app_path()`. For applications which already have published their config, nothing changes.
|
||||
- If you're implementing custom repositories, then update them according to the interface. The method `updatePropertyPayload` is renamed to `updatePropertiesPayload` and should now update multiple properties at once.
|
||||
- Add a new migration with the following content
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('settings', function (Blueprint $table): void {
|
||||
$table->boolean('locked')->default(false)->change();
|
||||
|
||||
$table->unique(['group', 'name']);
|
||||
|
||||
$table->dropIndex(['group']);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('settings', function (Blueprint $table): void {
|
||||
$table->boolean('locked')->default(null)->change();
|
||||
|
||||
$table->dropUnique(['group', 'name']);
|
||||
|
||||
$table->index('group');
|
||||
});
|
||||
}
|
||||
};
|
||||
```
|
||||
75
vendor/spatie/laravel-settings/composer.json
vendored
Normal file
75
vendor/spatie/laravel-settings/composer.json
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
{
|
||||
"name" : "spatie/laravel-settings",
|
||||
"description" : "Store your application settings",
|
||||
"keywords" : [
|
||||
"spatie",
|
||||
"laravel-settings"
|
||||
],
|
||||
"homepage" : "https://github.com/spatie/laravel-settings",
|
||||
"license" : "MIT",
|
||||
"authors" : [
|
||||
{
|
||||
"name" : "Ruben Van Assche",
|
||||
"email" : "ruben@spatie.be",
|
||||
"homepage" : "https://spatie.be",
|
||||
"role" : "Developer"
|
||||
}
|
||||
],
|
||||
"require" : {
|
||||
"php" : "^7.4|^8.0",
|
||||
"ext-json" : "*",
|
||||
"illuminate/database" : "^8.73|^9.0|^10.0|^11.0",
|
||||
"phpdocumentor/type-resolver" : "^1.5",
|
||||
"spatie/temporary-directory" : "^1.3|^2.0"
|
||||
},
|
||||
"require-dev" : {
|
||||
"ext-redis": "*",
|
||||
"mockery/mockery": "^1.4",
|
||||
"larastan/larastan": "^2.0",
|
||||
"orchestra/testbench": "^6.23|^7.0|^8.0|^9.0",
|
||||
"pestphp/pest": "^1.21|^2.0",
|
||||
"pestphp/pest-plugin-laravel": "^1.2|^2.0",
|
||||
"phpstan/extension-installer": "^1.1",
|
||||
"phpstan/phpstan-deprecation-rules": "^1.0",
|
||||
"phpstan/phpstan-phpunit": "^1.0",
|
||||
"phpunit/phpunit": "^9.5|^10.0",
|
||||
"spatie/laravel-data": "^1.0.0|^2.0.0|^4.0.0",
|
||||
"spatie/pest-plugin-snapshots": "^1.1|^2.0",
|
||||
"spatie/phpunit-snapshot-assertions": "^4.2|^5.0",
|
||||
"spatie/ray": "^1.36"
|
||||
},
|
||||
"suggest" : {
|
||||
"spatie/data-transfer-object" : "Allows for DTO casting to settings. (deprecated)"
|
||||
},
|
||||
"autoload" : {
|
||||
"psr-4" : {
|
||||
"Spatie\\LaravelSettings\\" : "src"
|
||||
}
|
||||
},
|
||||
"autoload-dev" : {
|
||||
"psr-4" : {
|
||||
"Spatie\\LaravelSettings\\Tests\\" : "tests"
|
||||
}
|
||||
},
|
||||
"scripts" : {
|
||||
"analyse" : "vendor/bin/phpstan analyse",
|
||||
"test" : "vendor/bin/pest",
|
||||
"test-coverage" : "vendor/bin/pest --coverage"
|
||||
},
|
||||
"config" : {
|
||||
"sort-packages" : true,
|
||||
"allow-plugins" : {
|
||||
"pestphp/pest-plugin" : true,
|
||||
"phpstan/extension-installer" : true
|
||||
}
|
||||
},
|
||||
"extra" : {
|
||||
"laravel" : {
|
||||
"providers" : [
|
||||
"Spatie\\LaravelSettings\\LaravelSettingsServiceProvider"
|
||||
]
|
||||
}
|
||||
},
|
||||
"minimum-stability" : "dev",
|
||||
"prefer-stable" : true
|
||||
}
|
||||
94
vendor/spatie/laravel-settings/config/settings.php
vendored
Normal file
94
vendor/spatie/laravel-settings/config/settings.php
vendored
Normal file
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
* Each settings class used in your application must be registered, you can
|
||||
* put them (manually) here.
|
||||
*/
|
||||
'settings' => [
|
||||
|
||||
],
|
||||
|
||||
/*
|
||||
* The path where the settings classes will be created.
|
||||
*/
|
||||
'setting_class_path' => app_path('Settings'),
|
||||
|
||||
/*
|
||||
* In these directories settings migrations will be stored and ran when migrating. A settings
|
||||
* migration created via the make:settings-migration command will be stored in the first path or
|
||||
* a custom defined path when running the command.
|
||||
*/
|
||||
'migrations_paths' => [
|
||||
database_path('settings'),
|
||||
],
|
||||
|
||||
/*
|
||||
* When no repository was set for a settings class the following repository
|
||||
* will be used for loading and saving settings.
|
||||
*/
|
||||
'default_repository' => 'database',
|
||||
|
||||
/*
|
||||
* Settings will be stored and loaded from these repositories.
|
||||
*/
|
||||
'repositories' => [
|
||||
'database' => [
|
||||
'type' => Spatie\LaravelSettings\SettingsRepositories\DatabaseSettingsRepository::class,
|
||||
'model' => null,
|
||||
'table' => null,
|
||||
'connection' => null,
|
||||
],
|
||||
'redis' => [
|
||||
'type' => Spatie\LaravelSettings\SettingsRepositories\RedisSettingsRepository::class,
|
||||
'connection' => null,
|
||||
'prefix' => null,
|
||||
],
|
||||
],
|
||||
|
||||
/*
|
||||
* The encoder and decoder will determine how settings are stored and
|
||||
* retrieved in the database. By default, `json_encode` and `json_decode`
|
||||
* are used.
|
||||
*/
|
||||
'encoder' => null,
|
||||
'decoder' => null,
|
||||
|
||||
/*
|
||||
* The contents of settings classes can be cached through your application,
|
||||
* settings will be stored within a provided Laravel store and can have an
|
||||
* additional prefix.
|
||||
*/
|
||||
'cache' => [
|
||||
'enabled' => env('SETTINGS_CACHE_ENABLED', false),
|
||||
'store' => null,
|
||||
'prefix' => null,
|
||||
'ttl' => null,
|
||||
],
|
||||
|
||||
/*
|
||||
* These global casts will be automatically used whenever a property within
|
||||
* your settings class isn't a default PHP type.
|
||||
*/
|
||||
'global_casts' => [
|
||||
DateTimeInterface::class => Spatie\LaravelSettings\SettingsCasts\DateTimeInterfaceCast::class,
|
||||
DateTimeZone::class => Spatie\LaravelSettings\SettingsCasts\DateTimeZoneCast::class,
|
||||
// Spatie\DataTransferObject\DataTransferObject::class => Spatie\LaravelSettings\SettingsCasts\DtoCast::class,
|
||||
Spatie\LaravelData\Data::class => Spatie\LaravelSettings\SettingsCasts\DataCast::class,
|
||||
],
|
||||
|
||||
/*
|
||||
* The package will look for settings in these paths and automatically
|
||||
* register them.
|
||||
*/
|
||||
'auto_discover_settings' => [
|
||||
app_path('Settings'),
|
||||
],
|
||||
|
||||
/*
|
||||
* Automatically discovered settings classes can be cached, so they don't
|
||||
* need to be searched each time the application boots up.
|
||||
*/
|
||||
'discovered_settings_cache_path' => base_path('bootstrap/cache'),
|
||||
];
|
||||
24
vendor/spatie/laravel-settings/database/migrations/create_settings_table.php.stub
vendored
Normal file
24
vendor/spatie/laravel-settings/database/migrations/create_settings_table.php.stub
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up()
|
||||
{
|
||||
Schema::create('settings', function (Blueprint $table): void {
|
||||
$table->id();
|
||||
|
||||
$table->string('group');
|
||||
$table->string('name');
|
||||
$table->boolean('locked')->default(false);
|
||||
$table->json('payload');
|
||||
|
||||
$table->timestamps();
|
||||
|
||||
$table->unique(['group', 'name']);
|
||||
});
|
||||
}
|
||||
};
|
||||
36
vendor/spatie/laravel-settings/src/Console/CacheDiscoveredSettingsCommand.php
vendored
Normal file
36
vendor/spatie/laravel-settings/src/Console/CacheDiscoveredSettingsCommand.php
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelSettings\Console;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Filesystem\Filesystem;
|
||||
use Illuminate\Support\Collection;
|
||||
use Spatie\LaravelSettings\SettingsContainer;
|
||||
|
||||
class CacheDiscoveredSettingsCommand extends Command
|
||||
{
|
||||
protected $signature = 'settings:discover';
|
||||
|
||||
protected $description = 'Cache all auto discovered settings';
|
||||
|
||||
public function handle(SettingsContainer $container, Filesystem $files): void
|
||||
{
|
||||
$this->info('Caching registered settings...');
|
||||
|
||||
$container
|
||||
->clearCache()
|
||||
->getSettingClasses()
|
||||
->pipe(function (Collection $settingClasses) use ($files) {
|
||||
$cachePath = config('settings.discovered_settings_cache_path');
|
||||
|
||||
$files->makeDirectory($cachePath, 0755, true, true);
|
||||
|
||||
$files->put(
|
||||
$cachePath . '/settings.php',
|
||||
'<?php return ' . var_export($settingClasses->toArray(), true) . ';'
|
||||
);
|
||||
});
|
||||
|
||||
$this->info('All done!');
|
||||
}
|
||||
}
|
||||
22
vendor/spatie/laravel-settings/src/Console/ClearCachedSettingsCommand.php
vendored
Normal file
22
vendor/spatie/laravel-settings/src/Console/ClearCachedSettingsCommand.php
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelSettings\Console;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Spatie\LaravelSettings\Support\SettingsCacheFactory;
|
||||
|
||||
class ClearCachedSettingsCommand extends Command
|
||||
{
|
||||
protected $signature = 'settings:clear-cache';
|
||||
|
||||
protected $description = 'Clear cached settings';
|
||||
|
||||
public function handle(SettingsCacheFactory $settingsCacheFactory): void
|
||||
{
|
||||
foreach ($settingsCacheFactory->all() as $settingsCache) {
|
||||
$settingsCache->clear();
|
||||
}
|
||||
|
||||
$this->info('Cached settings cleared!');
|
||||
}
|
||||
}
|
||||
20
vendor/spatie/laravel-settings/src/Console/ClearDiscoveredSettingsCacheCommand.php
vendored
Normal file
20
vendor/spatie/laravel-settings/src/Console/ClearDiscoveredSettingsCacheCommand.php
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelSettings\Console;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Filesystem\Filesystem;
|
||||
|
||||
class ClearDiscoveredSettingsCacheCommand extends Command
|
||||
{
|
||||
protected $signature = 'settings:clear-discovered';
|
||||
|
||||
protected $description = 'Clear cached auto discovered registered settings classes';
|
||||
|
||||
public function handle(Filesystem $files): void
|
||||
{
|
||||
$files->delete(config('settings.discovered_settings_cache_path') . '/settings.php');
|
||||
|
||||
$this->info('Cached discovered settings cleared!');
|
||||
}
|
||||
}
|
||||
134
vendor/spatie/laravel-settings/src/Console/MakeSettingCommand.php
vendored
Normal file
134
vendor/spatie/laravel-settings/src/Console/MakeSettingCommand.php
vendored
Normal file
@@ -0,0 +1,134 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelSettings\Console;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Filesystem\Filesystem;
|
||||
use InvalidArgumentException;
|
||||
|
||||
class MakeSettingCommand extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'make:setting {name : The name of the setting class} {--group=default : The group name} {--path= : Path to write the setting class file to}';
|
||||
|
||||
/**
|
||||
* The console command name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
|
||||
protected $name = 'make:setting';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Create a new Settings Class';
|
||||
|
||||
/**
|
||||
* @var Filesystem
|
||||
*/
|
||||
protected Filesystem $files;
|
||||
|
||||
public function __construct(Filesystem $files)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->files = $files;
|
||||
}
|
||||
|
||||
public function handle()
|
||||
{
|
||||
$name = trim($this->input->getArgument('name'));
|
||||
$group = trim($this->input->getOption('group'));
|
||||
$path = trim($this->input->getOption('path'));
|
||||
|
||||
if (empty($path)) {
|
||||
$path = $this->resolveSettingsPath();
|
||||
}
|
||||
|
||||
$this->ensureSettingClassDoesntAlreadyExist($name, $path);
|
||||
|
||||
$this->files->ensureDirectoryExists($path);
|
||||
|
||||
$this->files->put(
|
||||
$this->getPath($name, $path),
|
||||
$this->getContent($name, $group, $path)
|
||||
);
|
||||
}
|
||||
|
||||
protected function getStub(): string
|
||||
{
|
||||
return <<<EOT
|
||||
<?php
|
||||
|
||||
namespace {{ namespace }};
|
||||
|
||||
use Spatie\LaravelSettings\Settings;
|
||||
|
||||
class {{ class }} extends Settings
|
||||
{
|
||||
|
||||
public static function group(): string
|
||||
{
|
||||
return '{{ group }}';
|
||||
}
|
||||
}
|
||||
EOT;
|
||||
}
|
||||
|
||||
protected function getContent($name, $group, $path)
|
||||
{
|
||||
return str_replace(
|
||||
['{{ namespace }}', '{{ class }}', '{{ group }}'],
|
||||
[$this->getNamespace($path), $name, $group],
|
||||
$this->getStub()
|
||||
);
|
||||
}
|
||||
|
||||
protected function ensureSettingClassDoesntAlreadyExist($name, $path): void
|
||||
{
|
||||
if ($this->files->exists($this->getPath($name, $path))) {
|
||||
throw new InvalidArgumentException(sprintf('%s already exists!', $name));
|
||||
}
|
||||
}
|
||||
|
||||
protected function resolveSettingsPath(): string
|
||||
{
|
||||
return config('settings.setting_class_path', app_path('Settings'));
|
||||
}
|
||||
|
||||
protected function getPath($name, $path): string
|
||||
{
|
||||
return $path . '/' . $name . '.php';
|
||||
}
|
||||
|
||||
protected function getNamespace($path): string
|
||||
{
|
||||
$path = preg_replace(
|
||||
[
|
||||
'/^(' . preg_quote(base_path(), '/') . ')/',
|
||||
'/\//',
|
||||
],
|
||||
[
|
||||
'',
|
||||
'\\',
|
||||
],
|
||||
$path
|
||||
);
|
||||
|
||||
$namespace = implode('\\', array_map(fn ($directory) => ucfirst($directory), explode('\\', $path)));
|
||||
|
||||
// Remove leading backslash if present
|
||||
if (substr($namespace, 0, 1) === '\\') {
|
||||
$namespace = substr($namespace, 1);
|
||||
}
|
||||
|
||||
return $namespace;
|
||||
}
|
||||
}
|
||||
92
vendor/spatie/laravel-settings/src/Console/MakeSettingsMigrationCommand.php
vendored
Normal file
92
vendor/spatie/laravel-settings/src/Console/MakeSettingsMigrationCommand.php
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelSettings\Console;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Filesystem\Filesystem;
|
||||
use Illuminate\Support\Str;
|
||||
use InvalidArgumentException;
|
||||
|
||||
class MakeSettingsMigrationCommand extends Command
|
||||
{
|
||||
protected $signature = 'make:settings-migration {name : The name of the migration} {path? : Path to write migration file to}';
|
||||
|
||||
protected $description = 'Create a new settings migration file';
|
||||
|
||||
protected Filesystem $files;
|
||||
|
||||
public function __construct(Filesystem $files)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->files = $files;
|
||||
}
|
||||
|
||||
public function handle(): void
|
||||
{
|
||||
$name = trim($this->input->getArgument('name'));
|
||||
$path = trim($this->input->getArgument('path'));
|
||||
|
||||
// If path is still empty we get the first path from new settings.migrations_paths config
|
||||
if (empty($path)) {
|
||||
$path = $this->resolveMigrationPaths()[0];
|
||||
}
|
||||
|
||||
$this->ensureMigrationDoesntAlreadyExist($name, $path);
|
||||
|
||||
$this->files->ensureDirectoryExists($path);
|
||||
|
||||
$this->files->put(
|
||||
$file = $this->getPath($name, $path),
|
||||
$this->getStub()
|
||||
);
|
||||
|
||||
$this->info(sprintf('Setting migration [%s] created successfully.', $file));
|
||||
}
|
||||
|
||||
protected function getStub(): string
|
||||
{
|
||||
return <<<EOT
|
||||
<?php
|
||||
|
||||
use Spatie\LaravelSettings\Migrations\SettingsMigration;
|
||||
|
||||
return new class extends SettingsMigration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
EOT;
|
||||
}
|
||||
|
||||
protected function ensureMigrationDoesntAlreadyExist($name, $migrationPath = null): void
|
||||
{
|
||||
if (! empty($migrationPath)) {
|
||||
$migrationFiles = $this->files->glob($migrationPath . '/*.php');
|
||||
|
||||
foreach ($migrationFiles as $migrationFile) {
|
||||
$this->files->requireOnce($migrationFile);
|
||||
}
|
||||
}
|
||||
|
||||
if (class_exists($className = Str::studly($name))) {
|
||||
throw new InvalidArgumentException("A {$className} class already exists.");
|
||||
}
|
||||
}
|
||||
|
||||
protected function getPath($name, $path): string
|
||||
{
|
||||
return $path . '/' . Carbon::now()->format('Y_m_d_His') . '_' . Str::snake($name) . '.php';
|
||||
}
|
||||
|
||||
protected function resolveMigrationPaths(): array
|
||||
{
|
||||
return ! empty(config('settings.migrations_path'))
|
||||
? [config('settings.migrations_path')]
|
||||
: config('settings.migrations_paths');
|
||||
}
|
||||
}
|
||||
18
vendor/spatie/laravel-settings/src/Events/LoadingSettings.php
vendored
Normal file
18
vendor/spatie/laravel-settings/src/Events/LoadingSettings.php
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelSettings\Events;
|
||||
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
class LoadingSettings
|
||||
{
|
||||
public string $settingsClass;
|
||||
|
||||
public Collection $properties;
|
||||
|
||||
public function __construct(string $settingsClass, Collection $properties)
|
||||
{
|
||||
$this->settingsClass = $settingsClass;
|
||||
$this->properties = $properties;
|
||||
}
|
||||
}
|
||||
27
vendor/spatie/laravel-settings/src/Events/SavingSettings.php
vendored
Normal file
27
vendor/spatie/laravel-settings/src/Events/SavingSettings.php
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelSettings\Events;
|
||||
|
||||
use Illuminate\Support\Collection;
|
||||
use Spatie\LaravelSettings\Settings;
|
||||
|
||||
class SavingSettings
|
||||
{
|
||||
public Settings $settings;
|
||||
|
||||
public Collection $properties;
|
||||
|
||||
public ?Collection $originalValues;
|
||||
|
||||
public function __construct(
|
||||
Collection $properties,
|
||||
?Collection $originalValues,
|
||||
Settings $settings
|
||||
) {
|
||||
$this->properties = $properties;
|
||||
|
||||
$this->originalValues = $originalValues;
|
||||
|
||||
$this->settings = $settings;
|
||||
}
|
||||
}
|
||||
15
vendor/spatie/laravel-settings/src/Events/SettingsLoaded.php
vendored
Normal file
15
vendor/spatie/laravel-settings/src/Events/SettingsLoaded.php
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelSettings\Events;
|
||||
|
||||
use Spatie\LaravelSettings\Settings;
|
||||
|
||||
class SettingsLoaded
|
||||
{
|
||||
public Settings $settings;
|
||||
|
||||
public function __construct(Settings $settings)
|
||||
{
|
||||
$this->settings = $settings;
|
||||
}
|
||||
}
|
||||
15
vendor/spatie/laravel-settings/src/Events/SettingsSaved.php
vendored
Normal file
15
vendor/spatie/laravel-settings/src/Events/SettingsSaved.php
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelSettings\Events;
|
||||
|
||||
use Spatie\LaravelSettings\Settings;
|
||||
|
||||
class SettingsSaved
|
||||
{
|
||||
public Settings $settings;
|
||||
|
||||
public function __construct(Settings $settings)
|
||||
{
|
||||
$this->settings = $settings;
|
||||
}
|
||||
}
|
||||
16
vendor/spatie/laravel-settings/src/Exceptions/CouldNotResolveDocblockType.php
vendored
Normal file
16
vendor/spatie/laravel-settings/src/Exceptions/CouldNotResolveDocblockType.php
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelSettings\Exceptions;
|
||||
|
||||
use Exception;
|
||||
use ReflectionProperty;
|
||||
|
||||
class CouldNotResolveDocblockType extends Exception
|
||||
{
|
||||
public static function create(
|
||||
string $type,
|
||||
ReflectionProperty $reflectionProperty
|
||||
): self {
|
||||
return new self("Could not resolve type in docblock: `{$type}` of property `{$reflectionProperty->getDeclaringClass()->getName()}::{$reflectionProperty->getName()}`");
|
||||
}
|
||||
}
|
||||
9
vendor/spatie/laravel-settings/src/Exceptions/CouldNotUnserializeSettings.php
vendored
Normal file
9
vendor/spatie/laravel-settings/src/Exceptions/CouldNotUnserializeSettings.php
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelSettings\Exceptions;
|
||||
|
||||
use Exception;
|
||||
|
||||
class CouldNotUnserializeSettings extends Exception
|
||||
{
|
||||
}
|
||||
13
vendor/spatie/laravel-settings/src/Exceptions/InvalidSettingName.php
vendored
Normal file
13
vendor/spatie/laravel-settings/src/Exceptions/InvalidSettingName.php
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelSettings\Exceptions;
|
||||
|
||||
use Exception;
|
||||
|
||||
class InvalidSettingName extends Exception
|
||||
{
|
||||
public static function create(string $property): self
|
||||
{
|
||||
return new self("Setting {$property} is invalid, it should be formatted as such: group.name");
|
||||
}
|
||||
}
|
||||
15
vendor/spatie/laravel-settings/src/Exceptions/MissingSettings.php
vendored
Normal file
15
vendor/spatie/laravel-settings/src/Exceptions/MissingSettings.php
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelSettings\Exceptions;
|
||||
|
||||
use Exception;
|
||||
|
||||
class MissingSettings extends Exception
|
||||
{
|
||||
public static function create(string $settingsClass, array $missingProperties, string $operation): self
|
||||
{
|
||||
$missing = implode(', ', $missingProperties);
|
||||
|
||||
return new self("Tried {$operation} settings '{$settingsClass}', and following properties were missing: {$missing}");
|
||||
}
|
||||
}
|
||||
18
vendor/spatie/laravel-settings/src/Exceptions/SettingAlreadyExists.php
vendored
Normal file
18
vendor/spatie/laravel-settings/src/Exceptions/SettingAlreadyExists.php
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelSettings\Exceptions;
|
||||
|
||||
use Exception;
|
||||
|
||||
class SettingAlreadyExists extends Exception
|
||||
{
|
||||
public static function whenAdding(string $property): self
|
||||
{
|
||||
throw new self("Could not create setting {$property} because it already exists");
|
||||
}
|
||||
|
||||
public static function whenRenaming(string $from, string $to): self
|
||||
{
|
||||
return new self("Could not rename setting {$from} to {$to} because it already exists");
|
||||
}
|
||||
}
|
||||
23
vendor/spatie/laravel-settings/src/Exceptions/SettingDoesNotExist.php
vendored
Normal file
23
vendor/spatie/laravel-settings/src/Exceptions/SettingDoesNotExist.php
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelSettings\Exceptions;
|
||||
|
||||
use Exception;
|
||||
|
||||
class SettingDoesNotExist extends Exception
|
||||
{
|
||||
public static function whenDeleting(string $property): self
|
||||
{
|
||||
return new self("Could not delete setting {$property} because it does not exist");
|
||||
}
|
||||
|
||||
public static function whenEditing(string $property): self
|
||||
{
|
||||
return new self("Could not edit setting {$property} because it does not exist");
|
||||
}
|
||||
|
||||
public static function whenRenaming(string $from, string $to): self
|
||||
{
|
||||
return new self("Could not rename setting {$from} to {$to} because it does not exist");
|
||||
}
|
||||
}
|
||||
13
vendor/spatie/laravel-settings/src/Exceptions/SettingsCacheDisabled.php
vendored
Normal file
13
vendor/spatie/laravel-settings/src/Exceptions/SettingsCacheDisabled.php
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelSettings\Exceptions;
|
||||
|
||||
use Exception;
|
||||
|
||||
class SettingsCacheDisabled extends Exception
|
||||
{
|
||||
public static function create(): self
|
||||
{
|
||||
return new self('Settings cache is not enabled');
|
||||
}
|
||||
}
|
||||
140
vendor/spatie/laravel-settings/src/Factories/SettingsCastFactory.php
vendored
Normal file
140
vendor/spatie/laravel-settings/src/Factories/SettingsCastFactory.php
vendored
Normal file
@@ -0,0 +1,140 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelSettings\Factories;
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
use phpDocumentor\Reflection\Type;
|
||||
use phpDocumentor\Reflection\Types\AbstractList;
|
||||
use phpDocumentor\Reflection\Types\Boolean;
|
||||
use phpDocumentor\Reflection\Types\Float_;
|
||||
use phpDocumentor\Reflection\Types\Integer;
|
||||
use phpDocumentor\Reflection\Types\Nullable;
|
||||
use phpDocumentor\Reflection\Types\Object_;
|
||||
use phpDocumentor\Reflection\Types\String_;
|
||||
use ReflectionProperty;
|
||||
use Spatie\LaravelSettings\SettingsCasts\ArraySettingsCast;
|
||||
use Spatie\LaravelSettings\SettingsCasts\EnumCast;
|
||||
use Spatie\LaravelSettings\SettingsCasts\SettingsCast;
|
||||
use Spatie\LaravelSettings\Support\PropertyReflector;
|
||||
|
||||
class SettingsCastFactory
|
||||
{
|
||||
public static function resolve(
|
||||
ReflectionProperty $reflectionProperty,
|
||||
array $localCasts
|
||||
): ?SettingsCast {
|
||||
$name = $reflectionProperty->getName();
|
||||
|
||||
$reflectedType = PropertyReflector::resolveType($reflectionProperty);
|
||||
|
||||
if (array_key_exists($name, $localCasts)) {
|
||||
return self::createLocalCast($localCasts[$name], $reflectedType);
|
||||
}
|
||||
|
||||
if ($reflectedType === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return self::createDefaultCast($reflectedType);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|SettingsCast $castDefinition
|
||||
* @param \phpDocumentor\Reflection\Type|null $type
|
||||
*
|
||||
* @return \Spatie\LaravelSettings\SettingsCasts\SettingsCast
|
||||
*/
|
||||
protected static function createLocalCast(
|
||||
$castDefinition,
|
||||
?Type $type
|
||||
): SettingsCast {
|
||||
if ($castDefinition instanceof SettingsCast) {
|
||||
return $castDefinition;
|
||||
}
|
||||
|
||||
$castClass = Str::before($castDefinition, ':');
|
||||
|
||||
$arguments = Str::contains($castDefinition, ':')
|
||||
? explode(',', Str::after($castDefinition, ':'))
|
||||
: [];
|
||||
|
||||
$reflectedType = self::getLocalCastReflectedType($type);
|
||||
|
||||
if ($reflectedType) {
|
||||
array_push($arguments, $reflectedType);
|
||||
}
|
||||
|
||||
return new $castClass(...$arguments);
|
||||
}
|
||||
|
||||
protected static function createDefaultCast(
|
||||
Type $type
|
||||
): ?SettingsCast {
|
||||
$noCastRequired = self::isTypeWithNoCastRequired($type)
|
||||
|| ($type instanceof AbstractList && self::isTypeWithNoCastRequired($type->getValueType()))
|
||||
|| ($type instanceof Nullable && self::isTypeWithNoCastRequired($type->getActualType()));
|
||||
|
||||
if ($noCastRequired) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($type instanceof AbstractList) {
|
||||
return new ArraySettingsCast(self::createDefaultCast($type->getValueType()));
|
||||
}
|
||||
|
||||
if ($type instanceof Nullable) {
|
||||
return self::createDefaultCast($type->getActualType());
|
||||
}
|
||||
|
||||
if (! $type instanceof Object_) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$className = self::getObjectClassName($type);
|
||||
|
||||
if (enum_exists($className)) {
|
||||
return new EnumCast($className);
|
||||
}
|
||||
|
||||
foreach (config('settings.global_casts', []) as $base => $cast) {
|
||||
if (self::shouldCast($className, $base)) {
|
||||
return new $cast($className);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected static function isTypeWithNoCastRequired(Type $type): bool
|
||||
{
|
||||
return $type instanceof Integer
|
||||
|| $type instanceof Boolean
|
||||
|| $type instanceof Float_
|
||||
|| $type instanceof String_;
|
||||
}
|
||||
|
||||
protected static function shouldCast(string $type, string $base): bool
|
||||
{
|
||||
return $type === $base
|
||||
|| in_array($type, class_implements($base))
|
||||
|| is_subclass_of($type, $base);
|
||||
}
|
||||
|
||||
protected static function getLocalCastReflectedType(?Type $type): ?string
|
||||
{
|
||||
if ($type instanceof Object_) {
|
||||
return self::getObjectClassName($type);
|
||||
}
|
||||
|
||||
if ($type instanceof Nullable) {
|
||||
return self::getLocalCastReflectedType($type->getActualType());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected static function getObjectClassName(Object_ $type): string
|
||||
{
|
||||
return ltrim((string ) $type->getFqsen(), '\\');
|
||||
}
|
||||
}
|
||||
24
vendor/spatie/laravel-settings/src/Factories/SettingsRepositoryFactory.php
vendored
Normal file
24
vendor/spatie/laravel-settings/src/Factories/SettingsRepositoryFactory.php
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelSettings\Factories;
|
||||
|
||||
use Exception;
|
||||
use Spatie\LaravelSettings\SettingsRepositories\SettingsRepository;
|
||||
|
||||
class SettingsRepositoryFactory
|
||||
{
|
||||
public static function create(?string $name = null): SettingsRepository
|
||||
{
|
||||
$name ??= config('settings.default_repository');
|
||||
|
||||
if (! array_key_exists($name, config('settings.repositories'))) {
|
||||
throw new Exception("Tried to create unknown settings repository: {$name}");
|
||||
}
|
||||
|
||||
$config = config("settings.repositories.{$name}");
|
||||
|
||||
return app($config['type'], [
|
||||
'config' => $config,
|
||||
]);
|
||||
}
|
||||
}
|
||||
119
vendor/spatie/laravel-settings/src/LaravelSettingsServiceProvider.php
vendored
Normal file
119
vendor/spatie/laravel-settings/src/LaravelSettingsServiceProvider.php
vendored
Normal file
@@ -0,0 +1,119 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelSettings;
|
||||
|
||||
use Illuminate\Database\Events\SchemaLoaded;
|
||||
use Illuminate\Support\Facades\Event;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Spatie\LaravelSettings\Console\CacheDiscoveredSettingsCommand;
|
||||
use Spatie\LaravelSettings\Console\ClearCachedSettingsCommand;
|
||||
use Spatie\LaravelSettings\Console\ClearDiscoveredSettingsCacheCommand;
|
||||
use Spatie\LaravelSettings\Console\MakeSettingCommand;
|
||||
use Spatie\LaravelSettings\Console\MakeSettingsMigrationCommand;
|
||||
use Spatie\LaravelSettings\Factories\SettingsRepositoryFactory;
|
||||
use Spatie\LaravelSettings\Migrations\SettingsMigration;
|
||||
use Spatie\LaravelSettings\SettingsRepositories\SettingsRepository;
|
||||
use Spatie\LaravelSettings\Support\SettingsCacheFactory;
|
||||
use SplFileInfo;
|
||||
use Symfony\Component\Finder\Finder;
|
||||
|
||||
class LaravelSettingsServiceProvider extends ServiceProvider
|
||||
{
|
||||
public function boot()
|
||||
{
|
||||
if ($this->app->runningInConsole()) {
|
||||
$this->publishes([
|
||||
__DIR__ . '/../config/settings.php' => config_path('settings.php'),
|
||||
], 'config');
|
||||
|
||||
if (! class_exists('CreateSettingsTable')) {
|
||||
$this->publishes([
|
||||
__DIR__ . '/../database/migrations/create_settings_table.php.stub' => database_path('migrations/2022_12_14_083707_create_settings_table.php'),
|
||||
], 'migrations');
|
||||
}
|
||||
|
||||
$this->commands([
|
||||
MakeSettingCommand::class,
|
||||
MakeSettingsMigrationCommand::class,
|
||||
CacheDiscoveredSettingsCommand::class,
|
||||
ClearDiscoveredSettingsCacheCommand::class,
|
||||
ClearCachedSettingsCommand::class,
|
||||
]);
|
||||
}
|
||||
|
||||
Event::subscribe(SettingsEventSubscriber::class);
|
||||
Event::listen(SchemaLoaded::class, fn ($event) => $this->removeMigrationsWhenSchemaLoaded($event));
|
||||
|
||||
$this->loadMigrationsFrom($this->resolveMigrationPaths());
|
||||
}
|
||||
|
||||
public function register(): void
|
||||
{
|
||||
$this->mergeConfigFrom(__DIR__ . '/../config/settings.php', 'settings');
|
||||
|
||||
$this->app->bind(SettingsRepository::class, fn () => SettingsRepositoryFactory::create());
|
||||
|
||||
$this->app->bind(SettingsCacheFactory::class, fn () => new SettingsCacheFactory(
|
||||
config('settings'),
|
||||
));
|
||||
|
||||
$this->app->scoped(SettingsMapper::class);
|
||||
|
||||
$settingsContainer = app(SettingsContainer::class);
|
||||
$settingsContainer->registerBindings();
|
||||
}
|
||||
|
||||
private function removeMigrationsWhenSchemaLoaded(SchemaLoaded $event)
|
||||
{
|
||||
$files = Finder::create()
|
||||
->files()
|
||||
->ignoreDotFiles(true)
|
||||
->in($this->resolveMigrationPaths())
|
||||
->depth(0);
|
||||
|
||||
$migrations = collect(iterator_to_array($files))
|
||||
->map(function (SplFileInfo $file) {
|
||||
$contents = file_get_contents($file->getRealPath());
|
||||
|
||||
if (
|
||||
str_contains($contents, 'return new class extends '.SettingsMigration::class)
|
||||
|| str_contains($contents, 'return new class extends SettingsMigration')
|
||||
) {
|
||||
return $file->getBasename('.php');
|
||||
}
|
||||
|
||||
preg_match('/class\s*(?P<className>\w*)\s*extends/', $contents, $found);
|
||||
|
||||
if (empty($found['className'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
require_once $file->getRealPath();
|
||||
|
||||
if (! is_subclass_of($found['className'], SettingsMigration::class)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $file->getBasename('.php');
|
||||
})
|
||||
->filter()
|
||||
->values();
|
||||
|
||||
$migrationsConfig = config()->get('database.migrations');
|
||||
|
||||
$migrationsTable = is_array($migrationsConfig) ? ($migrationsConfig['table'] ?? null) : $migrationsConfig;
|
||||
|
||||
$event->connection
|
||||
->table($migrationsTable)
|
||||
->useWritePdo()
|
||||
->whereIn('migration', $migrations)
|
||||
->delete();
|
||||
}
|
||||
|
||||
protected function resolveMigrationPaths(): array
|
||||
{
|
||||
return ! empty(config('settings.migrations_path'))
|
||||
? [config('settings.migrations_path')]
|
||||
: config('settings.migrations_paths');
|
||||
}
|
||||
}
|
||||
67
vendor/spatie/laravel-settings/src/Migrations/SettingsBlueprint.php
vendored
Normal file
67
vendor/spatie/laravel-settings/src/Migrations/SettingsBlueprint.php
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelSettings\Migrations;
|
||||
|
||||
use Closure;
|
||||
|
||||
class SettingsBlueprint
|
||||
{
|
||||
protected string $group;
|
||||
|
||||
protected SettingsMigrator $migrator;
|
||||
|
||||
public function __construct(string $group, SettingsMigrator $migrator)
|
||||
{
|
||||
$this->group = $group;
|
||||
|
||||
$this->migrator = $migrator;
|
||||
}
|
||||
|
||||
public function rename(string $from, string $to): void
|
||||
{
|
||||
$this->migrator->rename(
|
||||
$this->prependWithGroup($from),
|
||||
$this->prependWithGroup($to)
|
||||
);
|
||||
}
|
||||
|
||||
public function add(string $name, $value = null, bool $encrypted = false): void
|
||||
{
|
||||
$this->migrator->add($this->prependWithGroup($name), $value, $encrypted);
|
||||
}
|
||||
|
||||
public function delete(string $name): void
|
||||
{
|
||||
$this->migrator->delete($this->prependWithGroup($name));
|
||||
}
|
||||
|
||||
public function update(string $name, Closure $closure, bool $encrypted = false): void
|
||||
{
|
||||
$this->migrator->update($this->prependWithGroup($name), $closure, $encrypted);
|
||||
}
|
||||
|
||||
public function addEncrypted(string $name, $value = null): void
|
||||
{
|
||||
$this->migrator->addEncrypted($this->prependWithGroup($name), $value);
|
||||
}
|
||||
|
||||
public function updateEncrypted(string $name, Closure $closure): void
|
||||
{
|
||||
$this->migrator->updateEncrypted($this->prependWithGroup($name), $closure);
|
||||
}
|
||||
|
||||
public function encrypt(string $name): void
|
||||
{
|
||||
$this->migrator->encrypt($this->prependWithGroup($name));
|
||||
}
|
||||
|
||||
public function decrypt(string $name): void
|
||||
{
|
||||
$this->migrator->decrypt($this->prependWithGroup($name));
|
||||
}
|
||||
|
||||
protected function prependWithGroup(string $name): string
|
||||
{
|
||||
return "{$this->group}.{$name}";
|
||||
}
|
||||
}
|
||||
17
vendor/spatie/laravel-settings/src/Migrations/SettingsMigration.php
vendored
Normal file
17
vendor/spatie/laravel-settings/src/Migrations/SettingsMigration.php
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelSettings\Migrations;
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
abstract class SettingsMigration extends Migration
|
||||
{
|
||||
protected SettingsMigrator $migrator;
|
||||
|
||||
abstract public function up();
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->migrator = app(SettingsMigrator::class);
|
||||
}
|
||||
}
|
||||
191
vendor/spatie/laravel-settings/src/Migrations/SettingsMigrator.php
vendored
Normal file
191
vendor/spatie/laravel-settings/src/Migrations/SettingsMigrator.php
vendored
Normal file
@@ -0,0 +1,191 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelSettings\Migrations;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Support\Collection;
|
||||
use Spatie\LaravelSettings\Exceptions\InvalidSettingName;
|
||||
use Spatie\LaravelSettings\Exceptions\SettingAlreadyExists;
|
||||
use Spatie\LaravelSettings\Exceptions\SettingDoesNotExist;
|
||||
use Spatie\LaravelSettings\Factories\SettingsRepositoryFactory;
|
||||
use Spatie\LaravelSettings\SettingsCasts\SettingsCast;
|
||||
use Spatie\LaravelSettings\SettingsConfig;
|
||||
use Spatie\LaravelSettings\SettingsContainer;
|
||||
use Spatie\LaravelSettings\SettingsRepositories\SettingsRepository;
|
||||
use Spatie\LaravelSettings\Support\Crypto;
|
||||
|
||||
class SettingsMigrator
|
||||
{
|
||||
protected SettingsRepository $repository;
|
||||
|
||||
public function __construct(SettingsRepository $connection)
|
||||
{
|
||||
$this->repository = $connection;
|
||||
}
|
||||
|
||||
public function repository(string $name): self
|
||||
{
|
||||
$this->repository = SettingsRepositoryFactory::create($name);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function rename(string $from, string $to): void
|
||||
{
|
||||
if (! $this->checkIfPropertyExists($from)) {
|
||||
throw SettingDoesNotExist::whenRenaming($from, $to);
|
||||
}
|
||||
|
||||
if ($this->checkIfPropertyExists($to)) {
|
||||
throw SettingAlreadyExists::whenRenaming($from, $to);
|
||||
}
|
||||
|
||||
$this->createProperty(
|
||||
$to,
|
||||
$this->getPropertyPayload($from)
|
||||
);
|
||||
|
||||
$this->deleteProperty($from);
|
||||
}
|
||||
|
||||
public function add(string $property, $value = null, bool $encrypted = false): void
|
||||
{
|
||||
if ($this->checkIfPropertyExists($property)) {
|
||||
throw SettingAlreadyExists::whenAdding($property);
|
||||
}
|
||||
|
||||
if ($encrypted) {
|
||||
$value = Crypto::encrypt($value);
|
||||
}
|
||||
|
||||
$this->createProperty($property, $value);
|
||||
}
|
||||
|
||||
public function delete(string $property): void
|
||||
{
|
||||
if (! $this->checkIfPropertyExists($property)) {
|
||||
throw SettingDoesNotExist::whenDeleting($property);
|
||||
}
|
||||
|
||||
$this->deleteProperty($property);
|
||||
}
|
||||
|
||||
public function deleteIfExists(string $property): void
|
||||
{
|
||||
if ($this->checkIfPropertyExists($property)) {
|
||||
$this->deleteProperty($property);
|
||||
}
|
||||
}
|
||||
|
||||
public function update(string $property, Closure $closure, bool $encrypted = false): void
|
||||
{
|
||||
if (! $this->checkIfPropertyExists($property)) {
|
||||
throw SettingDoesNotExist::whenEditing($property);
|
||||
}
|
||||
|
||||
$originalPayload = $encrypted
|
||||
? Crypto::decrypt($this->getPropertyPayload($property))
|
||||
: $this->getPropertyPayload($property);
|
||||
|
||||
$updatedPayload = $encrypted
|
||||
? Crypto::encrypt($closure($originalPayload))
|
||||
: $closure($originalPayload);
|
||||
|
||||
$this->updatePropertyPayload($property, $updatedPayload);
|
||||
}
|
||||
|
||||
public function addEncrypted(string $property, $value = null): void
|
||||
{
|
||||
$this->add($property, $value, true);
|
||||
}
|
||||
|
||||
public function updateEncrypted(string $property, Closure $closure): void
|
||||
{
|
||||
$this->update($property, $closure, true);
|
||||
}
|
||||
|
||||
public function encrypt(string $property): void
|
||||
{
|
||||
$this->update($property, fn ($payload) => Crypto::encrypt($payload));
|
||||
}
|
||||
|
||||
public function decrypt(string $property): void
|
||||
{
|
||||
$this->update($property, fn ($payload) => Crypto::decrypt($payload));
|
||||
}
|
||||
|
||||
public function inGroup(string $group, Closure $closure): void
|
||||
{
|
||||
$closure(new SettingsBlueprint($group, $this));
|
||||
}
|
||||
|
||||
protected function getPropertyParts(string $property): array
|
||||
{
|
||||
$propertyParts = explode('.', $property);
|
||||
|
||||
if (count($propertyParts) !== 2) {
|
||||
throw InvalidSettingName::create($property);
|
||||
}
|
||||
|
||||
return ['group' => $propertyParts[0], 'name' => $propertyParts[1]];
|
||||
}
|
||||
|
||||
protected function checkIfPropertyExists(string $property): bool
|
||||
{
|
||||
['group' => $group, 'name' => $name] = $this->getPropertyParts($property);
|
||||
|
||||
return $this->repository->checkIfPropertyExists($group, $name);
|
||||
}
|
||||
|
||||
protected function getPropertyPayload(string $property)
|
||||
{
|
||||
['group' => $group, 'name' => $name] = $this->getPropertyParts($property);
|
||||
|
||||
$payload = $this->repository->getPropertyPayload($group, $name);
|
||||
|
||||
return optional($this->getCast($group, $name))->get($payload) ?: $payload;
|
||||
}
|
||||
|
||||
protected function createProperty(string $property, $payload): void
|
||||
{
|
||||
['group' => $group, 'name' => $name] = $this->getPropertyParts($property);
|
||||
|
||||
if (is_object($payload)) {
|
||||
$payload = optional($this->getCast($group, $name))->set($payload) ?: $payload;
|
||||
}
|
||||
|
||||
$this->repository->createProperty($group, $name, $payload);
|
||||
}
|
||||
|
||||
protected function updatePropertyPayload(string $property, $payload): void
|
||||
{
|
||||
['group' => $group, 'name' => $name] = $this->getPropertyParts($property);
|
||||
|
||||
if (is_object($payload)) {
|
||||
$payload = optional($this->getCast($group, $name))->set($payload) ?: $payload;
|
||||
}
|
||||
|
||||
$this->repository->updatePropertiesPayload($group, [$name => $payload]);
|
||||
}
|
||||
|
||||
protected function deleteProperty(string $property): void
|
||||
{
|
||||
['group' => $group, 'name' => $name] = $this->getPropertyParts($property);
|
||||
|
||||
$this->repository->deleteProperty($group, $name);
|
||||
}
|
||||
|
||||
protected function getCast(string $group, string $name): ?SettingsCast
|
||||
{
|
||||
return optional($this->settingsGroups()->get($group))->getCast($name);
|
||||
}
|
||||
|
||||
protected function settingsGroups(): Collection
|
||||
{
|
||||
return app(SettingsContainer::class)
|
||||
->getSettingClasses()
|
||||
->mapWithKeys(fn (string $settingsClass) => [
|
||||
$settingsClass::group() => new SettingsConfig($settingsClass),
|
||||
]);
|
||||
}
|
||||
}
|
||||
28
vendor/spatie/laravel-settings/src/Models/SettingsProperty.php
vendored
Normal file
28
vendor/spatie/laravel-settings/src/Models/SettingsProperty.php
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelSettings\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class SettingsProperty extends Model
|
||||
{
|
||||
protected $table = 'settings';
|
||||
|
||||
protected $guarded = [];
|
||||
|
||||
protected $casts = [
|
||||
'locked' => 'boolean',
|
||||
];
|
||||
|
||||
public static function get(string $property)
|
||||
{
|
||||
[$group, $name] = explode('.', $property);
|
||||
|
||||
$setting = self::query()
|
||||
->where('group', $group)
|
||||
->where('name', $name)
|
||||
->first('payload');
|
||||
|
||||
return json_decode($setting->getAttribute('payload'));
|
||||
}
|
||||
}
|
||||
301
vendor/spatie/laravel-settings/src/Settings.php
vendored
Normal file
301
vendor/spatie/laravel-settings/src/Settings.php
vendored
Normal file
@@ -0,0 +1,301 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelSettings;
|
||||
|
||||
use Exception;
|
||||
use Illuminate\Container\Container;
|
||||
use Illuminate\Contracts\Support\Arrayable;
|
||||
use Illuminate\Contracts\Support\Jsonable;
|
||||
use Illuminate\Contracts\Support\Responsable;
|
||||
use Illuminate\Support\Collection;
|
||||
use ReflectionProperty;
|
||||
use Spatie\LaravelSettings\Events\SavingSettings;
|
||||
use Spatie\LaravelSettings\Events\SettingsLoaded;
|
||||
use Spatie\LaravelSettings\Events\SettingsSaved;
|
||||
use Spatie\LaravelSettings\Exceptions\MissingSettings;
|
||||
use Spatie\LaravelSettings\SettingsRepositories\SettingsRepository;
|
||||
use Spatie\LaravelSettings\Support\Crypto;
|
||||
|
||||
abstract class Settings implements Arrayable, Jsonable, Responsable
|
||||
{
|
||||
private SettingsMapper $mapper;
|
||||
|
||||
private SettingsConfig $config;
|
||||
|
||||
private bool $loaded = false;
|
||||
|
||||
private bool $configInitialized = false;
|
||||
|
||||
protected ?Collection $originalValues = null;
|
||||
|
||||
abstract public static function group(): string;
|
||||
|
||||
public static function repository(): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public static function casts(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
public static function encrypted(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $values
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public static function fake(array $values, bool $loadMissingValues = true): self
|
||||
{
|
||||
$settingsMapper = app(SettingsMapper::class);
|
||||
|
||||
$propertiesToLoad = $settingsMapper->initialize(static::class)
|
||||
->getReflectedProperties()
|
||||
->keys()
|
||||
->reject(fn (string $name) => array_key_exists($name, $values));
|
||||
|
||||
if ($propertiesToLoad->isEmpty()) {
|
||||
return app(Container::class)->instance(static::class, new static(
|
||||
$values
|
||||
));
|
||||
}
|
||||
|
||||
if($propertiesToLoad->isNotEmpty() && $loadMissingValues === false) {
|
||||
throw MissingSettings::create(static::class, $propertiesToLoad->toArray(), 'loading fake');
|
||||
}
|
||||
|
||||
$mergedValues = $settingsMapper
|
||||
->fetchProperties(static::class, $propertiesToLoad)
|
||||
->merge($values)
|
||||
->all();
|
||||
|
||||
return app(Container::class)->instance(static::class, new static(
|
||||
$mergedValues
|
||||
));
|
||||
}
|
||||
|
||||
final public function __construct(array $values = [])
|
||||
{
|
||||
$this->ensureConfigIsLoaded();
|
||||
|
||||
foreach ($this->config->getReflectedProperties() as $name => $property) {
|
||||
if (method_exists($property, 'isReadOnly') && $property->isReadOnly()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
unset($this->{$name});
|
||||
}
|
||||
|
||||
if (! empty($values)) {
|
||||
$this->loadValues($values);
|
||||
}
|
||||
}
|
||||
|
||||
public function __get($name)
|
||||
{
|
||||
$this->loadValues();
|
||||
|
||||
return $this->{$name};
|
||||
}
|
||||
|
||||
public function __set($name, $value)
|
||||
{
|
||||
$this->loadValues();
|
||||
|
||||
$this->{$name} = $value;
|
||||
}
|
||||
|
||||
public function __debugInfo(): array
|
||||
{
|
||||
try {
|
||||
$this->loadValues();
|
||||
|
||||
return $this->toArray();
|
||||
} catch (Exception $exception) {
|
||||
return [
|
||||
'Could not load values',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
public function __isset($name)
|
||||
{
|
||||
$this->loadValues();
|
||||
|
||||
return isset($this->{$name});
|
||||
}
|
||||
|
||||
public function __serialize(): array
|
||||
{
|
||||
/** @var Collection $encrypted */
|
||||
/** @var Collection $nonEncrypted */
|
||||
[$encrypted, $nonEncrypted] = $this->toCollection()->partition(
|
||||
fn ($value, string $name) => $this->config->isEncrypted($name)
|
||||
);
|
||||
|
||||
return array_merge(
|
||||
$encrypted->map(fn ($value) => Crypto::encrypt($value))->all(),
|
||||
$nonEncrypted->all()
|
||||
);
|
||||
}
|
||||
|
||||
public function __unserialize(array $data): void
|
||||
{
|
||||
$this->loaded = false;
|
||||
|
||||
$this->ensureConfigIsLoaded();
|
||||
|
||||
/** @var Collection $encrypted */
|
||||
/** @var Collection $nonEncrypted */
|
||||
[$encrypted, $nonEncrypted] = collect($data)->partition(
|
||||
fn ($value, string $name) => $this->config->isEncrypted($name)
|
||||
);
|
||||
|
||||
$data = array_merge(
|
||||
$encrypted->map(fn ($value) => Crypto::decrypt($value))->all(),
|
||||
$nonEncrypted->all()
|
||||
);
|
||||
|
||||
$this->loadValues($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Illuminate\Support\Collection|array $properties
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function fill($properties): self
|
||||
{
|
||||
foreach ($properties as $name => $payload) {
|
||||
$this->{$name} = $payload;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function save(): self
|
||||
{
|
||||
$properties = $this->toCollection();
|
||||
|
||||
event(new SavingSettings($properties, $this->originalValues, $this));
|
||||
|
||||
$values = $this->mapper->save(static::class, $properties);
|
||||
|
||||
$this->fill($values);
|
||||
$this->originalValues = $values;
|
||||
|
||||
event(new SettingsSaved($this));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function lock(string ...$properties)
|
||||
{
|
||||
$this->ensureConfigIsLoaded();
|
||||
|
||||
$this->config->lock(...$properties);
|
||||
}
|
||||
|
||||
public function unlock(string ...$properties)
|
||||
{
|
||||
$this->ensureConfigIsLoaded();
|
||||
|
||||
$this->config->unlock(...$properties);
|
||||
}
|
||||
|
||||
public function isLocked(string $property): bool
|
||||
{
|
||||
return in_array($property, $this->getLockedProperties());
|
||||
}
|
||||
|
||||
public function isUnlocked(string $property): bool
|
||||
{
|
||||
return ! $this->isLocked($property);
|
||||
}
|
||||
|
||||
public function getLockedProperties(): array
|
||||
{
|
||||
$this->ensureConfigIsLoaded();
|
||||
|
||||
return $this->config->getLocked()->toArray();
|
||||
}
|
||||
|
||||
public function toCollection(): Collection
|
||||
{
|
||||
$this->ensureConfigIsLoaded();
|
||||
|
||||
return $this->config
|
||||
->getReflectedProperties()
|
||||
->mapWithKeys(fn (ReflectionProperty $property) => [
|
||||
$property->getName() => $this->{$property->getName()},
|
||||
]);
|
||||
}
|
||||
|
||||
public function toArray(): array
|
||||
{
|
||||
return $this->toCollection()->toArray();
|
||||
}
|
||||
|
||||
public function toJson($options = 0): string
|
||||
{
|
||||
return json_encode($this->toArray(), $options);
|
||||
}
|
||||
|
||||
public function toResponse($request)
|
||||
{
|
||||
return response()->json($this->toJson());
|
||||
}
|
||||
|
||||
public function getRepository(): SettingsRepository
|
||||
{
|
||||
$this->ensureConfigIsLoaded();
|
||||
|
||||
return $this->config->getRepository();
|
||||
}
|
||||
|
||||
public function refresh(): self
|
||||
{
|
||||
$this->config->clearCachedLockedProperties();
|
||||
|
||||
$this->loaded = false;
|
||||
$this->loadValues();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function loadValues(?array $values = null): self
|
||||
{
|
||||
if ($this->loaded) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$values ??= $this->mapper->load(static::class);
|
||||
|
||||
$this->loaded = true;
|
||||
|
||||
$this->fill($values);
|
||||
$this->originalValues = collect($values);
|
||||
|
||||
event(new SettingsLoaded($this));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function ensureConfigIsLoaded(): self
|
||||
{
|
||||
if ($this->configInitialized) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$this->mapper = app(SettingsMapper::class);
|
||||
$this->config = $this->mapper->initialize(static::class);
|
||||
$this->configInitialized = true;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
93
vendor/spatie/laravel-settings/src/SettingsCache.php
vendored
Normal file
93
vendor/spatie/laravel-settings/src/SettingsCache.php
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelSettings;
|
||||
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Spatie\LaravelSettings\Exceptions\CouldNotUnserializeSettings;
|
||||
use Spatie\LaravelSettings\Exceptions\SettingsCacheDisabled;
|
||||
|
||||
class SettingsCache
|
||||
{
|
||||
private bool $enabled;
|
||||
|
||||
private ?string $store;
|
||||
|
||||
private ?string $prefix;
|
||||
|
||||
/** @var \DateTimeInterface|\DateInterval|int|null */
|
||||
private $ttl;
|
||||
|
||||
public function __construct(
|
||||
bool $enabled,
|
||||
?string $store,
|
||||
?string $prefix,
|
||||
$ttl = null
|
||||
) {
|
||||
$this->enabled = $enabled;
|
||||
$this->store = $store;
|
||||
$this->prefix = $prefix;
|
||||
$this->ttl = $ttl;
|
||||
}
|
||||
|
||||
public function isEnabled(): bool
|
||||
{
|
||||
return $this->enabled;
|
||||
}
|
||||
|
||||
public function has(string $settingsClass): bool
|
||||
{
|
||||
if ($this->enabled === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Cache::store($this->store)->has($this->resolveCacheKey($settingsClass));
|
||||
}
|
||||
|
||||
public function get(string $settingsClass): Settings
|
||||
{
|
||||
if ($this->enabled === false) {
|
||||
throw SettingsCacheDisabled::create();
|
||||
}
|
||||
|
||||
$serialized = Cache::store($this->store)->get($this->resolveCacheKey($settingsClass));
|
||||
|
||||
$settings = unserialize($serialized);
|
||||
|
||||
if (! $settings instanceof Settings) {
|
||||
throw new CouldNotUnserializeSettings();
|
||||
}
|
||||
|
||||
return $settings;
|
||||
}
|
||||
|
||||
public function put(Settings $settings): void
|
||||
{
|
||||
if ($this->enabled === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
$serialized = serialize($settings);
|
||||
|
||||
Cache::store($this->store)->put(
|
||||
$this->resolveCacheKey(get_class($settings)),
|
||||
$serialized,
|
||||
$this->ttl
|
||||
);
|
||||
}
|
||||
|
||||
public function clear(): void
|
||||
{
|
||||
app(SettingsContainer::class)
|
||||
->getSettingClasses()
|
||||
->map(fn (string $class) => $this->resolveCacheKey($class))
|
||||
->pipe(fn (Collection $keys) => Cache::store($this->store)->deleteMultiple($keys));
|
||||
}
|
||||
|
||||
private function resolveCacheKey(string $settingsClass): string
|
||||
{
|
||||
$prefix = $this->prefix ? "{$this->prefix}." : '';
|
||||
|
||||
return "{$prefix}settings.{$settingsClass}";
|
||||
}
|
||||
}
|
||||
34
vendor/spatie/laravel-settings/src/SettingsCasts/ArraySettingsCast.php
vendored
Normal file
34
vendor/spatie/laravel-settings/src/SettingsCasts/ArraySettingsCast.php
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelSettings\SettingsCasts;
|
||||
|
||||
class ArraySettingsCast implements SettingsCast
|
||||
{
|
||||
protected SettingsCast $cast;
|
||||
|
||||
public function __construct(SettingsCast $cast)
|
||||
{
|
||||
$this->cast = $cast;
|
||||
}
|
||||
|
||||
public function getCast(): ?SettingsCast
|
||||
{
|
||||
return $this->cast;
|
||||
}
|
||||
|
||||
public function get($payload): array
|
||||
{
|
||||
return array_map(
|
||||
fn ($data) => $this->cast->get($data),
|
||||
$payload
|
||||
);
|
||||
}
|
||||
|
||||
public function set($payload)
|
||||
{
|
||||
return array_map(
|
||||
fn ($data) => $this->cast->set($data),
|
||||
$payload
|
||||
);
|
||||
}
|
||||
}
|
||||
18
vendor/spatie/laravel-settings/src/SettingsCasts/CollectionCast.php
vendored
Normal file
18
vendor/spatie/laravel-settings/src/SettingsCasts/CollectionCast.php
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelSettings\SettingsCasts;
|
||||
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
class CollectionCast implements SettingsCast
|
||||
{
|
||||
public function get($payload): Collection
|
||||
{
|
||||
return collect($payload);
|
||||
}
|
||||
|
||||
public function set($payload): array
|
||||
{
|
||||
return $payload->toArray();
|
||||
}
|
||||
}
|
||||
44
vendor/spatie/laravel-settings/src/SettingsCasts/DataCast.php
vendored
Normal file
44
vendor/spatie/laravel-settings/src/SettingsCasts/DataCast.php
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelSettings\SettingsCasts;
|
||||
|
||||
use Exception;
|
||||
use Spatie\LaravelData\Data;
|
||||
|
||||
class DataCast implements SettingsCast
|
||||
{
|
||||
protected string $type;
|
||||
|
||||
public function __construct(?string $type)
|
||||
{
|
||||
$this->type = $this->ensureDataTypeExists($type);
|
||||
}
|
||||
|
||||
public function get($payload): Data
|
||||
{
|
||||
return $this->type::from($payload);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Data $payload
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function set($payload): array
|
||||
{
|
||||
return $payload->toArray();
|
||||
}
|
||||
|
||||
protected function ensureDataTypeExists(?string $type): string
|
||||
{
|
||||
if ($type === null) {
|
||||
throw new Exception('Cannot create a data cast because no data class was given');
|
||||
}
|
||||
|
||||
if (! class_exists($type)) {
|
||||
throw new Exception("Cannot create a data cast for `{$type}` because the data does not exist");
|
||||
}
|
||||
|
||||
return $type;
|
||||
}
|
||||
}
|
||||
53
vendor/spatie/laravel-settings/src/SettingsCasts/DateTimeInterfaceCast.php
vendored
Normal file
53
vendor/spatie/laravel-settings/src/SettingsCasts/DateTimeInterfaceCast.php
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelSettings\SettingsCasts;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Carbon\CarbonImmutable;
|
||||
use DateTime;
|
||||
use DateTimeImmutable;
|
||||
use DateTimeInterface;
|
||||
use Exception;
|
||||
|
||||
class DateTimeInterfaceCast implements SettingsCast
|
||||
{
|
||||
protected string $type;
|
||||
|
||||
public function __construct(?string $type)
|
||||
{
|
||||
$this->type = $type ?? DateTime::class;
|
||||
}
|
||||
|
||||
public function get($payload): ?DateTimeInterface
|
||||
{
|
||||
if ($payload === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($this->type === Carbon::class) {
|
||||
return new Carbon($payload);
|
||||
}
|
||||
|
||||
if ($this->type === CarbonImmutable::class) {
|
||||
return new CarbonImmutable($payload);
|
||||
}
|
||||
|
||||
if ($this->type === DateTimeImmutable::class) {
|
||||
return new DateTimeImmutable($payload);
|
||||
}
|
||||
|
||||
if ($this->type === DateTime::class) {
|
||||
return new DateTime($payload);
|
||||
}
|
||||
|
||||
throw new Exception("Could not cast DateTime type `{$this->type}`");
|
||||
}
|
||||
|
||||
/** @param DateTimeInterface|null $payload */
|
||||
public function set($payload): ?string
|
||||
{
|
||||
return $payload !== null
|
||||
? $payload->format(DATE_ATOM)
|
||||
: null;
|
||||
}
|
||||
}
|
||||
34
vendor/spatie/laravel-settings/src/SettingsCasts/DateTimeZoneCast.php
vendored
Normal file
34
vendor/spatie/laravel-settings/src/SettingsCasts/DateTimeZoneCast.php
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelSettings\SettingsCasts;
|
||||
|
||||
use DateTimeZone;
|
||||
|
||||
class DateTimeZoneCast implements SettingsCast
|
||||
{
|
||||
protected string $type;
|
||||
|
||||
public function __construct(?string $type)
|
||||
{
|
||||
$this->type = $type ?? DateTimeZone::class;
|
||||
}
|
||||
|
||||
public function get($payload): ?DateTimeZone
|
||||
{
|
||||
return $payload !== null
|
||||
? new DateTimeZone($payload)
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DateTimeZone|null $payload
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function set($payload): ?string
|
||||
{
|
||||
return $payload !== null
|
||||
? $payload->getName()
|
||||
: null;
|
||||
}
|
||||
}
|
||||
45
vendor/spatie/laravel-settings/src/SettingsCasts/DtoCast.php
vendored
Normal file
45
vendor/spatie/laravel-settings/src/SettingsCasts/DtoCast.php
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelSettings\SettingsCasts;
|
||||
|
||||
use Exception;
|
||||
use Spatie\DataTransferObject\DataTransferObject;
|
||||
|
||||
/** @deprecated */
|
||||
class DtoCast implements SettingsCast
|
||||
{
|
||||
protected string $type;
|
||||
|
||||
public function __construct(?string $type)
|
||||
{
|
||||
$this->type = $this->ensureDtoTypeExists($type);
|
||||
}
|
||||
|
||||
public function get($payload): DataTransferObject
|
||||
{
|
||||
return new $this->type($payload);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Spatie\DataTransferObject\DataTransferObject $payload
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function set($payload): array
|
||||
{
|
||||
return $payload->toArray();
|
||||
}
|
||||
|
||||
protected function ensureDtoTypeExists(?string $type): string
|
||||
{
|
||||
if ($type === null) {
|
||||
throw new Exception('Cannot create a DTO cast because no DTO class was given');
|
||||
}
|
||||
|
||||
if (! class_exists($type)) {
|
||||
throw new Exception("Cannot create a DTO cast for `{$type}` because the DTO does not exist");
|
||||
}
|
||||
|
||||
return $type;
|
||||
}
|
||||
}
|
||||
55
vendor/spatie/laravel-settings/src/SettingsCasts/EnumCast.php
vendored
Normal file
55
vendor/spatie/laravel-settings/src/SettingsCasts/EnumCast.php
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelSettings\SettingsCasts;
|
||||
|
||||
use BackedEnum;
|
||||
use Exception;
|
||||
use UnitEnum;
|
||||
|
||||
class EnumCast implements SettingsCast
|
||||
{
|
||||
private string $enum;
|
||||
|
||||
public function __construct(string $enum)
|
||||
{
|
||||
$this->enum = $enum;
|
||||
}
|
||||
|
||||
public function get($payload): ?UnitEnum
|
||||
{
|
||||
if($payload === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (is_a($this->enum, BackedEnum::class, true)) {
|
||||
return $this->enum::from($payload);
|
||||
}
|
||||
|
||||
if (is_a($this->enum, UnitEnum::class, true)) {
|
||||
foreach ($this->enum::cases() as $enum) {
|
||||
if ($enum->name === $payload) {
|
||||
return $enum;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw new Exception('Invalid enum');
|
||||
}
|
||||
|
||||
public function set($payload): string|int|null
|
||||
{
|
||||
if($payload === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($payload instanceof BackedEnum) {
|
||||
return $payload->value;
|
||||
}
|
||||
|
||||
if ($payload instanceof UnitEnum) {
|
||||
return $payload->name;
|
||||
}
|
||||
|
||||
throw new Exception('Invalid enum');
|
||||
}
|
||||
}
|
||||
18
vendor/spatie/laravel-settings/src/SettingsCasts/SettingsCast.php
vendored
Normal file
18
vendor/spatie/laravel-settings/src/SettingsCasts/SettingsCast.php
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelSettings\SettingsCasts;
|
||||
|
||||
interface SettingsCast
|
||||
{
|
||||
/**
|
||||
* Will be used to when retrieving a value from the repository, and
|
||||
* inserting it into the settings class.
|
||||
*/
|
||||
public function get($payload);
|
||||
|
||||
/**
|
||||
* Will be used to when retrieving a value from the settings class, and
|
||||
* inserting it into the repository.
|
||||
*/
|
||||
public function set($payload);
|
||||
}
|
||||
132
vendor/spatie/laravel-settings/src/SettingsConfig.php
vendored
Normal file
132
vendor/spatie/laravel-settings/src/SettingsConfig.php
vendored
Normal file
@@ -0,0 +1,132 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelSettings;
|
||||
|
||||
use Exception;
|
||||
use Illuminate\Support\Collection;
|
||||
use ReflectionClass;
|
||||
use ReflectionProperty;
|
||||
use Spatie\LaravelSettings\Factories\SettingsCastFactory;
|
||||
use Spatie\LaravelSettings\Factories\SettingsRepositoryFactory;
|
||||
use Spatie\LaravelSettings\SettingsCasts\SettingsCast;
|
||||
use Spatie\LaravelSettings\SettingsRepositories\SettingsRepository;
|
||||
|
||||
class SettingsConfig
|
||||
{
|
||||
/** @var class-string<\Spatie\LaravelSettings\Settings> */
|
||||
private string $settingsClass;
|
||||
|
||||
/** @var Collection<string, ?\Spatie\LaravelSettings\SettingsCasts\SettingsCast> */
|
||||
private Collection $casts;
|
||||
|
||||
/** @var Collection<string, \ReflectionProperty> */
|
||||
private Collection $reflectionProperties;
|
||||
|
||||
/** @var string[]|\Illuminate\Support\Collection */
|
||||
private Collection $encrypted;
|
||||
|
||||
/** @var string[]|\Illuminate\Support\Collection */
|
||||
private Collection $locked;
|
||||
|
||||
private SettingsRepository $repository;
|
||||
|
||||
public function __construct(string $settingsClass)
|
||||
{
|
||||
if (! is_subclass_of($settingsClass, Settings::class)) {
|
||||
throw new Exception("Tried decorating {$settingsClass} which is not extending `Spatie\LaravelSettings\Settings::class`");
|
||||
}
|
||||
|
||||
$this->settingsClass = $settingsClass;
|
||||
|
||||
$this->reflectionProperties = collect(
|
||||
(new ReflectionClass($settingsClass))->getProperties(ReflectionProperty::IS_PUBLIC)
|
||||
)->mapWithKeys(fn (ReflectionProperty $property) => [$property->getName() => $property]);
|
||||
|
||||
$this->casts = $this->reflectionProperties
|
||||
->map(fn (ReflectionProperty $reflectionProperty) => SettingsCastFactory::resolve(
|
||||
$reflectionProperty,
|
||||
$this->settingsClass::casts()
|
||||
));
|
||||
|
||||
$this->encrypted = collect($this->settingsClass::encrypted());
|
||||
|
||||
$this->repository = SettingsRepositoryFactory::create($this->settingsClass::repository());
|
||||
}
|
||||
|
||||
public function getName(): string
|
||||
{
|
||||
return $this->settingsClass;
|
||||
}
|
||||
|
||||
public function getReflectedProperties(): Collection
|
||||
{
|
||||
return $this->reflectionProperties;
|
||||
}
|
||||
|
||||
public function getRepository(): SettingsRepository
|
||||
{
|
||||
return $this->repository;
|
||||
}
|
||||
|
||||
public function getGroup(): string
|
||||
{
|
||||
return $this->settingsClass::group();
|
||||
}
|
||||
|
||||
public function isEncrypted(string $name): bool
|
||||
{
|
||||
return $this->encrypted->contains($name);
|
||||
}
|
||||
|
||||
public function isLocked(string $name): bool
|
||||
{
|
||||
return $this->getLocked()->contains($name);
|
||||
}
|
||||
|
||||
public function getCast(string $name): ?SettingsCast
|
||||
{
|
||||
return $this->casts->get($name);
|
||||
}
|
||||
|
||||
public function lock(string ...$names): self
|
||||
{
|
||||
$this->locked = $this->getLocked()->merge($names);
|
||||
|
||||
$this->repository->lockProperties(
|
||||
$this->getGroup(),
|
||||
$names
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function unlock(string ...$names): self
|
||||
{
|
||||
$this->locked = $this->getLocked()->diff($names);
|
||||
|
||||
$this->repository->unlockProperties(
|
||||
$this->getGroup(),
|
||||
$names
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getLocked(): Collection
|
||||
{
|
||||
if (! empty($this->locked)) {
|
||||
return $this->locked;
|
||||
}
|
||||
|
||||
return $this->locked = collect(
|
||||
$this->repository->getLockedProperties($this->settingsClass::group())
|
||||
);
|
||||
}
|
||||
|
||||
public function clearCachedLockedProperties(): self
|
||||
{
|
||||
unset($this->locked);
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
83
vendor/spatie/laravel-settings/src/SettingsContainer.php
vendored
Normal file
83
vendor/spatie/laravel-settings/src/SettingsContainer.php
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelSettings;
|
||||
|
||||
use Illuminate\Container\Container;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Spatie\LaravelSettings\Exceptions\CouldNotUnserializeSettings;
|
||||
use Spatie\LaravelSettings\Support\Composer;
|
||||
use Spatie\LaravelSettings\Support\DiscoverSettings;
|
||||
use Spatie\LaravelSettings\Support\SettingsCacheFactory;
|
||||
|
||||
class SettingsContainer
|
||||
{
|
||||
protected Container $container;
|
||||
|
||||
protected static ?Collection $settingsClasses = null;
|
||||
|
||||
public function __construct(Container $container)
|
||||
{
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
public function registerBindings(): void
|
||||
{
|
||||
$cacheFactory = $this->container->make(SettingsCacheFactory::class);
|
||||
|
||||
$this->getSettingClasses()->each(function (string $settingClass) use ($cacheFactory) {
|
||||
$this->container->scoped($settingClass, function () use ($cacheFactory, $settingClass) {
|
||||
$cache = $cacheFactory->build($settingClass::repository());
|
||||
|
||||
if ($cache->isEnabled() && $cache->has($settingClass)) {
|
||||
try {
|
||||
return $cache->get($settingClass);
|
||||
} catch (CouldNotUnserializeSettings $exception) {
|
||||
Log::error("Could not unserialize settings class: `{$settingClass}` from cache");
|
||||
}
|
||||
}
|
||||
|
||||
return new $settingClass();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public function getSettingClasses(): Collection
|
||||
{
|
||||
if (self::$settingsClasses !== null) {
|
||||
return self::$settingsClasses;
|
||||
}
|
||||
|
||||
$cachedDiscoveredSettings = config('settings.discovered_settings_cache_path') . '/settings.php';
|
||||
|
||||
if (file_exists($cachedDiscoveredSettings)) {
|
||||
$classes = require $cachedDiscoveredSettings;
|
||||
|
||||
return self::$settingsClasses = collect($classes);
|
||||
}
|
||||
|
||||
/** @var \Spatie\LaravelSettings\Settings[] $settings */
|
||||
$settings = array_merge(
|
||||
$this->discoverSettings(),
|
||||
config('settings.settings', [])
|
||||
);
|
||||
|
||||
return self::$settingsClasses = collect($settings)->unique();
|
||||
}
|
||||
|
||||
public function clearCache(): self
|
||||
{
|
||||
self::$settingsClasses = null;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function discoverSettings(): array
|
||||
{
|
||||
return (new DiscoverSettings())
|
||||
->within(config('settings.auto_discover_settings', []))
|
||||
->useBasePath(base_path())
|
||||
->ignoringFiles(Composer::getAutoloadedFiles(base_path('composer.json')))
|
||||
->discover();
|
||||
}
|
||||
}
|
||||
49
vendor/spatie/laravel-settings/src/SettingsEventSubscriber.php
vendored
Normal file
49
vendor/spatie/laravel-settings/src/SettingsEventSubscriber.php
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelSettings;
|
||||
|
||||
use Illuminate\Events\Dispatcher;
|
||||
use Spatie\LaravelSettings\Events\SettingsLoaded;
|
||||
use Spatie\LaravelSettings\Events\SettingsSaved;
|
||||
use Spatie\LaravelSettings\Support\SettingsCacheFactory;
|
||||
|
||||
class SettingsEventSubscriber
|
||||
{
|
||||
private SettingsCacheFactory $settingsCacheFactory;
|
||||
|
||||
public function __construct(SettingsCacheFactory $settingsCacheFactory)
|
||||
{
|
||||
$this->settingsCacheFactory = $settingsCacheFactory;
|
||||
}
|
||||
|
||||
public function subscribe(Dispatcher $dispatcher)
|
||||
{
|
||||
$dispatcher->listen(
|
||||
SettingsSaved::class,
|
||||
function (SettingsSaved $event) {
|
||||
$cache = $this->settingsCacheFactory->build(
|
||||
$event->settings::repository()
|
||||
);
|
||||
|
||||
if ($cache->isEnabled()) {
|
||||
$cache->put($event->settings);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
$dispatcher->listen(
|
||||
SettingsLoaded::class,
|
||||
function (SettingsLoaded $event) {
|
||||
$cache = $this->settingsCacheFactory->build(
|
||||
$event->settings::repository()
|
||||
);
|
||||
|
||||
if ($cache->has(get_class($event->settings))) {
|
||||
return;
|
||||
}
|
||||
|
||||
$cache->put($event->settings);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
125
vendor/spatie/laravel-settings/src/SettingsMapper.php
vendored
Normal file
125
vendor/spatie/laravel-settings/src/SettingsMapper.php
vendored
Normal file
@@ -0,0 +1,125 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelSettings;
|
||||
|
||||
use Illuminate\Support\Collection;
|
||||
use Spatie\LaravelSettings\Events\LoadingSettings;
|
||||
use Spatie\LaravelSettings\Exceptions\MissingSettings;
|
||||
use Spatie\LaravelSettings\Support\Crypto;
|
||||
|
||||
class SettingsMapper
|
||||
{
|
||||
/** @var array<string, \Spatie\LaravelSettings\SettingsConfig> */
|
||||
private array $configs = [];
|
||||
|
||||
public function initialize(string $settingsClass): SettingsConfig
|
||||
{
|
||||
if ($this->has($settingsClass)) {
|
||||
return $this->configs[$settingsClass];
|
||||
}
|
||||
|
||||
$config = new SettingsConfig($settingsClass);
|
||||
|
||||
return $this->configs[$settingsClass] = $config;
|
||||
}
|
||||
|
||||
public function has(string $settingsClass): bool
|
||||
{
|
||||
return array_key_exists($settingsClass, $this->configs);
|
||||
}
|
||||
|
||||
public function load(string $settingsClass): Collection
|
||||
{
|
||||
$config = $this->getConfig($settingsClass);
|
||||
|
||||
$properties = $this->fetchProperties(
|
||||
$settingsClass,
|
||||
$config->getReflectedProperties()->keys()
|
||||
);
|
||||
|
||||
event(new LoadingSettings($settingsClass, $properties));
|
||||
|
||||
$this->ensureNoMissingSettings($config, $properties, 'loading');
|
||||
|
||||
return $properties;
|
||||
}
|
||||
|
||||
public function save(
|
||||
string $settingsClass,
|
||||
Collection $properties
|
||||
): Collection {
|
||||
$config = $this->getConfig($settingsClass);
|
||||
|
||||
$this->ensureNoMissingSettings($config, $properties, 'saving');
|
||||
|
||||
$notRejectedProperties = $properties
|
||||
->reject(fn ($payload, string $name) => $config->isLocked($name));
|
||||
|
||||
$changedProperties = $notRejectedProperties
|
||||
->map(function ($payload, string $name) use ($config) {
|
||||
if ($cast = $config->getCast($name)) {
|
||||
$payload = $cast->set($payload);
|
||||
}
|
||||
|
||||
if ($config->isEncrypted($name)) {
|
||||
$payload = Crypto::encrypt($payload);
|
||||
}
|
||||
|
||||
return $payload;
|
||||
})
|
||||
->toArray();
|
||||
|
||||
$config->getRepository()->updatePropertiesPayload(
|
||||
$config->getGroup(),
|
||||
$changedProperties
|
||||
);
|
||||
|
||||
return $this
|
||||
->fetchProperties($settingsClass, $config->getLocked())
|
||||
->merge($notRejectedProperties);
|
||||
}
|
||||
|
||||
public function fetchProperties(string $settingsClass, Collection $names): Collection
|
||||
{
|
||||
$config = $this->getConfig($settingsClass);
|
||||
|
||||
return collect($config->getRepository()->getPropertiesInGroup($config->getGroup()))
|
||||
->filter(fn ($payload, string $name) => $names->contains($name))
|
||||
->map(function ($payload, string $name) use ($config) {
|
||||
if ($config->isEncrypted($name)) {
|
||||
$payload = Crypto::decrypt($payload);
|
||||
}
|
||||
|
||||
if ($cast = $config->getCast($name)) {
|
||||
$payload = $cast->get($payload);
|
||||
}
|
||||
|
||||
return $payload;
|
||||
});
|
||||
}
|
||||
|
||||
private function getConfig(string $settingsClass): SettingsConfig
|
||||
{
|
||||
if (! $this->has($settingsClass)) {
|
||||
$this->initialize($settingsClass);
|
||||
}
|
||||
|
||||
return $this->configs[$settingsClass];
|
||||
}
|
||||
|
||||
private function ensureNoMissingSettings(
|
||||
SettingsConfig $config,
|
||||
Collection $properties,
|
||||
string $operation
|
||||
): void {
|
||||
$missingSettings = $config
|
||||
->getReflectedProperties()
|
||||
->keys()
|
||||
->diff($properties->keys())
|
||||
->toArray();
|
||||
|
||||
if (! empty($missingSettings)) {
|
||||
throw MissingSettings::create($config->getName(), $missingSettings, $operation);
|
||||
}
|
||||
}
|
||||
}
|
||||
147
vendor/spatie/laravel-settings/src/SettingsRepositories/DatabaseSettingsRepository.php
vendored
Normal file
147
vendor/spatie/laravel-settings/src/SettingsRepositories/DatabaseSettingsRepository.php
vendored
Normal file
@@ -0,0 +1,147 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelSettings\SettingsRepositories;
|
||||
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Spatie\LaravelSettings\Models\SettingsProperty;
|
||||
|
||||
class DatabaseSettingsRepository implements SettingsRepository
|
||||
{
|
||||
/** @var class-string<\Illuminate\Database\Eloquent\Model> */
|
||||
protected string $propertyModel;
|
||||
|
||||
protected ?string $connection;
|
||||
|
||||
protected ?string $table;
|
||||
|
||||
public function __construct(array $config)
|
||||
{
|
||||
$this->propertyModel = $config['model'] ?? SettingsProperty::class;
|
||||
$this->connection = $config['connection'] ?? null;
|
||||
$this->table = $config['table'] ?? null;
|
||||
}
|
||||
|
||||
public function getPropertiesInGroup(string $group): array
|
||||
{
|
||||
return $this->getBuilder()
|
||||
->where('group', $group)
|
||||
->get(['name', 'payload'])
|
||||
->mapWithKeys(function (object $object) {
|
||||
return [$object->name => $this->decode($object->payload, true)];
|
||||
})
|
||||
->toArray();
|
||||
}
|
||||
|
||||
public function checkIfPropertyExists(string $group, string $name): bool
|
||||
{
|
||||
return $this->getBuilder()
|
||||
->where('group', $group)
|
||||
->where('name', $name)
|
||||
->exists();
|
||||
}
|
||||
|
||||
public function getPropertyPayload(string $group, string $name)
|
||||
{
|
||||
$setting = $this->getBuilder()
|
||||
->where('group', $group)
|
||||
->where('name', $name)
|
||||
->first('payload')
|
||||
->toArray();
|
||||
|
||||
return $this->decode($setting['payload']);
|
||||
}
|
||||
|
||||
public function createProperty(string $group, string $name, $payload): void
|
||||
{
|
||||
$this->getBuilder()->create([
|
||||
'group' => $group,
|
||||
'name' => $name,
|
||||
'payload' => $this->encode($payload),
|
||||
'locked' => false,
|
||||
]);
|
||||
}
|
||||
|
||||
public function updatePropertiesPayload(string $group, array $properties): void
|
||||
{
|
||||
$propertiesInBatch = collect($properties)->map(function ($payload, $name) use ($group) {
|
||||
return [
|
||||
'group' => $group,
|
||||
'name' => $name,
|
||||
'payload' => $this->encode($payload),
|
||||
];
|
||||
})->values()->toArray();
|
||||
|
||||
$this->getBuilder()
|
||||
->where('group', $group)
|
||||
->upsert($propertiesInBatch, ['group', 'name'], ['payload']);
|
||||
}
|
||||
|
||||
public function deleteProperty(string $group, string $name): void
|
||||
{
|
||||
$this->getBuilder()
|
||||
->where('group', $group)
|
||||
->where('name', $name)
|
||||
->delete();
|
||||
}
|
||||
|
||||
public function lockProperties(string $group, array $properties): void
|
||||
{
|
||||
$this->getBuilder()
|
||||
->where('group', $group)
|
||||
->whereIn('name', $properties)
|
||||
->update(['locked' => true]);
|
||||
}
|
||||
|
||||
public function unlockProperties(string $group, array $properties): void
|
||||
{
|
||||
$this->getBuilder()
|
||||
->where('group', $group)
|
||||
->whereIn('name', $properties)
|
||||
->update(['locked' => false]);
|
||||
}
|
||||
|
||||
public function getLockedProperties(string $group): array
|
||||
{
|
||||
return $this->getBuilder()
|
||||
->where('group', $group)
|
||||
->where('locked', true)
|
||||
->pluck('name')
|
||||
->toArray();
|
||||
}
|
||||
|
||||
public function getBuilder(): Builder
|
||||
{
|
||||
$model = new $this->propertyModel;
|
||||
|
||||
if ($this->connection) {
|
||||
$model->setConnection($this->connection);
|
||||
}
|
||||
|
||||
if ($this->table) {
|
||||
$model->setTable($this->table);
|
||||
}
|
||||
|
||||
return $model->newQuery();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
* @return mixed
|
||||
*/
|
||||
protected function encode($value)
|
||||
{
|
||||
$encoder = config('settings.encoder') ?? fn ($value) => json_encode($value);
|
||||
|
||||
return $encoder($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
protected function decode(string $payload, bool $associative = false)
|
||||
{
|
||||
$decoder = config('settings.decoder') ?? fn ($payload, $associative) => json_decode($payload, $associative);
|
||||
|
||||
return $decoder($payload, $associative);
|
||||
}
|
||||
}
|
||||
81
vendor/spatie/laravel-settings/src/SettingsRepositories/RedisSettingsRepository.php
vendored
Normal file
81
vendor/spatie/laravel-settings/src/SettingsRepositories/RedisSettingsRepository.php
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelSettings\SettingsRepositories;
|
||||
|
||||
use Illuminate\Redis\RedisManager;
|
||||
|
||||
class RedisSettingsRepository implements SettingsRepository
|
||||
{
|
||||
/** @var \Redis */
|
||||
protected $connection;
|
||||
|
||||
protected string $prefix;
|
||||
|
||||
public function __construct(array $config, RedisManager $connection)
|
||||
{
|
||||
$this->connection = $connection
|
||||
->connection($config['connection'] ?? null)
|
||||
->client();
|
||||
|
||||
$this->prefix = array_key_exists('prefix', $config)
|
||||
? "{$config['prefix']}."
|
||||
: '';
|
||||
}
|
||||
|
||||
public function getPropertiesInGroup(string $group): array
|
||||
{
|
||||
return collect($this->connection->hGetAll($this->prefix . $group))
|
||||
->mapWithKeys(function ($payload, string $name) {
|
||||
return [$name => json_decode($payload, true)];
|
||||
})->toArray();
|
||||
}
|
||||
|
||||
public function checkIfPropertyExists(string $group, string $name): bool
|
||||
{
|
||||
return $this->connection->hExists($this->prefix . $group, $name);
|
||||
}
|
||||
|
||||
public function getPropertyPayload(string $group, string $name)
|
||||
{
|
||||
return json_decode($this->connection->hGet($this->prefix . $group, $name));
|
||||
}
|
||||
|
||||
public function createProperty(string $group, string $name, $payload): void
|
||||
{
|
||||
$this->connection->hSet($this->prefix . $group, $name, json_encode($payload));
|
||||
}
|
||||
|
||||
public function updatePropertiesPayload(string $group, array $properties): void
|
||||
{
|
||||
$properties = collect($properties)->mapWithKeys(function ($payload, $name) {
|
||||
return [$name => json_encode($payload)];
|
||||
})->toArray();
|
||||
|
||||
$this->connection->hmset($this->prefix . $group, $properties);
|
||||
}
|
||||
|
||||
public function deleteProperty(string $group, string $name): void
|
||||
{
|
||||
$this->connection->hDel($this->prefix . $group, $name);
|
||||
}
|
||||
|
||||
public function lockProperties(string $group, array $properties): void
|
||||
{
|
||||
$this->connection->sAdd($this->getLocksSetKey($group), ...$properties);
|
||||
}
|
||||
|
||||
public function unlockProperties(string $group, array $properties): void
|
||||
{
|
||||
$this->connection->sRem($this->getLocksSetKey($group), ...$properties);
|
||||
}
|
||||
|
||||
public function getLockedProperties(string $group): array
|
||||
{
|
||||
return $this->connection->sMembers($this->getLocksSetKey($group));
|
||||
}
|
||||
|
||||
protected function getLocksSetKey(string $group): string
|
||||
{
|
||||
return $this->prefix . 'locks.' . $group;
|
||||
}
|
||||
}
|
||||
51
vendor/spatie/laravel-settings/src/SettingsRepositories/SettingsRepository.php
vendored
Normal file
51
vendor/spatie/laravel-settings/src/SettingsRepositories/SettingsRepository.php
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelSettings\SettingsRepositories;
|
||||
|
||||
interface SettingsRepository
|
||||
{
|
||||
/**
|
||||
* Get all the properties in the repository for a single group
|
||||
*/
|
||||
public function getPropertiesInGroup(string $group): array;
|
||||
|
||||
/**
|
||||
* Check if a property exists in a group
|
||||
*/
|
||||
public function checkIfPropertyExists(string $group, string $name): bool;
|
||||
|
||||
/**
|
||||
* Get the payload of a property
|
||||
*/
|
||||
public function getPropertyPayload(string $group, string $name);
|
||||
|
||||
/**
|
||||
* Create a property within a group with a payload
|
||||
*/
|
||||
public function createProperty(string $group, string $name, $payload): void;
|
||||
|
||||
/**
|
||||
* Update the payloads of properties within a group.
|
||||
*/
|
||||
public function updatePropertiesPayload(string $group, array $properties): void;
|
||||
|
||||
/**
|
||||
* Delete a property from a group
|
||||
*/
|
||||
public function deleteProperty(string $group, string $name): void;
|
||||
|
||||
/**
|
||||
* Lock a set of properties for a specific group
|
||||
*/
|
||||
public function lockProperties(string $group, array $properties): void;
|
||||
|
||||
/**
|
||||
* Unlock a set of properties for a group
|
||||
*/
|
||||
public function unlockProperties(string $group, array $properties): void;
|
||||
|
||||
/**
|
||||
* Get all the locked properties within a group
|
||||
*/
|
||||
public function getLockedProperties(string $group): array;
|
||||
}
|
||||
26
vendor/spatie/laravel-settings/src/Support/Composer.php
vendored
Normal file
26
vendor/spatie/laravel-settings/src/Support/Composer.php
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelSettings\Support;
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class Composer
|
||||
{
|
||||
public static function getAutoloadedFiles($composerJsonPath): array
|
||||
{
|
||||
if (! file_exists($composerJsonPath)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$basePath = Str::before($composerJsonPath, 'composer.json');
|
||||
|
||||
$composerContents = json_decode(file_get_contents($composerJsonPath), true);
|
||||
|
||||
$paths = array_merge(
|
||||
$composerContents['autoload']['files'] ?? [],
|
||||
$composerContents['autoload-dev']['files'] ?? []
|
||||
);
|
||||
|
||||
return array_map(fn (string $path) => realpath($basePath.$path), $paths);
|
||||
}
|
||||
}
|
||||
20
vendor/spatie/laravel-settings/src/Support/Crypto.php
vendored
Normal file
20
vendor/spatie/laravel-settings/src/Support/Crypto.php
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelSettings\Support;
|
||||
|
||||
class Crypto
|
||||
{
|
||||
public static function encrypt($payload): ?string
|
||||
{
|
||||
return $payload !== null
|
||||
? encrypt($payload)
|
||||
: $payload;
|
||||
}
|
||||
|
||||
public static function decrypt(?string $payload)
|
||||
{
|
||||
return $payload !== null
|
||||
? decrypt($payload)
|
||||
: null;
|
||||
}
|
||||
}
|
||||
92
vendor/spatie/laravel-settings/src/Support/DiscoverSettings.php
vendored
Normal file
92
vendor/spatie/laravel-settings/src/Support/DiscoverSettings.php
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelSettings\Support;
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
use ReflectionClass;
|
||||
use Spatie\LaravelSettings\Settings;
|
||||
use SplFileInfo;
|
||||
use Symfony\Component\Finder\Finder;
|
||||
use Throwable;
|
||||
|
||||
class DiscoverSettings
|
||||
{
|
||||
protected array $directories = [];
|
||||
|
||||
protected string $basePath = '';
|
||||
|
||||
protected string $rootNamespace = '';
|
||||
|
||||
protected array $ignoredFiles = [];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->basePath = app_path();
|
||||
}
|
||||
|
||||
public function within(array $directories): self
|
||||
{
|
||||
$this->directories = array_values(
|
||||
array_filter($directories, fn (string $directory) => is_dir($directory))
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function useBasePath(string $basePath): self
|
||||
{
|
||||
$this->basePath = $basePath;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function useRootNamespace(string $rootNamespace): self
|
||||
{
|
||||
$this->rootNamespace = $rootNamespace;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function ignoringFiles(array $ignoredFiles): self
|
||||
{
|
||||
$this->ignoredFiles = $ignoredFiles;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function discover(): array
|
||||
{
|
||||
if (empty($this->directories)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$files = (new Finder())->files()->in($this->directories);
|
||||
|
||||
return collect($files)
|
||||
->reject(fn (SplFileInfo $file) => in_array($file->getPathname(), $this->ignoredFiles))
|
||||
->map(fn (SplFileInfo $file) => $this->fullQualifiedClassNameFromFile($file))
|
||||
->filter(function (string $settingsClass) {
|
||||
try {
|
||||
return is_subclass_of($settingsClass, Settings::class) &&
|
||||
(new ReflectionClass($settingsClass))->isInstantiable();
|
||||
} catch (Throwable $e) {
|
||||
return false;
|
||||
}
|
||||
})
|
||||
->flatten()
|
||||
->toArray();
|
||||
}
|
||||
|
||||
protected function fullQualifiedClassNameFromFile(SplFileInfo $file): string
|
||||
{
|
||||
$class = trim(Str::replaceFirst($this->basePath, '', $file->getRealPath()), DIRECTORY_SEPARATOR);
|
||||
|
||||
$class = str_replace(
|
||||
[DIRECTORY_SEPARATOR, 'App\\'],
|
||||
['\\', app()->getNamespace()],
|
||||
ucfirst(Str::replaceLast('.php', '', $class))
|
||||
);
|
||||
|
||||
return $this->rootNamespace.$class;
|
||||
}
|
||||
}
|
||||
138
vendor/spatie/laravel-settings/src/Support/PropertyReflector.php
vendored
Normal file
138
vendor/spatie/laravel-settings/src/Support/PropertyReflector.php
vendored
Normal file
@@ -0,0 +1,138 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelSettings\Support;
|
||||
|
||||
use phpDocumentor\Reflection\Fqsen;
|
||||
use phpDocumentor\Reflection\FqsenResolver;
|
||||
use phpDocumentor\Reflection\Type;
|
||||
use phpDocumentor\Reflection\TypeResolver;
|
||||
use phpDocumentor\Reflection\Types\AbstractList;
|
||||
use phpDocumentor\Reflection\Types\Boolean;
|
||||
use phpDocumentor\Reflection\Types\Compound;
|
||||
use phpDocumentor\Reflection\Types\ContextFactory;
|
||||
use phpDocumentor\Reflection\Types\Float_;
|
||||
use phpDocumentor\Reflection\Types\Integer;
|
||||
use phpDocumentor\Reflection\Types\Null_;
|
||||
use phpDocumentor\Reflection\Types\Nullable;
|
||||
use phpDocumentor\Reflection\Types\Object_;
|
||||
use phpDocumentor\Reflection\Types\String_;
|
||||
use ReflectionNamedType;
|
||||
use ReflectionProperty;
|
||||
use Spatie\LaravelSettings\Exceptions\CouldNotResolveDocblockType;
|
||||
|
||||
class PropertyReflector
|
||||
{
|
||||
public static function resolveType(
|
||||
ReflectionProperty $reflectionProperty
|
||||
): ?Type {
|
||||
$reflectionType = $reflectionProperty->getType();
|
||||
$docblock = $reflectionProperty->getDocComment();
|
||||
|
||||
if ($reflectionType === null && empty($docblock)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($docblock) {
|
||||
preg_match('/@var ((?:(?:[\w?|\\\\<>,\s])+(?:\[])?)+)/', $docblock, $output_array);
|
||||
|
||||
return count($output_array) === 2
|
||||
? self::reflectDocblock($reflectionProperty, $output_array[1])
|
||||
: null;
|
||||
}
|
||||
|
||||
if (! $reflectionType instanceof ReflectionNamedType) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$builtInTypes = [
|
||||
'int',
|
||||
'string',
|
||||
'float',
|
||||
'bool',
|
||||
'mixed',
|
||||
'array',
|
||||
];
|
||||
|
||||
if (in_array($reflectionType->getName(), $builtInTypes)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$type = new Object_(new Fqsen('\\' . $reflectionType->getName()));
|
||||
|
||||
return $reflectionType->allowsNull()
|
||||
? new Nullable($type)
|
||||
: $type;
|
||||
}
|
||||
|
||||
protected static function reflectDocblock(
|
||||
ReflectionProperty $reflectionProperty,
|
||||
string $type
|
||||
): Type {
|
||||
$resolvedType = (new TypeResolver())->resolve($type);
|
||||
|
||||
$isValidPrimitive = $resolvedType instanceof Boolean
|
||||
|| $resolvedType instanceof Float_
|
||||
|| $resolvedType instanceof Integer
|
||||
|| $resolvedType instanceof String_;
|
||||
|
||||
if ($isValidPrimitive) {
|
||||
return $resolvedType;
|
||||
}
|
||||
|
||||
if ($resolvedType instanceof Object_) {
|
||||
return self::reflectObject($reflectionProperty, $resolvedType);
|
||||
}
|
||||
|
||||
if ($resolvedType instanceof Compound) {
|
||||
return self::reflectCompound($reflectionProperty, $resolvedType);
|
||||
}
|
||||
|
||||
if ($resolvedType instanceof Nullable) {
|
||||
return new Nullable(self::reflectDocblock($reflectionProperty, (string) $resolvedType->getActualType()));
|
||||
}
|
||||
|
||||
if ($resolvedType instanceof AbstractList) {
|
||||
$listType = get_class($resolvedType);
|
||||
|
||||
return new $listType(
|
||||
self::reflectDocblock($reflectionProperty, (string) $resolvedType->getValueType()),
|
||||
$resolvedType->getKeyType()
|
||||
);
|
||||
}
|
||||
|
||||
throw CouldNotResolveDocblockType::create($type, $reflectionProperty);
|
||||
}
|
||||
|
||||
private static function reflectCompound(
|
||||
ReflectionProperty $reflectionProperty,
|
||||
Compound $compound
|
||||
): Nullable {
|
||||
if ($compound->getIterator()->count() !== 2 || ! $compound->contains(new Null_())) {
|
||||
throw CouldNotResolveDocblockType::create((string) $compound, $reflectionProperty);
|
||||
}
|
||||
|
||||
$other = current(array_filter(
|
||||
iterator_to_array($compound->getIterator()),
|
||||
fn (Type $type) => ! $type instanceof Null_
|
||||
));
|
||||
|
||||
return new Nullable(self::reflectDocblock($reflectionProperty, (string) $other));
|
||||
}
|
||||
|
||||
private static function reflectObject(
|
||||
ReflectionProperty $reflectionProperty,
|
||||
Object_ $object
|
||||
): Object_ {
|
||||
if (class_exists((string) $object->getFqsen())) {
|
||||
return $object;
|
||||
}
|
||||
|
||||
$context = (new ContextFactory)->createFromReflector($reflectionProperty);
|
||||
|
||||
$className = ltrim((string) $object->getFqsen(), '\\');
|
||||
|
||||
$fqsen = (new FqsenResolver)->resolve($className, $context);
|
||||
|
||||
return new Object_($fqsen);
|
||||
}
|
||||
}
|
||||
64
vendor/spatie/laravel-settings/src/Support/SettingsCacheFactory.php
vendored
Normal file
64
vendor/spatie/laravel-settings/src/Support/SettingsCacheFactory.php
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelSettings\Support;
|
||||
|
||||
use Spatie\LaravelSettings\SettingsCache;
|
||||
|
||||
class SettingsCacheFactory
|
||||
{
|
||||
private array $config;
|
||||
|
||||
private SettingsCache $defaultCache;
|
||||
|
||||
private array $repositoryCaches = [];
|
||||
|
||||
public function __construct(array $settingsConfig)
|
||||
{
|
||||
$this->config = $settingsConfig;
|
||||
|
||||
$this->initializeCaches();
|
||||
}
|
||||
|
||||
public function build(?string $repository = null): SettingsCache
|
||||
{
|
||||
if ($repository === null) {
|
||||
return $this->defaultCache;
|
||||
}
|
||||
|
||||
if (array_key_exists($repository, $this->repositoryCaches)) {
|
||||
return $this->repositoryCaches[$repository];
|
||||
}
|
||||
|
||||
return $this->defaultCache;
|
||||
}
|
||||
|
||||
/** @return array<SettingsCache> */
|
||||
public function all(): array
|
||||
{
|
||||
return array_merge(
|
||||
['default' => $this->defaultCache],
|
||||
$this->repositoryCaches
|
||||
);
|
||||
}
|
||||
|
||||
protected function initializeCaches(): void
|
||||
{
|
||||
$this->defaultCache = $this->initializeCache($this->config['cache']);
|
||||
|
||||
foreach ($this->config['repositories'] as $name => $repositoryConfig) {
|
||||
if (array_key_exists('cache', $repositoryConfig)) {
|
||||
$this->repositoryCaches[$name] = $this->initializeCache($repositoryConfig['cache']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function initializeCache(array $config): SettingsCache
|
||||
{
|
||||
return new SettingsCache(
|
||||
$config['enabled'] ?? false,
|
||||
$config['store'] ?? null,
|
||||
$config['prefix'] ?? null,
|
||||
$config['ttl'] ?? null,
|
||||
);
|
||||
}
|
||||
}
|
||||
21
vendor/spatie/temporary-directory/LICENSE.md
vendored
Normal file
21
vendor/spatie/temporary-directory/LICENSE.md
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
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.
|
||||
180
vendor/spatie/temporary-directory/README.md
vendored
Normal file
180
vendor/spatie/temporary-directory/README.md
vendored
Normal file
@@ -0,0 +1,180 @@
|
||||
# Quickly create, use and delete temporary directories
|
||||
|
||||
[](https://packagist.org/packages/spatie/temporary-directory)
|
||||

|
||||
[](LICENSE.md)
|
||||
[](https://packagist.org/packages/spatie/temporary-directory)
|
||||
|
||||
This package allows you to quickly create, use and delete a temporary directory in the system's temporary directory.
|
||||
|
||||
Here's a quick example on how to create a temporary directory and delete it:
|
||||
|
||||
```php
|
||||
use Spatie\TemporaryDirectory\TemporaryDirectory;
|
||||
|
||||
$temporaryDirectory = (new TemporaryDirectory())->create();
|
||||
|
||||
// Get a path inside the temporary directory
|
||||
$temporaryDirectory->path('temporaryfile.txt');
|
||||
|
||||
// Delete the temporary directory and all the files inside it
|
||||
$temporaryDirectory->delete();
|
||||
```
|
||||
|
||||
## Support us
|
||||
|
||||
[<img src="https://github-ads.s3.eu-central-1.amazonaws.com/temporary-directory.jpg?t=1" width="419px" />](https://spatie.be/github-ad-click/temporary-directory)
|
||||
|
||||
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/temporary-directory
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Creating a temporary directory
|
||||
|
||||
To create a temporary directory simply call the `create` method on a `TemporaryDirectory` object.
|
||||
|
||||
```php
|
||||
(new TemporaryDirectory())->create();
|
||||
```
|
||||
|
||||
Alternatively, use the static `make` method on a `TemporaryDirectory` object.
|
||||
|
||||
```php
|
||||
TemporaryDirectory::make();
|
||||
```
|
||||
|
||||
By default, the temporary directory will be created in a timestamped directory in your system's temporary directory (usually `/tmp`).
|
||||
|
||||
### Naming your temporary directory
|
||||
|
||||
If you want to use a custom name for your temporary directory instead of the timestamp call the `name` method with a string `$name` argument before the `create` method.
|
||||
|
||||
```php
|
||||
(new TemporaryDirectory())
|
||||
->name($name)
|
||||
->create();
|
||||
```
|
||||
|
||||
By default an exception will be thrown if a directory already exists with the given argument. You can override this behaviour by calling the `force` method in combination with the `name` method.
|
||||
|
||||
```php
|
||||
(new TemporaryDirectory())
|
||||
->name($name)
|
||||
->force()
|
||||
->create();
|
||||
```
|
||||
|
||||
### Setting a custom location for a temporary directory
|
||||
|
||||
You can set a custom location in which your temporary directory will be created by passing a string `$location` argument to the `TemporaryDirectory` constructor.
|
||||
|
||||
```php
|
||||
(new TemporaryDirectory($location))
|
||||
->create();
|
||||
```
|
||||
|
||||
The `make` method also accepts a `$location` argument.
|
||||
|
||||
```php
|
||||
TemporaryDirectory::make($location);
|
||||
```
|
||||
|
||||
Finally, you can call the `location` method with a `$location` argument.
|
||||
|
||||
```php
|
||||
(new TemporaryDirectory())
|
||||
->location($location)
|
||||
->create();
|
||||
```
|
||||
|
||||
### Determining paths within the temporary directory
|
||||
|
||||
You can use the `path` method to determine the full path to a file or directory in the temporary directory:
|
||||
|
||||
```php
|
||||
$temporaryDirectory = (new TemporaryDirectory())->create();
|
||||
$temporaryDirectory->path('dumps/datadump.dat'); // return /tmp/1485941876276/dumps/datadump.dat
|
||||
```
|
||||
|
||||
### Emptying a temporary directory
|
||||
|
||||
Use the `empty` method to delete all the files inside the temporary directory.
|
||||
|
||||
```php
|
||||
$temporaryDirectory->empty();
|
||||
```
|
||||
|
||||
### Deleting a temporary directory
|
||||
|
||||
Once you're done processing your temporary data you can delete the entire temporary directory using the `delete` method. All files inside of it will be deleted.
|
||||
|
||||
```php
|
||||
$temporaryDirectory->delete();
|
||||
```
|
||||
|
||||
### Deleting a temporary directory when the object is destroyed
|
||||
|
||||
If you want to automatically have the filesystem directory deleted when the object instance has no more references in
|
||||
its defined scope, you can enable `deleteWhenDestroyed()` on the TemporaryDirectory object.
|
||||
|
||||
```php
|
||||
function handleTemporaryFiles()
|
||||
{
|
||||
$temporaryDirectory = (new TemporaryDirectory())
|
||||
->deleteWhenDestroyed()
|
||||
->create();
|
||||
|
||||
// ... use the temporary directory
|
||||
|
||||
return; // no need to manually call $temporaryDirectory->delete()!
|
||||
}
|
||||
|
||||
handleTemporaryFiles();
|
||||
```
|
||||
|
||||
You can also call `unset()` on an object instance.
|
||||
|
||||
## Testing
|
||||
|
||||
```bash
|
||||
composer test
|
||||
```
|
||||
|
||||
## Changelog
|
||||
|
||||
Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.
|
||||
|
||||
## Contributing
|
||||
|
||||
Please see [CONTRIBUTING](https://github.com/spatie/.github/blob/main/CONTRIBUTING.md) for details.
|
||||
|
||||
## Security Vulnerabilities
|
||||
|
||||
Please review [our security policy](../../security/policy) on how to report security vulnerabilities.
|
||||
|
||||
## Postcardware
|
||||
|
||||
You're free to use this package, but if it makes it to your production environment we highly appreciate you sending us a postcard from your hometown, mentioning which of our package(s) you are using.
|
||||
|
||||
Our address is: Spatie, Kruikstraat 22, 2018 Antwerp, Belgium.
|
||||
|
||||
We publish all received postcards [on our company website](https://spatie.be/en/opensource/postcards).
|
||||
|
||||
## Credits
|
||||
|
||||
- [Alex Vanderbist](https://github.com/AlexVanderbist)
|
||||
- [All Contributors](../../contributors)
|
||||
|
||||
## License
|
||||
|
||||
The MIT License (MIT). Please see [License File](LICENSE.md) for more information.
|
||||
44
vendor/spatie/temporary-directory/composer.json
vendored
Normal file
44
vendor/spatie/temporary-directory/composer.json
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
{
|
||||
"name": "spatie/temporary-directory",
|
||||
"description": "Easily create, use and destroy temporary directories",
|
||||
"license": "MIT",
|
||||
"keywords": [
|
||||
"spatie",
|
||||
"php",
|
||||
"temporary-directory"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Alex Vanderbist",
|
||||
"email": "alex@spatie.be",
|
||||
"homepage": "https://spatie.be",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"homepage": "https://github.com/spatie/temporary-directory",
|
||||
"require": {
|
||||
"php": "^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^9.5"
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
"prefer-stable": true,
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Spatie\\TemporaryDirectory\\": "src"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Spatie\\TemporaryDirectory\\Test\\": "tests"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"sort-packages": true
|
||||
},
|
||||
"scripts": {
|
||||
"test": "vendor/bin/phpunit",
|
||||
"test-coverage": "vendor/bin/phpunit --coverage-html coverage"
|
||||
}
|
||||
}
|
||||
11
vendor/spatie/temporary-directory/src/Exceptions/InvalidDirectoryName.php
vendored
Normal file
11
vendor/spatie/temporary-directory/src/Exceptions/InvalidDirectoryName.php
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\TemporaryDirectory\Exceptions;
|
||||
|
||||
class InvalidDirectoryName extends \Exception
|
||||
{
|
||||
public static function create(string $directoryName): static
|
||||
{
|
||||
return new static("The directory name `{$directoryName}` contains invalid characters.");
|
||||
}
|
||||
}
|
||||
11
vendor/spatie/temporary-directory/src/Exceptions/PathAlreadyExists.php
vendored
Normal file
11
vendor/spatie/temporary-directory/src/Exceptions/PathAlreadyExists.php
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\TemporaryDirectory\Exceptions;
|
||||
|
||||
class PathAlreadyExists extends \Exception
|
||||
{
|
||||
public static function create(string $path): static
|
||||
{
|
||||
return new static("Path `{$path}` already exists.");
|
||||
}
|
||||
}
|
||||
201
vendor/spatie/temporary-directory/src/TemporaryDirectory.php
vendored
Normal file
201
vendor/spatie/temporary-directory/src/TemporaryDirectory.php
vendored
Normal file
@@ -0,0 +1,201 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\TemporaryDirectory;
|
||||
|
||||
use FilesystemIterator;
|
||||
use Spatie\TemporaryDirectory\Exceptions\InvalidDirectoryName;
|
||||
use Spatie\TemporaryDirectory\Exceptions\PathAlreadyExists;
|
||||
use Throwable;
|
||||
|
||||
class TemporaryDirectory
|
||||
{
|
||||
protected string $location;
|
||||
|
||||
protected string $name = '';
|
||||
|
||||
protected bool $forceCreate = false;
|
||||
|
||||
protected bool $deleteWhenDestroyed = false;
|
||||
|
||||
public function __construct(string $location = '')
|
||||
{
|
||||
$this->location = $this->sanitizePath($location);
|
||||
}
|
||||
|
||||
public static function make(string $location = ''): self
|
||||
{
|
||||
return (new self($location))->create();
|
||||
}
|
||||
|
||||
public function create(): self
|
||||
{
|
||||
if (empty($this->location)) {
|
||||
$this->location = $this->getSystemTemporaryDirectory();
|
||||
}
|
||||
|
||||
if (empty($this->name)) {
|
||||
$this->name = mt_rand().'-'.str_replace([' ', '.'], '', microtime());
|
||||
}
|
||||
|
||||
if ($this->forceCreate && file_exists($this->getFullPath())) {
|
||||
$this->deleteDirectory($this->getFullPath());
|
||||
}
|
||||
|
||||
if ($this->exists()) {
|
||||
throw PathAlreadyExists::create($this->getFullPath());
|
||||
}
|
||||
|
||||
mkdir($this->getFullPath(), 0777, true);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function force(): self
|
||||
{
|
||||
$this->forceCreate = true;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function name(string $name): self
|
||||
{
|
||||
$this->name = $this->sanitizeName($name);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function location(string $location): self
|
||||
{
|
||||
$this->location = $this->sanitizePath($location);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function path(string $pathOrFilename = ''): string
|
||||
{
|
||||
if (empty($pathOrFilename)) {
|
||||
return $this->getFullPath();
|
||||
}
|
||||
|
||||
$path = $this->getFullPath().DIRECTORY_SEPARATOR.trim($pathOrFilename, '/');
|
||||
|
||||
$directoryPath = $this->removeFilenameFromPath($path);
|
||||
|
||||
if (! file_exists($directoryPath)) {
|
||||
mkdir($directoryPath, 0777, true);
|
||||
}
|
||||
|
||||
return $path;
|
||||
}
|
||||
|
||||
public function empty(): self
|
||||
{
|
||||
$this->deleteDirectory($this->getFullPath());
|
||||
|
||||
mkdir($this->getFullPath(), 0777, true);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function delete(): bool
|
||||
{
|
||||
return $this->deleteDirectory($this->getFullPath());
|
||||
}
|
||||
|
||||
public function exists(): bool
|
||||
{
|
||||
return file_exists($this->getFullPath());
|
||||
}
|
||||
|
||||
protected function getFullPath(): string
|
||||
{
|
||||
return $this->location.(! empty($this->name) ? DIRECTORY_SEPARATOR.$this->name : '');
|
||||
}
|
||||
|
||||
protected function isValidDirectoryName(string $directoryName): bool
|
||||
{
|
||||
return strpbrk($directoryName, '\\/?%*:|"<>') === false;
|
||||
}
|
||||
|
||||
protected function getSystemTemporaryDirectory(): string
|
||||
{
|
||||
return rtrim(sys_get_temp_dir(), DIRECTORY_SEPARATOR);
|
||||
}
|
||||
|
||||
protected function sanitizePath(string $path): string
|
||||
{
|
||||
$path = rtrim($path);
|
||||
|
||||
return rtrim($path, DIRECTORY_SEPARATOR);
|
||||
}
|
||||
|
||||
protected function sanitizeName(string $name): string
|
||||
{
|
||||
if (! $this->isValidDirectoryName($name)) {
|
||||
throw InvalidDirectoryName::create($name);
|
||||
}
|
||||
|
||||
return trim($name);
|
||||
}
|
||||
|
||||
protected function removeFilenameFromPath(string $path): string
|
||||
{
|
||||
if (! $this->isFilePath($path)) {
|
||||
return $path;
|
||||
}
|
||||
|
||||
return substr($path, 0, strrpos($path, DIRECTORY_SEPARATOR));
|
||||
}
|
||||
|
||||
protected function isFilePath(string $path): bool
|
||||
{
|
||||
return str_contains($path, '.');
|
||||
}
|
||||
|
||||
protected function deleteDirectory(string $path): bool
|
||||
{
|
||||
try {
|
||||
if (is_link($path)) {
|
||||
return unlink($path);
|
||||
}
|
||||
|
||||
if (! file_exists($path)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (! is_dir($path)) {
|
||||
return unlink($path);
|
||||
}
|
||||
|
||||
foreach (new FilesystemIterator($path) as $item) {
|
||||
if (! $this->deleteDirectory((string) $item)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* By forcing a php garbage collection cycle using gc_collect_cycles() we can ensure
|
||||
* that the rmdir does not fail due to files still being reserved in memory.
|
||||
*/
|
||||
gc_collect_cycles();
|
||||
|
||||
return rmdir($path);
|
||||
} catch (Throwable) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function deleteWhenDestroyed(bool $deleteWhenDestroyed = true): self
|
||||
{
|
||||
$this->deleteWhenDestroyed = $deleteWhenDestroyed;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function __destruct()
|
||||
{
|
||||
if ($this->deleteWhenDestroyed) {
|
||||
$this->delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user