Completed
Pull Request — master (#6)
by
unknown
02:20
created

ListHosts   A

Complexity

Total Complexity 7

Size/Duplication

Total Lines 80
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Importance

Changes 0
Metric Value
wmc 7
lcom 1
cbo 4
dl 0
loc 80
rs 10
c 0
b 0
f 0

4 Methods

Rating   Name   Duplication   Size   Complexity  
B handle() 0 26 3
A renderTable() 0 16 1
A formatCheckStatusCountForHost() 0 15 2
A formatCheckMessagesForHost() 0 11 1
1
<?php
2
3
namespace Spatie\ServerMonitor\Commands;
4
5
use Spatie\ServerMonitor\Models\Enums\CheckStatus;
6
use Spatie\ServerMonitor\Models\Host;
7
8
class ListHosts extends BaseCommand
9
{
10
    protected $signature = 'monitor:list
11
                            {--host= : Filter hosts by name}
12
                            {--check= : Filter checks by type}';
13
14
    protected $description = 'List all hosts with their checks';
15
16
    public function handle()
17
    {
18
        $hostName = $this->option('host');
19
        $checkType = $this->option('check');
20
21
        $hostsQuery = Host::query();
22
23
        if ($hostName) {
24
            $hostsQuery->where('name', 'LIKE', "%{$hostName}%");
25
        }
26
27
        if ($checkType) {
28
            $hostsQuery
0 ignored issues
show
Bug introduced by
The method with does only exist in Illuminate\Database\Eloquent\Builder, but not in Illuminate\Database\Eloq...ns\QueriesRelationships.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
29
                ->whereHas('checks', function ($query) use ($checkType) {
30
                    $query->where('type', 'LIKE', "%{$checkType}%");
31
                })
32
                ->with(['checks' => function ($query) use ($checkType) {
33
                    $query->where('type', 'LIKE', "%{$checkType}%");
34
                }]);
35
        }
36
37
        $hosts = $hostsQuery->get();
38
39
        $this->renderTable($hosts);
40
41
    }
42
43
    protected function renderTable($hosts)
44
    {
45
        $rows = $hosts->map(function ($host) {
46
            $name = $host->name;
47
48
            $checks = $this->formatCheckStatusCountForHost($host);
49
50
            $messages = $this->formatCheckMessagesForHost($host);
51
52
            return compact('name', 'checks', 'messages');
53
        });
54
55
        $header = ['Host', 'Checks', 'Message'];
56
57
        $this->table($header, $rows);
58
    }
59
60
    protected function formatCheckStatusCountForHost (Host $host): string
61
    {
62
        $statuses = collect([CheckStatus::SUCCESS, CheckStatus::FAILED, CheckStatus::NOT_YET_CHECKED, CheckStatus::WARNING]);
63
64
        $checks = $statuses
65
            ->map(function ($status) use ($host) {
66
                $checksWithStatus = $host->checks->where('status', $status);
0 ignored issues
show
Documentation introduced by
The property checks does not exist on object<Spatie\ServerMonitor\Models\Host>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
67
                $statusCount = $checksWithStatus->count();
68
                $emoji = $checksWithStatus->first()->statusAsEmoji ?? '';
69
70
                return $statusCount ? "{$emoji} {$statusCount}  " : '';
71
            })
72
            ->implode('');
73
        return substr($checks, 0, -2);
74
    }
75
76
    protected function formatCheckMessagesForHost(Host $host): string
77
    {
78
        return $host->checks
0 ignored issues
show
Documentation introduced by
The property checks does not exist on object<Spatie\ServerMonitor\Models\Host>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
79
            ->filter(function ($check) {
80
                return !empty($check->message);
81
            })
82
            ->map(function ($check) {
83
                return "<fg=black;bg=cyan>{$check->type}</>: {$check->message}";
84
            })
85
            ->implode("\n");
86
    }
87
}
88