Completed
Push — master ( d4b169...1f3ead )
by Freek
02:10
created

SyncFile::createOrUpdateHostsFromFile()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 11
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 5
nc 1
nop 1
1
<?php
2
3
namespace Spatie\ServerMonitor\Commands;
4
5
use Spatie\ServerMonitor\Models\Host;
6
use Spatie\ServerMonitor\Models\Check;
7
8
class SyncFile extends BaseCommand
9
{
10
    protected $signature = 'server-monitor:sync-file
11
                            {path : Path to JSON file with hosts}
12
                            {--delete-missing : Delete hosts from the database that are not in the hosts file}';
13
14
    protected $description = 'One way sync hosts from JSON file to database';
15
16
    public function handle()
17
    {
18
        $json = file_get_contents($this->argument('path'));
19
20
        $hostsInFile = collect(json_decode($json, true));
21
22
        $this->createOrUpdateHostsFromFile($hostsInFile);
23
24
        $this->deleteMissingHosts($hostsInFile);
25
    }
26
27
    protected function createOrUpdateHostsFromFile($hostsInFile)
28
    {
29
        $hostsInFile->each(function ($hostAttributes) {
30
31
            $host = $this->createOrUpdateHost($hostAttributes);
32
33
            $this->syncChecks($host, $hostAttributes['checks']);
34
        });
35
36
        $this->info("Synced {$hostsInFile->count()} host(s) to database");
37
    }
38
39
    protected function deleteMissingHosts($hostsInFile)
40
    {
41
        if (!$this->option('delete-missing')) {
42
            return;
43
        }
44
45
        Host::all()
46
            ->reject(function (Host $host) use ($hostsInFile) {
47
                return $hostsInFile->contains('name', $host->name);
0 ignored issues
show
Documentation introduced by
The property name 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...
48
            })
49
            ->each(function (Host $host) {
50
                $this->comment("Deleted host `{$host->name}` from database because was not found in hosts file");
0 ignored issues
show
Documentation introduced by
The property name 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...
51
                $host->delete();
52
            });
53
54
    }
55
56
    protected function createOrUpdateHost(array $hostAttributes): Host
57
    {
58
        unset($hostAttributes['checks']);
59
60
        return tap(Host::firstOrNew([
61
            'name' => $hostAttributes['name'],
62
        ]), function (Host $hostModel) use ($hostAttributes) {
63
            $hostModel
64
                ->fill($hostAttributes)
65
                ->save();
66
        });
67
    }
68
69
    protected function syncChecks(Host $host, array $checkTypes): Host
70
    {
71
        $this->removeChecksNotInArray($host, $checkTypes);
72
73
        $this->addChecksFromArray($host, $checkTypes);
74
75
        return $host;
76
    }
77
78
    protected function removeChecksNotInArray(Host $host, array $checkTypes)
79
    {
80
        $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...
81
            ->filter(function (Check $check) use ($checkTypes) {
82
                return !in_array($check->type, $checkTypes);
0 ignored issues
show
Documentation introduced by
The property type does not exist on object<Spatie\ServerMonitor\Models\Check>. 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...
83
            })
84
            ->each(function (Check $check) use ($host) {
85
                $this->comment("Deleted `{$check->type}` from host `{$host->name}` (not found in hosts file)");
0 ignored issues
show
Documentation introduced by
The property type does not exist on object<Spatie\ServerMonitor\Models\Check>. 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...
Documentation introduced by
The property name 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...
86
                return $check->delete();
87
            });
88
    }
89
90
    protected function addChecksFromArray(Host $host, array $checkTypes)
91
    {
92
        collect($checkTypes)
93
            ->reject(function (string $checkType) use ($host) {
94
                return $host->hasCheckType($checkType);
95
            })
96
            ->each(function (string $checkType) use ($host) {
97
                $host->checks()->create(['type' => $checkType]);
98
            });
99
    }
100
}
101