├── .gitignore
├── .styleci.yml
├── .idea
├── vcs.xml
├── markdown.xml
├── laravel-idea.xml
├── .gitignore
├── phpunit.xml
├── modules.xml
├── laravel-idea-personal.xml
├── codeception.xml
├── phpspec.xml
├── laravel-metrics.iml
├── php.xml
└── blade.xml
├── src
├── HasMetrics.php
├── LaravelMetricsFacade.php
├── Enums
│ ├── Aggregate.php
│ └── Period.php
├── Exceptions
│ ├── InvalidDateFormatException.php
│ ├── InvalidPeriodException.php
│ ├── InvalidAggregateException.php
│ └── InvalidVariationsCountException.php
├── DatesFunctions.php
└── LaravelMetrics.php
├── .github
└── FUNDING.yml
├── LICENSE.md
├── composer.json
├── CHANGELOG.md
├── CONTRIBUTING.md
├── README.md
└── composer.lock
/.gitignore:
--------------------------------------------------------------------------------
1 | /vendor
--------------------------------------------------------------------------------
/.styleci.yml:
--------------------------------------------------------------------------------
1 | preset: laravel
2 |
3 | disabled:
4 | - single_class_element_per_statement
5 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/markdown.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/laravel-idea.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | # Editor-based HTTP Client requests
5 | /httpRequests/
6 | # Datasource local storage ignored files
7 | /dataSources/
8 | /dataSources.local.xml
9 |
--------------------------------------------------------------------------------
/.idea/phpunit.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
10 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/src/HasMetrics.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/src/LaravelMetricsFacade.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/.idea/phpspec.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "eliseekn/laravel-metrics",
3 | "description": "Generate easily metrics and trends data of your models for your dashboards.",
4 | "keywords": [
5 | "laravel-package",
6 | "charts",
7 | "laravel",
8 | "dashboard"
9 | ],
10 | "homepage": "https://github.com/eliseekn/laravel-metrics",
11 | "license": "MIT",
12 | "type": "library",
13 | "authors": [
14 | {
15 | "name": "N'Guessan Kouadio Elisée",
16 | "email": "eliseekn@gmail.com",
17 | "homepage": "https://eliseekn.netlify.app",
18 | "role": "Developer"
19 | }
20 | ],
21 | "minimum-stability": "stable",
22 | "require": {
23 | "php": "^8.1",
24 | "illuminate/database": "^10.20",
25 | "illuminate/support": "^10.20",
26 | "nesbot/carbon": "^2.69"
27 | },
28 | "require-dev": {
29 | "laravel/pint": "^1.13",
30 | "phpunit/phpunit": "^9.6"
31 | },
32 | "autoload": {
33 | "psr-4": {
34 | "Eliseekn\\LaravelMetrics\\": "src"
35 | }
36 | },
37 | "autoload-dev": {
38 | "psr-4": {
39 | "Eliseekn\\LaravelMetrics\\Tests\\": "tests"
40 | }
41 | },
42 | "scripts": {
43 | "test": "vendor/bin/phpunit"
44 | },
45 | "config": {
46 | "sort-packages": true
47 | },
48 | "extra": {
49 | "laravel": {
50 | "aliases": {
51 | "LaravelMetrics": "Eliseekn\\LaravelMetrics\\LaravelMetricsFacade"
52 | }
53 | }
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | All notable changes to `laravel-metrics` will be documented in this file
4 |
5 | ## 2.9.3
6 |
7 | - Fix date function by database driver
8 | - Fix metrics negative variation value display
9 |
10 | ## 2.9.2
11 |
12 | - Rebase branch 2.9.0-beta-1 onto 2.x
13 |
14 | ## 2.9.2-beta-2
15 |
16 | - Add metricsWithVariations method
17 | - Fix some bugs
18 |
19 | ## 2.9.0-beta-1
20 |
21 | - Add SQLite support
22 | - Add $missingDataLabels auto discovery
23 | - Add metrics with variations option
24 | - Add trends in percents option
25 | - Fix PostgreSQL support bugs
26 |
27 | ## 2.8.0
28 |
29 | - Add PostgreSQL support
30 |
31 | ## 2.7.4
32 |
33 | - Add "from" period to set custom startDate end use the current date as endDate for between period
34 |
35 | ## 2.7.3
36 |
37 | - Fix null exception on get metrics data
38 |
39 | ## 2.7.0
40 |
41 | - Replace fillEmptyData by fillMissingData
42 | - Set fillMissingData as global method
43 | - Add groupBy methods for between period
44 | - Fix some bugs
45 |
46 | ## 2.6.1
47 |
48 | - Add Combined periods and aggregates methods
49 |
50 | ## 2.6
51 |
52 | - Add 'fillEmptyDates' method to fill data for empty dates
53 | - Fix get trends from 'between' method when using custom label
54 |
55 | ## 2.4.1
56 |
57 | - Fix undefined array key 'data' exception when trends are empty
58 |
59 | ## 2.4.0
60 |
61 | - Add HasMetrics trait for models
62 |
63 | ## 2.3.0
64 |
65 | - Add forDay and forMonth methods
66 |
67 | ## 2.1.0
68 |
69 | - Add custom label column definition
70 | - Move periods and aggregates constants to enums
71 |
72 | ## 2.0.0
73 |
74 | - Upgrade to PHP version to 8.1
75 | - Add SQLite support
76 | - Update whole code structure
77 | - Remove static method
78 | - Add eloquent query builder
79 |
80 | ## 1.0.5 - 2022-01-04
81 |
82 | - Fix parameters types
83 |
84 | ## 1.0.4 - 2022-01-04
85 |
86 | - Add demo project link
87 |
88 | ## 1.0.3 - 2021-12-30
89 |
90 | - Fix getTrends() returns data
91 | - Fix custom date range result
92 |
93 | ## 1.0.2 - 2021-12-30
94 |
95 | - Add custom date range
96 |
97 | ## 1.0.1 - 2021-09-25
98 |
99 | - Add Carbon package
100 | - Remove unnecessary files and folder
101 |
102 | ## 1.0.0 - 2021-09-25
103 |
104 | - Initial release
105 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | Contributions are **welcome** and will be fully **credited**.
4 |
5 | Please read and understand the contribution guide before creating an issue or pull request.
6 |
7 | ## Etiquette
8 |
9 | This project is open source, and as such, the maintainers give their free time to build and maintain the source code
10 | held within. They make the code freely available in the hope that it will be of use to other developers. It would be
11 | extremely unfair for them to suffer abuse or anger for their hard work.
12 |
13 | Please be considerate towards maintainers when raising issues or presenting pull requests. Let's show the
14 | world that developers are civilized and selfless people.
15 |
16 | It's the duty of the maintainer to ensure that all submissions to the project are of sufficient
17 | quality to benefit the project. Many developers have different skillsets, strengths, and weaknesses. Respect the maintainer's decision, and do not be upset or abusive if your submission is not used.
18 |
19 | ## Viability
20 |
21 | When requesting or submitting new features, first consider whether it might be useful to others. Open
22 | source projects are used by many developers, who may have entirely different needs to your own. Think about
23 | whether or not your feature is likely to be used by other users of the project.
24 |
25 | ## Procedure
26 |
27 | Before filing an issue:
28 |
29 | - Attempt to replicate the problem, to ensure that it wasn't a coincidental incident.
30 | - Check to make sure your feature suggestion isn't already present within the project.
31 | - Check the pull requests tab to ensure that the bug doesn't have a fix in progress.
32 | - Check the pull requests tab to ensure that the feature isn't already in progress.
33 |
34 | Before submitting a pull request:
35 |
36 | - Check the codebase to ensure that your feature doesn't already exist.
37 | - Check the pull requests to ensure that another person hasn't already submitted the feature or fix.
38 |
39 | ## Requirements
40 |
41 | If the project maintainer has any additional requirements, you will find them listed here.
42 |
43 | - **[PSR-2 Coding Standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)** - The easiest way to apply the conventions is to install [PHP Code Sniffer](https://pear.php.net/package/PHP_CodeSniffer).
44 |
45 | - **Add tests!** - Your patch won't be accepted if it doesn't have tests.
46 |
47 | - **Document any change in behaviour** - Make sure the `README.md` and any other relevant documentation are kept up-to-date.
48 |
49 | - **Consider our release cycle** - We try to follow [SemVer v2.0.0](https://semver.org/). Randomly breaking public APIs is not an option.
50 |
51 | - **One pull request per feature** - If you want to do more than one thing, send multiple pull requests.
52 |
53 | - **Send coherent history** - Make sure each individual commit in your pull request is meaningful. If you had to make multiple intermediate commits while developing, please [squash them](https://www.git-scm.com/book/en/v2/Git-Tools-Rewriting-History#Changing-Multiple-Commit-Messages) before submitting.
54 |
55 | **Happy coding**!
56 |
--------------------------------------------------------------------------------
/.idea/laravel-metrics.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/.idea/php.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
--------------------------------------------------------------------------------
/src/DatesFunctions.php:
--------------------------------------------------------------------------------
1 | year.'-'.$this->month.'-'.$this->day);
19 | }
20 |
21 | protected function getDayPeriod(): array
22 | {
23 | $day = $this->month !== Carbon::now()->month ? $this->carbon()->endOfMonth()->day : $this->day;
24 | $diff = $day - $this->carbon()->startOfMonth()->day;
25 |
26 | if ($diff < $this->count) {
27 | return [$this->carbon()->startOfMonth()->day, $day];
28 | }
29 |
30 | return [$this->carbon()->subDays($this->count)->day, $day];
31 | }
32 |
33 | protected function getWeekPeriod(): array
34 | {
35 | $week = $this->month !== Carbon::now()->month ? $this->carbon()->endOfMonth()->week : $this->week;
36 | $diff = $week - $this->carbon()->startOfMonth()->week;
37 |
38 | if ($diff < $this->count) {
39 | return [$this->carbon()->startOfMonth()->week, $week];
40 | }
41 |
42 | return [$this->carbon()->subWeeks($this->count)->week, $week];
43 | }
44 |
45 | protected function getMonthPeriod(): array
46 | {
47 | $month = $this->year !== Carbon::now()->year ? $this->carbon()->endOfYear()->month : $this->month;
48 | $diff = $month - $this->carbon()->startOfYear()->month;
49 |
50 | if ($diff < $this->count) {
51 | return [$this->carbon()->startOfYear()->month, $month];
52 | }
53 |
54 | return [$this->carbon()->subMonths($this->count)->month, $month];
55 | }
56 |
57 | protected function formatPeriod(string $period): string
58 | {
59 | $driver = $this->builder->getConnection()->getDriverName();
60 |
61 | if ($driver === 'mysql') {
62 | return match ($period) {
63 | Period::TODAY->value, Period::DAY->value => "day($this->dateColumn)",
64 | Period::WEEK->value => "week($this->dateColumn)",
65 | Period::MONTH->value => "month($this->dateColumn)",
66 | default => "year($this->dateColumn)",
67 | };
68 | }
69 |
70 | if ($driver === 'pgsql') {
71 | return match ($period) {
72 | Period::TODAY->value, Period::DAY->value => "EXTRACT(DAY FROM $this->dateColumn)",
73 | Period::WEEK->value => "EXTRACT(WEEK FROM $this->dateColumn)",
74 | Period::MONTH->value => "EXTRACT(MONTH FROM $this->dateColumn)",
75 | default => "EXTRACT(YEAR FROM $this->dateColumn)",
76 | };
77 | }
78 |
79 | return match ($period) {
80 | Period::TODAY->value, Period::DAY->value => "strftime('%d', $this->dateColumn)",
81 | Period::WEEK->value => "strftime('%W', $this->dateColumn)",
82 | Period::MONTH->value => "strftime('%m', $this->dateColumn)",
83 | default => "strftime('%Y', $this->dateColumn)",
84 | };
85 | }
86 |
87 | protected function formatDateColumn(): string
88 | {
89 | $driver = $this->builder->getConnection()->getDriverName();
90 |
91 | return match ($driver) {
92 | 'mysql' => "date($this->dateColumn)",
93 | 'pgsql' => "TO_CHAR($this->dateColumn, 'YYYY-MM-DD')",
94 | default => "strftime('%Y-%m-%d', $this->dateColumn)",
95 | };
96 | }
97 |
98 | protected function formatDate(array $data): array
99 | {
100 | return array_map(function ($datum) {
101 | if (! is_numeric($datum['label']) && ! DateTime::createFromFormat('Y-m-d', $datum['label'])) {
102 | return $datum;
103 | }
104 |
105 | if ($this->period === Period::MONTH->value) {
106 | $datum['label'] = Carbon::parse($this->year.'-'.$datum['label'])->locale(self::locale())->monthName;
107 | } elseif ($this->period === Period::DAY->value) {
108 | $datum['label'] = Carbon::parse($this->year.'-'.$this->month.'-'.$datum['label'])->locale(self::locale())->dayName;
109 | } elseif ($this->period === Period::WEEK->value) {
110 | $datum['label'] = 'Week '.$datum['label'];
111 | } elseif ($this->period === Period::YEAR->value) {
112 | $datum['label'] = intval($datum['label']);
113 | } else {
114 | $datum['label'] = Carbon::parse($datum['label'])->locale(self::locale())->isoFormat($this->dateIsoFormat);
115 | }
116 |
117 | return $datum;
118 | }, $data);
119 | }
120 |
121 | protected function checkDateFormat(array $dates): void
122 | {
123 | foreach ($dates as $date) {
124 | $d = DateTime::createFromFormat('Y-m-d', $date);
125 |
126 | if (! $d || $d->format('Y-m-d') !== $date) {
127 | throw new InvalidDateFormatException();
128 | }
129 | }
130 | }
131 |
132 | protected function getMonthsData(): array
133 | {
134 | $result = [];
135 |
136 | $dates = collect(
137 | CarbonPeriod::between(
138 | $this->carbon()->startOfYear()->format('Y-m-d'),
139 | $this->carbon()->format('Y-m-d')
140 | )->interval('1 month'))
141 | ->map(fn ($date) => Carbon::parse($date)->locale(self::locale())->monthName)->toArray();
142 |
143 | foreach ($dates as $date) {
144 | $result[$date] = $this->missingDataValue;
145 | }
146 |
147 | return $result;
148 | }
149 |
150 | protected function getDaysData(): array
151 | {
152 | $result = [];
153 |
154 | $dates = collect(
155 | CarbonPeriod::between(
156 | $this->carbon()->startOfWeek()->format('Y-m-d'),
157 | $this->carbon()->format('Y-m-d')
158 | )->interval('1 day'))
159 | ->map(fn ($date) => Carbon::parse($date)->locale(self::locale())->dayName)->toArray();
160 |
161 | foreach ($dates as $date) {
162 | $result[$date] = $this->missingDataValue;
163 | }
164 |
165 | return $result;
166 | }
167 |
168 | protected function getWeeksData(): array
169 | {
170 | $result = [];
171 |
172 | $dates = collect(
173 | CarbonPeriod::between(
174 | $this->carbon()->startOfMonth()->format('Y-m-d'),
175 | $this->carbon()->format('Y-m-d')
176 | )->interval('1 week'))
177 | ->map(fn ($date) => 'Week '.Carbon::parse($date)->locale(self::locale())->week)->toArray();
178 |
179 | foreach ($dates as $date) {
180 | $result[$date] = $this->missingDataValue;
181 | }
182 |
183 | return $result;
184 | }
185 |
186 | protected function getYearsData(): array
187 | {
188 | $result = [];
189 |
190 | $dates = collect(
191 | CarbonPeriod::between(
192 | $this->carbon()->subYears($this->count),
193 | $this->carbon()
194 | )->interval('1 year'))
195 | ->map(fn ($date) => Carbon::parse($date)->locale(self::locale())->year)->toArray();
196 |
197 | foreach ($dates as $date) {
198 | $result[$date] = $this->missingDataValue;
199 | }
200 |
201 | return $result;
202 | }
203 |
204 | protected function getLabelsData(): array
205 | {
206 | $result = [];
207 |
208 | $labelColumn = explode('.', $this->labelColumn)[1];
209 |
210 | $missingDataLabels = empty($this->missingDataLabels)
211 | ? DB::table($this->table)->get()->pluck($labelColumn)->toArray()
212 | : $this->missingDataLabels;
213 |
214 | foreach ($missingDataLabels as $label) {
215 | $result[$label] = $this->missingDataValue;
216 | }
217 |
218 | return $result;
219 | }
220 |
221 | protected function getCustomPeriod(): array
222 | {
223 | return collect(
224 | CarbonPeriod::between(
225 | $this->period[0],
226 | $this->period[1]
227 | )->interval('1 '.$this->groupBy))
228 | ->map(fn ($date) => Carbon::parse($date)->format('Y-m-d'))->toArray();
229 | }
230 |
231 | protected function getPeriod(): array
232 | {
233 | return match ($this->period) {
234 | Period::MONTH->value => $this->getMonthsData(),
235 | Period::DAY->value => $this->getDaysData(),
236 | Period::WEEK->value => $this->getWeeksData(),
237 | default => $this->getYearsData()
238 | };
239 | }
240 | }
241 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Metrics for Laravel
2 |
3 | [](https://packagist.org/packages/eliseekn/laravel-metrics)
4 | [](https://packagist.org/packages/eliseekn/laravel-metrics)
5 |
6 | Generate easily metrics and trends data of your models for your dashboards.
7 |
8 | ## Requirements
9 | ```bash
10 | PHP ^8.1.x
11 | Laravel ^10.x
12 | ```
13 |
14 | ***Note :*** For Laravel 11.x support check [3.x](https://github.com/eliseekn/laravel-metrics/tree/3.x) branch.
15 |
16 | ## Installation
17 | ```bash
18 | composer require eliseekn/laravel-metrics
19 | ```
20 |
21 | ## Features
22 | - MySQ, PostgreSQL and SQLite support
23 | - Verbose query builder
24 | - Custom columns and table definition
25 | - Days and months translation with Carbon
26 |
27 | ## Usage
28 |
29 | ### With Eloquent Query
30 |
31 | Import the `Eliseekn\LaravelMetrics\LaravelMetrics` class in your controller and use it as follows :
32 | - Basic usage
33 |
34 | ```php
35 | // generate trends of products amount's sum for the current year
36 | LaravelMetrics::query(Product::query())
37 | ->count()
38 | ->byMonth()
39 | ->trends();
40 |
41 | // generate trends of orders amount's sum for the last 6 months of the current year including current month
42 | LaravelMetrics::query(Order::query())
43 | ->sum('amount')
44 | ->byMonth(6)
45 | ->trends();
46 |
47 | // generate total orders amount's sum
48 | LaravelMetrics::query(Order::query())
49 | ->sum('amount')
50 | ->byYear()
51 | ->metrics();
52 |
53 | // generate total product count for the current day
54 | LaravelMetrics::query(Product::query())
55 | ->count()
56 | ->byDay(1)
57 | ->metrics();
58 | ```
59 |
60 | - Using custom query
61 | ```php
62 | LaravelMetrics::query(
63 | Post::query()->where('user_id', auth()->id())
64 | )
65 | ->count()
66 | ->byDay()
67 | ->trends();
68 | ```
69 |
70 | - Using custom date column
71 | ```php
72 | LaravelMetrics::query(Post::query())
73 | ->count()
74 | ->byDay()
75 | ->dateColumn('published_at')
76 | ->trends();
77 | ```
78 |
79 | - Using date range
80 | ```php
81 | LaravelMetrics::query(Post::query()))
82 | ->count()
83 | ->between('2020-05-01', '2022-08-21')
84 | ->trends();
85 | ```
86 |
87 | - Using custom label column
88 | ```php
89 | LaravelMetrics::query(Order::query())
90 | ->count()
91 | ->byMonth(12)
92 | ->labelColumn('status')
93 | ->trends();
94 | ```
95 |
96 | - Using custom table
97 | ```php
98 | LaravelMetrics::query(
99 | Order::query()->join('users', 'orders.id', 'users.order_id')
100 | )
101 | ->count()
102 | ->table('users')
103 | ->labelColumn('name')
104 | ->trends();
105 | ```
106 |
107 | ### With Query Builder
108 | ```php
109 | LaravelMetrics::query(
110 | DB::table('orders')
111 | )
112 | ->sum('amount')
113 | ->byMonth()
114 | ->trends();
115 | ```
116 |
117 | ### With traits
118 |
119 | Add `HasMetrics` trait to your models and use it as follows :
120 |
121 | ```php
122 | Order::metrics()
123 | ->sum('amount')
124 | ->byMonth()
125 | ->trends();
126 | ```
127 |
128 | ### Types of periods
129 | ```php
130 | LaravelMetrics::query(...)
131 | ->byDay(int $count = 0) //or
132 | ->byWeek(int $count = 0) //or
133 | ->byMonth(int $count = 0) //or
134 | ->byYear(int $count = 0) //or
135 | ->between(string $startDate, string $endDate, string $dateIsoFormat) //or
136 | ->from(string $date, string $dateIsoFormat)
137 | ```
138 |
139 | ***Note :*** Periods are defined for the current day, week, month or year by default. However, you can define a specific value using dedicated methods. For example:
140 |
141 | ```php
142 | // generate trends of orders count for the current year
143 | LaravelMetrics::query(Order::query())
144 | ->count()
145 | ->byMonth(12)
146 | ->forYear(now()->year)
147 | ->labelColumn('status')
148 | ->trends();
149 |
150 | // generate total orders amount's sum for the third month only
151 | LaravelMetrics::query(Product::query())
152 | ->sum('amount')
153 | ->byMonth(1)
154 | ->forMonth(3)
155 | ->metrics();
156 | ```
157 |
158 | ```php
159 | LaravelMetrics::query(...)
160 | ->forDay(int $day)
161 | ->forWeek(int $week)
162 | ->forMonth(int $month)
163 | ->forYear(int $year)
164 | ```
165 |
166 | ### Types of aggregates
167 | ```php
168 | LaravelMetrics::query(...)
169 | ->count(string $column = 'id') //or
170 | ->average(string $column) //or
171 | ->sum(string $column) //or
172 | ->max(string $column) //or
173 | ->min(string $column)
174 | ```
175 |
176 | ### Types of data
177 | ```php
178 | LaravelMetrics::query(...)
179 | ->trends(bool $inPercent = false) //or
180 | ->metrics() //or
181 | ->metricsWithVariations(int $previousCount, string $previousPeriod, bool $inPercent = false)
182 | ```
183 |
184 | ***Note 1 :*** The `trends` method can generate data in percentage format when the `$inPercent` parameter is set to `true`.
185 |
186 | ***Note 2 :*** The `metricsWithVariations` method generates metrics with variations from the `$previousPeriod` period (`day`, `week`, `month`, or `year`). The `$previousCount` parameter specifies the count for the past period. Set `$inPercent` parameter to true to get variations result in percent.
187 |
188 | ### Combining periods and aggregates
189 | Combining different time periods and data aggregates can enhance your overall experience. For example :
190 |
191 | ```php
192 | LaravelMetrics::query(...)
193 | ->sumByYear()
194 | ->trends();
195 |
196 | LaravelMetrics::query(...)
197 | ->countByMonth(count: 12)
198 | ->forYear(now()->year)
199 | ->labelColumn('status')
200 | ->trends();
201 |
202 | LaravelMetrics::query(...)
203 | ->countBetween([Carbon::now()->subDays(10)->format('Y-m-d'), Carbon::now()->format('Y-m-d')])
204 | ->trends();
205 |
206 | LaravelMetrics::query(...)
207 | ->averageFrom(Carbon::now()->subDays(10)->format('Y-m-d'))
208 | ->trends();
209 | ...
210 | ```
211 |
212 | Possible combinations :
213 |
214 | ```php
215 | LaravelMetrics::query(...)
216 | ->countByMonth(...) //or
217 | ->countByYear(...) //or
218 | ->countByDay(...) //or
219 | ->countByWeek(...) //or
220 | ->sumByMonth(...) //or
221 | ->sumByYear(...) //or
222 | ->sumByDay(...) //or
223 | ->sumByWeek(...) //or
224 | ->averageByMonth(...) //or
225 | ->averageByYear(...) //or
226 | ->averageByDay(...) //or
227 | ->averageByWeek(...) //or
228 | ->maxByMonth(...) //or
229 | ->maxByYear(...) //or
230 | ->maxByDay(...) //or
231 | ->maxByWeek(...) //or
232 | ->minByMonth(...) //or
233 | ->minByYear(...) //or
234 | ->minByDay(...) //or
235 | ->minByWeek(...) //or
236 | ->countBetween(...) //or
237 | ->sumBetween(...) //or
238 | ->averageBetween(...) //or
239 | ->maxBetween(...) //or
240 | ->minBetween(...) //or
241 | ->countFrom(...) //or
242 | ->sumFrom(...) //or
243 | ->averageFrom(...) //or
244 | ->maxFrom(...) //or
245 | ->minFrom(...)
246 | ```
247 |
248 | ### Fill missing data with default value
249 | You can fill missing data with default value with the global method ```fillMissingData```, especially for trends. For example :
250 |
251 | ```php
252 | LaravelMetrics::query(...)
253 | ->countBetween([Carbon::now()->subDays(10)->format('Y-m-d'), Carbon::now()->format('Y-m-d')])
254 | ->fillMissingData()
255 | ->trends();
256 |
257 | LaravelMetrics::query(...)
258 | ->sumByYear(count: 5)
259 | ->fillMissingData()
260 | ->trends();
261 | ...
262 | ```
263 |
264 | ***Note :*** The `fillMissingData` method automatically discovers all labels, ensuring that data is filled for all available labels without the need for explicit label specification.
265 |
266 | ### Group period (only when using ```between``` method)
267 | You can group period by days, months, weeks or years when using the ```between``` method (***default is day***). For example :
268 |
269 | ```php
270 | LaravelMetrics::query(...)
271 | ->countBetween([Carbon::now()->subDays(10)->format('Y-m-d'), Carbon::now()->format('Y-m-d')])
272 | ->groupByMonth()
273 | ->fillMissingData()
274 | ->trends();
275 | ```
276 |
277 | ```php
278 | LaravelMetrics::query(...)
279 | ->groupByYear() //or
280 | ->groupByMonth() //or
281 | ->groupByWeek() //or
282 | ->groupByDay()
283 | ```
284 |
285 | ### Group data (only for ```trends```)
286 | You can group data of a column with multiple values to use it in a dataset for your charts. For example :
287 |
288 | ```php
289 | Order::metrics()
290 | ->countByMonth(column: 'status')
291 | ->groupData(['pending', 'delivered', 'cancelled'], Aggregate::SUM->value)
292 | ->fillMissingData()
293 | ->trends();
294 | ```
295 |
296 | ***Note :*** Follow same order in the example to avoid false data.
297 |
298 | ## Translations
299 |
300 | Days and months names are automatically translated using `config(app.locale)` except 'week' period.
301 |
302 | ## Changelog
303 |
304 | Please see [CHANGELOG](CHANGELOG.md) for more information what has changed recently.
305 |
306 | ## Contributing
307 |
308 | Please see [CONTRIBUTING](CONTRIBUTING.md) for details.
309 |
310 | ## Security
311 |
312 | If you discover any security related issues, please email `eliseekn@gmail.com` instead of using the issue tracker.
313 |
314 | ## Credits
315 |
316 | - [N'Guessan Kouadio Elisée](https://github.com/eliseekn)
317 | - [Chris Brown](https://github.com/drbyte)
318 |
319 | ## License
320 |
321 | The MIT License (MIT). Please see [License File](LICENSE.md) for more information.
322 |
323 | ## Demo
324 |
325 | You can find a demo project [here](https://github.com/eliseekn/laravel-metrics-demo).
326 |
327 | ## Laravel Package Boilerplate
328 |
329 | This package was generated using the [Laravel Package Boilerplate](https://laravelpackageboilerplate.com).
330 |
--------------------------------------------------------------------------------
/.idea/blade.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
--------------------------------------------------------------------------------
/src/LaravelMetrics.php:
--------------------------------------------------------------------------------
1 | table = $this->builder->from;
67 | $this->dateColumn = $this->table.'.created_at';
68 | $this->period = null;
69 | $this->aggregate = Aggregate::COUNT->value;
70 | $this->year = Carbon::now()->year;
71 | $this->month = Carbon::now()->month;
72 | $this->day = Carbon::now()->day;
73 | $this->week = Carbon::now()->week;
74 | $this->groupBy = Period::DAY->value;
75 | }
76 |
77 | public static function query(Builder|QueryBuilder $builder): self
78 | {
79 | return new self($builder);
80 | }
81 |
82 | public function table(string $table): self
83 | {
84 | $this->table = $table;
85 |
86 | return $this;
87 | }
88 |
89 | protected function by(string $period, int $count = 0): self
90 | {
91 | $period = strtolower($period);
92 |
93 | if (! in_array($period, Period::values())) {
94 | throw new InvalidPeriodException();
95 | }
96 |
97 | $this->period = $period;
98 | $this->count = $count;
99 |
100 | return $this;
101 | }
102 |
103 | public function byDay(int $count = 0): self
104 | {
105 | return $this->by(Period::DAY->value, $count);
106 | }
107 |
108 | public function byWeek(int $count = 0): self
109 | {
110 | return $this->by(Period::WEEK->value, $count);
111 | }
112 |
113 | public function byMonth(int $count = 0): self
114 | {
115 | return $this->by(Period::MONTH->value, $count);
116 | }
117 |
118 | public function byYear(int $count = 0): self
119 | {
120 | return $this->by(Period::YEAR->value, $count);
121 | }
122 |
123 | public function between(string $start, string $end, string $dateIsoFormat = 'YYYY-MM-DD'): self
124 | {
125 | $this->checkDateFormat([$start, $end]);
126 | $this->period = [$start, $end];
127 | $this->dateIsoFormat = $dateIsoFormat;
128 |
129 | return $this;
130 | }
131 |
132 | public function from(string $date, string $dateIsoFormat = 'YYYY-MM-DD'): self
133 | {
134 | return $this->between($date, Carbon::now()->format('Y-m-d'), $dateIsoFormat);
135 | }
136 |
137 | protected function groupBy(string $period): self
138 | {
139 | $this->groupBy = $period;
140 |
141 | return $this;
142 | }
143 |
144 | public function groupByYear(): self
145 | {
146 | return $this->groupBy(Period::YEAR->value);
147 | }
148 |
149 | public function groupByMonth(): self
150 | {
151 | return $this->groupBy(Period::MONTH->value);
152 | }
153 |
154 | public function groupByWeek(): self
155 | {
156 | return $this->groupBy(Period::WEEK->value);
157 | }
158 |
159 | public function groupByDay(): self
160 | {
161 | return $this->groupBy(Period::DAY->value);
162 | }
163 |
164 | public function forDay(int $day): self
165 | {
166 | $this->day = $day;
167 |
168 | return $this;
169 | }
170 |
171 | public function forWeek(int $week): self
172 | {
173 | $this->week = $week;
174 |
175 | return $this;
176 | }
177 |
178 | public function forMonth(int $month): self
179 | {
180 | $this->month = $month;
181 |
182 | return $this;
183 | }
184 |
185 | public function forYear(int $year): self
186 | {
187 | $this->year = $year;
188 |
189 | return $this;
190 | }
191 |
192 | protected function aggregate(string $aggregate, string $column): self
193 | {
194 | $aggregate = strtolower($aggregate);
195 |
196 | if (! in_array($aggregate, Aggregate::values())) {
197 | throw new InvalidAggregateException();
198 | }
199 |
200 | $this->aggregate = $aggregate;
201 | $this->column = $this->table.'.'.$column;
202 |
203 | return $this;
204 | }
205 |
206 | public function count(string $column = 'id'): self
207 | {
208 | return $this->aggregate(Aggregate::COUNT->value, $column);
209 | }
210 |
211 | public function average(string $column): self
212 | {
213 | return $this->aggregate(Aggregate::AVERAGE->value, $column);
214 | }
215 |
216 | public function sum(string $column): self
217 | {
218 | return $this->aggregate(Aggregate::SUM->value, $column);
219 | }
220 |
221 | public function max(string $column): self
222 | {
223 | return $this->aggregate(Aggregate::MAX->value, $column);
224 | }
225 |
226 | public function min(string $column): self
227 | {
228 | return $this->aggregate(Aggregate::MIN->value, $column);
229 | }
230 |
231 | protected function countBy(string $period, string $column = 'id', int $count = 0): self
232 | {
233 | return $this
234 | ->by($period, $count)
235 | ->aggregate(Aggregate::COUNT->value, $column);
236 | }
237 |
238 | protected function averageBy(string $period, string $column = 'id', int $count = 0): self
239 | {
240 | return $this
241 | ->by($period, $count)
242 | ->aggregate(Aggregate::AVERAGE->value, $column);
243 | }
244 |
245 | protected function sumBy(string $period, string $column = 'id', int $count = 0): self
246 | {
247 | return $this
248 | ->by($period, $count)
249 | ->aggregate(Aggregate::SUM->value, $column);
250 | }
251 |
252 | protected function maxBy(string $period, string $column = 'id', int $count = 0): self
253 | {
254 | return $this
255 | ->by($period, $count)
256 | ->aggregate(Aggregate::MAX->value, $column);
257 | }
258 |
259 | protected function minBy(string $period, string $column = 'id', int $count = 0): self
260 | {
261 | return $this
262 | ->by($period, $count)
263 | ->aggregate(Aggregate::MIN->value, $column);
264 | }
265 |
266 | public function countByDay(string $column = 'id', int $count = 0): self
267 | {
268 | return $this->countBy(Period::DAY->value, $column, $count);
269 | }
270 |
271 | public function countByWeek(string $column = 'id', int $count = 0): self
272 | {
273 | return $this->countBy(Period::WEEK->value, $column, $count);
274 | }
275 |
276 | public function countByMonth(string $column = 'id', int $count = 0): self
277 | {
278 | return $this->countBy(Period::MONTH->value, $column, $count);
279 | }
280 |
281 | public function countByYear(string $column = 'id', int $count = 0): self
282 | {
283 | return $this->countBy(Period::YEAR->value, $column, $count);
284 | }
285 |
286 | public function sumByDay(string $column, int $count = 0): self
287 | {
288 | return $this->sumBy(Period::DAY->value, $column, $count);
289 | }
290 |
291 | public function sumByWeek(string $column, int $count = 0): self
292 | {
293 | return $this->sumBy(Period::WEEK->value, $column, $count);
294 | }
295 |
296 | public function sumByMonth(string $column, int $count = 0): self
297 | {
298 | return $this->sumBy(Period::MONTH->value, $column, $count);
299 | }
300 |
301 | public function sumByYear(string $column, int $count = 0): self
302 | {
303 | return $this->sumBy(Period::YEAR->value, $column, $count);
304 | }
305 |
306 | public function averageByDay(string $column, int $count = 0): self
307 | {
308 | return $this->averageBy(Period::DAY->value, $column, $count);
309 | }
310 |
311 | public function averageByWeek(string $column, int $count = 0): self
312 | {
313 | return $this->averageBy(Period::WEEK->value, $column, $count);
314 | }
315 |
316 | public function averageByMonth(string $column, int $count = 0): self
317 | {
318 | return $this->averageBy(Period::MONTH->value, $column, $count);
319 | }
320 |
321 | public function averageByYear(string $column, int $count = 0): self
322 | {
323 | return $this->averageBy(Period::YEAR->value, $column, $count);
324 | }
325 |
326 | public function maxByDay(string $column, int $count = 0): self
327 | {
328 | return $this->maxBy(Period::DAY->value, $column, $count);
329 | }
330 |
331 | public function maxByWeek(string $column, int $count = 0): self
332 | {
333 | return $this->maxBy(Period::WEEK->value, $column, $count);
334 | }
335 |
336 | public function maxByMonth(string $column, int $count = 0): self
337 | {
338 | return $this->maxBy(Period::MONTH->value, $column, $count);
339 | }
340 |
341 | public function maxByYear(string $column, int $count = 0): self
342 | {
343 | return $this->maxBy(Period::YEAR->value, $column, $count);
344 | }
345 |
346 | public function minByDay(string $column, int $count = 0): self
347 | {
348 | return $this->minBy(Period::DAY->value, $column, $count);
349 | }
350 |
351 | public function minByWeek(string $column, int $count = 0): self
352 | {
353 | return $this->minBy(Period::WEEK->value, $column, $count);
354 | }
355 |
356 | public function minByMonth(string $column, int $count = 0): self
357 | {
358 | return $this->minBy(Period::MONTH->value, $column, $count);
359 | }
360 |
361 | public function minByYear(string $column, int $count = 0): self
362 | {
363 | return $this->minBy(Period::YEAR->value, $column, $count);
364 | }
365 |
366 | public function countBetween(array $period, string $column = 'id', string $dateIsoFormat = 'YYYY-MM-DD'): self
367 | {
368 | return $this
369 | ->count($column)
370 | ->between($period[0], $period[1], $dateIsoFormat);
371 | }
372 |
373 | public function sumBetween(array $period, string $column, string $dateIsoFormat = 'YYYY-MM-DD'): self
374 | {
375 | return $this
376 | ->sum($column)
377 | ->between($period[0], $period[1], $dateIsoFormat);
378 | }
379 |
380 | public function averageBetween(array $period, string $column, string $dateIsoFormat = 'YYYY-MM-DD'): self
381 | {
382 | return $this
383 | ->average($column)
384 | ->between($period[0], $period[1], $dateIsoFormat);
385 | }
386 |
387 | public function maxBetween(array $period, string $column, string $dateIsoFormat = 'YYYY-MM-DD'): self
388 | {
389 | return $this
390 | ->max($column)
391 | ->between($period[0], $period[1], $dateIsoFormat);
392 | }
393 |
394 | public function minBetween(array $period, string $column, string $dateIsoFormat = 'YYYY-MM-DD'): self
395 | {
396 | return $this
397 | ->min($column)
398 | ->between($period[0], $period[1], $dateIsoFormat);
399 | }
400 |
401 | public function countFrom(string $date, string $column = 'id', string $dateIsoFormat = 'YYYY-MM-DD'): self
402 | {
403 | return $this
404 | ->count($column)
405 | ->from($date, $dateIsoFormat);
406 | }
407 |
408 | public function sumFrom(string $date, string $column, string $dateIsoFormat = 'YYYY-MM-DD'): self
409 | {
410 | return $this
411 | ->sum($column)
412 | ->from($date, $dateIsoFormat);
413 | }
414 |
415 | public function averageFrom(string $date, string $column, string $dateIsoFormat = 'YYYY-MM-DD'): self
416 | {
417 | return $this
418 | ->average($column)
419 | ->from($date, $dateIsoFormat);
420 | }
421 |
422 | public function maxFrom(string $date, string $column, string $dateIsoFormat = 'YYYY-MM-DD'): self
423 | {
424 | return $this
425 | ->max($column)
426 | ->from($date, $dateIsoFormat);
427 | }
428 |
429 | public function minFrom(string $date, string $column, string $dateIsoFormat = 'YYYY-MM-DD'): self
430 | {
431 | return $this
432 | ->min($column)
433 | ->from($date, $dateIsoFormat);
434 | }
435 |
436 | public function dateColumn(string $column): self
437 | {
438 | $this->dateColumn = $this->table.'.'.$column;
439 |
440 | return $this;
441 | }
442 |
443 | public function labelColumn(string $column): self
444 | {
445 | $this->labelColumn = $this->table.'.'.$column;
446 |
447 | return $this;
448 | }
449 |
450 | public function fillMissingData(int $missingDataValue = 0, array $missingDataLabels = []): self
451 | {
452 | $this->fillMissingData = true;
453 | $this->missingDataValue = $missingDataValue;
454 | $this->missingDataLabels = $missingDataLabels;
455 |
456 | return $this;
457 | }
458 |
459 | protected function metricsData(): mixed
460 | {
461 | if (is_array($this->period)) {
462 | return $this->builder
463 | ->selectRaw($this->asData())
464 | ->whereBetween(DB::raw($this->formatDateColumn()), [$this->period[0], $this->period[1]])
465 | ->first();
466 | }
467 |
468 | return match ($this->period) {
469 | Period::DAY->value => $this->builder
470 | ->selectRaw($this->asData())
471 | ->whereYear($this->dateColumn, $this->year)
472 | ->whereMonth($this->dateColumn, $this->month)
473 | ->when($this->count === 1, function (Builder|QueryBuilder $query) {
474 | return $query->where(DB::raw($this->formatPeriod(Period::TODAY->value)), $this->day);
475 | })
476 | ->when($this->count > 1, function (Builder|QueryBuilder $query) {
477 | return $query->whereBetween(DB::raw($this->formatPeriod(Period::TODAY->value)), $this->getDayPeriod());
478 | })
479 | ->first(),
480 |
481 | Period::WEEK->value => $this->builder
482 | ->selectRaw($this->asData())
483 | ->whereYear($this->dateColumn, $this->year)
484 | ->whereMonth($this->dateColumn, $this->month)
485 | ->when($this->count === 1, function (Builder|QueryBuilder $query) {
486 | return $query->where(DB::raw($this->formatPeriod(Period::WEEK->value)), $this->week);
487 | })
488 | ->when($this->count > 1, function (Builder|QueryBuilder $query) {
489 | return $query->whereBetween(DB::raw($this->formatPeriod(Period::WEEK->value)), $this->getWeekPeriod());
490 | })
491 | ->first(),
492 |
493 | Period::MONTH->value => $this->builder
494 | ->selectRaw($this->asData())
495 | ->whereYear($this->dateColumn, $this->year)
496 | ->when($this->count === 1, function (Builder|QueryBuilder $query) {
497 | return $query->where(DB::raw($this->formatPeriod(Period::MONTH->value)), $this->month);
498 | })
499 | ->when($this->count > 1, function (Builder|QueryBuilder $query) {
500 | return $query->whereBetween(DB::raw($this->formatPeriod(Period::MONTH->value)), $this->getMonthPeriod());
501 | })
502 | ->first(),
503 |
504 | Period::YEAR->value => $this->builder
505 | ->selectRaw($this->asData())
506 | ->when($this->count === 1, function (Builder|QueryBuilder $query) {
507 | return $query->where(DB::raw($this->formatPeriod(Period::YEAR->value)), $this->year);
508 | })
509 | ->when($this->count > 1, function (Builder|QueryBuilder $query) {
510 | return $query->whereBetween(DB::raw($this->formatPeriod(Period::YEAR->value)), [
511 | Carbon::now()->subYears($this->count)->year, $this->year,
512 | ]);
513 | })
514 | ->first(),
515 |
516 | default => $this->builder
517 | ->selectRaw($this->asData())
518 | ->first(),
519 | };
520 | }
521 |
522 | protected function trendsData(): Collection
523 | {
524 | if (is_array($this->period)) {
525 | return $this->builder
526 | ->selectRaw($this->asData().', '.$this->asLabel($this->formatDateColumn(), false).$this->groupedData)
527 | ->whereBetween(DB::raw($this->formatDateColumn()), [$this->period[0], $this->period[1]])
528 | ->groupBy('label')
529 | ->orderBy('label')
530 | ->get();
531 | }
532 |
533 | return match ($this->period) {
534 | Period::DAY->value => $this->builder
535 | ->selectRaw($this->asData().', '.$this->asLabel(Period::DAY->value).$this->groupedData)
536 | ->whereYear($this->dateColumn, $this->year)
537 | ->whereMonth($this->dateColumn, $this->month)
538 | ->when($this->count === 1, function (Builder|QueryBuilder $query) {
539 | return $query->where(DB::raw($this->formatPeriod(Period::TODAY->value)), $this->day);
540 | })
541 | ->when($this->count > 1, function (Builder|QueryBuilder $query) {
542 | return $query->whereBetween(DB::raw($this->formatPeriod(Period::TODAY->value)), $this->getDayPeriod());
543 | })
544 | ->groupBy('label')
545 | ->orderBy('label')
546 | ->get(),
547 |
548 | Period::WEEK->value => $this->builder
549 | ->selectRaw($this->asData().', '.$this->asLabel(Period::WEEK->value).$this->groupedData)
550 | ->whereYear($this->dateColumn, $this->year)
551 | ->whereMonth($this->dateColumn, $this->month)
552 | ->when($this->count === 1, function (Builder|QueryBuilder $query) {
553 | return $query->where(DB::raw($this->formatPeriod(Period::WEEK->value)), $this->week);
554 | })
555 | ->when($this->count > 1, function (Builder|QueryBuilder $query) {
556 | return $query->whereBetween(DB::raw($this->formatPeriod(Period::WEEK->value)), $this->getWeekPeriod());
557 | })
558 | ->groupBy('label')
559 | ->orderBy('label')
560 | ->get(),
561 |
562 | Period::MONTH->value => $this->builder
563 | ->selectRaw($this->asData().', '.$this->asLabel(Period::MONTH->value).$this->groupedData)
564 | ->whereYear($this->dateColumn, $this->year)
565 | ->when($this->count === 1, function (Builder|QueryBuilder $query) {
566 | return $query->where(DB::raw($this->formatPeriod(Period::MONTH->value)), $this->month);
567 | })
568 | ->when($this->count > 1, function (Builder|QueryBuilder $query) {
569 | return $query->whereBetween(DB::raw($this->formatPeriod(Period::MONTH->value)), $this->getMonthPeriod());
570 | })
571 | ->groupBy('label')
572 | ->orderBy('label')
573 | ->get(),
574 |
575 | Period::YEAR->value => $this->builder
576 | ->selectRaw($this->asData().', '.$this->asLabel(Period::YEAR->value).$this->groupedData)
577 | ->when($this->count === 1, function (Builder|QueryBuilder $query) {
578 | return $query->where(DB::raw($this->formatPeriod(Period::YEAR->value)), $this->year);
579 | })
580 | ->when($this->count > 1, function (Builder|QueryBuilder $query) {
581 | return $query->whereBetween(DB::raw($this->formatPeriod(Period::YEAR->value)), [
582 | Carbon::now()->subYears($this->count)->year, $this->year,
583 | ]);
584 | })
585 | ->groupBy('label')
586 | ->orderBy('label')
587 | ->get(),
588 |
589 | default => $this->builder
590 | ->selectRaw($this->asData().', '.$this->asLabel().$this->groupedData)
591 | ->groupBy('label')
592 | ->orderBy('label')
593 | ->get(),
594 | };
595 | }
596 |
597 | public function groupData(array $dataLabels, string $aggregate): self
598 | {
599 | $this->groupedDataLabels = $dataLabels;
600 | $result = [];
601 |
602 | foreach ($dataLabels as $key => $value) {
603 | $result[] = $aggregate.'('.$this->column.' = "'.$value.'")'." as data$key";
604 | }
605 |
606 | $this->groupedData = ', '.implode(', ', $result);
607 |
608 | return $this;
609 | }
610 |
611 | protected function asData(string $name = 'data'): string
612 | {
613 | return "$this->aggregate($this->column) as $name";
614 | }
615 |
616 | protected function asLabel(string $label = null, bool $format = true): string
617 | {
618 | if (is_null($this->labelColumn)) {
619 | $label = ! $format ? $label : $this->formatPeriod($label);
620 | } else {
621 | $label = $this->labelColumn;
622 | }
623 |
624 | return $label.' as label';
625 | }
626 |
627 | protected function populateMissingDataForPeriod(array $data, bool $inPercent = false, string $dataLabel = 'data'): array
628 | {
629 | $dates = $this->getCustomPeriod();
630 | $data = collect($data);
631 | $result = [];
632 |
633 | foreach ($dates as $date) {
634 | $dataForDate = $data->where('label', $date)->first();
635 |
636 | if ($dataForDate) {
637 | $result[] = [
638 | 'label' => $dataForDate['label'],
639 | 'data' => (int) $dataForDate[$dataLabel],
640 | ];
641 | } else {
642 | $result[] = [
643 | 'label' => $date,
644 | 'data' => $this->missingDataValue,
645 | ];
646 | }
647 | }
648 |
649 | $result = $this->formatDate($result);
650 |
651 | return $this->formatTrends($result, $inPercent);
652 | }
653 |
654 | protected function populateMissingData(array $labels, array $data): array
655 | {
656 | $result = [
657 | 'labels' => [],
658 | 'data' => [],
659 | ];
660 |
661 | foreach ($labels as $label => $defaultValue) {
662 | $key = array_search($label, $data['labels']);
663 | $result['labels'][] = $label;
664 |
665 | if ($key !== false) {
666 | $result['data'][] = $data['data'][$key];
667 | } else {
668 | $result['data'][] = $defaultValue;
669 | }
670 | }
671 |
672 | return $result;
673 | }
674 |
675 | /**
676 | * Generate metrics data
677 | */
678 | public function metrics(): mixed
679 | {
680 | $metricsData = $this->metricsData();
681 |
682 | return is_null($metricsData) ? 0 : ($metricsData->data ?? 0);
683 | }
684 |
685 | /**
686 | * Generate metrics data with variations
687 | */
688 | public function metricsWithVariations(int $previousCount, string $previousPeriod, bool $inPercent = false): array
689 | {
690 | if (! in_array($previousPeriod, Period::values())) {
691 | throw new InvalidPeriodException();
692 | }
693 |
694 | if ($previousCount <= 0) {
695 | throw new InvalidVariationsCountException();
696 | }
697 |
698 | $laravelMetrics = (new self(DB::table($this->table)))
699 | ->by($previousPeriod, $previousCount)
700 | ->aggregate($this->aggregate, str_replace($this->table.'.', '', $this->column));
701 |
702 | $variations = match ($previousPeriod) {
703 | Period::DAY->value => $laravelMetrics
704 | ->forDay(Carbon::now()->subDays($previousCount)->day)
705 | ->metrics(),
706 |
707 | Period::WEEK->value => $laravelMetrics
708 | ->forWeek(Carbon::now()->subWeeks($previousCount)->week)
709 | ->metrics(),
710 |
711 | Period::MONTH->value => $laravelMetrics
712 | ->forMonth(Carbon::now()->subMonths($previousCount)->month)
713 | ->metrics(),
714 |
715 | default => $laravelMetrics
716 | ->forYear(Carbon::now()->subYears($previousCount)->year)
717 | ->metrics(),
718 | };
719 |
720 | $result['count'] = $this->metrics();
721 | $result['variation'] = [];
722 |
723 | $value = $result['count'] - $variations;
724 |
725 | if ($inPercent && $variations > 0) {
726 | $value = (abs($value) / $variations) * 100 .'%';
727 | }
728 |
729 | if ($value > 0) {
730 | $result['variation'] = [
731 | 'type' => 'increase',
732 | 'value' => $value,
733 | ];
734 | } elseif ($value < 0) {
735 | $result['variation'] = [
736 | 'type' => 'decrease',
737 | 'value' => abs($value),
738 | ];
739 | }
740 |
741 | return $result;
742 | }
743 |
744 | protected function trendsWithMergedData(bool $inPercent = false): array
745 | {
746 | $result = [];
747 |
748 | $trendsData = $this
749 | ->trendsData()
750 | ->toArray();
751 |
752 | $trendsData = array_map(fn ($datum) => (array) $datum, $trendsData);
753 | $data = [$this->getFormattedTrendsData($trendsData, $inPercent)];
754 |
755 | foreach ($this->groupedDataLabels as $key => $value) {
756 | $data[] = $this->getFormattedTrendsData($trendsData, $inPercent, "data$key");
757 | }
758 |
759 | foreach ($data as $key => $value) {
760 | $result['labels'] = $value['labels'];
761 |
762 | if ($key === 0) {
763 | $result['data']['total'] = $value['data'];
764 | } else {
765 | $result['data'][$this->groupedDataLabels[$key - 1]] = $value['data'];
766 | }
767 | }
768 |
769 | return $result;
770 | }
771 |
772 | protected function getFormattedTrendsData(array $trendsData, bool $inPercent = false, string $dataLabel = 'data'): array
773 | {
774 | if (! $this->fillMissingData) {
775 | $trendsData = $this->formatDate($trendsData);
776 |
777 | return $this->formatTrends($trendsData, $inPercent, $dataLabel);
778 | } else {
779 | if (! is_null($this->labelColumn)) {
780 | $trendsData = $this->formatTrends($trendsData, $inPercent, $dataLabel);
781 |
782 | return $this->populateMissingData($this->getLabelsData(), $trendsData);
783 | }
784 |
785 | if (is_array($this->period)) {
786 | return $this->populateMissingDataForPeriod($trendsData, $inPercent, $dataLabel);
787 | }
788 |
789 | if (is_string($this->period)) {
790 | $trendsData = $this->formatDate($trendsData);
791 |
792 | return $this->populateMissingData($this->getPeriod(), $this->formatTrends($trendsData, $inPercent, $dataLabel));
793 | }
794 | }
795 |
796 | return [
797 | 'labels' => [],
798 | 'data' => [],
799 | ];
800 | }
801 |
802 | /**
803 | * Generate trends data for charts
804 | */
805 | public function trends(bool $inPercent = false): array
806 | {
807 | $trendsData = $this
808 | ->trendsData()
809 | ->toArray();
810 |
811 | $trendsData = array_map(fn ($datum) => (array) $datum, $trendsData);
812 |
813 | if (! empty($this->groupedDataLabels)) {
814 | return $this->trendsWithMergedData($inPercent);
815 | }
816 |
817 | return $this->getFormattedTrendsData($trendsData, $inPercent);
818 | }
819 |
820 | protected function formatTrends(array $data, bool $inPercent = false, string $dataLabel = 'data'): array
821 | {
822 | $total = 0;
823 |
824 | $result = [
825 | 'labels' => [],
826 | 'data' => [],
827 | ];
828 |
829 | foreach ($data as $datum) {
830 | $result['labels'][] = $datum['label'];
831 | $result['data'][] = (int) $datum[$dataLabel];
832 | $total += $datum[$dataLabel];
833 | }
834 |
835 | if (! $inPercent) {
836 | return $result;
837 | }
838 |
839 | $percentData = [];
840 |
841 | foreach ($result['data'] as $item) {
842 | $percentData[] = round(($item / $total) * 100, 2);
843 | }
844 |
845 | $result['data'] = $percentData;
846 |
847 | return $result;
848 | }
849 |
850 | protected function locale(): string
851 | {
852 | return Config::get('app.locale');
853 | }
854 | }
855 |
--------------------------------------------------------------------------------
/composer.lock:
--------------------------------------------------------------------------------
1 | {
2 | "_readme": [
3 | "This file locks the dependencies of your project to a known state",
4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
5 | "This file is @generated automatically"
6 | ],
7 | "content-hash": "15e76d464ffb1d9f73b846a7afbbb1bf",
8 | "packages": [
9 | {
10 | "name": "brick/math",
11 | "version": "0.11.0",
12 | "source": {
13 | "type": "git",
14 | "url": "https://github.com/brick/math.git",
15 | "reference": "0ad82ce168c82ba30d1c01ec86116ab52f589478"
16 | },
17 | "dist": {
18 | "type": "zip",
19 | "url": "https://api.github.com/repos/brick/math/zipball/0ad82ce168c82ba30d1c01ec86116ab52f589478",
20 | "reference": "0ad82ce168c82ba30d1c01ec86116ab52f589478",
21 | "shasum": ""
22 | },
23 | "require": {
24 | "php": "^8.0"
25 | },
26 | "require-dev": {
27 | "php-coveralls/php-coveralls": "^2.2",
28 | "phpunit/phpunit": "^9.0",
29 | "vimeo/psalm": "5.0.0"
30 | },
31 | "type": "library",
32 | "autoload": {
33 | "psr-4": {
34 | "Brick\\Math\\": "src/"
35 | }
36 | },
37 | "notification-url": "https://packagist.org/downloads/",
38 | "license": [
39 | "MIT"
40 | ],
41 | "description": "Arbitrary-precision arithmetic library",
42 | "keywords": [
43 | "Arbitrary-precision",
44 | "BigInteger",
45 | "BigRational",
46 | "arithmetic",
47 | "bigdecimal",
48 | "bignum",
49 | "brick",
50 | "math"
51 | ],
52 | "support": {
53 | "issues": "https://github.com/brick/math/issues",
54 | "source": "https://github.com/brick/math/tree/0.11.0"
55 | },
56 | "funding": [
57 | {
58 | "url": "https://github.com/BenMorel",
59 | "type": "github"
60 | }
61 | ],
62 | "time": "2023-01-15T23:15:59+00:00"
63 | },
64 | {
65 | "name": "doctrine/inflector",
66 | "version": "2.0.8",
67 | "source": {
68 | "type": "git",
69 | "url": "https://github.com/doctrine/inflector.git",
70 | "reference": "f9301a5b2fb1216b2b08f02ba04dc45423db6bff"
71 | },
72 | "dist": {
73 | "type": "zip",
74 | "url": "https://api.github.com/repos/doctrine/inflector/zipball/f9301a5b2fb1216b2b08f02ba04dc45423db6bff",
75 | "reference": "f9301a5b2fb1216b2b08f02ba04dc45423db6bff",
76 | "shasum": ""
77 | },
78 | "require": {
79 | "php": "^7.2 || ^8.0"
80 | },
81 | "require-dev": {
82 | "doctrine/coding-standard": "^11.0",
83 | "phpstan/phpstan": "^1.8",
84 | "phpstan/phpstan-phpunit": "^1.1",
85 | "phpstan/phpstan-strict-rules": "^1.3",
86 | "phpunit/phpunit": "^8.5 || ^9.5",
87 | "vimeo/psalm": "^4.25 || ^5.4"
88 | },
89 | "type": "library",
90 | "autoload": {
91 | "psr-4": {
92 | "Doctrine\\Inflector\\": "lib/Doctrine/Inflector"
93 | }
94 | },
95 | "notification-url": "https://packagist.org/downloads/",
96 | "license": [
97 | "MIT"
98 | ],
99 | "authors": [
100 | {
101 | "name": "Guilherme Blanco",
102 | "email": "guilhermeblanco@gmail.com"
103 | },
104 | {
105 | "name": "Roman Borschel",
106 | "email": "roman@code-factory.org"
107 | },
108 | {
109 | "name": "Benjamin Eberlei",
110 | "email": "kontakt@beberlei.de"
111 | },
112 | {
113 | "name": "Jonathan Wage",
114 | "email": "jonwage@gmail.com"
115 | },
116 | {
117 | "name": "Johannes Schmitt",
118 | "email": "schmittjoh@gmail.com"
119 | }
120 | ],
121 | "description": "PHP Doctrine Inflector is a small library that can perform string manipulations with regard to upper/lowercase and singular/plural forms of words.",
122 | "homepage": "https://www.doctrine-project.org/projects/inflector.html",
123 | "keywords": [
124 | "inflection",
125 | "inflector",
126 | "lowercase",
127 | "manipulation",
128 | "php",
129 | "plural",
130 | "singular",
131 | "strings",
132 | "uppercase",
133 | "words"
134 | ],
135 | "support": {
136 | "issues": "https://github.com/doctrine/inflector/issues",
137 | "source": "https://github.com/doctrine/inflector/tree/2.0.8"
138 | },
139 | "funding": [
140 | {
141 | "url": "https://www.doctrine-project.org/sponsorship.html",
142 | "type": "custom"
143 | },
144 | {
145 | "url": "https://www.patreon.com/phpdoctrine",
146 | "type": "patreon"
147 | },
148 | {
149 | "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finflector",
150 | "type": "tidelift"
151 | }
152 | ],
153 | "time": "2023-06-16T13:40:37+00:00"
154 | },
155 | {
156 | "name": "illuminate/collections",
157 | "version": "v10.20.0",
158 | "source": {
159 | "type": "git",
160 | "url": "https://github.com/illuminate/collections.git",
161 | "reference": "f494398dbaaead9e5ff16a18002d11634e8358e6"
162 | },
163 | "dist": {
164 | "type": "zip",
165 | "url": "https://api.github.com/repos/illuminate/collections/zipball/f494398dbaaead9e5ff16a18002d11634e8358e6",
166 | "reference": "f494398dbaaead9e5ff16a18002d11634e8358e6",
167 | "shasum": ""
168 | },
169 | "require": {
170 | "illuminate/conditionable": "^10.0",
171 | "illuminate/contracts": "^10.0",
172 | "illuminate/macroable": "^10.0",
173 | "php": "^8.1"
174 | },
175 | "suggest": {
176 | "symfony/var-dumper": "Required to use the dump method (^6.2)."
177 | },
178 | "type": "library",
179 | "extra": {
180 | "branch-alias": {
181 | "dev-master": "10.x-dev"
182 | }
183 | },
184 | "autoload": {
185 | "files": [
186 | "helpers.php"
187 | ],
188 | "psr-4": {
189 | "Illuminate\\Support\\": ""
190 | }
191 | },
192 | "notification-url": "https://packagist.org/downloads/",
193 | "license": [
194 | "MIT"
195 | ],
196 | "authors": [
197 | {
198 | "name": "Taylor Otwell",
199 | "email": "taylor@laravel.com"
200 | }
201 | ],
202 | "description": "The Illuminate Collections package.",
203 | "homepage": "https://laravel.com",
204 | "support": {
205 | "issues": "https://github.com/laravel/framework/issues",
206 | "source": "https://github.com/laravel/framework"
207 | },
208 | "time": "2023-08-11T14:48:51+00:00"
209 | },
210 | {
211 | "name": "illuminate/conditionable",
212 | "version": "v10.20.0",
213 | "source": {
214 | "type": "git",
215 | "url": "https://github.com/illuminate/conditionable.git",
216 | "reference": "d0958e4741fc9d6f516a552060fd1b829a85e009"
217 | },
218 | "dist": {
219 | "type": "zip",
220 | "url": "https://api.github.com/repos/illuminate/conditionable/zipball/d0958e4741fc9d6f516a552060fd1b829a85e009",
221 | "reference": "d0958e4741fc9d6f516a552060fd1b829a85e009",
222 | "shasum": ""
223 | },
224 | "require": {
225 | "php": "^8.0.2"
226 | },
227 | "type": "library",
228 | "extra": {
229 | "branch-alias": {
230 | "dev-master": "10.x-dev"
231 | }
232 | },
233 | "autoload": {
234 | "psr-4": {
235 | "Illuminate\\Support\\": ""
236 | }
237 | },
238 | "notification-url": "https://packagist.org/downloads/",
239 | "license": [
240 | "MIT"
241 | ],
242 | "authors": [
243 | {
244 | "name": "Taylor Otwell",
245 | "email": "taylor@laravel.com"
246 | }
247 | ],
248 | "description": "The Illuminate Conditionable package.",
249 | "homepage": "https://laravel.com",
250 | "support": {
251 | "issues": "https://github.com/laravel/framework/issues",
252 | "source": "https://github.com/laravel/framework"
253 | },
254 | "time": "2023-02-03T08:06:17+00:00"
255 | },
256 | {
257 | "name": "illuminate/container",
258 | "version": "v10.20.0",
259 | "source": {
260 | "type": "git",
261 | "url": "https://github.com/illuminate/container.git",
262 | "reference": "ddc26273085fad3c471b2602ad820e0097ff7939"
263 | },
264 | "dist": {
265 | "type": "zip",
266 | "url": "https://api.github.com/repos/illuminate/container/zipball/ddc26273085fad3c471b2602ad820e0097ff7939",
267 | "reference": "ddc26273085fad3c471b2602ad820e0097ff7939",
268 | "shasum": ""
269 | },
270 | "require": {
271 | "illuminate/contracts": "^10.0",
272 | "php": "^8.1",
273 | "psr/container": "^1.1.1|^2.0.1"
274 | },
275 | "provide": {
276 | "psr/container-implementation": "1.1|2.0"
277 | },
278 | "type": "library",
279 | "extra": {
280 | "branch-alias": {
281 | "dev-master": "10.x-dev"
282 | }
283 | },
284 | "autoload": {
285 | "psr-4": {
286 | "Illuminate\\Container\\": ""
287 | }
288 | },
289 | "notification-url": "https://packagist.org/downloads/",
290 | "license": [
291 | "MIT"
292 | ],
293 | "authors": [
294 | {
295 | "name": "Taylor Otwell",
296 | "email": "taylor@laravel.com"
297 | }
298 | ],
299 | "description": "The Illuminate Container package.",
300 | "homepage": "https://laravel.com",
301 | "support": {
302 | "issues": "https://github.com/laravel/framework/issues",
303 | "source": "https://github.com/laravel/framework"
304 | },
305 | "time": "2023-06-18T09:12:03+00:00"
306 | },
307 | {
308 | "name": "illuminate/contracts",
309 | "version": "v10.20.0",
310 | "source": {
311 | "type": "git",
312 | "url": "https://github.com/illuminate/contracts.git",
313 | "reference": "eb1a7e72e159136a832f2c0467de5570bdc208ae"
314 | },
315 | "dist": {
316 | "type": "zip",
317 | "url": "https://api.github.com/repos/illuminate/contracts/zipball/eb1a7e72e159136a832f2c0467de5570bdc208ae",
318 | "reference": "eb1a7e72e159136a832f2c0467de5570bdc208ae",
319 | "shasum": ""
320 | },
321 | "require": {
322 | "php": "^8.1",
323 | "psr/container": "^1.1.1|^2.0.1",
324 | "psr/simple-cache": "^1.0|^2.0|^3.0"
325 | },
326 | "type": "library",
327 | "extra": {
328 | "branch-alias": {
329 | "dev-master": "10.x-dev"
330 | }
331 | },
332 | "autoload": {
333 | "psr-4": {
334 | "Illuminate\\Contracts\\": ""
335 | }
336 | },
337 | "notification-url": "https://packagist.org/downloads/",
338 | "license": [
339 | "MIT"
340 | ],
341 | "authors": [
342 | {
343 | "name": "Taylor Otwell",
344 | "email": "taylor@laravel.com"
345 | }
346 | ],
347 | "description": "The Illuminate Contracts package.",
348 | "homepage": "https://laravel.com",
349 | "support": {
350 | "issues": "https://github.com/laravel/framework/issues",
351 | "source": "https://github.com/laravel/framework"
352 | },
353 | "time": "2023-07-26T21:27:34+00:00"
354 | },
355 | {
356 | "name": "illuminate/database",
357 | "version": "v10.20.0",
358 | "source": {
359 | "type": "git",
360 | "url": "https://github.com/illuminate/database.git",
361 | "reference": "10b3518ee8a8282f0cc16850b26d8b70f57349ad"
362 | },
363 | "dist": {
364 | "type": "zip",
365 | "url": "https://api.github.com/repos/illuminate/database/zipball/10b3518ee8a8282f0cc16850b26d8b70f57349ad",
366 | "reference": "10b3518ee8a8282f0cc16850b26d8b70f57349ad",
367 | "shasum": ""
368 | },
369 | "require": {
370 | "brick/math": "^0.9.3|^0.10.2|^0.11",
371 | "ext-pdo": "*",
372 | "illuminate/collections": "^10.0",
373 | "illuminate/container": "^10.0",
374 | "illuminate/contracts": "^10.0",
375 | "illuminate/macroable": "^10.0",
376 | "illuminate/support": "^10.0",
377 | "php": "^8.1"
378 | },
379 | "suggest": {
380 | "doctrine/dbal": "Required to rename columns and drop SQLite columns (^3.5.1).",
381 | "ext-filter": "Required to use the Postgres database driver.",
382 | "fakerphp/faker": "Required to use the eloquent factory builder (^1.21).",
383 | "illuminate/console": "Required to use the database commands (^10.0).",
384 | "illuminate/events": "Required to use the observers with Eloquent (^10.0).",
385 | "illuminate/filesystem": "Required to use the migrations (^10.0).",
386 | "illuminate/pagination": "Required to paginate the result set (^10.0).",
387 | "symfony/finder": "Required to use Eloquent model factories (^6.2)."
388 | },
389 | "type": "library",
390 | "extra": {
391 | "branch-alias": {
392 | "dev-master": "10.x-dev"
393 | }
394 | },
395 | "autoload": {
396 | "psr-4": {
397 | "Illuminate\\Database\\": ""
398 | }
399 | },
400 | "notification-url": "https://packagist.org/downloads/",
401 | "license": [
402 | "MIT"
403 | ],
404 | "authors": [
405 | {
406 | "name": "Taylor Otwell",
407 | "email": "taylor@laravel.com"
408 | }
409 | ],
410 | "description": "The Illuminate Database package.",
411 | "homepage": "https://laravel.com",
412 | "keywords": [
413 | "database",
414 | "laravel",
415 | "orm",
416 | "sql"
417 | ],
418 | "support": {
419 | "issues": "https://github.com/laravel/framework/issues",
420 | "source": "https://github.com/laravel/framework"
421 | },
422 | "time": "2023-08-21T21:08:22+00:00"
423 | },
424 | {
425 | "name": "illuminate/macroable",
426 | "version": "v10.20.0",
427 | "source": {
428 | "type": "git",
429 | "url": "https://github.com/illuminate/macroable.git",
430 | "reference": "dff667a46ac37b634dcf68909d9d41e94dc97c27"
431 | },
432 | "dist": {
433 | "type": "zip",
434 | "url": "https://api.github.com/repos/illuminate/macroable/zipball/dff667a46ac37b634dcf68909d9d41e94dc97c27",
435 | "reference": "dff667a46ac37b634dcf68909d9d41e94dc97c27",
436 | "shasum": ""
437 | },
438 | "require": {
439 | "php": "^8.1"
440 | },
441 | "type": "library",
442 | "extra": {
443 | "branch-alias": {
444 | "dev-master": "10.x-dev"
445 | }
446 | },
447 | "autoload": {
448 | "psr-4": {
449 | "Illuminate\\Support\\": ""
450 | }
451 | },
452 | "notification-url": "https://packagist.org/downloads/",
453 | "license": [
454 | "MIT"
455 | ],
456 | "authors": [
457 | {
458 | "name": "Taylor Otwell",
459 | "email": "taylor@laravel.com"
460 | }
461 | ],
462 | "description": "The Illuminate Macroable package.",
463 | "homepage": "https://laravel.com",
464 | "support": {
465 | "issues": "https://github.com/laravel/framework/issues",
466 | "source": "https://github.com/laravel/framework"
467 | },
468 | "time": "2023-06-05T12:46:42+00:00"
469 | },
470 | {
471 | "name": "illuminate/support",
472 | "version": "v10.20.0",
473 | "source": {
474 | "type": "git",
475 | "url": "https://github.com/illuminate/support.git",
476 | "reference": "38d3e064b7b9420d2173f23a31a435bde221b56d"
477 | },
478 | "dist": {
479 | "type": "zip",
480 | "url": "https://api.github.com/repos/illuminate/support/zipball/38d3e064b7b9420d2173f23a31a435bde221b56d",
481 | "reference": "38d3e064b7b9420d2173f23a31a435bde221b56d",
482 | "shasum": ""
483 | },
484 | "require": {
485 | "doctrine/inflector": "^2.0",
486 | "ext-ctype": "*",
487 | "ext-filter": "*",
488 | "ext-mbstring": "*",
489 | "illuminate/collections": "^10.0",
490 | "illuminate/conditionable": "^10.0",
491 | "illuminate/contracts": "^10.0",
492 | "illuminate/macroable": "^10.0",
493 | "nesbot/carbon": "^2.67",
494 | "php": "^8.1",
495 | "voku/portable-ascii": "^2.0"
496 | },
497 | "conflict": {
498 | "tightenco/collect": "<5.5.33"
499 | },
500 | "suggest": {
501 | "illuminate/filesystem": "Required to use the composer class (^10.0).",
502 | "league/commonmark": "Required to use Str::markdown() and Stringable::markdown() (^2.0.2).",
503 | "ramsey/uuid": "Required to use Str::uuid() (^4.7).",
504 | "symfony/process": "Required to use the composer class (^6.2).",
505 | "symfony/uid": "Required to use Str::ulid() (^6.2).",
506 | "symfony/var-dumper": "Required to use the dd function (^6.2).",
507 | "vlucas/phpdotenv": "Required to use the Env class and env helper (^5.4.1)."
508 | },
509 | "type": "library",
510 | "extra": {
511 | "branch-alias": {
512 | "dev-master": "10.x-dev"
513 | }
514 | },
515 | "autoload": {
516 | "files": [
517 | "helpers.php"
518 | ],
519 | "psr-4": {
520 | "Illuminate\\Support\\": ""
521 | }
522 | },
523 | "notification-url": "https://packagist.org/downloads/",
524 | "license": [
525 | "MIT"
526 | ],
527 | "authors": [
528 | {
529 | "name": "Taylor Otwell",
530 | "email": "taylor@laravel.com"
531 | }
532 | ],
533 | "description": "The Illuminate Support package.",
534 | "homepage": "https://laravel.com",
535 | "support": {
536 | "issues": "https://github.com/laravel/framework/issues",
537 | "source": "https://github.com/laravel/framework"
538 | },
539 | "time": "2023-08-21T13:45:59+00:00"
540 | },
541 | {
542 | "name": "nesbot/carbon",
543 | "version": "2.69.0",
544 | "source": {
545 | "type": "git",
546 | "url": "https://github.com/briannesbitt/Carbon.git",
547 | "reference": "4308217830e4ca445583a37d1bf4aff4153fa81c"
548 | },
549 | "dist": {
550 | "type": "zip",
551 | "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/4308217830e4ca445583a37d1bf4aff4153fa81c",
552 | "reference": "4308217830e4ca445583a37d1bf4aff4153fa81c",
553 | "shasum": ""
554 | },
555 | "require": {
556 | "ext-json": "*",
557 | "php": "^7.1.8 || ^8.0",
558 | "psr/clock": "^1.0",
559 | "symfony/polyfill-mbstring": "^1.0",
560 | "symfony/polyfill-php80": "^1.16",
561 | "symfony/translation": "^3.4 || ^4.0 || ^5.0 || ^6.0"
562 | },
563 | "provide": {
564 | "psr/clock-implementation": "1.0"
565 | },
566 | "require-dev": {
567 | "doctrine/dbal": "^2.0 || ^3.1.4",
568 | "doctrine/orm": "^2.7",
569 | "friendsofphp/php-cs-fixer": "^3.0",
570 | "kylekatarnls/multi-tester": "^2.0",
571 | "ondrejmirtes/better-reflection": "*",
572 | "phpmd/phpmd": "^2.9",
573 | "phpstan/extension-installer": "^1.0",
574 | "phpstan/phpstan": "^0.12.99 || ^1.7.14",
575 | "phpunit/php-file-iterator": "^2.0.5 || ^3.0.6",
576 | "phpunit/phpunit": "^7.5.20 || ^8.5.26 || ^9.5.20",
577 | "squizlabs/php_codesniffer": "^3.4"
578 | },
579 | "bin": [
580 | "bin/carbon"
581 | ],
582 | "type": "library",
583 | "extra": {
584 | "branch-alias": {
585 | "dev-3.x": "3.x-dev",
586 | "dev-master": "2.x-dev"
587 | },
588 | "laravel": {
589 | "providers": [
590 | "Carbon\\Laravel\\ServiceProvider"
591 | ]
592 | },
593 | "phpstan": {
594 | "includes": [
595 | "extension.neon"
596 | ]
597 | }
598 | },
599 | "autoload": {
600 | "psr-4": {
601 | "Carbon\\": "src/Carbon/"
602 | }
603 | },
604 | "notification-url": "https://packagist.org/downloads/",
605 | "license": [
606 | "MIT"
607 | ],
608 | "authors": [
609 | {
610 | "name": "Brian Nesbitt",
611 | "email": "brian@nesbot.com",
612 | "homepage": "https://markido.com"
613 | },
614 | {
615 | "name": "kylekatarnls",
616 | "homepage": "https://github.com/kylekatarnls"
617 | }
618 | ],
619 | "description": "An API extension for DateTime that supports 281 different languages.",
620 | "homepage": "https://carbon.nesbot.com",
621 | "keywords": [
622 | "date",
623 | "datetime",
624 | "time"
625 | ],
626 | "support": {
627 | "docs": "https://carbon.nesbot.com/docs",
628 | "issues": "https://github.com/briannesbitt/Carbon/issues",
629 | "source": "https://github.com/briannesbitt/Carbon"
630 | },
631 | "funding": [
632 | {
633 | "url": "https://github.com/sponsors/kylekatarnls",
634 | "type": "github"
635 | },
636 | {
637 | "url": "https://opencollective.com/Carbon#sponsor",
638 | "type": "opencollective"
639 | },
640 | {
641 | "url": "https://tidelift.com/subscription/pkg/packagist-nesbot-carbon?utm_source=packagist-nesbot-carbon&utm_medium=referral&utm_campaign=readme",
642 | "type": "tidelift"
643 | }
644 | ],
645 | "time": "2023-08-03T09:00:52+00:00"
646 | },
647 | {
648 | "name": "psr/clock",
649 | "version": "1.0.0",
650 | "source": {
651 | "type": "git",
652 | "url": "https://github.com/php-fig/clock.git",
653 | "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d"
654 | },
655 | "dist": {
656 | "type": "zip",
657 | "url": "https://api.github.com/repos/php-fig/clock/zipball/e41a24703d4560fd0acb709162f73b8adfc3aa0d",
658 | "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d",
659 | "shasum": ""
660 | },
661 | "require": {
662 | "php": "^7.0 || ^8.0"
663 | },
664 | "type": "library",
665 | "autoload": {
666 | "psr-4": {
667 | "Psr\\Clock\\": "src/"
668 | }
669 | },
670 | "notification-url": "https://packagist.org/downloads/",
671 | "license": [
672 | "MIT"
673 | ],
674 | "authors": [
675 | {
676 | "name": "PHP-FIG",
677 | "homepage": "https://www.php-fig.org/"
678 | }
679 | ],
680 | "description": "Common interface for reading the clock.",
681 | "homepage": "https://github.com/php-fig/clock",
682 | "keywords": [
683 | "clock",
684 | "now",
685 | "psr",
686 | "psr-20",
687 | "time"
688 | ],
689 | "support": {
690 | "issues": "https://github.com/php-fig/clock/issues",
691 | "source": "https://github.com/php-fig/clock/tree/1.0.0"
692 | },
693 | "time": "2022-11-25T14:36:26+00:00"
694 | },
695 | {
696 | "name": "psr/container",
697 | "version": "2.0.2",
698 | "source": {
699 | "type": "git",
700 | "url": "https://github.com/php-fig/container.git",
701 | "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963"
702 | },
703 | "dist": {
704 | "type": "zip",
705 | "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963",
706 | "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963",
707 | "shasum": ""
708 | },
709 | "require": {
710 | "php": ">=7.4.0"
711 | },
712 | "type": "library",
713 | "extra": {
714 | "branch-alias": {
715 | "dev-master": "2.0.x-dev"
716 | }
717 | },
718 | "autoload": {
719 | "psr-4": {
720 | "Psr\\Container\\": "src/"
721 | }
722 | },
723 | "notification-url": "https://packagist.org/downloads/",
724 | "license": [
725 | "MIT"
726 | ],
727 | "authors": [
728 | {
729 | "name": "PHP-FIG",
730 | "homepage": "https://www.php-fig.org/"
731 | }
732 | ],
733 | "description": "Common Container Interface (PHP FIG PSR-11)",
734 | "homepage": "https://github.com/php-fig/container",
735 | "keywords": [
736 | "PSR-11",
737 | "container",
738 | "container-interface",
739 | "container-interop",
740 | "psr"
741 | ],
742 | "support": {
743 | "issues": "https://github.com/php-fig/container/issues",
744 | "source": "https://github.com/php-fig/container/tree/2.0.2"
745 | },
746 | "time": "2021-11-05T16:47:00+00:00"
747 | },
748 | {
749 | "name": "psr/simple-cache",
750 | "version": "3.0.0",
751 | "source": {
752 | "type": "git",
753 | "url": "https://github.com/php-fig/simple-cache.git",
754 | "reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865"
755 | },
756 | "dist": {
757 | "type": "zip",
758 | "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/764e0b3939f5ca87cb904f570ef9be2d78a07865",
759 | "reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865",
760 | "shasum": ""
761 | },
762 | "require": {
763 | "php": ">=8.0.0"
764 | },
765 | "type": "library",
766 | "extra": {
767 | "branch-alias": {
768 | "dev-master": "3.0.x-dev"
769 | }
770 | },
771 | "autoload": {
772 | "psr-4": {
773 | "Psr\\SimpleCache\\": "src/"
774 | }
775 | },
776 | "notification-url": "https://packagist.org/downloads/",
777 | "license": [
778 | "MIT"
779 | ],
780 | "authors": [
781 | {
782 | "name": "PHP-FIG",
783 | "homepage": "https://www.php-fig.org/"
784 | }
785 | ],
786 | "description": "Common interfaces for simple caching",
787 | "keywords": [
788 | "cache",
789 | "caching",
790 | "psr",
791 | "psr-16",
792 | "simple-cache"
793 | ],
794 | "support": {
795 | "source": "https://github.com/php-fig/simple-cache/tree/3.0.0"
796 | },
797 | "time": "2021-10-29T13:26:27+00:00"
798 | },
799 | {
800 | "name": "symfony/deprecation-contracts",
801 | "version": "v3.3.0",
802 | "source": {
803 | "type": "git",
804 | "url": "https://github.com/symfony/deprecation-contracts.git",
805 | "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf"
806 | },
807 | "dist": {
808 | "type": "zip",
809 | "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/7c3aff79d10325257a001fcf92d991f24fc967cf",
810 | "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf",
811 | "shasum": ""
812 | },
813 | "require": {
814 | "php": ">=8.1"
815 | },
816 | "type": "library",
817 | "extra": {
818 | "branch-alias": {
819 | "dev-main": "3.4-dev"
820 | },
821 | "thanks": {
822 | "name": "symfony/contracts",
823 | "url": "https://github.com/symfony/contracts"
824 | }
825 | },
826 | "autoload": {
827 | "files": [
828 | "function.php"
829 | ]
830 | },
831 | "notification-url": "https://packagist.org/downloads/",
832 | "license": [
833 | "MIT"
834 | ],
835 | "authors": [
836 | {
837 | "name": "Nicolas Grekas",
838 | "email": "p@tchwork.com"
839 | },
840 | {
841 | "name": "Symfony Community",
842 | "homepage": "https://symfony.com/contributors"
843 | }
844 | ],
845 | "description": "A generic function and convention to trigger deprecation notices",
846 | "homepage": "https://symfony.com",
847 | "support": {
848 | "source": "https://github.com/symfony/deprecation-contracts/tree/v3.3.0"
849 | },
850 | "funding": [
851 | {
852 | "url": "https://symfony.com/sponsor",
853 | "type": "custom"
854 | },
855 | {
856 | "url": "https://github.com/fabpot",
857 | "type": "github"
858 | },
859 | {
860 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
861 | "type": "tidelift"
862 | }
863 | ],
864 | "time": "2023-05-23T14:45:45+00:00"
865 | },
866 | {
867 | "name": "symfony/polyfill-mbstring",
868 | "version": "v1.27.0",
869 | "source": {
870 | "type": "git",
871 | "url": "https://github.com/symfony/polyfill-mbstring.git",
872 | "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534"
873 | },
874 | "dist": {
875 | "type": "zip",
876 | "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
877 | "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
878 | "shasum": ""
879 | },
880 | "require": {
881 | "php": ">=7.1"
882 | },
883 | "provide": {
884 | "ext-mbstring": "*"
885 | },
886 | "suggest": {
887 | "ext-mbstring": "For best performance"
888 | },
889 | "type": "library",
890 | "extra": {
891 | "branch-alias": {
892 | "dev-main": "1.27-dev"
893 | },
894 | "thanks": {
895 | "name": "symfony/polyfill",
896 | "url": "https://github.com/symfony/polyfill"
897 | }
898 | },
899 | "autoload": {
900 | "files": [
901 | "bootstrap.php"
902 | ],
903 | "psr-4": {
904 | "Symfony\\Polyfill\\Mbstring\\": ""
905 | }
906 | },
907 | "notification-url": "https://packagist.org/downloads/",
908 | "license": [
909 | "MIT"
910 | ],
911 | "authors": [
912 | {
913 | "name": "Nicolas Grekas",
914 | "email": "p@tchwork.com"
915 | },
916 | {
917 | "name": "Symfony Community",
918 | "homepage": "https://symfony.com/contributors"
919 | }
920 | ],
921 | "description": "Symfony polyfill for the Mbstring extension",
922 | "homepage": "https://symfony.com",
923 | "keywords": [
924 | "compatibility",
925 | "mbstring",
926 | "polyfill",
927 | "portable",
928 | "shim"
929 | ],
930 | "support": {
931 | "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.27.0"
932 | },
933 | "funding": [
934 | {
935 | "url": "https://symfony.com/sponsor",
936 | "type": "custom"
937 | },
938 | {
939 | "url": "https://github.com/fabpot",
940 | "type": "github"
941 | },
942 | {
943 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
944 | "type": "tidelift"
945 | }
946 | ],
947 | "time": "2022-11-03T14:55:06+00:00"
948 | },
949 | {
950 | "name": "symfony/polyfill-php80",
951 | "version": "v1.27.0",
952 | "source": {
953 | "type": "git",
954 | "url": "https://github.com/symfony/polyfill-php80.git",
955 | "reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936"
956 | },
957 | "dist": {
958 | "type": "zip",
959 | "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936",
960 | "reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936",
961 | "shasum": ""
962 | },
963 | "require": {
964 | "php": ">=7.1"
965 | },
966 | "type": "library",
967 | "extra": {
968 | "branch-alias": {
969 | "dev-main": "1.27-dev"
970 | },
971 | "thanks": {
972 | "name": "symfony/polyfill",
973 | "url": "https://github.com/symfony/polyfill"
974 | }
975 | },
976 | "autoload": {
977 | "files": [
978 | "bootstrap.php"
979 | ],
980 | "psr-4": {
981 | "Symfony\\Polyfill\\Php80\\": ""
982 | },
983 | "classmap": [
984 | "Resources/stubs"
985 | ]
986 | },
987 | "notification-url": "https://packagist.org/downloads/",
988 | "license": [
989 | "MIT"
990 | ],
991 | "authors": [
992 | {
993 | "name": "Ion Bazan",
994 | "email": "ion.bazan@gmail.com"
995 | },
996 | {
997 | "name": "Nicolas Grekas",
998 | "email": "p@tchwork.com"
999 | },
1000 | {
1001 | "name": "Symfony Community",
1002 | "homepage": "https://symfony.com/contributors"
1003 | }
1004 | ],
1005 | "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions",
1006 | "homepage": "https://symfony.com",
1007 | "keywords": [
1008 | "compatibility",
1009 | "polyfill",
1010 | "portable",
1011 | "shim"
1012 | ],
1013 | "support": {
1014 | "source": "https://github.com/symfony/polyfill-php80/tree/v1.27.0"
1015 | },
1016 | "funding": [
1017 | {
1018 | "url": "https://symfony.com/sponsor",
1019 | "type": "custom"
1020 | },
1021 | {
1022 | "url": "https://github.com/fabpot",
1023 | "type": "github"
1024 | },
1025 | {
1026 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
1027 | "type": "tidelift"
1028 | }
1029 | ],
1030 | "time": "2022-11-03T14:55:06+00:00"
1031 | },
1032 | {
1033 | "name": "symfony/translation",
1034 | "version": "v6.3.3",
1035 | "source": {
1036 | "type": "git",
1037 | "url": "https://github.com/symfony/translation.git",
1038 | "reference": "3ed078c54bc98bbe4414e1e9b2d5e85ed5a5c8bd"
1039 | },
1040 | "dist": {
1041 | "type": "zip",
1042 | "url": "https://api.github.com/repos/symfony/translation/zipball/3ed078c54bc98bbe4414e1e9b2d5e85ed5a5c8bd",
1043 | "reference": "3ed078c54bc98bbe4414e1e9b2d5e85ed5a5c8bd",
1044 | "shasum": ""
1045 | },
1046 | "require": {
1047 | "php": ">=8.1",
1048 | "symfony/deprecation-contracts": "^2.5|^3",
1049 | "symfony/polyfill-mbstring": "~1.0",
1050 | "symfony/translation-contracts": "^2.5|^3.0"
1051 | },
1052 | "conflict": {
1053 | "symfony/config": "<5.4",
1054 | "symfony/console": "<5.4",
1055 | "symfony/dependency-injection": "<5.4",
1056 | "symfony/http-client-contracts": "<2.5",
1057 | "symfony/http-kernel": "<5.4",
1058 | "symfony/service-contracts": "<2.5",
1059 | "symfony/twig-bundle": "<5.4",
1060 | "symfony/yaml": "<5.4"
1061 | },
1062 | "provide": {
1063 | "symfony/translation-implementation": "2.3|3.0"
1064 | },
1065 | "require-dev": {
1066 | "nikic/php-parser": "^4.13",
1067 | "psr/log": "^1|^2|^3",
1068 | "symfony/config": "^5.4|^6.0",
1069 | "symfony/console": "^5.4|^6.0",
1070 | "symfony/dependency-injection": "^5.4|^6.0",
1071 | "symfony/finder": "^5.4|^6.0",
1072 | "symfony/http-client-contracts": "^2.5|^3.0",
1073 | "symfony/http-kernel": "^5.4|^6.0",
1074 | "symfony/intl": "^5.4|^6.0",
1075 | "symfony/polyfill-intl-icu": "^1.21",
1076 | "symfony/routing": "^5.4|^6.0",
1077 | "symfony/service-contracts": "^2.5|^3",
1078 | "symfony/yaml": "^5.4|^6.0"
1079 | },
1080 | "type": "library",
1081 | "autoload": {
1082 | "files": [
1083 | "Resources/functions.php"
1084 | ],
1085 | "psr-4": {
1086 | "Symfony\\Component\\Translation\\": ""
1087 | },
1088 | "exclude-from-classmap": [
1089 | "/Tests/"
1090 | ]
1091 | },
1092 | "notification-url": "https://packagist.org/downloads/",
1093 | "license": [
1094 | "MIT"
1095 | ],
1096 | "authors": [
1097 | {
1098 | "name": "Fabien Potencier",
1099 | "email": "fabien@symfony.com"
1100 | },
1101 | {
1102 | "name": "Symfony Community",
1103 | "homepage": "https://symfony.com/contributors"
1104 | }
1105 | ],
1106 | "description": "Provides tools to internationalize your application",
1107 | "homepage": "https://symfony.com",
1108 | "support": {
1109 | "source": "https://github.com/symfony/translation/tree/v6.3.3"
1110 | },
1111 | "funding": [
1112 | {
1113 | "url": "https://symfony.com/sponsor",
1114 | "type": "custom"
1115 | },
1116 | {
1117 | "url": "https://github.com/fabpot",
1118 | "type": "github"
1119 | },
1120 | {
1121 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
1122 | "type": "tidelift"
1123 | }
1124 | ],
1125 | "time": "2023-07-31T07:08:24+00:00"
1126 | },
1127 | {
1128 | "name": "symfony/translation-contracts",
1129 | "version": "v3.3.0",
1130 | "source": {
1131 | "type": "git",
1132 | "url": "https://github.com/symfony/translation-contracts.git",
1133 | "reference": "02c24deb352fb0d79db5486c0c79905a85e37e86"
1134 | },
1135 | "dist": {
1136 | "type": "zip",
1137 | "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/02c24deb352fb0d79db5486c0c79905a85e37e86",
1138 | "reference": "02c24deb352fb0d79db5486c0c79905a85e37e86",
1139 | "shasum": ""
1140 | },
1141 | "require": {
1142 | "php": ">=8.1"
1143 | },
1144 | "type": "library",
1145 | "extra": {
1146 | "branch-alias": {
1147 | "dev-main": "3.4-dev"
1148 | },
1149 | "thanks": {
1150 | "name": "symfony/contracts",
1151 | "url": "https://github.com/symfony/contracts"
1152 | }
1153 | },
1154 | "autoload": {
1155 | "psr-4": {
1156 | "Symfony\\Contracts\\Translation\\": ""
1157 | },
1158 | "exclude-from-classmap": [
1159 | "/Test/"
1160 | ]
1161 | },
1162 | "notification-url": "https://packagist.org/downloads/",
1163 | "license": [
1164 | "MIT"
1165 | ],
1166 | "authors": [
1167 | {
1168 | "name": "Nicolas Grekas",
1169 | "email": "p@tchwork.com"
1170 | },
1171 | {
1172 | "name": "Symfony Community",
1173 | "homepage": "https://symfony.com/contributors"
1174 | }
1175 | ],
1176 | "description": "Generic abstractions related to translation",
1177 | "homepage": "https://symfony.com",
1178 | "keywords": [
1179 | "abstractions",
1180 | "contracts",
1181 | "decoupling",
1182 | "interfaces",
1183 | "interoperability",
1184 | "standards"
1185 | ],
1186 | "support": {
1187 | "source": "https://github.com/symfony/translation-contracts/tree/v3.3.0"
1188 | },
1189 | "funding": [
1190 | {
1191 | "url": "https://symfony.com/sponsor",
1192 | "type": "custom"
1193 | },
1194 | {
1195 | "url": "https://github.com/fabpot",
1196 | "type": "github"
1197 | },
1198 | {
1199 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
1200 | "type": "tidelift"
1201 | }
1202 | ],
1203 | "time": "2023-05-30T17:17:10+00:00"
1204 | },
1205 | {
1206 | "name": "voku/portable-ascii",
1207 | "version": "2.0.1",
1208 | "source": {
1209 | "type": "git",
1210 | "url": "https://github.com/voku/portable-ascii.git",
1211 | "reference": "b56450eed252f6801410d810c8e1727224ae0743"
1212 | },
1213 | "dist": {
1214 | "type": "zip",
1215 | "url": "https://api.github.com/repos/voku/portable-ascii/zipball/b56450eed252f6801410d810c8e1727224ae0743",
1216 | "reference": "b56450eed252f6801410d810c8e1727224ae0743",
1217 | "shasum": ""
1218 | },
1219 | "require": {
1220 | "php": ">=7.0.0"
1221 | },
1222 | "require-dev": {
1223 | "phpunit/phpunit": "~6.0 || ~7.0 || ~9.0"
1224 | },
1225 | "suggest": {
1226 | "ext-intl": "Use Intl for transliterator_transliterate() support"
1227 | },
1228 | "type": "library",
1229 | "autoload": {
1230 | "psr-4": {
1231 | "voku\\": "src/voku/"
1232 | }
1233 | },
1234 | "notification-url": "https://packagist.org/downloads/",
1235 | "license": [
1236 | "MIT"
1237 | ],
1238 | "authors": [
1239 | {
1240 | "name": "Lars Moelleken",
1241 | "homepage": "http://www.moelleken.org/"
1242 | }
1243 | ],
1244 | "description": "Portable ASCII library - performance optimized (ascii) string functions for php.",
1245 | "homepage": "https://github.com/voku/portable-ascii",
1246 | "keywords": [
1247 | "ascii",
1248 | "clean",
1249 | "php"
1250 | ],
1251 | "support": {
1252 | "issues": "https://github.com/voku/portable-ascii/issues",
1253 | "source": "https://github.com/voku/portable-ascii/tree/2.0.1"
1254 | },
1255 | "funding": [
1256 | {
1257 | "url": "https://www.paypal.me/moelleken",
1258 | "type": "custom"
1259 | },
1260 | {
1261 | "url": "https://github.com/voku",
1262 | "type": "github"
1263 | },
1264 | {
1265 | "url": "https://opencollective.com/portable-ascii",
1266 | "type": "open_collective"
1267 | },
1268 | {
1269 | "url": "https://www.patreon.com/voku",
1270 | "type": "patreon"
1271 | },
1272 | {
1273 | "url": "https://tidelift.com/funding/github/packagist/voku/portable-ascii",
1274 | "type": "tidelift"
1275 | }
1276 | ],
1277 | "time": "2022-03-08T17:03:00+00:00"
1278 | }
1279 | ],
1280 | "packages-dev": [
1281 | {
1282 | "name": "doctrine/instantiator",
1283 | "version": "2.0.0",
1284 | "source": {
1285 | "type": "git",
1286 | "url": "https://github.com/doctrine/instantiator.git",
1287 | "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0"
1288 | },
1289 | "dist": {
1290 | "type": "zip",
1291 | "url": "https://api.github.com/repos/doctrine/instantiator/zipball/c6222283fa3f4ac679f8b9ced9a4e23f163e80d0",
1292 | "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0",
1293 | "shasum": ""
1294 | },
1295 | "require": {
1296 | "php": "^8.1"
1297 | },
1298 | "require-dev": {
1299 | "doctrine/coding-standard": "^11",
1300 | "ext-pdo": "*",
1301 | "ext-phar": "*",
1302 | "phpbench/phpbench": "^1.2",
1303 | "phpstan/phpstan": "^1.9.4",
1304 | "phpstan/phpstan-phpunit": "^1.3",
1305 | "phpunit/phpunit": "^9.5.27",
1306 | "vimeo/psalm": "^5.4"
1307 | },
1308 | "type": "library",
1309 | "autoload": {
1310 | "psr-4": {
1311 | "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/"
1312 | }
1313 | },
1314 | "notification-url": "https://packagist.org/downloads/",
1315 | "license": [
1316 | "MIT"
1317 | ],
1318 | "authors": [
1319 | {
1320 | "name": "Marco Pivetta",
1321 | "email": "ocramius@gmail.com",
1322 | "homepage": "https://ocramius.github.io/"
1323 | }
1324 | ],
1325 | "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors",
1326 | "homepage": "https://www.doctrine-project.org/projects/instantiator.html",
1327 | "keywords": [
1328 | "constructor",
1329 | "instantiate"
1330 | ],
1331 | "support": {
1332 | "issues": "https://github.com/doctrine/instantiator/issues",
1333 | "source": "https://github.com/doctrine/instantiator/tree/2.0.0"
1334 | },
1335 | "funding": [
1336 | {
1337 | "url": "https://www.doctrine-project.org/sponsorship.html",
1338 | "type": "custom"
1339 | },
1340 | {
1341 | "url": "https://www.patreon.com/phpdoctrine",
1342 | "type": "patreon"
1343 | },
1344 | {
1345 | "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator",
1346 | "type": "tidelift"
1347 | }
1348 | ],
1349 | "time": "2022-12-30T00:23:10+00:00"
1350 | },
1351 | {
1352 | "name": "laravel/pint",
1353 | "version": "v1.13.5",
1354 | "source": {
1355 | "type": "git",
1356 | "url": "https://github.com/laravel/pint.git",
1357 | "reference": "df105cf8ce7a8f0b8a9425ff45cd281a5448e423"
1358 | },
1359 | "dist": {
1360 | "type": "zip",
1361 | "url": "https://api.github.com/repos/laravel/pint/zipball/df105cf8ce7a8f0b8a9425ff45cd281a5448e423",
1362 | "reference": "df105cf8ce7a8f0b8a9425ff45cd281a5448e423",
1363 | "shasum": ""
1364 | },
1365 | "require": {
1366 | "ext-json": "*",
1367 | "ext-mbstring": "*",
1368 | "ext-tokenizer": "*",
1369 | "ext-xml": "*",
1370 | "php": "^8.1.0"
1371 | },
1372 | "require-dev": {
1373 | "friendsofphp/php-cs-fixer": "^3.34.1",
1374 | "illuminate/view": "^10.26.2",
1375 | "laravel-zero/framework": "^10.1.2",
1376 | "mockery/mockery": "^1.6.6",
1377 | "nunomaduro/larastan": "^2.6.4",
1378 | "nunomaduro/termwind": "^1.15.1",
1379 | "pestphp/pest": "^2.20.0"
1380 | },
1381 | "bin": [
1382 | "builds/pint"
1383 | ],
1384 | "type": "project",
1385 | "autoload": {
1386 | "psr-4": {
1387 | "App\\": "app/",
1388 | "Database\\Seeders\\": "database/seeders/",
1389 | "Database\\Factories\\": "database/factories/"
1390 | }
1391 | },
1392 | "notification-url": "https://packagist.org/downloads/",
1393 | "license": [
1394 | "MIT"
1395 | ],
1396 | "authors": [
1397 | {
1398 | "name": "Nuno Maduro",
1399 | "email": "enunomaduro@gmail.com"
1400 | }
1401 | ],
1402 | "description": "An opinionated code formatter for PHP.",
1403 | "homepage": "https://laravel.com",
1404 | "keywords": [
1405 | "format",
1406 | "formatter",
1407 | "lint",
1408 | "linter",
1409 | "php"
1410 | ],
1411 | "support": {
1412 | "issues": "https://github.com/laravel/pint/issues",
1413 | "source": "https://github.com/laravel/pint"
1414 | },
1415 | "time": "2023-10-26T09:26:10+00:00"
1416 | },
1417 | {
1418 | "name": "myclabs/deep-copy",
1419 | "version": "1.11.1",
1420 | "source": {
1421 | "type": "git",
1422 | "url": "https://github.com/myclabs/DeepCopy.git",
1423 | "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c"
1424 | },
1425 | "dist": {
1426 | "type": "zip",
1427 | "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/7284c22080590fb39f2ffa3e9057f10a4ddd0e0c",
1428 | "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c",
1429 | "shasum": ""
1430 | },
1431 | "require": {
1432 | "php": "^7.1 || ^8.0"
1433 | },
1434 | "conflict": {
1435 | "doctrine/collections": "<1.6.8",
1436 | "doctrine/common": "<2.13.3 || >=3,<3.2.2"
1437 | },
1438 | "require-dev": {
1439 | "doctrine/collections": "^1.6.8",
1440 | "doctrine/common": "^2.13.3 || ^3.2.2",
1441 | "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13"
1442 | },
1443 | "type": "library",
1444 | "autoload": {
1445 | "files": [
1446 | "src/DeepCopy/deep_copy.php"
1447 | ],
1448 | "psr-4": {
1449 | "DeepCopy\\": "src/DeepCopy/"
1450 | }
1451 | },
1452 | "notification-url": "https://packagist.org/downloads/",
1453 | "license": [
1454 | "MIT"
1455 | ],
1456 | "description": "Create deep copies (clones) of your objects",
1457 | "keywords": [
1458 | "clone",
1459 | "copy",
1460 | "duplicate",
1461 | "object",
1462 | "object graph"
1463 | ],
1464 | "support": {
1465 | "issues": "https://github.com/myclabs/DeepCopy/issues",
1466 | "source": "https://github.com/myclabs/DeepCopy/tree/1.11.1"
1467 | },
1468 | "funding": [
1469 | {
1470 | "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy",
1471 | "type": "tidelift"
1472 | }
1473 | ],
1474 | "time": "2023-03-08T13:26:56+00:00"
1475 | },
1476 | {
1477 | "name": "nikic/php-parser",
1478 | "version": "v4.17.1",
1479 | "source": {
1480 | "type": "git",
1481 | "url": "https://github.com/nikic/PHP-Parser.git",
1482 | "reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d"
1483 | },
1484 | "dist": {
1485 | "type": "zip",
1486 | "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d",
1487 | "reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d",
1488 | "shasum": ""
1489 | },
1490 | "require": {
1491 | "ext-tokenizer": "*",
1492 | "php": ">=7.0"
1493 | },
1494 | "require-dev": {
1495 | "ircmaxell/php-yacc": "^0.0.7",
1496 | "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0"
1497 | },
1498 | "bin": [
1499 | "bin/php-parse"
1500 | ],
1501 | "type": "library",
1502 | "extra": {
1503 | "branch-alias": {
1504 | "dev-master": "4.9-dev"
1505 | }
1506 | },
1507 | "autoload": {
1508 | "psr-4": {
1509 | "PhpParser\\": "lib/PhpParser"
1510 | }
1511 | },
1512 | "notification-url": "https://packagist.org/downloads/",
1513 | "license": [
1514 | "BSD-3-Clause"
1515 | ],
1516 | "authors": [
1517 | {
1518 | "name": "Nikita Popov"
1519 | }
1520 | ],
1521 | "description": "A PHP parser written in PHP",
1522 | "keywords": [
1523 | "parser",
1524 | "php"
1525 | ],
1526 | "support": {
1527 | "issues": "https://github.com/nikic/PHP-Parser/issues",
1528 | "source": "https://github.com/nikic/PHP-Parser/tree/v4.17.1"
1529 | },
1530 | "time": "2023-08-13T19:53:39+00:00"
1531 | },
1532 | {
1533 | "name": "phar-io/manifest",
1534 | "version": "2.0.3",
1535 | "source": {
1536 | "type": "git",
1537 | "url": "https://github.com/phar-io/manifest.git",
1538 | "reference": "97803eca37d319dfa7826cc2437fc020857acb53"
1539 | },
1540 | "dist": {
1541 | "type": "zip",
1542 | "url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53",
1543 | "reference": "97803eca37d319dfa7826cc2437fc020857acb53",
1544 | "shasum": ""
1545 | },
1546 | "require": {
1547 | "ext-dom": "*",
1548 | "ext-phar": "*",
1549 | "ext-xmlwriter": "*",
1550 | "phar-io/version": "^3.0.1",
1551 | "php": "^7.2 || ^8.0"
1552 | },
1553 | "type": "library",
1554 | "extra": {
1555 | "branch-alias": {
1556 | "dev-master": "2.0.x-dev"
1557 | }
1558 | },
1559 | "autoload": {
1560 | "classmap": [
1561 | "src/"
1562 | ]
1563 | },
1564 | "notification-url": "https://packagist.org/downloads/",
1565 | "license": [
1566 | "BSD-3-Clause"
1567 | ],
1568 | "authors": [
1569 | {
1570 | "name": "Arne Blankerts",
1571 | "email": "arne@blankerts.de",
1572 | "role": "Developer"
1573 | },
1574 | {
1575 | "name": "Sebastian Heuer",
1576 | "email": "sebastian@phpeople.de",
1577 | "role": "Developer"
1578 | },
1579 | {
1580 | "name": "Sebastian Bergmann",
1581 | "email": "sebastian@phpunit.de",
1582 | "role": "Developer"
1583 | }
1584 | ],
1585 | "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)",
1586 | "support": {
1587 | "issues": "https://github.com/phar-io/manifest/issues",
1588 | "source": "https://github.com/phar-io/manifest/tree/2.0.3"
1589 | },
1590 | "time": "2021-07-20T11:28:43+00:00"
1591 | },
1592 | {
1593 | "name": "phar-io/version",
1594 | "version": "3.2.1",
1595 | "source": {
1596 | "type": "git",
1597 | "url": "https://github.com/phar-io/version.git",
1598 | "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74"
1599 | },
1600 | "dist": {
1601 | "type": "zip",
1602 | "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74",
1603 | "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74",
1604 | "shasum": ""
1605 | },
1606 | "require": {
1607 | "php": "^7.2 || ^8.0"
1608 | },
1609 | "type": "library",
1610 | "autoload": {
1611 | "classmap": [
1612 | "src/"
1613 | ]
1614 | },
1615 | "notification-url": "https://packagist.org/downloads/",
1616 | "license": [
1617 | "BSD-3-Clause"
1618 | ],
1619 | "authors": [
1620 | {
1621 | "name": "Arne Blankerts",
1622 | "email": "arne@blankerts.de",
1623 | "role": "Developer"
1624 | },
1625 | {
1626 | "name": "Sebastian Heuer",
1627 | "email": "sebastian@phpeople.de",
1628 | "role": "Developer"
1629 | },
1630 | {
1631 | "name": "Sebastian Bergmann",
1632 | "email": "sebastian@phpunit.de",
1633 | "role": "Developer"
1634 | }
1635 | ],
1636 | "description": "Library for handling version information and constraints",
1637 | "support": {
1638 | "issues": "https://github.com/phar-io/version/issues",
1639 | "source": "https://github.com/phar-io/version/tree/3.2.1"
1640 | },
1641 | "time": "2022-02-21T01:04:05+00:00"
1642 | },
1643 | {
1644 | "name": "phpunit/php-code-coverage",
1645 | "version": "9.2.27",
1646 | "source": {
1647 | "type": "git",
1648 | "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
1649 | "reference": "b0a88255cb70d52653d80c890bd7f38740ea50d1"
1650 | },
1651 | "dist": {
1652 | "type": "zip",
1653 | "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/b0a88255cb70d52653d80c890bd7f38740ea50d1",
1654 | "reference": "b0a88255cb70d52653d80c890bd7f38740ea50d1",
1655 | "shasum": ""
1656 | },
1657 | "require": {
1658 | "ext-dom": "*",
1659 | "ext-libxml": "*",
1660 | "ext-xmlwriter": "*",
1661 | "nikic/php-parser": "^4.15",
1662 | "php": ">=7.3",
1663 | "phpunit/php-file-iterator": "^3.0.3",
1664 | "phpunit/php-text-template": "^2.0.2",
1665 | "sebastian/code-unit-reverse-lookup": "^2.0.2",
1666 | "sebastian/complexity": "^2.0",
1667 | "sebastian/environment": "^5.1.2",
1668 | "sebastian/lines-of-code": "^1.0.3",
1669 | "sebastian/version": "^3.0.1",
1670 | "theseer/tokenizer": "^1.2.0"
1671 | },
1672 | "require-dev": {
1673 | "phpunit/phpunit": "^9.3"
1674 | },
1675 | "suggest": {
1676 | "ext-pcov": "PHP extension that provides line coverage",
1677 | "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage"
1678 | },
1679 | "type": "library",
1680 | "extra": {
1681 | "branch-alias": {
1682 | "dev-master": "9.2-dev"
1683 | }
1684 | },
1685 | "autoload": {
1686 | "classmap": [
1687 | "src/"
1688 | ]
1689 | },
1690 | "notification-url": "https://packagist.org/downloads/",
1691 | "license": [
1692 | "BSD-3-Clause"
1693 | ],
1694 | "authors": [
1695 | {
1696 | "name": "Sebastian Bergmann",
1697 | "email": "sebastian@phpunit.de",
1698 | "role": "lead"
1699 | }
1700 | ],
1701 | "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
1702 | "homepage": "https://github.com/sebastianbergmann/php-code-coverage",
1703 | "keywords": [
1704 | "coverage",
1705 | "testing",
1706 | "xunit"
1707 | ],
1708 | "support": {
1709 | "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
1710 | "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy",
1711 | "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.27"
1712 | },
1713 | "funding": [
1714 | {
1715 | "url": "https://github.com/sebastianbergmann",
1716 | "type": "github"
1717 | }
1718 | ],
1719 | "time": "2023-07-26T13:44:30+00:00"
1720 | },
1721 | {
1722 | "name": "phpunit/php-file-iterator",
1723 | "version": "3.0.6",
1724 | "source": {
1725 | "type": "git",
1726 | "url": "https://github.com/sebastianbergmann/php-file-iterator.git",
1727 | "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf"
1728 | },
1729 | "dist": {
1730 | "type": "zip",
1731 | "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf",
1732 | "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf",
1733 | "shasum": ""
1734 | },
1735 | "require": {
1736 | "php": ">=7.3"
1737 | },
1738 | "require-dev": {
1739 | "phpunit/phpunit": "^9.3"
1740 | },
1741 | "type": "library",
1742 | "extra": {
1743 | "branch-alias": {
1744 | "dev-master": "3.0-dev"
1745 | }
1746 | },
1747 | "autoload": {
1748 | "classmap": [
1749 | "src/"
1750 | ]
1751 | },
1752 | "notification-url": "https://packagist.org/downloads/",
1753 | "license": [
1754 | "BSD-3-Clause"
1755 | ],
1756 | "authors": [
1757 | {
1758 | "name": "Sebastian Bergmann",
1759 | "email": "sebastian@phpunit.de",
1760 | "role": "lead"
1761 | }
1762 | ],
1763 | "description": "FilterIterator implementation that filters files based on a list of suffixes.",
1764 | "homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
1765 | "keywords": [
1766 | "filesystem",
1767 | "iterator"
1768 | ],
1769 | "support": {
1770 | "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues",
1771 | "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6"
1772 | },
1773 | "funding": [
1774 | {
1775 | "url": "https://github.com/sebastianbergmann",
1776 | "type": "github"
1777 | }
1778 | ],
1779 | "time": "2021-12-02T12:48:52+00:00"
1780 | },
1781 | {
1782 | "name": "phpunit/php-invoker",
1783 | "version": "3.1.1",
1784 | "source": {
1785 | "type": "git",
1786 | "url": "https://github.com/sebastianbergmann/php-invoker.git",
1787 | "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67"
1788 | },
1789 | "dist": {
1790 | "type": "zip",
1791 | "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67",
1792 | "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67",
1793 | "shasum": ""
1794 | },
1795 | "require": {
1796 | "php": ">=7.3"
1797 | },
1798 | "require-dev": {
1799 | "ext-pcntl": "*",
1800 | "phpunit/phpunit": "^9.3"
1801 | },
1802 | "suggest": {
1803 | "ext-pcntl": "*"
1804 | },
1805 | "type": "library",
1806 | "extra": {
1807 | "branch-alias": {
1808 | "dev-master": "3.1-dev"
1809 | }
1810 | },
1811 | "autoload": {
1812 | "classmap": [
1813 | "src/"
1814 | ]
1815 | },
1816 | "notification-url": "https://packagist.org/downloads/",
1817 | "license": [
1818 | "BSD-3-Clause"
1819 | ],
1820 | "authors": [
1821 | {
1822 | "name": "Sebastian Bergmann",
1823 | "email": "sebastian@phpunit.de",
1824 | "role": "lead"
1825 | }
1826 | ],
1827 | "description": "Invoke callables with a timeout",
1828 | "homepage": "https://github.com/sebastianbergmann/php-invoker/",
1829 | "keywords": [
1830 | "process"
1831 | ],
1832 | "support": {
1833 | "issues": "https://github.com/sebastianbergmann/php-invoker/issues",
1834 | "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1"
1835 | },
1836 | "funding": [
1837 | {
1838 | "url": "https://github.com/sebastianbergmann",
1839 | "type": "github"
1840 | }
1841 | ],
1842 | "time": "2020-09-28T05:58:55+00:00"
1843 | },
1844 | {
1845 | "name": "phpunit/php-text-template",
1846 | "version": "2.0.4",
1847 | "source": {
1848 | "type": "git",
1849 | "url": "https://github.com/sebastianbergmann/php-text-template.git",
1850 | "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28"
1851 | },
1852 | "dist": {
1853 | "type": "zip",
1854 | "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28",
1855 | "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28",
1856 | "shasum": ""
1857 | },
1858 | "require": {
1859 | "php": ">=7.3"
1860 | },
1861 | "require-dev": {
1862 | "phpunit/phpunit": "^9.3"
1863 | },
1864 | "type": "library",
1865 | "extra": {
1866 | "branch-alias": {
1867 | "dev-master": "2.0-dev"
1868 | }
1869 | },
1870 | "autoload": {
1871 | "classmap": [
1872 | "src/"
1873 | ]
1874 | },
1875 | "notification-url": "https://packagist.org/downloads/",
1876 | "license": [
1877 | "BSD-3-Clause"
1878 | ],
1879 | "authors": [
1880 | {
1881 | "name": "Sebastian Bergmann",
1882 | "email": "sebastian@phpunit.de",
1883 | "role": "lead"
1884 | }
1885 | ],
1886 | "description": "Simple template engine.",
1887 | "homepage": "https://github.com/sebastianbergmann/php-text-template/",
1888 | "keywords": [
1889 | "template"
1890 | ],
1891 | "support": {
1892 | "issues": "https://github.com/sebastianbergmann/php-text-template/issues",
1893 | "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4"
1894 | },
1895 | "funding": [
1896 | {
1897 | "url": "https://github.com/sebastianbergmann",
1898 | "type": "github"
1899 | }
1900 | ],
1901 | "time": "2020-10-26T05:33:50+00:00"
1902 | },
1903 | {
1904 | "name": "phpunit/php-timer",
1905 | "version": "5.0.3",
1906 | "source": {
1907 | "type": "git",
1908 | "url": "https://github.com/sebastianbergmann/php-timer.git",
1909 | "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2"
1910 | },
1911 | "dist": {
1912 | "type": "zip",
1913 | "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2",
1914 | "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2",
1915 | "shasum": ""
1916 | },
1917 | "require": {
1918 | "php": ">=7.3"
1919 | },
1920 | "require-dev": {
1921 | "phpunit/phpunit": "^9.3"
1922 | },
1923 | "type": "library",
1924 | "extra": {
1925 | "branch-alias": {
1926 | "dev-master": "5.0-dev"
1927 | }
1928 | },
1929 | "autoload": {
1930 | "classmap": [
1931 | "src/"
1932 | ]
1933 | },
1934 | "notification-url": "https://packagist.org/downloads/",
1935 | "license": [
1936 | "BSD-3-Clause"
1937 | ],
1938 | "authors": [
1939 | {
1940 | "name": "Sebastian Bergmann",
1941 | "email": "sebastian@phpunit.de",
1942 | "role": "lead"
1943 | }
1944 | ],
1945 | "description": "Utility class for timing",
1946 | "homepage": "https://github.com/sebastianbergmann/php-timer/",
1947 | "keywords": [
1948 | "timer"
1949 | ],
1950 | "support": {
1951 | "issues": "https://github.com/sebastianbergmann/php-timer/issues",
1952 | "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3"
1953 | },
1954 | "funding": [
1955 | {
1956 | "url": "https://github.com/sebastianbergmann",
1957 | "type": "github"
1958 | }
1959 | ],
1960 | "time": "2020-10-26T13:16:10+00:00"
1961 | },
1962 | {
1963 | "name": "phpunit/phpunit",
1964 | "version": "9.6.11",
1965 | "source": {
1966 | "type": "git",
1967 | "url": "https://github.com/sebastianbergmann/phpunit.git",
1968 | "reference": "810500e92855eba8a7a5319ae913be2da6f957b0"
1969 | },
1970 | "dist": {
1971 | "type": "zip",
1972 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/810500e92855eba8a7a5319ae913be2da6f957b0",
1973 | "reference": "810500e92855eba8a7a5319ae913be2da6f957b0",
1974 | "shasum": ""
1975 | },
1976 | "require": {
1977 | "doctrine/instantiator": "^1.3.1 || ^2",
1978 | "ext-dom": "*",
1979 | "ext-json": "*",
1980 | "ext-libxml": "*",
1981 | "ext-mbstring": "*",
1982 | "ext-xml": "*",
1983 | "ext-xmlwriter": "*",
1984 | "myclabs/deep-copy": "^1.10.1",
1985 | "phar-io/manifest": "^2.0.3",
1986 | "phar-io/version": "^3.0.2",
1987 | "php": ">=7.3",
1988 | "phpunit/php-code-coverage": "^9.2.13",
1989 | "phpunit/php-file-iterator": "^3.0.5",
1990 | "phpunit/php-invoker": "^3.1.1",
1991 | "phpunit/php-text-template": "^2.0.3",
1992 | "phpunit/php-timer": "^5.0.2",
1993 | "sebastian/cli-parser": "^1.0.1",
1994 | "sebastian/code-unit": "^1.0.6",
1995 | "sebastian/comparator": "^4.0.8",
1996 | "sebastian/diff": "^4.0.3",
1997 | "sebastian/environment": "^5.1.3",
1998 | "sebastian/exporter": "^4.0.5",
1999 | "sebastian/global-state": "^5.0.1",
2000 | "sebastian/object-enumerator": "^4.0.3",
2001 | "sebastian/resource-operations": "^3.0.3",
2002 | "sebastian/type": "^3.2",
2003 | "sebastian/version": "^3.0.2"
2004 | },
2005 | "suggest": {
2006 | "ext-soap": "To be able to generate mocks based on WSDL files",
2007 | "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage"
2008 | },
2009 | "bin": [
2010 | "phpunit"
2011 | ],
2012 | "type": "library",
2013 | "extra": {
2014 | "branch-alias": {
2015 | "dev-master": "9.6-dev"
2016 | }
2017 | },
2018 | "autoload": {
2019 | "files": [
2020 | "src/Framework/Assert/Functions.php"
2021 | ],
2022 | "classmap": [
2023 | "src/"
2024 | ]
2025 | },
2026 | "notification-url": "https://packagist.org/downloads/",
2027 | "license": [
2028 | "BSD-3-Clause"
2029 | ],
2030 | "authors": [
2031 | {
2032 | "name": "Sebastian Bergmann",
2033 | "email": "sebastian@phpunit.de",
2034 | "role": "lead"
2035 | }
2036 | ],
2037 | "description": "The PHP Unit Testing framework.",
2038 | "homepage": "https://phpunit.de/",
2039 | "keywords": [
2040 | "phpunit",
2041 | "testing",
2042 | "xunit"
2043 | ],
2044 | "support": {
2045 | "issues": "https://github.com/sebastianbergmann/phpunit/issues",
2046 | "security": "https://github.com/sebastianbergmann/phpunit/security/policy",
2047 | "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.11"
2048 | },
2049 | "funding": [
2050 | {
2051 | "url": "https://phpunit.de/sponsors.html",
2052 | "type": "custom"
2053 | },
2054 | {
2055 | "url": "https://github.com/sebastianbergmann",
2056 | "type": "github"
2057 | },
2058 | {
2059 | "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit",
2060 | "type": "tidelift"
2061 | }
2062 | ],
2063 | "time": "2023-08-19T07:10:56+00:00"
2064 | },
2065 | {
2066 | "name": "sebastian/cli-parser",
2067 | "version": "1.0.1",
2068 | "source": {
2069 | "type": "git",
2070 | "url": "https://github.com/sebastianbergmann/cli-parser.git",
2071 | "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2"
2072 | },
2073 | "dist": {
2074 | "type": "zip",
2075 | "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/442e7c7e687e42adc03470c7b668bc4b2402c0b2",
2076 | "reference": "442e7c7e687e42adc03470c7b668bc4b2402c0b2",
2077 | "shasum": ""
2078 | },
2079 | "require": {
2080 | "php": ">=7.3"
2081 | },
2082 | "require-dev": {
2083 | "phpunit/phpunit": "^9.3"
2084 | },
2085 | "type": "library",
2086 | "extra": {
2087 | "branch-alias": {
2088 | "dev-master": "1.0-dev"
2089 | }
2090 | },
2091 | "autoload": {
2092 | "classmap": [
2093 | "src/"
2094 | ]
2095 | },
2096 | "notification-url": "https://packagist.org/downloads/",
2097 | "license": [
2098 | "BSD-3-Clause"
2099 | ],
2100 | "authors": [
2101 | {
2102 | "name": "Sebastian Bergmann",
2103 | "email": "sebastian@phpunit.de",
2104 | "role": "lead"
2105 | }
2106 | ],
2107 | "description": "Library for parsing CLI options",
2108 | "homepage": "https://github.com/sebastianbergmann/cli-parser",
2109 | "support": {
2110 | "issues": "https://github.com/sebastianbergmann/cli-parser/issues",
2111 | "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.1"
2112 | },
2113 | "funding": [
2114 | {
2115 | "url": "https://github.com/sebastianbergmann",
2116 | "type": "github"
2117 | }
2118 | ],
2119 | "time": "2020-09-28T06:08:49+00:00"
2120 | },
2121 | {
2122 | "name": "sebastian/code-unit",
2123 | "version": "1.0.8",
2124 | "source": {
2125 | "type": "git",
2126 | "url": "https://github.com/sebastianbergmann/code-unit.git",
2127 | "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120"
2128 | },
2129 | "dist": {
2130 | "type": "zip",
2131 | "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120",
2132 | "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120",
2133 | "shasum": ""
2134 | },
2135 | "require": {
2136 | "php": ">=7.3"
2137 | },
2138 | "require-dev": {
2139 | "phpunit/phpunit": "^9.3"
2140 | },
2141 | "type": "library",
2142 | "extra": {
2143 | "branch-alias": {
2144 | "dev-master": "1.0-dev"
2145 | }
2146 | },
2147 | "autoload": {
2148 | "classmap": [
2149 | "src/"
2150 | ]
2151 | },
2152 | "notification-url": "https://packagist.org/downloads/",
2153 | "license": [
2154 | "BSD-3-Clause"
2155 | ],
2156 | "authors": [
2157 | {
2158 | "name": "Sebastian Bergmann",
2159 | "email": "sebastian@phpunit.de",
2160 | "role": "lead"
2161 | }
2162 | ],
2163 | "description": "Collection of value objects that represent the PHP code units",
2164 | "homepage": "https://github.com/sebastianbergmann/code-unit",
2165 | "support": {
2166 | "issues": "https://github.com/sebastianbergmann/code-unit/issues",
2167 | "source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8"
2168 | },
2169 | "funding": [
2170 | {
2171 | "url": "https://github.com/sebastianbergmann",
2172 | "type": "github"
2173 | }
2174 | ],
2175 | "time": "2020-10-26T13:08:54+00:00"
2176 | },
2177 | {
2178 | "name": "sebastian/code-unit-reverse-lookup",
2179 | "version": "2.0.3",
2180 | "source": {
2181 | "type": "git",
2182 | "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git",
2183 | "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5"
2184 | },
2185 | "dist": {
2186 | "type": "zip",
2187 | "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5",
2188 | "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5",
2189 | "shasum": ""
2190 | },
2191 | "require": {
2192 | "php": ">=7.3"
2193 | },
2194 | "require-dev": {
2195 | "phpunit/phpunit": "^9.3"
2196 | },
2197 | "type": "library",
2198 | "extra": {
2199 | "branch-alias": {
2200 | "dev-master": "2.0-dev"
2201 | }
2202 | },
2203 | "autoload": {
2204 | "classmap": [
2205 | "src/"
2206 | ]
2207 | },
2208 | "notification-url": "https://packagist.org/downloads/",
2209 | "license": [
2210 | "BSD-3-Clause"
2211 | ],
2212 | "authors": [
2213 | {
2214 | "name": "Sebastian Bergmann",
2215 | "email": "sebastian@phpunit.de"
2216 | }
2217 | ],
2218 | "description": "Looks up which function or method a line of code belongs to",
2219 | "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/",
2220 | "support": {
2221 | "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues",
2222 | "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3"
2223 | },
2224 | "funding": [
2225 | {
2226 | "url": "https://github.com/sebastianbergmann",
2227 | "type": "github"
2228 | }
2229 | ],
2230 | "time": "2020-09-28T05:30:19+00:00"
2231 | },
2232 | {
2233 | "name": "sebastian/comparator",
2234 | "version": "4.0.8",
2235 | "source": {
2236 | "type": "git",
2237 | "url": "https://github.com/sebastianbergmann/comparator.git",
2238 | "reference": "fa0f136dd2334583309d32b62544682ee972b51a"
2239 | },
2240 | "dist": {
2241 | "type": "zip",
2242 | "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a",
2243 | "reference": "fa0f136dd2334583309d32b62544682ee972b51a",
2244 | "shasum": ""
2245 | },
2246 | "require": {
2247 | "php": ">=7.3",
2248 | "sebastian/diff": "^4.0",
2249 | "sebastian/exporter": "^4.0"
2250 | },
2251 | "require-dev": {
2252 | "phpunit/phpunit": "^9.3"
2253 | },
2254 | "type": "library",
2255 | "extra": {
2256 | "branch-alias": {
2257 | "dev-master": "4.0-dev"
2258 | }
2259 | },
2260 | "autoload": {
2261 | "classmap": [
2262 | "src/"
2263 | ]
2264 | },
2265 | "notification-url": "https://packagist.org/downloads/",
2266 | "license": [
2267 | "BSD-3-Clause"
2268 | ],
2269 | "authors": [
2270 | {
2271 | "name": "Sebastian Bergmann",
2272 | "email": "sebastian@phpunit.de"
2273 | },
2274 | {
2275 | "name": "Jeff Welch",
2276 | "email": "whatthejeff@gmail.com"
2277 | },
2278 | {
2279 | "name": "Volker Dusch",
2280 | "email": "github@wallbash.com"
2281 | },
2282 | {
2283 | "name": "Bernhard Schussek",
2284 | "email": "bschussek@2bepublished.at"
2285 | }
2286 | ],
2287 | "description": "Provides the functionality to compare PHP values for equality",
2288 | "homepage": "https://github.com/sebastianbergmann/comparator",
2289 | "keywords": [
2290 | "comparator",
2291 | "compare",
2292 | "equality"
2293 | ],
2294 | "support": {
2295 | "issues": "https://github.com/sebastianbergmann/comparator/issues",
2296 | "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8"
2297 | },
2298 | "funding": [
2299 | {
2300 | "url": "https://github.com/sebastianbergmann",
2301 | "type": "github"
2302 | }
2303 | ],
2304 | "time": "2022-09-14T12:41:17+00:00"
2305 | },
2306 | {
2307 | "name": "sebastian/complexity",
2308 | "version": "2.0.2",
2309 | "source": {
2310 | "type": "git",
2311 | "url": "https://github.com/sebastianbergmann/complexity.git",
2312 | "reference": "739b35e53379900cc9ac327b2147867b8b6efd88"
2313 | },
2314 | "dist": {
2315 | "type": "zip",
2316 | "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/739b35e53379900cc9ac327b2147867b8b6efd88",
2317 | "reference": "739b35e53379900cc9ac327b2147867b8b6efd88",
2318 | "shasum": ""
2319 | },
2320 | "require": {
2321 | "nikic/php-parser": "^4.7",
2322 | "php": ">=7.3"
2323 | },
2324 | "require-dev": {
2325 | "phpunit/phpunit": "^9.3"
2326 | },
2327 | "type": "library",
2328 | "extra": {
2329 | "branch-alias": {
2330 | "dev-master": "2.0-dev"
2331 | }
2332 | },
2333 | "autoload": {
2334 | "classmap": [
2335 | "src/"
2336 | ]
2337 | },
2338 | "notification-url": "https://packagist.org/downloads/",
2339 | "license": [
2340 | "BSD-3-Clause"
2341 | ],
2342 | "authors": [
2343 | {
2344 | "name": "Sebastian Bergmann",
2345 | "email": "sebastian@phpunit.de",
2346 | "role": "lead"
2347 | }
2348 | ],
2349 | "description": "Library for calculating the complexity of PHP code units",
2350 | "homepage": "https://github.com/sebastianbergmann/complexity",
2351 | "support": {
2352 | "issues": "https://github.com/sebastianbergmann/complexity/issues",
2353 | "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.2"
2354 | },
2355 | "funding": [
2356 | {
2357 | "url": "https://github.com/sebastianbergmann",
2358 | "type": "github"
2359 | }
2360 | ],
2361 | "time": "2020-10-26T15:52:27+00:00"
2362 | },
2363 | {
2364 | "name": "sebastian/diff",
2365 | "version": "4.0.5",
2366 | "source": {
2367 | "type": "git",
2368 | "url": "https://github.com/sebastianbergmann/diff.git",
2369 | "reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131"
2370 | },
2371 | "dist": {
2372 | "type": "zip",
2373 | "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/74be17022044ebaaecfdf0c5cd504fc9cd5a7131",
2374 | "reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131",
2375 | "shasum": ""
2376 | },
2377 | "require": {
2378 | "php": ">=7.3"
2379 | },
2380 | "require-dev": {
2381 | "phpunit/phpunit": "^9.3",
2382 | "symfony/process": "^4.2 || ^5"
2383 | },
2384 | "type": "library",
2385 | "extra": {
2386 | "branch-alias": {
2387 | "dev-master": "4.0-dev"
2388 | }
2389 | },
2390 | "autoload": {
2391 | "classmap": [
2392 | "src/"
2393 | ]
2394 | },
2395 | "notification-url": "https://packagist.org/downloads/",
2396 | "license": [
2397 | "BSD-3-Clause"
2398 | ],
2399 | "authors": [
2400 | {
2401 | "name": "Sebastian Bergmann",
2402 | "email": "sebastian@phpunit.de"
2403 | },
2404 | {
2405 | "name": "Kore Nordmann",
2406 | "email": "mail@kore-nordmann.de"
2407 | }
2408 | ],
2409 | "description": "Diff implementation",
2410 | "homepage": "https://github.com/sebastianbergmann/diff",
2411 | "keywords": [
2412 | "diff",
2413 | "udiff",
2414 | "unidiff",
2415 | "unified diff"
2416 | ],
2417 | "support": {
2418 | "issues": "https://github.com/sebastianbergmann/diff/issues",
2419 | "source": "https://github.com/sebastianbergmann/diff/tree/4.0.5"
2420 | },
2421 | "funding": [
2422 | {
2423 | "url": "https://github.com/sebastianbergmann",
2424 | "type": "github"
2425 | }
2426 | ],
2427 | "time": "2023-05-07T05:35:17+00:00"
2428 | },
2429 | {
2430 | "name": "sebastian/environment",
2431 | "version": "5.1.5",
2432 | "source": {
2433 | "type": "git",
2434 | "url": "https://github.com/sebastianbergmann/environment.git",
2435 | "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed"
2436 | },
2437 | "dist": {
2438 | "type": "zip",
2439 | "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/830c43a844f1f8d5b7a1f6d6076b784454d8b7ed",
2440 | "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed",
2441 | "shasum": ""
2442 | },
2443 | "require": {
2444 | "php": ">=7.3"
2445 | },
2446 | "require-dev": {
2447 | "phpunit/phpunit": "^9.3"
2448 | },
2449 | "suggest": {
2450 | "ext-posix": "*"
2451 | },
2452 | "type": "library",
2453 | "extra": {
2454 | "branch-alias": {
2455 | "dev-master": "5.1-dev"
2456 | }
2457 | },
2458 | "autoload": {
2459 | "classmap": [
2460 | "src/"
2461 | ]
2462 | },
2463 | "notification-url": "https://packagist.org/downloads/",
2464 | "license": [
2465 | "BSD-3-Clause"
2466 | ],
2467 | "authors": [
2468 | {
2469 | "name": "Sebastian Bergmann",
2470 | "email": "sebastian@phpunit.de"
2471 | }
2472 | ],
2473 | "description": "Provides functionality to handle HHVM/PHP environments",
2474 | "homepage": "http://www.github.com/sebastianbergmann/environment",
2475 | "keywords": [
2476 | "Xdebug",
2477 | "environment",
2478 | "hhvm"
2479 | ],
2480 | "support": {
2481 | "issues": "https://github.com/sebastianbergmann/environment/issues",
2482 | "source": "https://github.com/sebastianbergmann/environment/tree/5.1.5"
2483 | },
2484 | "funding": [
2485 | {
2486 | "url": "https://github.com/sebastianbergmann",
2487 | "type": "github"
2488 | }
2489 | ],
2490 | "time": "2023-02-03T06:03:51+00:00"
2491 | },
2492 | {
2493 | "name": "sebastian/exporter",
2494 | "version": "4.0.5",
2495 | "source": {
2496 | "type": "git",
2497 | "url": "https://github.com/sebastianbergmann/exporter.git",
2498 | "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d"
2499 | },
2500 | "dist": {
2501 | "type": "zip",
2502 | "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d",
2503 | "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d",
2504 | "shasum": ""
2505 | },
2506 | "require": {
2507 | "php": ">=7.3",
2508 | "sebastian/recursion-context": "^4.0"
2509 | },
2510 | "require-dev": {
2511 | "ext-mbstring": "*",
2512 | "phpunit/phpunit": "^9.3"
2513 | },
2514 | "type": "library",
2515 | "extra": {
2516 | "branch-alias": {
2517 | "dev-master": "4.0-dev"
2518 | }
2519 | },
2520 | "autoload": {
2521 | "classmap": [
2522 | "src/"
2523 | ]
2524 | },
2525 | "notification-url": "https://packagist.org/downloads/",
2526 | "license": [
2527 | "BSD-3-Clause"
2528 | ],
2529 | "authors": [
2530 | {
2531 | "name": "Sebastian Bergmann",
2532 | "email": "sebastian@phpunit.de"
2533 | },
2534 | {
2535 | "name": "Jeff Welch",
2536 | "email": "whatthejeff@gmail.com"
2537 | },
2538 | {
2539 | "name": "Volker Dusch",
2540 | "email": "github@wallbash.com"
2541 | },
2542 | {
2543 | "name": "Adam Harvey",
2544 | "email": "aharvey@php.net"
2545 | },
2546 | {
2547 | "name": "Bernhard Schussek",
2548 | "email": "bschussek@gmail.com"
2549 | }
2550 | ],
2551 | "description": "Provides the functionality to export PHP variables for visualization",
2552 | "homepage": "https://www.github.com/sebastianbergmann/exporter",
2553 | "keywords": [
2554 | "export",
2555 | "exporter"
2556 | ],
2557 | "support": {
2558 | "issues": "https://github.com/sebastianbergmann/exporter/issues",
2559 | "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.5"
2560 | },
2561 | "funding": [
2562 | {
2563 | "url": "https://github.com/sebastianbergmann",
2564 | "type": "github"
2565 | }
2566 | ],
2567 | "time": "2022-09-14T06:03:37+00:00"
2568 | },
2569 | {
2570 | "name": "sebastian/global-state",
2571 | "version": "5.0.6",
2572 | "source": {
2573 | "type": "git",
2574 | "url": "https://github.com/sebastianbergmann/global-state.git",
2575 | "reference": "bde739e7565280bda77be70044ac1047bc007e34"
2576 | },
2577 | "dist": {
2578 | "type": "zip",
2579 | "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bde739e7565280bda77be70044ac1047bc007e34",
2580 | "reference": "bde739e7565280bda77be70044ac1047bc007e34",
2581 | "shasum": ""
2582 | },
2583 | "require": {
2584 | "php": ">=7.3",
2585 | "sebastian/object-reflector": "^2.0",
2586 | "sebastian/recursion-context": "^4.0"
2587 | },
2588 | "require-dev": {
2589 | "ext-dom": "*",
2590 | "phpunit/phpunit": "^9.3"
2591 | },
2592 | "suggest": {
2593 | "ext-uopz": "*"
2594 | },
2595 | "type": "library",
2596 | "extra": {
2597 | "branch-alias": {
2598 | "dev-master": "5.0-dev"
2599 | }
2600 | },
2601 | "autoload": {
2602 | "classmap": [
2603 | "src/"
2604 | ]
2605 | },
2606 | "notification-url": "https://packagist.org/downloads/",
2607 | "license": [
2608 | "BSD-3-Clause"
2609 | ],
2610 | "authors": [
2611 | {
2612 | "name": "Sebastian Bergmann",
2613 | "email": "sebastian@phpunit.de"
2614 | }
2615 | ],
2616 | "description": "Snapshotting of global state",
2617 | "homepage": "http://www.github.com/sebastianbergmann/global-state",
2618 | "keywords": [
2619 | "global state"
2620 | ],
2621 | "support": {
2622 | "issues": "https://github.com/sebastianbergmann/global-state/issues",
2623 | "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.6"
2624 | },
2625 | "funding": [
2626 | {
2627 | "url": "https://github.com/sebastianbergmann",
2628 | "type": "github"
2629 | }
2630 | ],
2631 | "time": "2023-08-02T09:26:13+00:00"
2632 | },
2633 | {
2634 | "name": "sebastian/lines-of-code",
2635 | "version": "1.0.3",
2636 | "source": {
2637 | "type": "git",
2638 | "url": "https://github.com/sebastianbergmann/lines-of-code.git",
2639 | "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc"
2640 | },
2641 | "dist": {
2642 | "type": "zip",
2643 | "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/c1c2e997aa3146983ed888ad08b15470a2e22ecc",
2644 | "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc",
2645 | "shasum": ""
2646 | },
2647 | "require": {
2648 | "nikic/php-parser": "^4.6",
2649 | "php": ">=7.3"
2650 | },
2651 | "require-dev": {
2652 | "phpunit/phpunit": "^9.3"
2653 | },
2654 | "type": "library",
2655 | "extra": {
2656 | "branch-alias": {
2657 | "dev-master": "1.0-dev"
2658 | }
2659 | },
2660 | "autoload": {
2661 | "classmap": [
2662 | "src/"
2663 | ]
2664 | },
2665 | "notification-url": "https://packagist.org/downloads/",
2666 | "license": [
2667 | "BSD-3-Clause"
2668 | ],
2669 | "authors": [
2670 | {
2671 | "name": "Sebastian Bergmann",
2672 | "email": "sebastian@phpunit.de",
2673 | "role": "lead"
2674 | }
2675 | ],
2676 | "description": "Library for counting the lines of code in PHP source code",
2677 | "homepage": "https://github.com/sebastianbergmann/lines-of-code",
2678 | "support": {
2679 | "issues": "https://github.com/sebastianbergmann/lines-of-code/issues",
2680 | "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.3"
2681 | },
2682 | "funding": [
2683 | {
2684 | "url": "https://github.com/sebastianbergmann",
2685 | "type": "github"
2686 | }
2687 | ],
2688 | "time": "2020-11-28T06:42:11+00:00"
2689 | },
2690 | {
2691 | "name": "sebastian/object-enumerator",
2692 | "version": "4.0.4",
2693 | "source": {
2694 | "type": "git",
2695 | "url": "https://github.com/sebastianbergmann/object-enumerator.git",
2696 | "reference": "5c9eeac41b290a3712d88851518825ad78f45c71"
2697 | },
2698 | "dist": {
2699 | "type": "zip",
2700 | "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71",
2701 | "reference": "5c9eeac41b290a3712d88851518825ad78f45c71",
2702 | "shasum": ""
2703 | },
2704 | "require": {
2705 | "php": ">=7.3",
2706 | "sebastian/object-reflector": "^2.0",
2707 | "sebastian/recursion-context": "^4.0"
2708 | },
2709 | "require-dev": {
2710 | "phpunit/phpunit": "^9.3"
2711 | },
2712 | "type": "library",
2713 | "extra": {
2714 | "branch-alias": {
2715 | "dev-master": "4.0-dev"
2716 | }
2717 | },
2718 | "autoload": {
2719 | "classmap": [
2720 | "src/"
2721 | ]
2722 | },
2723 | "notification-url": "https://packagist.org/downloads/",
2724 | "license": [
2725 | "BSD-3-Clause"
2726 | ],
2727 | "authors": [
2728 | {
2729 | "name": "Sebastian Bergmann",
2730 | "email": "sebastian@phpunit.de"
2731 | }
2732 | ],
2733 | "description": "Traverses array structures and object graphs to enumerate all referenced objects",
2734 | "homepage": "https://github.com/sebastianbergmann/object-enumerator/",
2735 | "support": {
2736 | "issues": "https://github.com/sebastianbergmann/object-enumerator/issues",
2737 | "source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4"
2738 | },
2739 | "funding": [
2740 | {
2741 | "url": "https://github.com/sebastianbergmann",
2742 | "type": "github"
2743 | }
2744 | ],
2745 | "time": "2020-10-26T13:12:34+00:00"
2746 | },
2747 | {
2748 | "name": "sebastian/object-reflector",
2749 | "version": "2.0.4",
2750 | "source": {
2751 | "type": "git",
2752 | "url": "https://github.com/sebastianbergmann/object-reflector.git",
2753 | "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7"
2754 | },
2755 | "dist": {
2756 | "type": "zip",
2757 | "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7",
2758 | "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7",
2759 | "shasum": ""
2760 | },
2761 | "require": {
2762 | "php": ">=7.3"
2763 | },
2764 | "require-dev": {
2765 | "phpunit/phpunit": "^9.3"
2766 | },
2767 | "type": "library",
2768 | "extra": {
2769 | "branch-alias": {
2770 | "dev-master": "2.0-dev"
2771 | }
2772 | },
2773 | "autoload": {
2774 | "classmap": [
2775 | "src/"
2776 | ]
2777 | },
2778 | "notification-url": "https://packagist.org/downloads/",
2779 | "license": [
2780 | "BSD-3-Clause"
2781 | ],
2782 | "authors": [
2783 | {
2784 | "name": "Sebastian Bergmann",
2785 | "email": "sebastian@phpunit.de"
2786 | }
2787 | ],
2788 | "description": "Allows reflection of object attributes, including inherited and non-public ones",
2789 | "homepage": "https://github.com/sebastianbergmann/object-reflector/",
2790 | "support": {
2791 | "issues": "https://github.com/sebastianbergmann/object-reflector/issues",
2792 | "source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4"
2793 | },
2794 | "funding": [
2795 | {
2796 | "url": "https://github.com/sebastianbergmann",
2797 | "type": "github"
2798 | }
2799 | ],
2800 | "time": "2020-10-26T13:14:26+00:00"
2801 | },
2802 | {
2803 | "name": "sebastian/recursion-context",
2804 | "version": "4.0.5",
2805 | "source": {
2806 | "type": "git",
2807 | "url": "https://github.com/sebastianbergmann/recursion-context.git",
2808 | "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1"
2809 | },
2810 | "dist": {
2811 | "type": "zip",
2812 | "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1",
2813 | "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1",
2814 | "shasum": ""
2815 | },
2816 | "require": {
2817 | "php": ">=7.3"
2818 | },
2819 | "require-dev": {
2820 | "phpunit/phpunit": "^9.3"
2821 | },
2822 | "type": "library",
2823 | "extra": {
2824 | "branch-alias": {
2825 | "dev-master": "4.0-dev"
2826 | }
2827 | },
2828 | "autoload": {
2829 | "classmap": [
2830 | "src/"
2831 | ]
2832 | },
2833 | "notification-url": "https://packagist.org/downloads/",
2834 | "license": [
2835 | "BSD-3-Clause"
2836 | ],
2837 | "authors": [
2838 | {
2839 | "name": "Sebastian Bergmann",
2840 | "email": "sebastian@phpunit.de"
2841 | },
2842 | {
2843 | "name": "Jeff Welch",
2844 | "email": "whatthejeff@gmail.com"
2845 | },
2846 | {
2847 | "name": "Adam Harvey",
2848 | "email": "aharvey@php.net"
2849 | }
2850 | ],
2851 | "description": "Provides functionality to recursively process PHP variables",
2852 | "homepage": "https://github.com/sebastianbergmann/recursion-context",
2853 | "support": {
2854 | "issues": "https://github.com/sebastianbergmann/recursion-context/issues",
2855 | "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.5"
2856 | },
2857 | "funding": [
2858 | {
2859 | "url": "https://github.com/sebastianbergmann",
2860 | "type": "github"
2861 | }
2862 | ],
2863 | "time": "2023-02-03T06:07:39+00:00"
2864 | },
2865 | {
2866 | "name": "sebastian/resource-operations",
2867 | "version": "3.0.3",
2868 | "source": {
2869 | "type": "git",
2870 | "url": "https://github.com/sebastianbergmann/resource-operations.git",
2871 | "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8"
2872 | },
2873 | "dist": {
2874 | "type": "zip",
2875 | "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8",
2876 | "reference": "0f4443cb3a1d92ce809899753bc0d5d5a8dd19a8",
2877 | "shasum": ""
2878 | },
2879 | "require": {
2880 | "php": ">=7.3"
2881 | },
2882 | "require-dev": {
2883 | "phpunit/phpunit": "^9.0"
2884 | },
2885 | "type": "library",
2886 | "extra": {
2887 | "branch-alias": {
2888 | "dev-master": "3.0-dev"
2889 | }
2890 | },
2891 | "autoload": {
2892 | "classmap": [
2893 | "src/"
2894 | ]
2895 | },
2896 | "notification-url": "https://packagist.org/downloads/",
2897 | "license": [
2898 | "BSD-3-Clause"
2899 | ],
2900 | "authors": [
2901 | {
2902 | "name": "Sebastian Bergmann",
2903 | "email": "sebastian@phpunit.de"
2904 | }
2905 | ],
2906 | "description": "Provides a list of PHP built-in functions that operate on resources",
2907 | "homepage": "https://www.github.com/sebastianbergmann/resource-operations",
2908 | "support": {
2909 | "issues": "https://github.com/sebastianbergmann/resource-operations/issues",
2910 | "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.3"
2911 | },
2912 | "funding": [
2913 | {
2914 | "url": "https://github.com/sebastianbergmann",
2915 | "type": "github"
2916 | }
2917 | ],
2918 | "time": "2020-09-28T06:45:17+00:00"
2919 | },
2920 | {
2921 | "name": "sebastian/type",
2922 | "version": "3.2.1",
2923 | "source": {
2924 | "type": "git",
2925 | "url": "https://github.com/sebastianbergmann/type.git",
2926 | "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7"
2927 | },
2928 | "dist": {
2929 | "type": "zip",
2930 | "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7",
2931 | "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7",
2932 | "shasum": ""
2933 | },
2934 | "require": {
2935 | "php": ">=7.3"
2936 | },
2937 | "require-dev": {
2938 | "phpunit/phpunit": "^9.5"
2939 | },
2940 | "type": "library",
2941 | "extra": {
2942 | "branch-alias": {
2943 | "dev-master": "3.2-dev"
2944 | }
2945 | },
2946 | "autoload": {
2947 | "classmap": [
2948 | "src/"
2949 | ]
2950 | },
2951 | "notification-url": "https://packagist.org/downloads/",
2952 | "license": [
2953 | "BSD-3-Clause"
2954 | ],
2955 | "authors": [
2956 | {
2957 | "name": "Sebastian Bergmann",
2958 | "email": "sebastian@phpunit.de",
2959 | "role": "lead"
2960 | }
2961 | ],
2962 | "description": "Collection of value objects that represent the types of the PHP type system",
2963 | "homepage": "https://github.com/sebastianbergmann/type",
2964 | "support": {
2965 | "issues": "https://github.com/sebastianbergmann/type/issues",
2966 | "source": "https://github.com/sebastianbergmann/type/tree/3.2.1"
2967 | },
2968 | "funding": [
2969 | {
2970 | "url": "https://github.com/sebastianbergmann",
2971 | "type": "github"
2972 | }
2973 | ],
2974 | "time": "2023-02-03T06:13:03+00:00"
2975 | },
2976 | {
2977 | "name": "sebastian/version",
2978 | "version": "3.0.2",
2979 | "source": {
2980 | "type": "git",
2981 | "url": "https://github.com/sebastianbergmann/version.git",
2982 | "reference": "c6c1022351a901512170118436c764e473f6de8c"
2983 | },
2984 | "dist": {
2985 | "type": "zip",
2986 | "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c",
2987 | "reference": "c6c1022351a901512170118436c764e473f6de8c",
2988 | "shasum": ""
2989 | },
2990 | "require": {
2991 | "php": ">=7.3"
2992 | },
2993 | "type": "library",
2994 | "extra": {
2995 | "branch-alias": {
2996 | "dev-master": "3.0-dev"
2997 | }
2998 | },
2999 | "autoload": {
3000 | "classmap": [
3001 | "src/"
3002 | ]
3003 | },
3004 | "notification-url": "https://packagist.org/downloads/",
3005 | "license": [
3006 | "BSD-3-Clause"
3007 | ],
3008 | "authors": [
3009 | {
3010 | "name": "Sebastian Bergmann",
3011 | "email": "sebastian@phpunit.de",
3012 | "role": "lead"
3013 | }
3014 | ],
3015 | "description": "Library that helps with managing the version number of Git-hosted PHP projects",
3016 | "homepage": "https://github.com/sebastianbergmann/version",
3017 | "support": {
3018 | "issues": "https://github.com/sebastianbergmann/version/issues",
3019 | "source": "https://github.com/sebastianbergmann/version/tree/3.0.2"
3020 | },
3021 | "funding": [
3022 | {
3023 | "url": "https://github.com/sebastianbergmann",
3024 | "type": "github"
3025 | }
3026 | ],
3027 | "time": "2020-09-28T06:39:44+00:00"
3028 | },
3029 | {
3030 | "name": "theseer/tokenizer",
3031 | "version": "1.2.1",
3032 | "source": {
3033 | "type": "git",
3034 | "url": "https://github.com/theseer/tokenizer.git",
3035 | "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e"
3036 | },
3037 | "dist": {
3038 | "type": "zip",
3039 | "url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e",
3040 | "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e",
3041 | "shasum": ""
3042 | },
3043 | "require": {
3044 | "ext-dom": "*",
3045 | "ext-tokenizer": "*",
3046 | "ext-xmlwriter": "*",
3047 | "php": "^7.2 || ^8.0"
3048 | },
3049 | "type": "library",
3050 | "autoload": {
3051 | "classmap": [
3052 | "src/"
3053 | ]
3054 | },
3055 | "notification-url": "https://packagist.org/downloads/",
3056 | "license": [
3057 | "BSD-3-Clause"
3058 | ],
3059 | "authors": [
3060 | {
3061 | "name": "Arne Blankerts",
3062 | "email": "arne@blankerts.de",
3063 | "role": "Developer"
3064 | }
3065 | ],
3066 | "description": "A small library for converting tokenized PHP source code into XML and potentially other formats",
3067 | "support": {
3068 | "issues": "https://github.com/theseer/tokenizer/issues",
3069 | "source": "https://github.com/theseer/tokenizer/tree/1.2.1"
3070 | },
3071 | "funding": [
3072 | {
3073 | "url": "https://github.com/theseer",
3074 | "type": "github"
3075 | }
3076 | ],
3077 | "time": "2021-07-28T10:34:58+00:00"
3078 | }
3079 | ],
3080 | "aliases": [],
3081 | "minimum-stability": "stable",
3082 | "stability-flags": [],
3083 | "prefer-stable": false,
3084 | "prefer-lowest": false,
3085 | "platform": {
3086 | "php": "^8.1"
3087 | },
3088 | "platform-dev": [],
3089 | "plugin-api-version": "2.3.0"
3090 | }
3091 |
--------------------------------------------------------------------------------