1 | <?php |
||||
2 | |||||
3 | /* |
||||
4 | * This file is part of Laravel Love. |
||||
5 | * |
||||
6 | * (c) Anton Komarev <[email protected]> |
||||
7 | * |
||||
8 | * For the full copyright and license information, please view the LICENSE |
||||
9 | * file that was distributed with this source code. |
||||
10 | */ |
||||
11 | |||||
12 | declare(strict_types=1); |
||||
13 | |||||
14 | namespace Cog\Laravel\Love\Console\Commands; |
||||
15 | |||||
16 | use Cog\Contracts\Love\Reacterable\Exceptions\ReacterableInvalid; |
||||
17 | use Cog\Contracts\Love\Reacterable\Models\Reacterable as ReacterableInterface; |
||||
18 | use Illuminate\Console\Command; |
||||
19 | use Illuminate\Database\Eloquent\Collection; |
||||
20 | use Illuminate\Database\Eloquent\Relations\Relation; |
||||
21 | use Symfony\Component\Console\Attribute\AsCommand; |
||||
22 | use Symfony\Component\Console\Input\InputOption; |
||||
23 | |||||
24 | #[AsCommand(name: 'love:register-reacters', description: 'Register Reacterable models as Reacters')] |
||||
25 | final class RegisterReacters extends Command |
||||
26 | { |
||||
27 | /** |
||||
28 | * @return array<int, InputOption> |
||||
29 | */ |
||||
30 | protected function getOptions(): array |
||||
31 | { |
||||
32 | return [ |
||||
33 | new InputOption( |
||||
34 | name: 'model', |
||||
35 | mode: InputOption::VALUE_REQUIRED, |
||||
36 | description: 'The name of the Reacterable model', |
||||
37 | ), |
||||
38 | new InputOption( |
||||
39 | name: 'ids', |
||||
40 | mode: InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, |
||||
41 | description: '(optional) Comma-separated list of model IDs (e.g. `--ids=1,2,16,34`)', |
||||
42 | ), |
||||
43 | ]; |
||||
44 | } |
||||
45 | |||||
46 | /** |
||||
47 | * Execute the console command. |
||||
48 | */ |
||||
49 | public function handle(): int |
||||
50 | { |
||||
51 | $reacterableType = $this->option('model'); |
||||
52 | if ($reacterableType === null) { |
||||
53 | $this->error('Option `--model` is required!'); |
||||
54 | |||||
55 | return self::FAILURE; |
||||
56 | } |
||||
57 | |||||
58 | try { |
||||
59 | $reacterableModel = $this->reacterableModelFromType($reacterableType); |
||||
60 | |||||
61 | $modelIds = $this->option('ids'); |
||||
62 | $modelIds = $this->normalizeIds($modelIds); |
||||
0 ignored issues
–
show
Bug
introduced
by
Loading history...
|
|||||
63 | |||||
64 | $models = $this->collectModels($reacterableModel, $modelIds); |
||||
65 | |||||
66 | $this->info(sprintf('Models registering as Reacters %s', PHP_EOL)); |
||||
67 | $this->line(sprintf('Model Type: <fg=Cyan>%s</>', get_class($reacterableModel))); |
||||
68 | |||||
69 | $this->registerModelsAsReacters($models); |
||||
70 | |||||
71 | $this->info('Models has been registered as Reacters'); |
||||
72 | } catch (ReacterableInvalid $exception) { |
||||
73 | $this->error($exception->getMessage()); |
||||
74 | |||||
75 | return self::FAILURE; |
||||
76 | } |
||||
77 | |||||
78 | return self::SUCCESS; |
||||
79 | } |
||||
80 | |||||
81 | /** |
||||
82 | * Instantiate model from type or morph map value. |
||||
83 | * |
||||
84 | * @param string $modelType |
||||
85 | * @return \Cog\Contracts\Love\Reacterable\Models\Reacterable|\Illuminate\Database\Eloquent\Model |
||||
86 | * |
||||
87 | * @throws \Cog\Contracts\Love\Reacterable\Exceptions\ReacterableInvalid |
||||
88 | */ |
||||
89 | private function reacterableModelFromType( |
||||
90 | string $modelType, |
||||
91 | ): ReacterableInterface { |
||||
92 | if (!class_exists($modelType)) { |
||||
93 | $modelType = $this->findModelTypeInMorphMap($modelType); |
||||
94 | } |
||||
95 | |||||
96 | $model = new $modelType(); |
||||
97 | |||||
98 | if (!$model instanceof ReacterableInterface) { |
||||
99 | throw ReacterableInvalid::notImplementInterface($modelType); |
||||
100 | } |
||||
101 | |||||
102 | return $model; |
||||
103 | } |
||||
104 | |||||
105 | /** |
||||
106 | * Find model type in morph mappings registry. |
||||
107 | * |
||||
108 | * @throws \Cog\Contracts\Love\Reacterable\Exceptions\ReacterableInvalid |
||||
109 | */ |
||||
110 | private function findModelTypeInMorphMap( |
||||
111 | string $modelType, |
||||
112 | ): string { |
||||
113 | $morphMap = Relation::morphMap(); |
||||
114 | |||||
115 | if (!isset($morphMap[$modelType])) { |
||||
116 | throw ReacterableInvalid::classNotExists($modelType); |
||||
117 | } |
||||
118 | |||||
119 | return $morphMap[$modelType]; |
||||
120 | } |
||||
121 | |||||
122 | private function normalizeIds( |
||||
123 | array $modelIds, |
||||
124 | ): array { |
||||
125 | if (!isset($modelIds[0])) { |
||||
126 | return $modelIds; |
||||
127 | } |
||||
128 | |||||
129 | $firstItem = $modelIds[0]; |
||||
130 | |||||
131 | if (is_string($firstItem) && strpos($firstItem, ',')) { |
||||
132 | $modelIds = explode(',', $firstItem); |
||||
133 | } |
||||
134 | |||||
135 | return $modelIds; |
||||
136 | } |
||||
137 | |||||
138 | /** |
||||
139 | * @param \Cog\Contracts\Love\Reacterable\Models\Reacterable|\Illuminate\Database\Eloquent\Model $reacterableModel |
||||
140 | * @param array $modelIds |
||||
141 | * @return Collection |
||||
142 | */ |
||||
143 | private function collectModels( |
||||
144 | ReacterableInterface $reacterableModel, |
||||
145 | array $modelIds, |
||||
146 | ): Collection { |
||||
147 | $query = $reacterableModel |
||||
148 | ->query() |
||||
0 ignored issues
–
show
The method
query() does not exist on Cog\Contracts\Love\Reacterable\Models\Reacterable . Since it exists in all sub-types, consider adding an abstract or default implementation to Cog\Contracts\Love\Reacterable\Models\Reacterable .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||
149 | ->whereNull('love_reacter_id'); |
||||
150 | |||||
151 | if (!empty($modelIds)) { |
||||
152 | $query->whereKey($modelIds); |
||||
153 | } |
||||
154 | |||||
155 | return $query->get(); |
||||
156 | } |
||||
157 | |||||
158 | private function registerModelsAsReacters( |
||||
159 | Collection $models, |
||||
160 | ): void { |
||||
161 | $collectedCount = $models->count(); |
||||
162 | $progressBar = $this->output->createProgressBar($collectedCount); |
||||
163 | |||||
164 | foreach ($models as $model) { |
||||
165 | $model->registerAsLoveReacter(); |
||||
166 | $progressBar->advance(); |
||||
167 | } |
||||
168 | |||||
169 | $progressBar->finish(); |
||||
170 | $this->line(PHP_EOL); |
||||
171 | } |
||||
172 | } |
||||
173 |