Passed
Push — master ( 0cf9a8...478c1f )
by Anton
03:37
created

src/Console/Commands/ReactionTypeAdd.php (1 issue)

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\Laravel\Love\ReactionType\Models\ReactionType;
17
use Illuminate\Console\Command;
18
use Illuminate\Support\Str;
19
20
final class ReactionTypeAdd extends Command
21
{
22
    /**
23
     * The name and signature of the console command.
24
     *
25
     * @var string
26
     */
27
    protected $signature = 'love:reaction-type-add
28
                            {--default : Create default Like & Dislike reactions}
29
                            {--name= : The name of the reaction}
30
                            {--mass= : The mass of the reaction}';
31
32
    /**
33
     * The console command description.
34
     *
35
     * @var string
36
     */
37
    protected $description = 'Add Reaction Type to Laravel Love';
38
39
    /**
40
     * Execute the console command.
41
     *
42
     * @return int
43
     */
44
    public function handle(): int
45
    {
46
        if ($this->option('default')) {
47
            $this->createDefaultReactionTypes();
48
49
            return 0;
50
        }
51
52
        $name = $this->resolveName();
53
        $name = $this->sanitizeName($name);
54
55
        if ($this->isNameInvalid($name)) {
56
            $this->error(sprintf(
57
                'Reaction type with name `%s` is invalid.',
58
                $name
59
            ));
60
61
            return 1;
62
        }
63
64
        if ($this->isReactionTypeNameExists($name)) {
65
            $this->error(sprintf(
66
                'Reaction type with name `%s` already exists.',
67
                $name
68
            ));
69
70
            return 1;
71
        }
72
73
        $this->createReactionType($name, $this->resolveMass());
74
75
        return 0;
76
    }
77
78
    private function createDefaultReactionTypes(): void
79
    {
80
        $types = [
81
            [
82
                'name' => 'Like',
83
                'mass' => 1,
84
            ],
85
            [
86
                'name' => 'Dislike',
87
                'mass' => -1,
88
            ],
89
        ];
90
91
        foreach ($types as $type) {
92
            if ($this->isReactionTypeNameExists($type['name'])) {
93
                $this->line(sprintf(
94
                    'Reaction type with name `%s` already exists.',
95
                    $type['name']
96
                ));
97
                continue;
98
            }
99
100
            $this->createReactionType($type['name'], $type['mass']);
101
        }
102
    }
103
104
    private function createReactionType(string $name, int $mass): void
105
    {
106
        ReactionType::query()->create([
107
            'name' => $name,
108
            'mass' => $mass,
109
        ]);
110
111
        $this->line(sprintf(
112
            'Reaction type with name `%s` and mass `%d` was added.',
113
            $name,
114
            $mass
115
        ));
116
    }
117
118
    private function resolveName(): string
119
    {
120
        return $this->option('name')
121
            ?? $this->ask('How to name reaction type?')
122
            ?? '';
123
    }
124
125
    private function resolveMass(): int
126
    {
127
        $mass = $this->option('mass')
128
            ?? $this->ask('What is the mass of this reaction type?')
129
            ?? ReactionType::MASS_DEFAULT;
130
131
        return intval($mass);
132
    }
133
134
    private function sanitizeName(string $name): string
135
    {
136
        $name = trim($name);
137
        $name = Str::studly($name);
138
139
        return $name;
140
    }
141
142
    private function isReactionTypeNameExists(string $name): bool
143
    {
144
        return ReactionType::query()
0 ignored issues
show
Bug Best Practice introduced by
The expression return Cog\Laravel\Love\...name', $name)->exists() could return the type Illuminate\Database\Eloquent\Builder which is incompatible with the type-hinted return boolean. Consider adding an additional type-check to rule them out.
Loading history...
145
            ->where('name', $name)
146
            ->exists();
147
    }
148
149
    private function isNameInvalid(string $name): bool
150
    {
151
        return preg_match('#^[A-Z][a-zA-Z0-9_]*$#', $name) === 0;
152
    }
153
}
154