Test Failed
Push — feature-laravel-5.4 ( 91d9b6...3f0a47 )
by Kirill
04:00
created

GitHubDocsImport::getTopLevelHeader()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 5
nc 2
nop 2
dl 0
loc 10
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * This file is part of laravel.su package.
5
 * For the full copyright and license information, please view the LICENSE
6
 * file that was distributed with this source code.
7
 */
8
declare(strict_types=1);
9
10
namespace App\Console\Commands;
11
12
use App\Models\Docs;
13
use Illuminate\Support\Str;
14
use Illuminate\Console\Command;
15
use Illuminate\Support\Collection;
16
use App\Services\GitHub\DocsStatus;
17
use App\Services\GitHub\DocsCollection;
18
use App\Services\GitHub\ExternalDocsPage;
19
use App\Services\GitHub\GitHubDocsManager;
20
use App\Services\GitHub\GitHubConfigRepository;
21
22
/**
23
 * Class GitHubDocsImport.
24
 */
25
class GitHubDocsImport extends Command
26
{
27
    /**
28
     * The name and signature of the console command.
29
     *
30
     * @var string
31
     */
32
    protected $signature = 'docs:import {?--force}';
33
34
    /**
35
     * The console command description.
36
     *
37
     * @var string
38
     */
39
    protected $description = 'Import documentation from GitHub.';
40
41
    /**
42
     * Execute the console command.
43
     *
44
     * @param  GitHubDocsManager                          $manager
45
     * @param  GitHubConfigRepository                     $config
46
     * @return void
47
     * @throws \Github\Exception\ErrorException
48
     * @throws \Github\Exception\InvalidArgumentException
49
     * @throws \RuntimeException
50
     */
51
    public function handle(GitHubDocsManager $manager, GitHubConfigRepository $config): void
52
    {
53
        $exists = $this->getDocsCurrentState(...$config->values());
0 ignored issues
show
Bug introduced by
The call to getDocsCurrentState() misses some required arguments starting with $repo.
Loading history...
Documentation introduced by
$config->values() is of type array, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
54
55
        $files = $this->getFilesForSync($manager, $config, $exists);
0 ignored issues
show
Bug introduced by
It seems like $exists defined by $this->getDocsCurrentState(...$config->values()) on line 53 can also be of type array<integer,object<Ill...base\Eloquent\Builder>>; however, App\Console\Commands\Git...port::getFilesForSync() does only seem to accept object<Illuminate\Support\Collection>, 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...
56
57
        if (count($files) === 0) {
58
            $this->info('Skipping: Documentation are actual.');
59
        } else {
60
            $this->info('Found ' . count($files) . ' new pages.');
61
            $this->info('Start sync progress...');
62
63
            $this->output->progressStart(count($files));
64
65
            $this->sync($files, $manager, $config);
0 ignored issues
show
Compatibility introduced by
$files of type object<Illuminate\Support\Collection> is not a sub-type of object<App\Services\GitHub\DocsCollection>. It seems like you assume a child class of the class Illuminate\Support\Collection to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
66
67
            $this->output->progressFinish();
68
        }
69
70
        $this->info('Completed');
71
        $this->output->newLine();
72
    }
73
74
    /**
75
     * @param  string     $org
76
     * @param  string     $repo
77
     * @param  string     $branch
78
     * @return Collection
79
     */
80
    private function getDocsCurrentState(string $org, string $repo, string $branch)
81
    {
82
        return Docs::query()
83
            ->where('github_org', $org)
84
            ->where('github_repo', $repo)
85
            ->where('github_branch', $branch)
86
            ->get(['github_hash']);
87
    }
88
89
    /**
90
     * @param  GitHubDocsManager                          $manager
91
     * @param  GitHubConfigRepository                     $config
92
     * @param  Collection                                 $exists
93
     * @return Collection|DocsCollection
94
     * @throws \Github\Exception\ErrorException
95
     * @throws \Github\Exception\InvalidArgumentException
96
     * @throws \RuntimeException
97
     */
98
    private function getFilesForSync(GitHubDocsManager $manager, GitHubConfigRepository $config, Collection $exists)
99
    {
100
        $isForce = $this->option('force');
101
102
        return $manager->findFiles(...$config->values())
0 ignored issues
show
Bug introduced by
The call to findFiles() misses some required arguments starting with $repo.
Loading history...
Documentation introduced by
$config->values() is of type array, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
103
            // Remove not updated docs
104
            ->reject(function (DocsStatus $status) use ($exists, $isForce) {
105
                if ($isForce) {
106
                    return false;
107
                }
108
109
                return $exists->where('github_hash', $status->getHash())->first();
110
            });
111
    }
112
113
    /**
114
     * @param  DocsCollection                             $files
115
     * @param  GitHubDocsManager                          $manager
116
     * @param  GitHubConfigRepository                     $config
117
     * @throws \Github\Exception\ErrorException
118
     * @throws \Github\Exception\InvalidArgumentException
119
     */
120
    private function sync(DocsCollection $files, GitHubDocsManager $manager, GitHubConfigRepository $config): void
121
    {
122
        /** @var DocsStatus $status */
123
        foreach ($files as $status) {
124
            $args = $config->values();
125
            $args[] = $status->getPath();
126
127
            /** @var ExternalDocsPage $page */
128
            $page = $manager->import(...$args);
0 ignored issues
show
Bug introduced by
The call to import() misses some required arguments starting with $repo.
Loading history...
Documentation introduced by
$args is of type array<integer,?>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
129
130
            $docs = $this->getDocsModel(...$args);
0 ignored issues
show
Bug introduced by
The call to getDocsModel() misses some required arguments starting with $repo.
Loading history...
Documentation introduced by
$args is of type array<integer,?>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
131
132
            $docs->content_source = $page->getContent();
133
            $docs->github_hash = $status->getHash();
134
135
            if (! $docs->category_id) {
136
                $docs->category_id = 0; // TODO
137
            }
138
139
            if (! $docs->title) {
140
                $docs->title = $this->getTopLevelHeader($page->getUrl(), $page->getContent());
141
                $docs->slug  = $page->getUrl();
142
            }
143
144
            $docs->save();
145
146
            $this->output->progressAdvance();
147
            $this->output->write(sprintf(' <info>Synchronizing "%s" page</info>', $docs->title));
148
        }
149
    }
150
151
    /**
152
     * @param string $url
153
     * @param string $markdown
154
     * @return string
155
     */
156
    private function getTopLevelHeader(string $url, string $markdown)
157
    {
158
        preg_match_all('/^\s*#\s+(.*?)$/mius', $markdown, $matches);
159
160
        if (count($matches[1])) {
161
            return Str::ucfirst($matches[1][0]);
162
        }
163
164
        return Str::ucfirst(str_replace(['-', '_', '+'], ' ', urldecode($url)));
165
    }
166
167
    /**
168
     * @param  string                                   $org
169
     * @param  string                                   $repo
170
     * @param  string                                   $branch
171
     * @param  string                                   $file
172
     * @return \Illuminate\Database\Eloquent\Model|Docs
173
     */
174
    private function getDocsModel(string $org, string $repo, string $branch, string $file)
175
    {
176
        return Docs::query()
177
            ->firstOrNew([
178
                'github_org'    => $org,
179
                'github_repo'   => $repo,
180
                'github_branch' => $branch,
181
                'github_file'   => $file,
182
            ]);
183
    }
184
}
185