Completed
Push — master ( 69fccb...ece5bb )
by David
11:52 queued 34s
created

BaseValidatorCommand::compileRowsFromSource()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 6
nc 1
nop 1
dl 0
loc 8
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
namespace App\Commands;
4
5
use Carbon\Carbon;
6
use App\PhoneNumberValidator;
7
use Illuminate\Support\Collection;
8
use Illuminate\Support\Facades\File;
9
use LaravelZero\Framework\Commands\Command;
10
use Symfony\Component\Console\Exception\RuntimeException;
11
12
abstract class BaseValidatorCommand extends Command
13
{
14
    /**
15
     * @var mixed
16
     */
17
    protected $source;
18
19
    /**
20
     * Make a validator for a given number.
21
     *
22
     * @param  mixed $number
23
     * @return App\PhoneNumberValidator
0 ignored issues
show
Bug introduced by
The type App\Commands\App\PhoneNumberValidator was not found. Did you mean App\PhoneNumberValidator? If so, make sure to prefix the type with \.
Loading history...
24
     */
25
    abstract public function makeValidatorForNumer($number): PhoneNumberValidator;
26
27
    /**
28
     * Is the number valid?
29
     *
30
     * @param  App\PhoneNumberValidator $validator
31
     * @return bool
32
     */
33
    abstract public function isNumberValid(PhoneNumberValidator $validator): bool;
34
35
    /**
36
     * Create a new command instance.
37
     *
38
     * @return void
39
     */
40
    public function __construct()
41
    {
42
        parent::__construct();
43
44
        $date = Carbon::now()->format('Ymd_his');
45
        $rand = mb_strtolower(str_random(6));
46
47
        $this->fileName = $date.'-'.$rand.'.csv';
0 ignored issues
show
Bug Best Practice introduced by
The property fileName does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
48
        $this->outputPath = base_path('output');
0 ignored issues
show
Bug Best Practice introduced by
The property outputPath does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
49
    }
50
51
    /**
52
     * Execute the console command.
53
     *
54
     * @return mixed
55
     */
56
    public function handle(): void
57
    {
58
        $this->setSource();
59
        $this->validateOutputPath();
60
61
        $this->buildCsvFromRows(
62
            $this->compileRowsFromSource($this->source)
63
        );
64
65
        $this->info('Total: '.count($this->source));
66
        $this->info('Filename: '.$this->fileName);
67
    }
68
69
    /**
70
     * Build a CSV from the rows.
71
     *
72
     * @param  Collection $rows
73
     * @return void
74
     */
75
    protected function buildCsvFromRows(Collection $rows)
76
    {
77
        File::put(
78
            $this->outputPath.'/'.$this->fileName,
79
            implode("\n", $rows->toArray())
80
        );
81
    }
82
83
    /**
84
     * Process a list of numbers.
85
     *
86
     * @param array $source
87
     * @return Illuminate\Support\Collection
0 ignored issues
show
Bug introduced by
The type App\Commands\Illuminate\Support\Collection was not found. Did you mean Illuminate\Support\Collection? If so, make sure to prefix the type with \.
Loading history...
88
     */
89
    protected function compileRowsFromSource(array $source): Collection
90
    {
91
        return collect($source)
92
            ->map([$this, 'makeValidatorForNumer'])
93
            ->map([$this, 'buildRowFromValidator'])
94
            ->prepend(['phone number', 'carrier', 'status'])
95
            ->map(function ($row) {
96
                return implode(',', $row);
97
            });
98
    }
99
100
    /**
101
     * Build a row.
102
     *
103
     * @param  App\PhoneNumberValidator $validator
104
     * @return array
105
     */
106
    public function buildRowFromValidator(PhoneNumberValidator $validator): array
107
    {
108
        $row = [$validator->getNumber(), '', 'not valid'];
0 ignored issues
show
Bug introduced by
The method getNumber() does not exist on App\PhoneNumberValidator. Since it exists in all sub-types, consider adding an abstract or default implementation to App\PhoneNumberValidator. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

108
        $row = [$validator->/** @scrutinizer ignore-call */ getNumber(), '', 'not valid'];
Loading history...
109
110
        if ($this->isNumberValid($validator)) {
111
            $row[1] = $validator->getCarrierName();
112
            $row[2] = 'valid';
113
        }
114
115
        return $row;
116
    }
117
118
    /**
119
     * Set the source.
120
     */
121
    protected function setSource(): void
122
    {
123
        $this->source = $this->option('file')
124
            ? $this->getSourceFromFile($this->argument('source'))
125
            : array_wrap($this->argument('source'));
126
127
        $this->info('Source valid: '.($this->option('file') ? 'File' : 'List'));
128
    }
129
130
    /**
131
     * Return the contents of the source file.
132
     *
133
     * @return array
134
     */
135
    protected function getSourceFromFile($file): array
136
    {
137
        $file = head(array_wrap($file));
138
139
        throw_unless(
140
            File::exists($file),
141
            RuntimeException::class,
142
            "Source does not exist [{$file}]"
0 ignored issues
show
Bug introduced by
EncapsedNode of type string is incompatible with the type array expected by parameter $parameters of throw_unless(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

142
            /** @scrutinizer ignore-type */ "Source does not exist [{$file}]"
Loading history...
143
        );
144
145
        return array_wrap(explode("\n", File::get($file)));
146
    }
147
148
    /**
149
     * Set the output path.
150
     */
151
    protected function validateOutputPath(): void
152
    {
153
        if ($this->option('output')) {
154
            $this->outputPath = $this->option('output');
0 ignored issues
show
Bug Best Practice introduced by
The property outputPath does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
155
        }
156
157
        throw_unless(
158
            is_dir($this->outputPath),
0 ignored issues
show
Bug introduced by
It seems like $this->outputPath can also be of type array; however, parameter $filename of is_dir() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

158
            is_dir(/** @scrutinizer ignore-type */ $this->outputPath),
Loading history...
159
            RuntimeException::class,
160
            "The output path does not exist [{$this->outputPath}]"
0 ignored issues
show
Bug introduced by
EncapsedNode of type string is incompatible with the type array expected by parameter $parameters of throw_unless(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

160
            /** @scrutinizer ignore-type */ "The output path does not exist [{$this->outputPath}]"
Loading history...
161
        );
162
    }
163
}
164