$class */
55 | $class = $fullQualifiedName;
56 |
57 | $methods = ['create', 'update', 'delete'];
58 |
59 | $method = $this->option('method') ?? $this->choice(
60 | 'For which event do you want to create the webhook?',
61 | $methods,
62 | 'update',
63 | );
64 |
65 | if (!in_array($method, $methods, true)) {
66 | $this->error((new InvalidWebhookMethodException())->getMessage());
67 |
68 | return self::FAILURE;
69 | }
70 |
71 | $mappedMethod = match ($method) {
72 | 'create' => Method::CREATE,
73 | 'update' => Method::UPDATE,
74 | 'delete' => Method::DELETE,
75 | };
76 |
77 | try {
78 | $class::createWebhook($mappedMethod);
79 | } catch (Exception $e) {
80 | $this->error($e->getMessage());
81 |
82 | return self::FAILURE;
83 | }
84 |
85 | $this->info('Webhook created successfully!');
86 |
87 | return self::SUCCESS;
88 | }
89 |
90 | private function getModels(): array
91 | {
92 | $glob = glob(__DIR__ . '/../Models/*.php') ?: [];
93 |
94 | $pattern = '/\/(?:Model|PopularityPrimitive|Search|Webhook|Image)\.php$/';
95 | $grep = preg_grep($pattern, $glob, PREG_GREP_INVERT);
96 |
97 | return collect($grep ?: [])
98 | ->map(static fn (string $path): string => basename($path, '.php'))
99 | ->toArray();
100 | }
101 |
102 | private function getClosestModel(string $model): ?string
103 | {
104 | return collect($this->getModels())->map(static fn (string $m): array => [
105 | 'model' => $m,
106 | 'levenshtein' => levenshtein($m, $model),
107 | ])
108 | ->filter(static fn (array $m) => $m['levenshtein'] <= 5)
109 | ->sortBy(static fn (array $m) => $m['levenshtein'])
110 | ->map(static fn (array $m) => $m['model'])
111 | ->first();
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Laravel IGDB Wrapper
2 |
3 |
4 | This is a Laravel wrapper for version 4 of the IGDB API (Apicalypse)
5 | including webhook handling.
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 | ## Basic installation
38 |
39 | You can install this package via composer using:
40 |
41 | ```bash
42 | composer require marcreichel/igdb-laravel
43 | ```
44 |
45 | The package will automatically register its service provider.
46 |
47 | To publish the config file to `config/igdb.php` run:
48 |
49 | ```bash
50 | php artisan igdb:publish
51 | ```
52 |
53 | This is the default content of the config file:
54 |
55 | ```php
56 | return [
57 | /*
58 | * These are the credentials you got from https://dev.twitch.tv/console/apps
59 | */
60 | 'credentials' => [
61 | 'client_id' => env('TWITCH_CLIENT_ID', ''),
62 | 'client_secret' => env('TWITCH_CLIENT_SECRET', ''),
63 | ],
64 |
65 | /*
66 | * This package caches queries automatically (for 1 hour per default).
67 | * Here you can set how long each query should be cached (in seconds).
68 | *
69 | * To turn cache off set this value to 0
70 | */
71 | 'cache_lifetime' => env('IGDB_CACHE_LIFETIME', 3600),
72 |
73 | /**
74 | * The prefix used to cache the results.
75 | *
76 | * E.g.: `[CACHE_PREFIX].75170fc230cd88f32e475ff4087f81d9`
77 | */
78 | 'cache_prefix' => 'igdb_cache',
79 |
80 | /*
81 | * Path where the webhooks should be handled.
82 | */
83 | 'webhook_path' => 'igdb-webhook/handle',
84 |
85 | /*
86 | * The webhook secret.
87 | *
88 | * This needs to be a string of your choice in order to use the webhook
89 | * functionality.
90 | */
91 | 'webhook_secret' => env('IGDB_WEBHOOK_SECRET', null),
92 | ];
93 | ```
94 |
95 | ## Documentation
96 |
97 | You will find the full documentation on [the dedicated documentation site](https://marcreichel.dev/docs/igdb-laravel).
98 |
99 | ## Testing
100 |
101 | Run the tests with:
102 |
103 | ```bash
104 | composer test
105 | ```
106 |
107 | ## Contribution
108 |
109 | Pull requests are welcome :)
110 |
--------------------------------------------------------------------------------
/pint.json:
--------------------------------------------------------------------------------
1 | {
2 | "preset": "psr12",
3 | "rules": {
4 | "align_multiline_comment": true,
5 | "array_indentation": true,
6 | "array_push": true,
7 | "array_syntax": {
8 | "syntax": "short"
9 | },
10 | "assign_null_coalescing_to_coalesce_equal": true,
11 | "binary_operator_spaces": true,
12 | "blank_line_before_statement": true,
13 | "cast_spaces": true,
14 | "clean_namespace": true,
15 | "combine_consecutive_issets": true,
16 | "combine_consecutive_unsets": true,
17 | "compact_nullable_typehint": true,
18 | "concat_space": {
19 | "spacing": "one"
20 | },
21 | "declare_strict_types": true,
22 | "fully_qualified_strict_types": true,
23 | "function_to_constant": true,
24 | "general_phpdoc_annotation_remove": {
25 | "annotations": [
26 | "author",
27 | "package",
28 | "since"
29 | ],
30 | "case_sensitive": false
31 | },
32 | "get_class_to_class_keyword": true,
33 | "is_null": true,
34 | "lambda_not_used_import": true,
35 | "logical_operators": true,
36 | "method_chaining_indentation": true,
37 | "modernize_types_casting": true,
38 | "multiline_whitespace_before_semicolons": true,
39 | "no_empty_comment": true,
40 | "no_empty_phpdoc": true,
41 | "no_empty_statement": true,
42 | "no_extra_blank_lines": {
43 | "tokens": ["attribute", "break", "case", "continue", "curly_brace_block", "default", "extra", "parenthesis_brace_block", "return", "square_brace_block", "switch", "throw", "use", "use_trait"]
44 | },
45 | "no_multiline_whitespace_around_double_arrow": true,
46 | "no_short_bool_cast": true,
47 | "no_singleline_whitespace_before_semicolons": true,
48 | "no_superfluous_elseif": true,
49 | "no_superfluous_phpdoc_tags": true,
50 | "no_trailing_comma_in_singleline": true,
51 | "no_unneeded_control_parentheses": true,
52 | "no_useless_concat_operator": true,
53 | "no_useless_else": true,
54 | "no_useless_nullsafe_operator": true,
55 | "no_useless_return": true,
56 | "no_whitespace_before_comma_in_array": true,
57 | "nullable_type_declaration": true,
58 | "object_operator_without_whitespace": true,
59 | "ordered_imports": {
60 | "imports_order": [
61 | "class",
62 | "function",
63 | "const"
64 | ],
65 | "sort_algorithm": "alpha"
66 | },
67 | "ordered_interfaces": true,
68 | "ordered_types": {
69 | "null_adjustment": "always_last"
70 | },
71 | "phpdoc_align": {
72 | "align": "left"
73 | },
74 | "phpdoc_indent": true,
75 | "phpdoc_no_useless_inheritdoc": true,
76 | "phpdoc_order": true,
77 | "phpdoc_scalar": true,
78 | "phpdoc_single_line_var_spacing": true,
79 | "phpdoc_separation": {
80 | "groups": [
81 | [
82 | "deprecated",
83 | "link",
84 | "see"
85 | ],
86 | [
87 | "template",
88 | "template-extends",
89 | "template-implements"
90 | ]
91 | ]
92 | },
93 | "phpdoc_summary": true,
94 | "phpdoc_tag_casing": true,
95 | "phpdoc_trim": true,
96 | "phpdoc_trim_consecutive_blank_line_separation": true,
97 | "phpdoc_var_without_name": true,
98 | "php_unit_construct": true,
99 | "php_unit_dedicate_assert": true,
100 | "php_unit_dedicate_assert_internal_type": true,
101 | "php_unit_internal_class": true,
102 | "php_unit_method_casing": true,
103 | "return_assignment": true,
104 | "return_type_declaration": true,
105 | "short_scalar_cast": true,
106 | "single_line_comment_spacing": true,
107 | "single_line_comment_style": true,
108 | "single_quote": true,
109 | "single_space_around_construct": true,
110 | "ternary_to_null_coalescing": true,
111 | "trailing_comma_in_multiline": {
112 | "elements": [
113 | "arguments",
114 | "arrays",
115 | "match",
116 | "parameters"
117 | ]
118 | },
119 | "trim_array_spaces": true,
120 | "type_declaration_spaces": true,
121 | "types_spaces": {
122 | "space": "single"
123 | },
124 | "use_arrow_functions": true,
125 | "void_return": true,
126 | "whitespace_after_comma_in_array": {
127 | "ensure_single_space": true
128 | }
129 | }
130 | }
131 |
--------------------------------------------------------------------------------
/tests/ImageTest.php:
--------------------------------------------------------------------------------
1 | Http::response([
34 | [
35 | 'id' => 1,
36 | 'alpha_channel' => false,
37 | 'animated' => false,
38 | 'checksum' => 'abc',
39 | 'height' => 100,
40 | 'image_id' => 'abc',
41 | 'url' => '//images.igdb.com/igdb/image/upload/t_thumb/abc.jpg',
42 | 'width' => 100,
43 | ],
44 | ]),
45 | ]);
46 | }
47 |
48 | public static function imageSizeDataProvider(): array
49 | {
50 | $enumCases = collect(Size::cases())
51 | ->map(static fn (Size $size) => [$size, $size->value])
52 | ->toArray();
53 | $stringCases = collect(Size::cases())
54 | ->map(static fn (Size $size) => [$size->value, $size->value])
55 | ->toArray();
56 |
57 | return array_merge($enumCases, $stringCases);
58 | }
59 |
60 | public function testArtworkShouldBeMappedAsInstanceOfImage(): void
61 | {
62 | self::assertInstanceOf(Image::class, Artwork::first());
63 | }
64 |
65 | public function testCharacterMugShotShouldBeMappedAsInstanceOfImage(): void
66 | {
67 | self::assertInstanceOf(Image::class, CharacterMugShot::first());
68 | }
69 |
70 | public function testCompanyLogoShouldBeMappedAsInstanceOfImage(): void
71 | {
72 | self::assertInstanceOf(Image::class, CompanyLogo::first());
73 | }
74 |
75 | public function testCoverShouldBeMappedAsInstanceOfImage(): void
76 | {
77 | self::assertInstanceOf(Image::class, Cover::first());
78 | }
79 |
80 | public function testGameEngineLogoShouldBeMappedAsInstanceOfImage(): void
81 | {
82 | self::assertInstanceOf(Image::class, GameEngineLogo::first());
83 | }
84 |
85 | public function testPlatformLogoShouldBeMappedAsInstanceOfImage(): void
86 | {
87 | self::assertInstanceOf(Image::class, PlatformLogo::first());
88 | }
89 |
90 | public function testScreenshotShouldBeMappedAsInstanceOfImage(): void
91 | {
92 | self::assertInstanceOf(Image::class, Screenshot::first());
93 | }
94 |
95 | public function testItShouldGenerateDefaultImageUrlWithoutAttributes(): void
96 | {
97 | $url = Artwork::first()?->getUrl();
98 |
99 | self::assertEquals('//images.igdb.com/igdb/image/upload/t_thumb/abc.jpg', $url);
100 | }
101 |
102 | #[DataProvider('imageSizeDataProvider')]
103 | public function testItShouldGenerateDesiredImageUrlWithParameter(Size | string $size, string $value): void
104 | {
105 | $url = Artwork::first()?->getUrl($size);
106 |
107 | self::assertEquals('//images.igdb.com/igdb/image/upload/t_' . $value . '/abc.jpg', $url);
108 | }
109 |
110 | #[DataProvider('imageSizeDataProvider')]
111 | public function testItShouldGenerateRetinaImageUrl(Size | string $size, string $value): void
112 | {
113 | $url = Artwork::first()?->getUrl($size, true);
114 |
115 | self::assertEquals('//images.igdb.com/igdb/image/upload/t_' . $value . '_2x/abc.jpg', $url);
116 | }
117 |
118 | public function testItShouldThrowExceptionWithInvalidImageSize(): void
119 | {
120 | $this->expectException(InvalidArgumentException::class);
121 |
122 | Artwork::first()?->getUrl('foo');
123 | }
124 | }
125 |
--------------------------------------------------------------------------------
/docs/06-where-clauses.md:
--------------------------------------------------------------------------------
1 | # Where clauses
2 |
3 | ## Simple where clause
4 |
5 | ```php
6 | // torchlight! {"lineNumbers": false}
7 | use MarcReichel\IGDBLaravel\Models\Game;
8 |
9 | $games = Game::where('first_release_date', '>=', now()->subMonth())
10 | ->get();
11 | ```
12 |
13 | > **Please note**: `Carbon` objects are supported since v3.4.0.
14 |
15 | For convenience, if you want to verify that a column is equal to a given value, you may pass the value directly as the
16 | second argument to the `where` method:
17 |
18 | ```php
19 | // torchlight! {"lineNumbers": false}
20 | use MarcReichel\IGDBLaravel\Models\Game;
21 |
22 | $games = Game::where('name', 'Fortnite')->get();
23 |
24 | // this is the same as
25 |
26 | $games = Game::where('name', '=', 'Fortnite')->get();
27 | ```
28 |
29 | ## OR statements
30 |
31 | You may chain where constraints together as well as add `or` clauses to the query. The `orWhere` method accepts the same
32 | arguments as the where method:
33 |
34 | ```php
35 | // torchlight! {"lineNumbers": false}
36 | use MarcReichel\IGDBLaravel\Models\Game;
37 |
38 | $games = Game::where('name', 'Fortnite')
39 | ->orWhere('name', 'Borderlands 2')
40 | ->get();
41 | ```
42 |
43 | ## Additional Where Clauses
44 |
45 | ### whereBetween
46 |
47 | The `whereBetween` method verifies that a fields's value is between two values:
48 |
49 | ```php
50 | // torchlight! {"lineNumbers": false}
51 | use MarcReichel\IGDBLaravel\Models\Game;
52 |
53 | $games = Game::whereBetween('first_release_date', now()->subYear(), now())
54 | ->get();
55 | ```
56 |
57 | > **Please note**: `Carbon` objects are supported since v3.4.0.
58 |
59 | ### whereNotBetween
60 |
61 | The `whereNotBetween` method verifies that a field's value lies outside of two
62 | values:
63 |
64 | ```php
65 | // torchlight! {"lineNumbers": false}
66 | use MarcReichel\IGDBLaravel\Models\Game;
67 |
68 | $games = Game::whereNotBetween('first_release_date', now()->subYear(), now())
69 | ->get();
70 | ```
71 |
72 | > **Please note**: `Carbon` objects are supported since v3.4.0.
73 |
74 | ### whereIn
75 |
76 | The `whereIn` method verifies that a given field's value is contained within the
77 | given array:
78 |
79 | ```php
80 | // torchlight! {"lineNumbers": false}
81 | use MarcReichel\IGDBLaravel\Models\Game;
82 |
83 | $games = Game::whereIn('category', [0,4])->get();
84 | ```
85 |
86 | ### whereNotIn
87 |
88 | The `whereNotIn` method verifies that the given field's value is **not**
89 | contained in the given array:
90 |
91 | ```php
92 | // torchlight! {"lineNumbers": false}
93 | use MarcReichel\IGDBLaravel\Models\Game;
94 |
95 | $games = Game::whereNotIn('category', [0,4])->get();
96 | ```
97 |
98 | ### whereInAll / whereNotInAll / whereInExact / whereNotInExact
99 |
100 | Alternatively you could use one of these methods to match against **all** or **exactly** the given array.
101 |
102 | ### whereNull
103 |
104 | The `whereNull` method verifies that the value of the given field is `NULL`:
105 |
106 | ```php
107 | // torchlight! {"lineNumbers": false}
108 | use MarcReichel\IGDBLaravel\Models\Game;
109 |
110 | $games = Game::whereNull('first_release_date')->get();
111 | ```
112 |
113 | ### whereNotNull
114 |
115 | The `whereNotNull` method verifies that the field's value is **not** `NULL`:
116 |
117 | ```php
118 | // torchlight! {"lineNumbers": false}
119 | use MarcReichel\IGDBLaravel\Models\Game;
120 |
121 | $games = Game::whereNotNull('first_release_date')->get();
122 | ```
123 |
124 | ### whereDate
125 |
126 | The `whereDate` method may be used to compare a field's value against a date:
127 |
128 | ```php
129 | // torchlight! {"lineNumbers": false}
130 | use MarcReichel\IGDBLaravel\Models\Game;
131 |
132 | $games = Game::whereDate('first_release_date', '2019-01-01')
133 | ->get();
134 | ```
135 |
136 | ### whereYear
137 |
138 | The `whereYear` method may be used to compare a fields's value against a specific
139 | year:
140 |
141 | ```php
142 | // torchlight! {"lineNumbers": false}
143 | use MarcReichel\IGDBLaravel\Models\Game;
144 |
145 | $games = Game::whereYear('first_release_date', 2019)
146 | ->get();
147 | ```
148 |
149 | ### whereHas / whereHasNot
150 |
151 | These methods have the same syntax as `whereNull` and `whereNotNull` and literally
152 | do the exact same thing.
153 |
154 | ## Parameter Grouping
155 |
156 | ```php
157 | // torchlight! {"lineNumbers": false}
158 | use MarcReichel\IGDBLaravel\Models\Game;
159 |
160 | $games = Game::where('name', 'Fortnite')
161 | ->orWhere(function($query) {
162 | $query->where('aggregated_rating', '>=', 90)
163 | ->where('aggregated_rating_count', '>=', 3000);
164 | })
165 | ->get();
166 | ```
167 |
--------------------------------------------------------------------------------
/src/Traits/HasWhere.php:
--------------------------------------------------------------------------------
1 | whereNested($key, $boolean);
35 | }
36 |
37 | if (is_array($key)) {
38 | return $this->addArrayOfWheres($key, $boolean);
39 | }
40 |
41 | if (!is_string($key)) {
42 | throw new InvalidArgumentException('Parameter #1 $key needs to be string. ' . gettype($key) . ' given.');
43 | }
44 |
45 | [$value, $operator] = $this->prepareValueAndOperator(
46 | $value,
47 | $operator,
48 | func_num_args() === 2,
49 | );
50 |
51 | $select = $this->query->get('fields', new Collection());
52 | if (!$select->contains($key) && !$select->contains('*')) {
53 | $this->query->put('fields', $select->push($key));
54 | }
55 |
56 | $where = $this->query->get('where', new Collection());
57 |
58 | if (collect($this->dates)->has($key) && $this->dates[$key] === 'date') {
59 | $value = $this->castDate($value);
60 | }
61 |
62 | if (is_string($value)) {
63 | if ($operator === 'like') {
64 | $this->whereLike($key, $value, true, $boolean);
65 | } elseif ($operator === 'ilike') {
66 | $this->whereLike($key, $value, false, $boolean);
67 | } elseif ($operator === 'not like') {
68 | $this->whereNotLike($key, $value, true, $boolean);
69 | } elseif ($operator === 'not ilike') {
70 | $this->whereNotLike($key, $value, false, $boolean);
71 | } else {
72 | $where->push(($where->count() ? $boolean . ' ' : '') . $key . ' ' . $operator . ' "' . $value . '"');
73 | $this->query->put('where', $where);
74 | }
75 | } else {
76 | $value = !is_int($value) ? json_encode($value, JSON_THROW_ON_ERROR) : $value;
77 | $where->push(($where->count() ? $boolean . ' ' : '') . $key . ' ' . $operator . ' ' . $value);
78 | $this->query->put('where', $where);
79 | }
80 |
81 | return $this;
82 | }
83 |
84 | /**
85 | * Add an "or where" clause to the query.
86 | *
87 | * @throws ReflectionException
88 | * @throws JsonException
89 | * @throws InvalidParamsException
90 | */
91 | public function orWhere(
92 | mixed $key,
93 | ?string $operator = null,
94 | mixed $value = null,
95 | string $boolean = '|',
96 | ): self {
97 | if ($key instanceof Closure) {
98 | return $this->whereNested($key, $boolean);
99 | }
100 |
101 | if (is_array($key)) {
102 | return $this->addArrayOfWheres($key, $boolean);
103 | }
104 |
105 | [$value, $operator] = $this->prepareValueAndOperator(
106 | $value,
107 | $operator,
108 | func_num_args() === 2,
109 | );
110 |
111 | return $this->where($key, $operator, $value, $boolean);
112 | }
113 |
114 | /**
115 | * Add an array of where clauses to the query.
116 | *
117 | * @throws ReflectionException
118 | * @throws InvalidParamsException
119 | */
120 | protected function addArrayOfWheres(
121 | array $arrayOfWheres,
122 | string $boolean,
123 | string $method = 'where',
124 | ): self {
125 | return $this->whereNested(static function (Builder $query) use (
126 | $arrayOfWheres,
127 | $method,
128 | $boolean
129 | ): void {
130 | foreach ($arrayOfWheres as $key => $value) {
131 | if (is_numeric($key) && is_array($value)) {
132 | $query->$method(...array_values($value));
133 | } else {
134 | $query->$method($key, '=', $value, $boolean);
135 | }
136 | }
137 | }, $boolean);
138 | }
139 | }
140 |
--------------------------------------------------------------------------------
/docs/90-webhooks.md:
--------------------------------------------------------------------------------
1 | # Webhooks
2 |
3 | Since version 2.3.0 of this package you can create webhooks and handle their requests with ease. 🎉
4 |
5 | ## Initial Setup
6 |
7 | ### Configuration
8 |
9 | Inside your `config/igdb.php` file you need to have a `webhook_path` and `webhook_secret` of your choice like so:
10 |
11 | ```php
12 | // torchlight! {"lineNumbers": false}
13 | // torchlight! {"summaryCollapsedIndicator": "⌄"}
14 | [
22 | 'client_id' => env('TWITCH_CLIENT_ID', ''),
23 | 'client_secret' => env('TWITCH_CLIENT_SECRET', ''),
24 | ],
25 |
26 | /*
27 | * This package caches queries automatically (for 1 hour per default).
28 | * Here you can set how long each query should be cached (in seconds).
29 | *
30 | * To turn cache off set this value to 0
31 | */
32 | 'cache_lifetime' => env('IGDB_CACHE_LIFETIME', 3600), // [tl! collapse:end]
33 |
34 | /*
35 | * Path where the webhooks should be handled.
36 | */
37 | 'webhook_path' => 'igdb-webhook/handle',
38 |
39 | /*
40 | * The webhook secret.
41 | *
42 | * This needs to be a string of your choice in order to use the webhook
43 | * functionality.
44 | */
45 | 'webhook_secret' => env('IGDB_WEBHOOK_SECRET'),
46 | ];
47 | ```
48 |
49 | _**Please note**: You only need to add this part to your config if you have upgraded from a prior version of this
50 | package. New installations have this configured automatically._
51 |
52 | And then set a secret inside your `.env` file:
53 |
54 | ```dotenv
55 | // torchlight! {"lineNumbers": false}
56 | IGDB_WEBHOOK_SECRET=yoursecret
57 | ```
58 |
59 | > Make sure your `APP_URL` (inside your `.env`) is something different than `localhost` or `127.0.0.1`. Otherwise webhooks can
60 | > not be created.
61 |
62 | That's it!
63 |
64 | ## Create a webhook
65 |
66 | Let's say we want to be informed whenever a new game is created on https://igdb.com.
67 |
68 | First of all we need to inform IGDB that we want to be informed.
69 |
70 | For this we create a webhook like so (for example inside a controller):
71 |
72 | ```php
73 | // torchlight! {"lineNumbers": false}
74 | use MarcReichel\IGDBLaravel\Enums\Webhook\Method;
75 | use MarcReichel\IGDBLaravel\Models\Game;
76 | use Illuminate\Routing\Controller;
77 |
78 | class ExampleController extends Controller
79 | {
80 | public function createWebhook()
81 | {
82 | Game::createWebhook(Method::CREATE)
83 | }
84 | }
85 | ```
86 |
87 | ## Listen for events
88 |
89 | Now that we have created our webhook we can listen for a specific event - in our case when a game is created.
90 |
91 | For this we create a Laravel EventListener or for sake of simplicity we just listen for an event inside the `boot()`
92 | method of our `app/providers/EventServiceProvider.php`:
93 |
94 | ```php
95 | // torchlight! {"lineNumbers": false}
96 | use MarcReichel\IGDBLaravel\Events\GameCreated;
97 | use Illuminate\Support\Facades\Event;
98 |
99 | public function boot()
100 | {
101 | Event::listen(function (GameCreated $event) {
102 | // $event->data holds the (unexpanded!) data (of the game in this case)
103 | });
104 | }
105 | ```
106 |
107 | [Here](https://github.com/marcreichel/igdb-laravel/tree/main/src/Events) you can find a list of all available events.
108 |
109 | Further information on how to set up event listeners can be found on
110 | the [official docs](https://laravel.com/docs/events).
111 |
112 | ## Manage webhooks via CLI
113 |
114 | ### List your webhooks
115 |
116 | ```bash
117 | // torchlight! {"lineNumbers": false}
118 | $ php artisan igdb:webhooks
119 | ```
120 |
121 | ### Create a webhook
122 |
123 | ```bash
124 | // torchlight! {"lineNumbers": false}
125 | $ php artisan igdb:webhooks:create {model?} {--method=}
126 | ```
127 |
128 | You can also just call `php artisan igdb:webhooks:create` without any arguments. The command will then ask for the
129 | required data interactively.
130 |
131 | The `model` parameter needs to be the (studly cased) class name of a model (e.g. `Game`).
132 |
133 | The `--method` option needs to be one of `create`, `update` or `delete` accordingly for which event you want to listen.
134 |
135 | ### Reactivate a webhook
136 |
137 | ```bash
138 | // torchlight! {"lineNumbers": false}
139 | $ php artisan igdb:webhooks:reactivate {id}
140 | ```
141 |
142 | For `{id}` insert the id of the (inactive) webhook.
143 |
144 | ### Delete a webhook
145 |
146 | ```bash
147 | // torchlight! {"lineNumbers": false}
148 | $ php artisan igdb:webhooks:delete {id?} {--A|all}
149 | ```
150 |
151 | You may provide the `id` of a webhook to delete it or use the `-A`/`--all` flag to delete all your registered webhooks.
152 |
--------------------------------------------------------------------------------
/src/Traits/HasWhereDate.php:
--------------------------------------------------------------------------------
1 | prepareValueAndOperator(
28 | $value,
29 | $operator,
30 | func_num_args() === 2,
31 | );
32 |
33 | $start = Carbon::parse($value)->startOfDay()->timestamp;
34 | $end = Carbon::parse($value)->endOfDay()->timestamp;
35 |
36 | return match ($operator) {
37 | '>' => $this->whereDateGreaterThan($key, $operator, $value, $boolean),
38 | '>=' => $this->whereDateGreaterThanOrEquals($key, $operator, $value, $boolean),
39 | '<' => $this->whereDateLowerThan($key, $operator, $value, $boolean),
40 | '<=' => $this->whereDateLowerThanOrEquals($key, $operator, $value, $boolean),
41 | '!=' => $this->whereNotBetween($key, $start, $end, false, $boolean),
42 | default => $this->whereBetween($key, $start, $end, true, $boolean),
43 | };
44 | }
45 |
46 | /**
47 | * @throws JsonException
48 | * @throws ReflectionException
49 | * @throws InvalidParamsException
50 | */
51 | private function whereDateGreaterThan(string $key, mixed $operator, mixed $value, string $boolean): self
52 | {
53 | if (is_string($value) || $value instanceof DateTimeInterface) {
54 | $value = Carbon::parse($value)->addDay()->startOfDay()->timestamp;
55 | }
56 |
57 | return $this->where($key, $operator, $value, $boolean);
58 | }
59 |
60 | /**
61 | * @throws JsonException
62 | * @throws ReflectionException
63 | * @throws InvalidParamsException
64 | */
65 | private function whereDateGreaterThanOrEquals(string $key, mixed $operator, mixed $value, string $boolean): self
66 | {
67 | if (is_string($value) || $value instanceof DateTimeInterface) {
68 | $value = Carbon::parse($value)->startOfDay()->timestamp;
69 | }
70 |
71 | return $this->where($key, $operator, $value, $boolean);
72 | }
73 |
74 | /**
75 | * @throws JsonException
76 | * @throws ReflectionException
77 | * @throws InvalidParamsException
78 | */
79 | private function whereDateLowerThan(string $key, mixed $operator, mixed $value, string $boolean): self
80 | {
81 | if (is_string($value) || $value instanceof DateTimeInterface) {
82 | $value = Carbon::parse($value)->subDay()->endOfDay()->timestamp;
83 | }
84 |
85 | return $this->where($key, $operator, $value, $boolean);
86 | }
87 |
88 | /**
89 | * @throws JsonException
90 | * @throws ReflectionException
91 | * @throws InvalidParamsException
92 | */
93 | private function whereDateLowerThanOrEquals(string $key, mixed $operator, mixed $value, string $boolean): self
94 | {
95 | if (is_string($value) || $value instanceof DateTimeInterface) {
96 | $value = Carbon::parse($value)->endOfDay()->timestamp;
97 | }
98 |
99 | return $this->where($key, $operator, $value, $boolean);
100 | }
101 |
102 | /**
103 | * Add an "or where date" statement to the query.
104 | *
105 | * @throws ReflectionException
106 | * @throws JsonException
107 | * @throws InvalidParamsException
108 | */
109 | public function orWhereDate(string $key, mixed $operator, mixed $value = null, string $boolean = '|'): self
110 | {
111 | return $this->whereDate($key, $operator, $value, $boolean);
112 | }
113 |
114 | /**
115 | * Add a "where year" statement to the query.
116 | *
117 | * @throws ReflectionException
118 | * @throws JsonException
119 | * @throws InvalidParamsException
120 | */
121 | public function whereYear(string $key, mixed $operator, mixed $value = null, string $boolean = '&'): self
122 | {
123 | [$value, $operator] = $this->prepareValueAndOperator(
124 | $value,
125 | $operator,
126 | func_num_args() === 2,
127 | );
128 |
129 | $value = Carbon::now()->setYear($value)->startOfYear();
130 |
131 | if ($operator === '=') {
132 | $start = $value->clone()->startOfYear()->timestamp;
133 | $end = $value->clone()->endOfYear()->timestamp;
134 |
135 | return $this->whereBetween($key, $start, $end, true, $boolean);
136 | }
137 |
138 | if ($operator === '>' || $operator === '<=') {
139 | $value = $value->clone()->endOfYear()->timestamp;
140 | } elseif ($operator === '>=' || $operator === '<') {
141 | $value = $value->clone()->startOfYear()->timestamp;
142 | }
143 |
144 | return $this->where($key, $operator, $value, $boolean);
145 | }
146 |
147 | /**
148 | * Add an "or where year" statement to the query.
149 | *
150 | * @throws ReflectionException
151 | * @throws JsonException
152 | * @throws InvalidParamsException
153 | */
154 | public function orWhereYear(string $key, mixed $operator, mixed $value = null, string $boolean = '|'): self
155 | {
156 | [$value, $operator] = $this->prepareValueAndOperator(
157 | $value,
158 | $operator,
159 | func_num_args() === 2,
160 | );
161 |
162 | return $this->whereYear($key, $operator, $value, $boolean);
163 | }
164 | }
165 |
--------------------------------------------------------------------------------