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

leeqvip / php-apollo / 21236454181

22 Jan 2026 04:48AM UTC coverage: 51.887% (-0.7%) from 52.632%
21236454181

push

github

leeqvip
fix: add get Config instance

0 of 3 new or added lines in 1 file covered. (0.0%)

110 of 212 relevant lines covered (51.89%)

6.11 hits per line

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

26.53
/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
     */
59
    protected function __construct(array $options)
60
    {
61
        $this->options = $options;
6✔
62
        $this->config = new Config();
6✔
63
        $this->client = new Client($options);
6✔
64
        $this->namespaces = $options['namespaces'] ?? $this->namespaces;
6✔
65
        $this->defaultNamespace = count($this->namespaces) > 0 ? $this->namespaces[0] : $this->defaultNamespace;
6✔
66
        $this->cacheDir = $options['cache_dir'] ?? sys_get_temp_dir() . '/apollo';
6✔
67

68
        // Initialize
69
        $this->init();
6✔
70
    }
71

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

86
    /**
87
     * Initialize
88
     *
89
     * @return void
90
     */
91
    protected function init(): void
92
    {
93
        // Ensure cache directory exists
94
        if (!is_dir($this->cacheDir)) {
6✔
95
            mkdir($this->cacheDir, 0755, true);
6✔
96
        }
97
    }
98

99
    public function load(): void
100
    {
101
        // Load local cache
102
        $this->loadCache();
×
103

104
        $this->pullConfigs();
×
105
    }
106

107
    /**
108
     * Pull configurations
109
     *
110
     * @return void
111
     * @throws ApolloException
112
     * @throws GuzzleException
113
     */
114
    public function pullConfigs(): void
115
    {
116
        foreach ($this->namespaces as $namespace) {
×
117
            $configString = $this->client->getConfig($namespace);
×
118
            $config = $this->parse($configString, $namespace);
×
119
            $this->config->setBatch($config, $namespace);
×
120
            $this->saveCache($namespace, $config);
×
121
        }
122
    }
123

124
    protected function parse(string $content, string $namespace): array
125
    {
126
        $parser = Parser::create($namespace);
×
127
        return $parser->parse($content);
×
128
    }
129

130
    /**
131
     *
132
     * Get config instance
133
     *
134
     * @return Config
135
     */
136
    public function getConfig(): Config
137
    {
NEW
138
        return $this->config;
×
139
    }
140

141
    /**
142
     * Get configuration
143
     *
144
     * @param string $key Configuration key
145
     * @param mixed $default Default value
146
     * @param string|null $namespace Namespace
147
     * @return mixed
148
     */
149
    public function get(string $key, mixed $default = null, ?string $namespace = null): mixed
150
    {
151
        return $this->config->get($key, $default, empty($namespace) ? $this->defaultNamespace : $namespace);
6✔
152
    }
153

154
    /**
155
     * Get all configurations
156
     *
157
     * @param string|null $namespace Namespace
158
     * @return array<string, mixed>
159
     */
160
    public function getAll(?string $namespace = null): array
161
    {
162
        return $this->config->getAll(empty($namespace) ? $this->defaultNamespace : $namespace);
×
163
    }
164

165
    /**
166
     * Register configuration change callback
167
     *
168
     * @param callable $callback Callback function
169
     * @param string $namespace Namespace
170
     * @return void
171
     */
172
    public function onUpdate(callable $callback, string $namespace = '*'): void
173
    {
174
        $this->config->registerCallback($callback, $namespace);
×
175
    }
176

177
    /**
178
     * Start listening for configuration changes
179
     *
180
     * @param callable|null $callback Change callback
181
     * @return void
182
     */
183
    public function listen(?callable $callback = null): void
184
    {
185
        while (true) {
×
186
            $notifications = $this->client->listenConfig($this->namespaces);
×
187
            if (!empty($notifications)) {
×
188
                foreach ($notifications as $notification) {
×
189
                    ['namespaceName' => $namespace, 'notificationId' => $notificationId] = $notification;
×
190
                    $config = $this->client->getConfigImmediately($namespace);
×
191

192
                    $this->config->setBatch($config, $namespace);
×
193
                    $this->saveCache($namespace, $config);
×
194
                    // notificationId
195
                    $this->client->setNotificationId($namespace, $notificationId);
×
196

197
                    if ($callback) {
×
198
                        call_user_func($callback, $config, $namespace);
×
199
                    }
200
                }
201
            }
202
        }
203
    }
204

205
    /**
206
     * Load local cache
207
     *
208
     * @return void
209
     */
210
    protected function loadCache(): void
211
    {
212
        foreach ($this->namespaces as $namespace) {
×
213
            $cacheFile = $this->getCacheFile($namespace);
×
214
            if (file_exists($cacheFile)) {
×
215
                $content = file_get_contents($cacheFile);
×
216
                if ($content) {
×
217
                    $config = json_decode($content, true);
×
218
                    if ($config) {
×
219
                        $this->config->setBatch($config, $namespace);
×
220
                    }
221
                }
222
            }
223
        }
224
    }
225

226
    /**
227
     * Save cache
228
     *
229
     * @param string $namespace Namespace
230
     * @param array<string, mixed> $config Configuration
231
     * @return void
232
     */
233
    protected function saveCache(string $namespace, array $config): void
234
    {
235
        $cacheFile = $this->getCacheFile($namespace);
×
236
        file_put_contents($cacheFile, json_encode($config, JSON_UNESCAPED_UNICODE));
×
237
    }
238

239
    /**
240
     * Get cache file path
241
     *
242
     * @param string $namespace Namespace
243
     * @return string
244
     */
245
    protected function getCacheFile(string $namespace): string
246
    {
247
        return $this->cacheDir . '/' . md5($this->options['app_id'] . '_' . $namespace) . '.json';
×
248
    }
249

250
    /**
251
     * Disable cloning
252
     */
253
    public function __clone(): void
254
    {
NEW
255
    }
×
256

257
    /**
258
     * Disable serialization
259
     */
260
    public function __wakeup(): void
261
    {
NEW
262
    }
×
263
}
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