Completed
Push — master ( abe227...316baf )
by Raffael
13:55 queued 08:01
created

Ucs::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 6
ccs 5
cts 5
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 8
crap 1

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * tubee.io
7
 *
8
 * @copyright   Copryright (c) 2017-2019 gyselroth GmbH (https://gyselroth.com)
9
 * @license     GPL-3.0 https://opensource.org/licenses/GPL-3.0
10
 */
11
12
namespace Tubee\Endpoint;
13
14
use Generator;
15
use GuzzleHttp\Client;
16
use InvalidArgumentException;
17
use Psr\Log\LoggerInterface;
18
use Tubee\AttributeMap\AttributeMapInterface;
19
use Tubee\Collection\CollectionInterface;
20
use Tubee\Endpoint\Ucs\Exception as UcsException;
21
use Tubee\EndpointObject\EndpointObjectInterface;
22
use Tubee\Workflow\Factory as WorkflowFactory;
23
24
class Ucs extends AbstractEndpoint
25
{
26
    /**
27
     * Kind.
28
     */
29
    public const KIND = 'UcsEndpoint';
30
31
    /**
32
     * Constants.
33
     */
34
    public const ATTR_DN = '$dn$';
35
    public const SESSION_COOKIE_NAME = 'UMCSessionId';
36
37
    /**
38
     * Guzzle client.
39
     *
40
     * @var Client
41
     */
42
    protected $client;
43
44
    /**
45
     * UCS session ID.
46
     *
47
     * @var string
48
     */
49
    protected $session;
50
51
    /**
52
     * Object type.
53
     *
54
     * @var string
55
     */
56
    protected $flavor;
57
58
    /**
59
     * Init endpoint.
60
     */
61 27
    public function __construct(string $name, string $type, string $flavor, Client $client, CollectionInterface $collection, WorkflowFactory $workflow, LoggerInterface $logger, array $resource = [])
62
    {
63 27
        $this->client = $client;
64 27
        $this->flavor = $flavor;
65 27
        parent::__construct($name, $type, $collection, $workflow, $logger, $resource);
66 27
    }
67
68
    /**
69
     * {@inheritdoc}
70
     */
71 2
    public function setup(bool $simulate = false): EndpointInterface
72
    {
73 2
        $auth = $this->resource['data']['resource']['auth'];
74
75 2
        $url = $this->resource['data']['resource']['base_uri'].'/auth';
76 2
        $this->logger->debug('create ucs auth session from ['.$url.']', [
77 2
            'category' => get_class($this),
78
        ]);
79
80 2
        $response = $this->client->post($url, [
81
            'json' => [
82
                'options' => [
83 2
                    'username' => $auth['username'],
84 2
                    'password' => $auth['password'],
85
                ],
86
            ],
87
        ]);
88
89 2
        $body = json_decode($response->getBody()->getContents(), true);
0 ignored issues
show
Unused Code introduced by
$body is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
90 2
        $this->session = $this->getSessionId();
91
92 1
        return $this;
93
    }
94
95
    /**
96
     * {@inheritdoc}
97
     */
98 1
    public function shutdown(bool $simulate = false): EndpointInterface
99
    {
100 1
        $this->client->getConfig('cookies')->clear();
101
102 1
        return $this;
103
    }
104
105
    /**
106
     * {@inheritdoc}
107
     */
108 2
    public function delete(AttributeMapInterface $map, array $object, array $endpoint_object, bool $simulate = false): bool
109
    {
110 2
        $url = $this->client->getConfig('base_uri').'/command/udm/remove';
111 2
        $this->logger->info('delete ucs object from endpoint ['.$this->getIdentifier().'] using udm/remove to ['.$url.']', [
112 2
            'category' => get_class($this),
113
        ]);
114
115 2
        if ($simulate === false) {
116 1
            $result = $this->parse($this->client->post($url, $this->getRequestOptions([
117 1
                'json' => [
118
                    'options' => [
119
                        [
120 1
                            'object' => $this->getResourceId($object, $endpoint_object),
121
                            'options' => [
122
                                'cleanup' => true,
123
                            ],
124
                        ],
125
                    ],
126
                ],
127
            ])));
128
129 1
            $result = array_shift($result);
130 1
            $this->verifyWriteResult($result);
131
        }
132
133 2
        return true;
134
    }
135
136
    /**
137
     * {@inheritdoc}
138
     */
139 6
    public function create(AttributeMapInterface $map, array $object, bool $simulate = false): ?string
140
    {
141 6
        $url = $this->client->getConfig('base_uri').'/command/udm/add';
142
143 6
        $dn = explode(',', $this->getResourceId($object));
144 5
        array_shift($dn);
145 5
        $container = implode(',', $dn);
146 5
        unset($object[self::ATTR_DN]);
147
148 5
        $this->logger->info('create new ucs object in ['.$container.'] on endpoint ['.$this->getIdentifier().'] using udm/add to ['.$url.']', [
149 5
            'category' => get_class($this),
150
        ]);
151
152 5
        if ($simulate === false) {
153 4
            $result = $this->parse($this->client->post($url, $this->getRequestOptions([
154
                'json' => [
155
                    'options' => [
156
                        [
157
                            'options' => [
158 4
                                'objectType' => $this->flavor,
159 4
                                'container' => $container,
160
                            ],
161 4
                            'object' => $object,
162
                        ],
163
                    ],
164
                ],
165
            ])));
166
167 3
            $result = array_shift($result);
168 3
            $this->verifyWriteResult($result);
169
170 1
            return $this->getResourceId($result);
171
        }
172
173 1
        return null;
174
    }
175
176
    /**
177
     * {@inheritdoc}
178
     */
179 5
    public function getDiff(AttributeMapInterface $map, array $diff): array
180
    {
181 5
        $result = [];
182 5
        foreach ($diff as $attribute => $update) {
183 4
            switch ($update['action']) {
184
                case AttributeMapInterface::ACTION_REPLACE:
185
                case AttributeMapInterface::ACTION_ADD:
186 3
                    $result[$attribute] = $update['value'];
187
188 3
                break;
189
                case AttributeMapInterface::ACTION_REMOVE:
190 1
                    $result[$attribute] = '';
191
192 1
                break;
193
                default:
194 4
                    throw new InvalidArgumentException('unknown diff action '.$update['action'].' given');
195
            }
196
        }
197
198 5
        return $result;
199
    }
200
201
    /**
202
     * {@inheritdoc}
203
     */
204 3
    public function change(AttributeMapInterface $map, array $diff, array $object, array $endpoint_object, bool $simulate = false): ?string
205
    {
206 3
        $url = $this->client->getConfig('base_uri').'/command/udm/put';
207
208 3
        $this->logger->info('update ucs object on endpoint ['.$this->getIdentifier().'] using udm/put to ['.$url.']', [
209 3
            'category' => get_class($this),
210
        ]);
211
212 3
        $dn = $this->getResourceId($object, $endpoint_object);
213 3
        $map_parent = substr($dn, strpos($dn, ',') + 1);
214 3
        $ep_parent = substr($endpoint_object[self::ATTR_DN], strpos($endpoint_object[self::ATTR_DN], ',') + 1);
215
216 3
        if ($ep_parent !== $map_parent) {
217 1
            $this->moveUcsObject($endpoint_object[self::ATTR_DN], $map_parent, $simulate);
218
        }
219
220 3
        if ($simulate === false) {
221 2
            $result = $this->parse($this->client->post($url, $this->getRequestOptions([
222
                'json' => [
223
                    'options' => [
224 2
                        ['object' => $diff],
225
                    ],
226
                ],
227
            ])));
228
229 2
            $result = array_shift($result);
230 2
            $this->verifyWriteResult($result);
231
232 2
            return $dn;
233
        }
234
235 1
        return null;
236
    }
237
238
    /**
239
     * {@inheritdoc}
240
     */
241 4
    public function transformQuery(?array $query = null)
242
    {
243 4
        $result = null;
0 ignored issues
show
Unused Code introduced by
$result is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
244
245 4
        if ($this->filter_all !== null && empty($query)) {
246 2
            $filter_all = json_decode(stripslashes($this->getFilterAll()), true);
247 2
            if (!isset($filter_all['objectProperty']) || !isset($filter_all['objectPropertyValue'])) {
248 1
                throw new UcsException\InvalidFilter('Either objectProperty or objectPropertyValue not set in filter_all');
249
            }
250
251 1
            return $filter_all;
252
        }
253
254 2
        if (!empty($query)) {
255 1
            if ($this->filter_all !== null) {
256
                $this->logger->warning('this endpoint does not support combining queries, ignore filter_all configuration for this request', [
257
                    'category' => get_class($this),
258
                ]);
259
            }
260
261
            return [
262 1
                'objectProperty' => key($query),
263 1
                'objectPropertyValue' => reset($query),
264
            ];
265
        }
266
267
        return [
268 1
            'objectProperty' => 'None',
269
        ];
270
    }
271
272
    /**
273
     * {@inheritdoc}
274
     */
275
    public function getAll(?array $query = null): Generator
276
    {
277
        $url = $this->client->getConfig('base_uri').'/command/udm/query';
278
        $this->logger->debug('find all ucs objects on endpoint ['.$this->getIdentifier().'] using udm/query to ['.$url.']', [
279
            'category' => get_class($this),
280
        ]);
281
282
        $filter_all = $this->transformQuery($query);
283
        $filter_all['objectType'] = $this->flavor;
284
        $options = [
285
            'json' => [
286
                'options' => $filter_all,
287
            ],
288
        ];
289
290
        $i = 0;
291
        $body = $this->parse($this->client->post($url, $this->getRequestOptions($options)));
292
293
        foreach ($body as $object) {
294
            $dn = $this->getResourceId($object);
295
            yield $this->build($this->fetchObject($dn));
296
        }
297
298
        return $i;
299
    }
300
301
    /**
302
     * {@inheritdoc}
303
     */
304 4
    public function getOne(array $object, ?array $attributes = []): EndpointObjectInterface
305
    {
306 4
        $url = $this->client->getConfig('base_uri').'/command/udm/query';
307 4
        $filter = $this->getFilterOne($object);
308
309 4
        $this->logger->debug('find ucs object with filter ['.$filter.'] on endpoint ['.$this->getIdentifier().'] using udm/query to ['.$url.']', [
310 4
            'category' => get_class($this),
311
        ]);
312
313 4
        $query = json_decode(stripslashes($filter), true);
314 4
        if (!isset($query['objectProperty']) || !isset($query['objectPropertyValue'])) {
315 1
            throw new UcsException\InvalidFilter('Either objectProperty or objectPropertyValue not set in filter_one');
316
        }
317
318 3
        $query['objectType'] = $this->flavor;
319
        $options = [
320
            'json' => [
321 3
                'options' => $query,
322
            ],
323
        ];
324
325 3
        $result = $this->parse($this->client->post($url, $this->getRequestOptions($options)));
326
327 3
        if (count($result) > 1) {
328 1
            throw new Exception\ObjectMultipleFound('found more than one object with filter '.$filter);
329
        }
330 2
        if (count($result) === 0) {
331 1
            throw new Exception\ObjectNotFound('no object found with filter '.$filter);
332
        }
333
334 1
        $dn = $this->getResourceId(array_shift($result));
335
336 1
        return $this->build($this->fetchObject($dn));
337
    }
338
339
    /**
340
     * Get session id.
341
     */
342 2
    protected function getSessionId()
343
    {
344 2
        $jar = $this->client->getConfig('cookies')->toArray();
345 2
        foreach ($jar as $cookie) {
346 1
            if ($cookie['Name'] === self::SESSION_COOKIE_NAME) {
347 1
                return $cookie['Value'];
348
            }
349
        }
350
351 1
        throw new UcsException\SessionCookieNotAvailable('no session cookie '.self::SESSION_COOKIE_NAME.' found');
352
    }
353
354
    /**
355
     * Verify write result.
356
     */
357 6
    protected function verifyWriteResult(array $result): array
358
    {
359 6
        if (isset($result['details'])) {
360
            $message = $result['details'];
361
        } else {
362 6
            $message = 'write command failed with no further details provided';
363
        }
364
365 6
        if (isset($result['success'])) {
366 6
            if ($result['success'] === false) {
367 2
                throw new UcsException\RequestFailed($message);
368
            }
369
370 4
            return $result;
371
        }
372
373
        throw new UcsException\RequestFailed($message);
374
    }
375
376
    /**
377
     * Parse response.
378
     */
379 10
    protected function parse($response): array
380
    {
381 10
        $data = json_decode($response->getBody()->getContents(), true);
382
383 10
        $this->logger->debug('request to ['.$this->client->getConfig('base_uri').'] ended with code ['.$response->getStatusCode().']', [
384 10
            'category' => get_class($this),
385
        ]);
386
387 10
        if (!isset($data['result']) || !is_array($data['result'])) {
388 1
            throw new Exception\NotIterable('response body is invalid, iterable data expected');
389
        }
390
391 9
        return $data['result'];
392
    }
393
394
    /**
395
     * Get headers.
396
     */
397 10
    protected function getRequestOptions(array $options): array
398
    {
399 10
        return array_replace_recursive($options, [
400
            'json' => [
401 10
                'flavor' => $this->flavor,
402
            ],
403
            'headers' => [
404 10
                'Accept' => 'application/json',
405 10
                'X-Xsrf-Protection' => $this->session,
406
            ],
407
        ]);
408
    }
409
410
    /**
411
     * Get identifier.
412
     */
413 11
    protected function getResourceId(array $object, array $endpoint_object = []): ?string
414
    {
415 11
        if (isset($object[self::ATTR_DN])) {
416 10
            return $object[self::ATTR_DN];
417
        }
418
419 1
        if (isset($endpoint_object[self::ATTR_DN])) {
420
            return $endpoint_object[self::ATTR_DN];
421
        }
422
423 1
        throw new UcsException\NoEntryDn('no attribute $dn$ found in data object');
424
    }
425
426
    /**
427
     * Move ucs object.
428
     */
429 1
    protected function moveUcsObject(string $current_dn, string $container, bool $simulate = false): bool
430
    {
431 1
        $url = $this->client->getConfig('base_uri').'/command/udm/move';
432
433 1
        $this->logger->info('found ucs object ['.$current_dn.'] but is not at the expected place ['.$container.'], move object using udm/move ['.$url.']', [
434 1
            'category' => get_class($this),
435
        ]);
436
437 1
        if ($simulate === false) {
438 1
            $this->parse($this->client->post($url, $this->getRequestOptions([
439
                'json' => [
440
                    'options' => [
441 1
                        'container' => $container,
442
                    ],
443 1
                    'object' => $current_dn,
444
                ],
445
            ])));
446
        }
447
448 1
        return true;
449
    }
450
451
    /**
452
     * Request all object attributes.
453
     */
454 1
    protected function fetchObject(string $dn): array
455
    {
456 1
        $url = $this->client->getConfig('base_uri').'/command/udm/get';
457 1
        $this->logger->debug('fetch ucs object attributes from ['.$dn.'] on endpoint ['.$this->getIdentifier().'] using udm/get to ['.$url.']', [
458 1
            'category' => get_class($this),
459
        ]);
460
461 1
        $result = $this->parse($this->client->post($url, $this->getRequestOptions([
462
            'json' => [
463
                'options' => [
464 1
                    $dn,
465
                ],
466
            ],
467
        ])));
468
469 1
        return array_shift($result);
470
    }
471
}
472