• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

visavi / rotor / 26723576697

31 May 2026 08:27PM UTC coverage: 14.172% (-0.4%) from 14.618%
26723576697

push

github

visavi
Перенес файлы обновлений бд в отдельную папку

785 of 5539 relevant lines covered (14.17%)

1.26 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/app/Models/ModuleRegistry.php
1
<?php
2

3
declare(strict_types=1);
4

5
namespace App\Models;
6

7
use Illuminate\Database\Eloquent\Model;
8
use Illuminate\Support\Facades\Http;
9

10
/**
11
 * @property int                 $id
12
 * @property string              $url
13
 * @property string              $name
14
 * @property bool                $active
15
 * @property array               $cached_data
16
 * @property \Carbon\Carbon|null $cached_at
17
 * @property \Carbon\Carbon      $created_at
18
 * @property \Carbon\Carbon      $updated_at
19
 */
20
class ModuleRegistry extends Model
21
{
22
    protected $guarded = [];
23

24
    protected function casts(): array
×
25
    {
26
        return [
×
27
            'active'      => 'bool',
×
28
            'cached_data' => 'array',
×
29
            'cached_at'   => 'datetime',
×
30
        ];
×
31
    }
32

33
    /**
34
     * Fetches the data from the registry.
35
     */
36
    public bool $fetchFailed = false;
37

38
    public function fetch(bool $force = false): array
×
39
    {
40
        $ttl = 3600;
×
41

42
        if (! $force && $this->cached_data && $this->cached_at?->gt(now()->subSeconds($ttl))) {
×
43
            return $this->cached_data;
×
44
        }
45

46
        try {
47
            $response = Http::timeout(10)->get($this->url);
×
48

49
            if (! $response->ok()) {
×
50
                return $this->markFailed();
×
51
            }
52

53
            $data = $response->json();
×
54

55
            if (! is_array($data)) {
×
56
                return $this->markFailed();
×
57
            }
58

59
            $this->update([
×
60
                'name'        => $data['name'] ?? $this->name,
×
61
                'cached_data' => $data,
×
62
                'cached_at'   => now(),
×
63
            ]);
×
64

65
            return $data;
×
66
        } catch (\Exception) {
×
67
            return $this->markFailed();
×
68
        }
69
    }
70

71
    /**
72
     * Помечает реестр недоступным и продлевает кэш, чтобы не опрашивать его каждый запрос.
73
     */
74
    private function markFailed(): array
×
75
    {
76
        $this->fetchFailed = true;
×
77
        $this->update(['cached_at' => now()]);
×
78

79
        return $this->cached_data ?? [];
×
80
    }
81

82
    /**
83
     * Returns an array of available modules.
84
     */
85
    public static function getAvailableModules(bool $force = false): array
×
86
    {
87
        $registries = self::query()->where('active', true)->get();
×
88
        $modules = [];
×
89

90
        foreach ($registries as $registry) {
×
91
            $data = $registry->fetch($force);
×
92
            $registryLabel = $registry->name ?: $registry->url;
×
93

94
            foreach ($data['modules'] ?? [] as $module) {
×
95
                if (! isset($module['module'])) {
×
96
                    continue;
×
97
                }
98

99
                $name = $module['module'];
×
100

101
                if (isset($modules[$name])) {
×
102
                    $modules[$name]['conflict'][] = $registryLabel;
×
103
                    continue;
×
104
                }
105

106
                $versions = $module['versions'] ?? [];
×
107
                $best = self::bestCompatibleVersion($versions);
×
108
                $latest = $versions[0] ?? [];
×
109
                $version = $best ?? $latest;
×
110

111
                $extra = ['registry' => $registryLabel, 'conflict' => []];
×
112

113
                if ($best && isset($latest['version']) && version_compare($latest['version'], $best['version'], '>')) {
×
114
                    $extra['latest_version'] = $latest['version'];
×
115
                    $extra['latest_requires'] = $latest['requires'] ?? null;
×
116
                }
117

118
                $modules[$name] = array_merge(
×
119
                    array_diff_key($module, ['versions' => true]),
×
120
                    $version,
×
121
                    $extra,
×
122
                );
×
123
            }
124
        }
125

126
        return $modules;
×
127
    }
128

129
    /**
130
     * Returns the best compatible version of a module.
131
     */
132
    private static function bestCompatibleVersion(array $versions): ?array
×
133
    {
134
        $compatible = array_filter(
×
135
            $versions,
×
136
            static fn (array $v) => empty($v['requires']) || version_compare(ROTOR_VERSION, $v['requires'], '>='),
×
137
        );
×
138

139
        if (empty($compatible)) {
×
140
            return null;
×
141
        }
142

143
        usort($compatible, static fn ($a, $b) => version_compare($b['version'], $a['version']));
×
144

145
        return $compatible[0];
×
146
    }
147
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc