Completed
Push — master ( 115cf1...6727e2 )
by Anton
03:30
created

ReactionTypeAdd::createReactionType()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 7
dl 0
loc 11
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 2
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}
29
                            {name?}
30
                            {weight?}';
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->resolveWeight());
74
75
        return 0;
76
    }
77
78
    private function createDefaultReactionTypes(): void
79
    {
80
        $types = [
81
            [
82
                'name' => 'Like',
83
                'weight' => 1,
84
            ],
85
            [
86
                'name' => 'Dislike',
87
                'weight' => -1,
88
            ],
89
        ];
90
91
        foreach ($types as $type) {
92
            if ($this->isReactionTypeNameExists($type['name'])) {
93
                continue;
94
            }
95
96
            $this->createReactionType($type['name'], $type['weight']);
97
        }
98
    }
99
100
    private function createReactionType(string $name, int $weight): void
101
    {
102
        ReactionType::query()->create([
103
            'name' => $name,
104
            'weight' => $weight,
105
        ]);
106
107
        $this->line(sprintf(
108
            'Reaction type with name `%s` and weight `%d` was added.',
109
            $name,
110
            $weight
111
        ));
112
    }
113
114
    private function resolveName(): string
115
    {
116
        return $this->argument('name')
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->argument('...?? $this->resolveName() could return the type null|string[] which is incompatible with the type-hinted return string. Consider adding an additional type-check to rule them out.
Loading history...
117
            ?? $this->ask('How to name reaction type?')
118
            ?? $this->resolveName();
119
    }
120
121
    private function resolveWeight(): int
122
    {
123
        return intval($this->argument('weight') ?? $this->ask('What is the weight of this reaction type?'));
124
    }
125
126
    private function sanitizeName(string $name): string
127
    {
128
        $name = trim($name);
129
        $name = Str::studly($name);
130
131
        return $name;
132
    }
133
134
    private function isReactionTypeNameExists(string $name): bool
135
    {
136
        return ReactionType::query()->where('name', $name)->exists();
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...
137
    }
138
139
    private function isNameInvalid(string $name): bool
140
    {
141
        return preg_match('#^[A-Z][a-zA-Z0-9_]*$#', $name) === 0;
142
    }
143
}
144