Passed
Push — master ( 18146c...908f69 )
by Andrea
16:21 queued 12s
created

ApiManager::isBrokenPipe()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 4
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 7
rs 10
ccs 0
cts 5
cp 0
crap 6
1
<?php
2
3
/**
4
 * API Manager version 3.0 / embedded into Bicore
5
 * This service provides methods that help to manage API Rest communications.
6
 * Each API client can use it to reduce time to interact with API services
7
 */
8
9
namespace Cdf\BiCoreBundle\Service\Api;
10
11
use Cdf\BiCoreBundle\Utils\Api\ApiUtils;
12
use Cdf\BiCoreBundle\Utils\Api\ApiManagerUtil;
13
use Cdf\BiCoreBundle\Utils\String\StringUtils;
14
use Cdf\BiCoreBundle\Service\Api\Oauth2TokenService;
15
use \Exception;
16
17
/**
18
 * It provides services to use API Rest.
19
 */
20
class ApiManager
21
{
22
23
    private string $project;
24
    private Oauth2TokenService $oauth2Service;
25
    private bool $oauth2Enabled;
26
    private mixed $map;
27
    private object $headerSelector;
28
    private object $config;
29
30
    private ApiManagerUtil $apiManUtil;
31
32
    /**
33
     * Build an ApiManager instance
34
     */
35
    public function __construct(String $oauth2Parameter, Oauth2TokenService $oauth2Service)
36
    {
37
        $this->map = array();
38
        $this->oauth2Service = $oauth2Service;
39
        $this->oauth2Enabled = false;
40
        if ($oauth2Parameter == 1) {
41
            $this->oauth2Enabled = true;
42
        }
43
        $this->apiManUtil = new ApiManagerUtil();
44
    }
45
46
    //Set the project name of client api
47
    public function setProjectName(string $projectName): void
48
    {
49
        $this->project = $projectName;
50
    }
51
52
    //Get the project name of client api
53
    public function getProjectName(): string
54
    {
55
        return $this->project;
56
    }
57
58
    //Allow to set a config and an headerselector for the client api
59
    public function setApiClientConfigs(object $headerSelector, object $config): void
60
    {
61
        $this->headerSelector = $headerSelector;
62
        $this->config = $config;
63
    }
64
65
    private function isApiClientConfigs(): void
66
    {
67
        if (!isset($this->headerSelector) || !isset($this->config)) {
68
            throw new Exception("Header selector not set or Config not set. Set them using setApiClientConfigs() method");
69
        }
70
    }
71
72
    //Return true if oauth2 is enabled
73
    private function isOauth2(): bool
74
    {
75
        return $this->oauth2Enabled;
76
    }
77
78
79
    //generic setup
80
    public function setupCollection(string $collectionString): void
81
    {
82
        $this->setApiController($collectionString);
83
    }
84
85
86
    /**
87
     * Assure that exist an item mapped into ApiManager having the given collection
88
     * and project as key.
89
     */
90
    public function setApiController(String $collection, String $subcollection = ''): void
91
    {
92
        //if not set it throws a new exception
93
        $this->isApiClientConfigs();
94
95
        $apiUtils = new ApiUtils($collection);
96
        $parametri = array('str' => $collection, 'primamaiuscola' => true);
97
        $outcome = StringUtils::toCamelCase($parametri);
98
99
        $subcollectionValue = '';
100
        if (!empty($subcollection)) {
101
            $parametri2 = array('str' => $subcollection, 'primamaiuscola' => true);
102
            $subcollectionValue = StringUtils::toCamelCase($parametri2);
103
        }
104
        //NOT VALID FOR WINDOWS OS
105
        $apiClass = $apiUtils->getApiControllerClass($this->project, $outcome);
106
107
        $apiController = new $apiClass(null, $this->config, $this->headerSelector);
108
        $subArray = [ $subcollection => $subcollectionValue ];
109
        if (!empty($this->map[$collection]['sub-api'])) {
110
            $subArray = $this->map[$collection]['sub-api'][$subcollection] = $subcollectionValue;
111
        }
112
        $this->map($collection, [
113
            'util' => $apiUtils,
114
            'api' => $apiController,
115
            'sub-api' => $subArray,
116
            ]);
117
    }
118
119
    private function map(string $collection, mixed $tools): void
120
    {
121
        if (!isset($this->map[$collection])) {
122
            $this->map[$collection] = $tools;
123
        }
124
    }
125
126
    /**
127
     * It checks if error is due to a Broken Pipe
128
     */
129
    private function isBrokenPipe(Exception &$error) : bool
130
    {
131
        $outcome = false;
132
        if (strpos($error->getMessage(), 'broken pipe') !== false) {
133
            $outcome = true;
134
        }
135
        return $outcome;
136
    }
137
138
    /**
139
     * Set the token managed by wso2TokenService into api-service
140
     * If token is already set, then it doesn't change it
141
     */
142
    private function setToken(mixed $api): string
143
    {
144
        $token = '';
145
        if ($this->isOauth2()) {
146
            $token = $this->oauth2Service->getToken();
147
            if (empty($api->getConfig()->getAccessToken())) {
148
                $this->refreshToken($api, $token);
149
            }
150
        }
151
        return $token;
152
    }
153
154
    /**
155
     * Set the token managed by wso2TokenService into api-service
156
     * If token is already set, it replaces it
157
     */
158
    private function refreshToken(mixed $api, string $token): void
159
    {
160
        if ($this->isOauth2()) {
161
            $api->getConfig()->setAccessToken($token);
162
        }
163
    }
164
165
166
    /**
167
     * Return the proper method to be used
168
     */
169
    private function getMethod(String $collection, String $getMethod, String $subcollection = null): string
170
    {
171
        $tools = $this->map[$collection];
172
        $method = $tools['util']->$getMethod();
173
        if ($subcollection != null) {
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $subcollection of type null|string against null; this is ambiguous if the string can be empty. Consider using a strict comparison !== instead.
Loading history...
174
            $method .= $tools['sub-api'][$subcollection];
175
        }
176
        return $method;
177
    }
178
179
180
    /**
181
     * Retry one more time if exception is for broken pipes
182
     */
183
    private function retry(Exception $apiEx, object $object, string $method, mixed $args): mixed
184
    {
185
        if ($this->isBrokenPipe($apiEx)) {
186
            return $object->$method(...$args);
187
        }
188
        throw $apiEx;
189
    }
190
191
    /**
192
     * Return the amount of element existent for the given collection.
193
     */
194
    public function getCount(String $collection, String $subcollection = null): mixed
195
    {
196
        $getCountmethod = $this->getMethod($collection, 'getCount', $subcollection);
197
        $tools = $this->map[$collection];
198
        //the array of arguments
199
        $arguments = array();
200
        if ($subcollection != null) {
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $subcollection of type null|string against null; this is ambiguous if the string can be empty. Consider using a strict comparison !== instead.
Loading history...
201
            array_push($arguments, $subcollection);
202
        }
203
        $amount = null;
0 ignored issues
show
Unused Code introduced by
The assignment to $amount is dead and can be removed.
Loading history...
204
        $token = $this->setToken($tools['api']);
205
        try {
206
                $amount = $tools['api']->$getCountmethod(...$arguments);
207
        } catch (\Exception $apiEx) {
208
            $this->refreshToken($tools['api'], $token);
209
            $amount = $this->retry($apiEx, $tools['api'], $getCountmethod, $arguments);
210
        }
211
        return $amount;
212
    }
213
214
    /**
215
     * Get items existent for the given collection, filtered as requested.
216
     */
217
    public function getAll(string $collection, ?int $offset, ?int $limit, mixed $sort = null, ?string $condition, string $subcollection = null): mixed
218
    {
219
        $tools = $this->map[$collection];
220
        $getAllmethod = $this->getMethod($collection, 'getAll', $subcollection);
221
        $results = [];
0 ignored issues
show
Unused Code introduced by
The assignment to $results is dead and can be removed.
Loading history...
222
        //the array of arguments
223
        $arguments = array();
224
        if ($subcollection != null) {
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $subcollection of type null|string against null; this is ambiguous if the string can be empty. Consider using a strict comparison !== instead.
Loading history...
225
            array_push($arguments, $subcollection);
226
        }
227
        array_push($arguments, $offset);
228
        array_push($arguments, $limit);
229
        array_push($arguments, $sort);
230
        array_push($arguments, $condition);
231
232
        $token = $this->setToken($tools['api']);
233
        try {
234
                $results = $tools['api']->$getAllmethod(...$arguments);
235
        } catch (\Exception $apiEx) {
236
            $this->refreshToken($tools['api'], $token);
237
            $results = $this->retry($apiEx, $tools['api'], $getAllmethod, $arguments);
238
        }
239
        return $results;
240
    }
241
242
      /**
243
     * Get items existent for the given collection, filtered as requested.
244
     * subcollection contains the name of sub-collection if any
245
     * subcollectionVar contains the value of sub-collection if any
246
     */
247
    public function getItem(String $collection, int $id, String $subcollection = null, string $subcollectionVar = null): mixed
248
    {
249
        $tools = $this->map[$collection];
250
        $getAllmethod = $this->getMethod($collection, 'getItem', $subcollection);
251
        $results = [];
0 ignored issues
show
Unused Code introduced by
The assignment to $results is dead and can be removed.
Loading history...
252
        $arguments = array();
253
        if ($subcollectionVar != null) {
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $subcollectionVar of type null|string against null; this is ambiguous if the string can be empty. Consider using a strict comparison !== instead.
Loading history...
254
            array_push($arguments, $subcollectionVar);
255
        }
256
        array_push($arguments, $id);
257
        $token = $this->setToken($tools['api']);
258
        try {
259
            $results = $tools['api']->$getAllmethod(...$arguments);
260
        } catch (\Exception $apiEx) {
261
            $this->refreshToken($tools['api'], $token);
262
            $results = $this->retry($apiEx, $tools['api'], $getAllmethod, $arguments);
263
        }
264
        return $results;
265
    }
266
267
    /**
268
     * Delete an existent item
269
     */
270
    public function deleteItem(String $collection, int $id, String $subcollection = null): mixed
271
    {
272
        $tools = $this->map[$collection];
273
        $deleteMethod = $this->getMethod($collection, 'getDelete', $subcollection);
274
        $arguments = array();
275
        if ($subcollection != null) {
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $subcollection of type null|string against null; this is ambiguous if the string can be empty. Consider using a strict comparison !== instead.
Loading history...
276
            array_push($arguments, $subcollection);
277
        }
278
        array_push($arguments, $id);
279
        $token = $this->setToken($tools['api']);
280
        try {
281
            $response = $tools['api']->$deleteMethod(...$arguments);
282
        } catch (\Exception $apiEx) {
283
            $this->refreshToken($tools['api'], $token);
284
            $response = $this->retry($apiEx, $tools['api'], $deleteMethod, $arguments);
285
        }
286
        return $response;
287
    }
288
289
290
    /**
291
     * Create the requested object, using the given body item.
292
     */
293
    public function postCreate(String $collection, mixed $body, String $subcollection = null): mixed
294
    {
295
        $tools = $this->map[$collection];
296
        $createMethod = $this->getMethod($collection, 'getCreate', $subcollection);
297
        $results = [];
0 ignored issues
show
Unused Code introduced by
The assignment to $results is dead and can be removed.
Loading history...
298
        $arguments = array();
299
        array_push($arguments, $body);
300
        if ($subcollection != null) {
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $subcollection of type null|string against null; this is ambiguous if the string can be empty. Consider using a strict comparison !== instead.
Loading history...
301
            array_push($arguments, $subcollection);
302
        }
303
        $token = $this->setToken($tools['api']);
304
        try {
305
            $results = $tools['api']->$createMethod(...$arguments);
306
        } catch (\Exception $apiEx) {
307
            $this->refreshToken($tools['api'], $token);
308
            $results = $this->retry($apiEx, $tools['api'], $createMethod, $arguments);
309
        }
310
        return $results;
311
    }
312
313
314
     /**
315
     * Create the requested object, using the given body item.
316
     */
317
    public function postUpdate(String $collection, object $body, int $id, String $subcollection = null): mixed
318
    {
319
        $tools = $this->map[$collection];
320
        $createMethod = $this->getMethod($collection, 'getUpdateItem', $subcollection);
321
        $results = [];
0 ignored issues
show
Unused Code introduced by
The assignment to $results is dead and can be removed.
Loading history...
322
        $arguments = array();
323
        array_push($arguments, $body);
324
        array_push($arguments, $id);
325
        if ($subcollection != null) {
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $subcollection of type null|string against null; this is ambiguous if the string can be empty. Consider using a strict comparison !== instead.
Loading history...
326
            array_push($arguments, $subcollection);
327
        }
328
        $token = $this->setToken($tools['api']);
329
        try {
330
            $results = $tools['api']->$createMethod(...$arguments);
331
        } catch (\Exception $apiEx) {
332
            $this->refreshToken($tools['api'], $token);
333
            $results = $this->retry($apiEx, $tools['api'], $createMethod, $arguments);
334
        }
335
        return $results;
336
    }
337
338
    /**
339
     * It prepares entity values so that they can be used with types compliant with BiCoreBundle.
340
     * For example it transforms a date that arrive in string format into a DateTime.
341
     * @deprecated: evaluate to migrate on ApiManagerUtil
342
     */
343
    public function setupApiValues(mixed $entityout): mixed
344
    {
345
        return $this->apiManUtil->setupApiValues($entityout);
346
    }
347
348
    /**
349
     * Map first object transformed into the second where possible,
350
     * attempting to map each field of first into field of the second.
351
     * @deprecated: evaluate to migrate on ApiManagerUtil
352
     */
353
    public function mapData(object $modelEntity, object $controllerItem): mixed
354
    {
355
        return $this->apiManUtil->mapData($modelEntity, $controllerItem);
356
    }
357
}
358