Passed
Push — master ( 8c15d4...cea66e )
by Scrutinizer
01:21
created

ConfigProtectedMethods::setCache()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 6
c 0
b 0
f 0
nc 1
nop 2
dl 0
loc 10
rs 10
1
<?php
2
3
/**
4
 * This file is part of the keinos/mastodon-streaming-api-config package.
5
 *
6
 * - Authors, copyright, license, usage and etc.:
7
 *   - See: https://github.com/KEINOS/Mastodon_StreamingAPI_Config/
8
 */
9
10
declare(strict_types=1);
11
12
namespace KEINOS\MSTDN_TOOLS;
13
14
use Symfony\Component\HttpClient\HttpClient           as HttpClient;
0 ignored issues
show
Bug introduced by
The type Symfony\Component\HttpClient\HttpClient was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
15
use Symfony\Component\Cache\Adapter\FilesystemAdapter as FilesystemAdapter;
0 ignored issues
show
Bug introduced by
The type Symfony\Component\Cache\Adapter\FilesystemAdapter was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
16
17
/**
18
 * Parent class of \KEINOS\MSTDN_TOOLS\Config class.
19
 *
20
 * Note that the only public method allowed is "__construct()". Other public
21
 * methods and properties must be defined in "Config" child class.
22
 */
23
class ConfigProtectedMethods extends ConfigStaticMethods
24
{
25
    /** @var string */
26
    protected $url_host;
27
    /** @var string */
28
    protected $url_api_instance;
29
    /** @var array<mixed,mixed> */
30
    protected $info_server;
31
    /** @var string */
32
    protected $access_token = '';
33
    /** @var string */
34
    protected $id_hash_self;
35
    /** @var int */
36
    protected $ttl_cache;
37
38
    public function __construct(string $url_host, string $access_token = '')
39
    {
40
        $this->id_hash_self = strval(hash_file('md5', __FILE__));
41
        $this->ttl_cache = self::CACHE_TTL_DEFAULT;
42
43
        $this->setUrlHost($url_host);
44
        $this->setToken($access_token);
45
        $this->setServerInfo();
46
    }
47
48
    protected function getAccessToken(): string
49
    {
50
        return $this->access_token;
51
    }
52
53
    /**
54
     * @return array<mixed,mixed>
55
     * @throws \Exception
56
     * @suppress PhanUndeclaredClassMethod
57
     */
58
    protected function getContentsAsArray(string $url_api): array
59
    {
60
        try {
61
            $client_http = HttpClient::create();
62
            $response = $client_http->request('GET', $url_api);
63
            // Get contents as array
64
            return $response->toArray();
65
        } catch (\Exception $e) {
66
            $msg = 'Error while setting server info.' . PHP_EOL
67
                 . '- Error details: ' . $e->getMessage() . PHP_EOL;
68
            throw new \Exception($msg);
69
        }
70
    }
71
72
    /**
73
     * Get value from cache.
74
     *
75
     * @param  string $key
76
     * @return null|mixed
77
     * @suppress PhanUndeclaredClassMethod
78
     */
79
    protected function getCache(string $key)
80
    {
81
        $cache_namespace = $this->id_hash_self;
82
        $cache_lifetime  = $this->ttl_cache;
83
84
        $cache_pool = new FilesystemAdapter($cache_namespace, $cache_lifetime);
85
        $cache_item = $cache_pool->getItem($key);
86
87
        if (! $cache_item->isHit()) {
88
            return null;
89
        }
90
        return $cache_item->get();
91
    }
92
93
    /**
94
     * setCache
95
     *
96
     * @param  string $key
97
     * @param  mixed $value
98
     * @return void
99
     * @suppress PhanUndeclaredClassMethod
100
     */
101
    protected function setCache(string $key, $value): void
102
    {
103
        $cache_namespace = $this->id_hash_self;
104
        $cache_lifetime  = $this->ttl_cache;
105
106
        $cache_pool = new FilesystemAdapter($cache_namespace, $cache_lifetime);
107
        $cache_item = $cache_pool->getItem($key);
108
109
        $cache_item->set($value);
110
        $cache_pool->save($cache_item);
111
    }
112
113
    protected function setServerInfo(): void
114
    {
115
        $url_api = rtrim($this->url_host, '/') . self::ENDPOINT_API_INFO_INSTANCE;
116
        $info    = $this->getCache('info_server');
117
        if (null === $info) {
118
            $info    = $this->getContentsAsArray($url_api);
119
            // Check if must keys are set
120
            if (! isset($info['urls']['streaming_api'])) {
121
                throw new \Exception('The server did NOT return with "streaming_api" key.');
122
            }
123
        }
124
        // Set cache
125
        $this->setCache('info_server', $info);
126
        // Set property
127
        $this->url_api_instance = $url_api;
128
        $this->info_server = $info;
129
    }
130
131
    /**
132
     * @param  string $access_token
133
     * @return void
134
     * @throws \Exception            If the token is in bad format.
135
     */
136
    protected function setToken(string $access_token): void
137
    {
138
        if (empty($access_token)) {
139
            return;
140
        }
141
142
        if (! self::isAlphaNumeric($access_token)) {
143
            $msg = 'Invalid access token. Should be alpha numeric.';
144
            throw new \Exception($msg);
145
        }
146
147
        // Mastodon's token is 64 byte in length
148
        if (64 !== strlen($access_token)) {
149
            $msg = 'Invalid access token. Should be 64 chars in length.';
150
            throw new \Exception($msg);
151
        }
152
153
        // Set property
154
        $this->access_token = $access_token;
155
    }
156
157
    /**
158
     * @param  string $url_host  The URL of Mastodon server/instance.
159
     * @return void
160
     * @throws \Exception        If the server isn't available.
161
     */
162
    protected function setUrlHost(string $url_host): void
163
    {
164
        try {
165
            if (self::isUrlProtocolHttp($url_host)) {
166
                $msg = 'Not in "https:" protocol. We do not allow "http:" protocol.';
167
                throw new \Exception($msg);
168
            }
169
170
            /** @phan-suppress-next-line PhanUndeclaredClassMethod */
171
            $client_http = HttpClient::create();
172
173
            $response = $client_http->request('HEAD', $url_host);
174
            if (200 !== $response->getStatusCode()) {
175
                throw new \Exception('The server did not return 200 status.');
176
            }
177
            // Set property
178
            $this->url_host = $url_host;
179
        } catch (\Exception $e) {
180
            $msg = 'Error while setting server host URL.' . PHP_EOL
181
                 . '- Error details: ' . $e->getMessage() . PHP_EOL;
182
            throw new \Exception($msg);
183
        }
184
    }
185
}
186