Completed
Push — master ( 9cf0b1...f9bdca )
by Erik van
01:09
created

PlaybookCommand::isAllowedInProduction()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 10
c 0
b 0
f 0
cc 3
nc 2
nop 0
1
<?php
2
3
namespace Scaling\Playbook\Console;
4
5
use Illuminate\Support\Str;
6
use Scaling\Playbook\Playbook;
7
use Illuminate\Console\Command;
8
use Illuminate\Console\ConfirmableTrait;
9
use Scaling\Playbook\PlaybookDefenition;
10
11
class PlaybookCommand extends Command
12
{
13
    use ConfirmableTrait;
14
15
    /**
16
     * The name and signature of the console command.
17
     *
18
     * @var string
19
     */
20
    protected $signature = 'playbook:run {playbook?}
21
                            {--force : Force the operation to run when in production}';
22
23
    /**
24
     * The console command description.
25
     *
26
     * @var string
27
     */
28
    protected $description = 'Run a predefined playbook to fill your application.';
29
30
    /**
31
     * List of definitions that has been run.
32
     *
33
     * @var array
34
     */
35
    private $ranDefenitions = [];
36
37
    /**
38
     * Execute the console command.
39
     *
40
     * @return mixed
41
     */
42
    public function handle()
43
    {
44
        if (! $this->confirmToProceed()) {
45
            return;
46
        }
47
48
        if (is_null($name = $this->argument('playbook'))) {
49
            $name = $this->askWhichBook($this->getAvailablePlaybooks());
50
        }
51
52
        $this->call('migrate:refresh');
53
54
        $this->runPlaybook($this->resolvePlaybook($name));
0 ignored issues
show
Bug introduced by
It seems like $name defined by $this->argument('playbook') on line 48 can also be of type array; however, Scaling\Playbook\Console...mand::resolvePlaybook() does only seem to accept object<Scaling\Playbook\...ybookDefinition>|string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
55
    }
56
57
    /**
58
     * Run the selected playbook.
59
     *
60
     * @param \Scaling\Playbook\PlaybookDefenition $definition
61
     * @return void
62
     */
63
    private function runPlaybook(PlaybookDefenition $definition): void
64
    {
65
        foreach ($definition->playbook->before() as $book) {
66
            $this->runPlaybook($this->resolvePlaybook($book));
67
        }
68
69
        for ($i = 1; $i <= $definition->times; $i++) {
70
            if ($definition->once && $this->definitionHasRun($definition)) {
71
                continue;
72
            }
73
74
            $name = get_class($definition->playbook);
75
76
            $this->info("Running playbook `{$name}` (#{$i})");
77
78
            $definition->playbook->run($this->input, $this->output);
79
            $definition->playbook->finished();
80
81
            $this->ranDefenitions[$definition->id] = ($this->ranDefenitions[$definition->id] ?? 0) + 1;
82
        }
83
84
        foreach ($definition->playbook->after() as $book) {
85
            $this->runPlaybook($this->resolvePlaybook($book));
86
        }
87
    }
88
89
    /**
90
     * Get a list of available playbooks.
91
     *
92
     * @return array
93
     */
94
    private function getAvailablePlaybooks(): array
95
    {
96
        $files = scandir(config('laravel-playbook.path'));
97
98
        unset($files[0], $files[1]);
99
100
        return array_values(array_map(function (string $fileName) {
101
            return str_replace('.php', '', $fileName);
102
        }, $files));
103
    }
104
105
    /**
106
     * Ask which playbook the developer wants to run.
107
     *
108
     * @param array $available
109
     * @return string
110
     */
111
    private function askWhichBook(array $available): string
112
    {
113
        return $this->choice('Please choose a playbook', $available);
114
    }
115
116
    /**
117
     * Resolve the definition for the given playbook.
118
     *
119
     * @param Scaling\Playbook\Playbook|Scaling\Playbook\PlaybookDefinition|string $class
120
     * @return \Scaling\Playbook\PlaybookDefenition
121
     */
122
    private function resolvePlaybook($class): PlaybookDefenition
123
    {
124
        if ($class instanceof PlaybookDefenition) {
125
            return $class;
126
        }
127
128
        if ($class instanceof Playbook) {
129
            return new PlaybookDefenition(get_class($class));
130
        }
131
132
        $namespace = config('laravel-playbook.namespace');
133
134
        if (! Str::startsWith($class, [$namespace, "\\{$namespace}"])) {
135
            $class = "{$namespace}\\{$class}";
136
        }
137
138
        return new PlaybookDefenition($class);
139
    }
140
141
    /**
142
     * Determine if the given definition has ran before.
143
     *
144
     * @param \Scaling\Playbook\PlaybookDefenition $definition
145
     * @return bool
146
     */
147
    private function definitionHasRun(PlaybookDefenition $definition): bool
148
    {
149
        return isset($this->ranDefenitions[$definition->id]);
150
    }
151
}
152