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

leeqvip / php-apollo / 21219920138

21 Jan 2026 05:48PM UTC coverage: 52.607%. First build
21219920138

push

github

leeqvip
feat: first commit

111 of 211 new or added lines in 9 files covered. (52.61%)

111 of 211 relevant lines covered (52.61%)

6.17 hits per line

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

27.66
/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
NEW
102
        $this->loadCache();
×
103

NEW
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
    {
NEW
116
        foreach ($this->namespaces as $namespace) {
×
NEW
117
            $configString = $this->client->getConfig($namespace);
×
NEW
118
            $config = $this->parse($configString, $namespace);
×
NEW
119
            var_dump($configString);
×
120
            //            var_dump($config);die;
NEW
121
            $this->config->setBatch($config, $namespace);
×
NEW
122
            $this->saveCache($namespace, $config);
×
123
        }
124
    }
125

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

132
    /**
133
     * Get configuration
134
     *
135
     * @param string $key Configuration key
136
     * @param mixed $default Default value
137
     * @param string|null $namespace Namespace
138
     * @return mixed
139
     */
140
    public function get(string $key, mixed $default = null, ?string $namespace = null): mixed
141
    {
142
        return $this->config->get($key, $default, empty($namespace) ? $this->defaultNamespace : $namespace);
6✔
143
    }
144

145
    /**
146
     * Get all configurations
147
     *
148
     * @param string|null $namespace Namespace
149
     * @return array<string, mixed>
150
     */
151
    public function getAll(?string $namespace = null): array
152
    {
NEW
153
        return $this->config->getAll(empty($namespace) ? $this->defaultNamespace : $namespace);
×
154
    }
155

156
    /**
157
     * Register configuration change callback
158
     *
159
     * @param callable $callback Callback function
160
     * @param string $namespace Namespace
161
     * @return void
162
     */
163
    public function onUpdate(callable $callback, string $namespace = '*'): void
164
    {
NEW
165
        $this->config->registerCallback($callback, $namespace);
×
166
    }
167

168
    /**
169
     * Start listening for configuration changes
170
     *
171
     * @param callable|null $callback Change callback
172
     * @return void
173
     */
174
    public function listen(?callable $callback = null): void
175
    {
NEW
176
        while (true) {
×
NEW
177
            $notifications = $this->client->listenConfig($this->namespaces);
×
NEW
178
            if (!empty($notifications)) {
×
NEW
179
                foreach ($notifications as $notification) {
×
NEW
180
                    ['namespaceName' => $namespace, 'notificationId' => $notificationId] = $notification;
×
NEW
181
                    $config = $this->client->getConfigImmediately($namespace);
×
182

NEW
183
                    $this->config->setBatch($config, $namespace);
×
NEW
184
                    $this->saveCache($namespace, $config);
×
185
                    // notificationId
NEW
186
                    $this->client->setNotificationId($namespace, $notificationId);
×
187

NEW
188
                    if ($callback) {
×
NEW
189
                        call_user_func($callback, $config, $namespace);
×
190
                    }
191
                }
192
            }
193
        }
194
    }
195

196
    /**
197
     * Load local cache
198
     *
199
     * @return void
200
     */
201
    protected function loadCache(): void
202
    {
NEW
203
        foreach ($this->namespaces as $namespace) {
×
NEW
204
            $cacheFile = $this->getCacheFile($namespace);
×
NEW
205
            if (file_exists($cacheFile)) {
×
NEW
206
                $content = file_get_contents($cacheFile);
×
NEW
207
                if ($content) {
×
NEW
208
                    $config = json_decode($content, true);
×
NEW
209
                    if ($config) {
×
NEW
210
                        $this->config->setBatch($config, $namespace);
×
211
                    }
212
                }
213
            }
214
        }
215
    }
216

217
    /**
218
     * Save cache
219
     *
220
     * @param string $namespace Namespace
221
     * @param array<string, mixed> $config Configuration
222
     * @return void
223
     */
224
    protected function saveCache(string $namespace, array $config): void
225
    {
NEW
226
        $cacheFile = $this->getCacheFile($namespace);
×
NEW
227
        file_put_contents($cacheFile, json_encode($config, JSON_UNESCAPED_UNICODE));
×
228
    }
229

230
    /**
231
     * Get cache file path
232
     *
233
     * @param string $namespace Namespace
234
     * @return string
235
     */
236
    protected function getCacheFile(string $namespace): string
237
    {
NEW
238
        return $this->cacheDir . '/' . md5($this->options['app_id'] . '_' . $namespace) . '.json';
×
239
    }
240

241
    /**
242
     * Disable cloning
243
     */
244
    public function __clone(): void {}
245

246
    /**
247
     * Disable serialization
248
     */
249
    public function __wakeup(): void {}
250
}
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