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

leeqvip / php-apollo / 21240912360

22 Jan 2026 08:10AM UTC coverage: 47.727% (-4.2%) from 51.887%
21240912360

push

github

leeqvip
feat: add clearCache

3 of 22 new or added lines in 3 files covered. (13.64%)

11 existing lines in 2 files now uncovered.

105 of 220 relevant lines covered (47.73%)

5.37 hits per line

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

5.17
/src/Apollo.php
1
<?php
2

3
declare(strict_types=1);
4

5
namespace Leeqvip\Apollo;
6

7
use GuzzleHttp\Exception\GuzzleException;
8
use Leeqvip\Apollo\Exceptions\ApolloException;
9
use Leeqvip\Apollo\Parsers\Parser;
10

11
/**
12
 * Apollo client core class
13
 */
14
class Apollo
15
{
16
    /**
17
     * Instance
18
     * @var Apollo|null
19
     */
20
    protected static ?Apollo $instance = null;
21

22
    /**
23
     * Configuration management
24
     * @var Config
25
     */
26
    protected Config $config;
27

28
    /**
29
     * Apollo server communication client
30
     * @var Client
31
     */
32
    protected Client $client;
33

34
    /**
35
     * Configuration
36
     * @var array<string, mixed>
37
     */
38
    protected array $options;
39

40
    /**
41
     * Namespace list
42
     * @var array<string>
43
     */
44
    protected array $namespaces = ['application'];
45

46
    protected string $defaultNamespace = 'application';
47

48
    /**
49
     * Cache directory
50
     * @var string
51
     */
52
    protected string $cacheDir;
53

54
    /**
55
     * Constructor
56
     *
57
     * @param array<string, mixed> $options Configuration parameters
58
     * @throws ApolloException
59
     * @throws GuzzleException
60
     */
61
    protected function __construct(array $options)
62
    {
UNCOV
63
        $this->options = $options;
×
UNCOV
64
        $this->config = new Config();
×
UNCOV
65
        $this->client = new Client($options);
×
UNCOV
66
        $this->namespaces = $options['namespaces'] ?? $this->namespaces;
×
UNCOV
67
        $this->defaultNamespace = count($this->namespaces) > 0 ? $this->namespaces[0] : $this->defaultNamespace;
×
UNCOV
68
        $this->cacheDir = $options['cache_dir'] ?? sys_get_temp_dir() . '/apollo';
×
69

70
        // Initialize
UNCOV
71
        $this->init();
×
72
    }
73

74
    /**
75
     * Get instance (singleton pattern)
76
     *
77
     * @param array<string, mixed> $options Configuration parameters
78
     * @return Apollo
79
     * @throws ApolloException|GuzzleException
80
     */
81
    public static function getInstance(array $options = []): Apollo
82
    {
83
        if (!self::$instance) {
12✔
UNCOV
84
            self::$instance = new self($options);
×
85
        }
86
        return self::$instance;
12✔
87
    }
88

89
    /**
90
     * Initialize
91
     * @return void
92
     * @throws ApolloException|GuzzleException
93
     */
94
    private function init(): void
95
    {
96
        // Ensure cache directory exists
UNCOV
97
        if (!is_dir($this->cacheDir)) {
×
UNCOV
98
            mkdir($this->cacheDir, 0755, true);
×
99
        }
NEW
100
        $this->loadOrPull();
×
101
    }
102

103
    /**
104
     * @throws GuzzleException
105
     * @throws ApolloException
106
     */
107
    private function loadOrPull(): void
108
    {
109
        // Load cache
NEW
110
        if ($this->loadCache()) {
×
NEW
111
            return;
×
112
        }
113

114
        $this->pullConfigs();
×
115
    }
116

117
    /**
118
     * @throws ApolloException
119
     * @throws GuzzleException
120
     */
121
    public function pull(): void
122
    {
NEW
123
        $this->pullConfigs();
×
124
    }
125

126
    /**
127
     * Pull configurations
128
     *
129
     * @return void
130
     * @throws ApolloException
131
     * @throws GuzzleException
132
     */
133
    protected function pullConfigs(): void
134
    {
135
        foreach ($this->namespaces as $namespace) {
×
136
            $configString = $this->client->getConfig($namespace);
×
137
            $config = $this->parse($configString, $namespace);
×
138
            $this->config->setBatch($config, $namespace);
×
139
            $this->saveCache($namespace, $config);
×
140
        }
141
    }
142

143
    protected function parse(string $content, string $namespace): array
144
    {
145
        $parser = Parser::create($namespace);
×
146
        return $parser->parse($content);
×
147
    }
148

149
    /**
150
     *
151
     * Get config instance
152
     *
153
     * @return Config
154
     */
155
    public function getConfig(): Config
156
    {
157
        return $this->config;
×
158
    }
159

160
    /**
161
     * Get configuration
162
     *
163
     * @param string $key Configuration key
164
     * @param mixed $default Default value
165
     * @param string|null $namespace Namespace
166
     * @return mixed
167
     */
168
    public function get(string $key, mixed $default = null, ?string $namespace = null): mixed
169
    {
170
        return $this->config->get($key, $default, empty($namespace) ? $this->defaultNamespace : $namespace);
6✔
171
    }
172

173
    /**
174
     * Get all configurations
175
     *
176
     * @param string|null $namespace Namespace
177
     * @return array<string, mixed>
178
     */
179
    public function all(?string $namespace = null): array
180
    {
NEW
181
        return $this->config->all(empty($namespace) ? $this->defaultNamespace : $namespace);
×
182
    }
183

184
    /**
185
     * Register configuration change callback
186
     *
187
     * @param callable $callback Callback function
188
     * @param string $namespace Namespace
189
     * @return void
190
     */
191
    public function onUpdate(callable $callback, string $namespace = '*'): void
192
    {
193
        $this->config->registerCallback($callback, $namespace);
×
194
    }
195

196
    /**
197
     * Start listening for configuration changes
198
     *
199
     * @param callable|null $callback Change callback
200
     * @return void
201
     */
202
    public function listen(?callable $callback = null): void
203
    {
204
        while (true) {
×
205
            $notifications = $this->client->listenConfig($this->namespaces);
×
206
            if (!empty($notifications)) {
×
207
                foreach ($notifications as $notification) {
×
208
                    ['namespaceName' => $namespace, 'notificationId' => $notificationId] = $notification;
×
209
                    $config = $this->client->getConfigImmediately($namespace);
×
210

211
                    $this->config->setBatch($config, $namespace);
×
212
                    $this->saveCache($namespace, $config);
×
213
                    // notificationId
214
                    $this->client->setNotificationId($namespace, $notificationId);
×
215

216
                    if ($callback) {
×
217
                        call_user_func($callback, $config, $namespace);
×
218
                    }
219
                }
220
            }
221
        }
222
    }
223

224
    /**
225
     * Load from local cache
226
     *
227
     * @return bool
228
     */
229
    protected function loadCache(): bool
230
    {
231
        foreach ($this->namespaces as $namespace) {
×
232
            $cacheFile = $this->getCacheFile($namespace);
×
NEW
233
            if (!file_exists($cacheFile)) {
×
NEW
234
                return false;
×
235
            }
NEW
236
            $config = require $cacheFile;
×
NEW
237
            if (!is_array($config)) {
×
NEW
238
                return false;
×
239
            }
NEW
240
            $this->config->setBatch($config, $namespace);
×
241
        }
242

NEW
243
        return true;
×
244
    }
245

246
    /**
247
     * Save cache
248
     *
249
     * @param string $namespace Namespace
250
     * @param array<string, mixed> $config Configuration
251
     * @return void
252
     */
253
    protected function saveCache(string $namespace, array $config): void
254
    {
255
        $cacheFile = $this->getCacheFile($namespace);
×
NEW
256
        $content = "<?php\n\nreturn " . var_export($config, true) . ";\n";
×
NEW
257
        file_put_contents($cacheFile, $content);
×
258
    }
259

260
    /**
261
     * @param string $namespace
262
     * @return void
263
     */
264
    public function removeCache(string $namespace = '*'): void
265
    {
NEW
266
        foreach ($this->namespaces as $namespace) {
×
NEW
267
            $cacheFile = $this->getCacheFile($namespace);
×
NEW
268
            if (file_exists($cacheFile)) {
×
NEW
269
                unlink($cacheFile);
×
270
            }
271
        }
272
    }
273

274
    /**
275
     * Get cache file path
276
     *
277
     * @param string $namespace Namespace
278
     * @return string
279
     */
280
    protected function getCacheFile(string $namespace): string
281
    {
NEW
282
        return $this->cacheDir . '/' . md5($this->options['app_id'] . '_' . $namespace) . '.php';
×
283
    }
284

285
    /**
286
     * Disable cloning
287
     */
288
    public function __clone(): void
289
    {
290
    }
×
291

292
    /**
293
     * Disable serialization
294
     */
295
    public function __wakeup(): void
296
    {
297
    }
×
298
}
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