Completed
Push — master ( 519f76...318dd5 )
by Raffael
24:13 queued 15:29
created

AbstractEndpoint::count()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 0
cts 2
cp 0
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 2
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * tubee
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 InvalidArgumentException;
16
use Psr\Http\Message\ServerRequestInterface;
17
use Psr\Log\LoggerInterface;
18
use Tubee\Collection\CollectionInterface;
19
use Tubee\EndpointObject;
20
use Tubee\EndpointObject\EndpointObjectInterface;
21
use Tubee\Helper;
22
use Tubee\Resource\AbstractResource;
23
use Tubee\Resource\AttributeResolver;
24
use Tubee\Workflow\Factory as WorkflowFactory;
25
use Tubee\Workflow\WorkflowInterface;
26
27
abstract class AbstractEndpoint extends AbstractResource implements EndpointInterface
28
{
29
    /**
30
     * Kind.
31
     */
32
    public const KIND = 'Endpoint';
33
34
    /**
35
     * Endpoint name.
36
     *
37
     * @var string
38
     */
39
    protected $name;
40
41
    /**
42
     * CollectionInterface.
43
     *
44
     * @var CollectionInterface
45
     */
46
    protected $collection;
47
48
    /**
49
     * Logger.
50
     *
51
     * @var LoggerInterface
52
     */
53
    protected $logger;
54
55
    /**
56
     * Filter All.
57
     *
58
     * @var string
59
     */
60
    protected $filter_all;
61
62
    /**
63
     * Filter One.
64
     *
65
     * @var string
66
     */
67
    protected $filter_one;
68
69
    /**
70
     * Import.
71
     *
72
     * @var array
73
     */
74
    protected $import = [];
75
76
    /**
77
     * Type.
78
     *
79
     * @var string
80
     */
81
    protected $type;
82
83
    /**
84
     * Flush.
85
     *
86
     * @var bool
87
     */
88
    protected $flush = false;
89
90
    /**
91
     * Workflow factory.
92
     *
93
     * @var WorkflowFactory
94
     */
95
    protected $workflow_factory;
96
97
    /**
98
     * Endpoint object identifiers.
99
     *
100
     * @var string
101
     */
102
    protected $identifier;
103
104
    /**
105
     * Init endpoint.
106
     */
107 99
    public function __construct(string $name, string $type, CollectionInterface $collection, WorkflowFactory $workflow_factory, LoggerInterface $logger, array $resource = [])
108
    {
109 99
        $this->name = $name;
110 99
        $this->type = $type;
111 99
        $this->resource = $resource;
112 99
        $this->collection = $collection;
113 99
        $this->logger = $logger;
114 99
        $this->workflow_factory = $workflow_factory;
115
116 99
        if (isset($resource['data']['options'])) {
117 25
            $this->setOptions($resource['data']['options']);
118
        }
119 99
    }
120
121
    /**
122
     * {@inheritdoc}
123
     */
124
    public function setup(bool $simulate = false): EndpointInterface
125
    {
126
        return $this;
127
    }
128
129
    /**
130
     * {@inheritdoc}
131
     */
132
    public function getKind(): string
133
    {
134
        return $this->resource['kind'];
135
    }
136
137
    /**
138
     * Set options.
139
     */
140 25
    public function setOptions(array $config = []): EndpointInterface
141
    {
142 25
        foreach ($config as $option => $value) {
143
            switch ($option) {
144 25
                case 'flush':
145 25
                case 'import':
146 25
                case 'identifier':
147 25
                case 'filter_one':
148 5
                case 'filter_all':
149 25
                    $this->{$option} = $value;
150
151 25
                break;
152
                default:
153
                    throw new InvalidArgumentException('unknown option '.$option.' given');
154
            }
155
        }
156
157 25
        return $this;
158
    }
159
160
    /**
161
     * {@inheritdoc}
162
     */
163
    public function decorate(ServerRequestInterface $request): array
164
    {
165
        $collection = $this->collection->getName();
166
        $namespace = $this->collection->getResourceNamespace()->getName();
167
168
        $resource = [
169
            '_links' => [
170
                'namespace' => ['href' => (string) $request->getUri()->withPath('/api/v1/namespaces/'.$namespace)],
171
                'collection' => ['href' => (string) $request->getUri()->withPath('/api/v1/namespaces/'.$namespace.'/collections/'.$collection)],
172
           ],
173
            'kind' => static::KIND,
174
            'namespace' => $namespace,
175
            'collection' => $collection,
176
            'data' => $this->getData(),
177
            'status' => function ($endpoint) {
178
                try {
179
                    $endpoint->setup();
180
181
                    return [
182
                        'available' => true,
183
                    ];
184
                } catch (\Throwable $e) {
185
                    return [
186
                        'available' => false,
187
                        'exception' => get_class($e),
188
                        'error' => $e->getMessage(),
189
                        'code' => $e->getCode(),
190
                    ];
191
                }
192
            },
193
        ];
194
195
        return AttributeResolver::resolve($request, $this, $resource);
196
    }
197
198
    /**
199
     * {@inheritdoc}
200
     */
201 1
    public function shutdown(bool $simulate = false): EndpointInterface
202
    {
203 1
        return $this;
204
    }
205
206
    /**
207
     * {@inheritdoc}
208
     */
209
    public function flushRequired(): bool
210
    {
211
        return $this->flush;
212
    }
213
214
    /**
215
     * {@inheritdoc}
216
     */
217
    public function flush(bool $simulate = false): bool
218
    {
219
        return true;
220
    }
221
222
    /**
223
     * {@inheritdoc}
224
     */
225
    public function getCollection(): CollectionInterface
226
    {
227
        return $this->collection;
228
    }
229
230
    /**
231
     * {@inheritdoc}
232
     */
233
    public function getResourceIdentifier(): ?string
234
    {
235
        return $this->identifier;
236
    }
237
238
    /**
239
     * {@inheritdoc}
240
     */
241
    public function getImport(): array
242
    {
243
        return $this->import;
244
    }
245
246
    /**
247
     * {@inheritdoc}
248
     */
249 3
    public function exists(array $object): bool
250
    {
251
        try {
252 3
            $this->getOne($object, []);
253
254 1
            return true;
255 2
        } catch (Exception\ObjectMultipleFound $e) {
256 1
            return true;
257 1
        } catch (\Exception $e) {
258 1
            return false;
259
        }
260
    }
261
262
    /**
263
     * {@inheritdoc}
264
     */
265
    public function hasWorkflow(string $name): bool
266
    {
267
        return $this->workflow_factory->has($this, $name);
268
    }
269
270
    /**
271
     * {@inheritdoc}
272
     */
273
    public function getWorkflow(string $name): WorkflowInterface
274
    {
275
        return $this->workflow_factory->getOne($this, $name);
276
    }
277
278
    /**
279
     * {@inheritdoc}
280
     */
281
    public function getWorkflows(array $workflows = [], ?int $offset = null, ?int $limit = null): Generator
282
    {
283
        return $this->workflow_factory->getAll($this, $workflows, $offset, $limit, [
284
            'data.priority' => 1,
285
        ]);
286
    }
287
288
    /**
289
     * {@inheritdoc}
290
     */
291
    public function count(?array $query = null): int
292
    {
293
        return 0;
294
    }
295
296
    /**
297
     * {@inheritdoc}
298
     */
299
    public function getType(): string
300
    {
301
        return $this->type;
302
    }
303
304
    /**
305
     * {@inheritdoc}
306
     */
307 35
    public function getIdentifier(): string
308
    {
309 35
        return $this->collection->getIdentifier().'::'.$this->name;
310
    }
311
312
    /**
313
     * {@inheritdoc}
314
     */
315 18
    public function getFilterOne(array $object): ?array
316
    {
317 18
        if ($this->filter_one === null) {
318
            return null;
319
        }
320
321 18
        return Helper::jsonDecode(stripslashes($this->parseAttribute($this->filter_one, $object)), true);
322
    }
323
324
    /**
325
     * {@inheritdoc}
326
     */
327 4
    public function getFilterAll(): ?array
328
    {
329 4
        if ($this->filter_all === null) {
330
            return null;
331
        }
332
333 4
        return Helper::jsonDecode(stripslashes($this->filter_all), true);
334
    }
335
336
    /**
337
     * Build endpoint object.
338
     */
339 6
    protected function build(array $object, $filter = null): EndpointObjectInterface
340
    {
341 6
        return new EndpointObject([
342 6
            'data' => $object,
343 6
            'filter' => $filter,
344 6
        ], $this);
345
    }
346
347
    /**
348
     * Parse and replace string with attribute values.
349
     */
350
    private function parseAttribute(string $string, array $data): string
351
    {
352 18
        return preg_replace_callback('/(\{(([^\}\{\"]*)+)\})/', function ($match) use ($string, $data) {
353 7
            if (substr($match[0], 0, 2) === '{{' && $match[4][0] === '}') {
354
                return $match[2].$match[4];
355
            }
356
357 7
            $attribute = $match[2];
358
359
            try {
360 7
                return Helper::getArrayValue($data, $attribute);
361 1
            } catch (\Exception $e) {
362 1
                throw new Exception\AttributeNotResolvable('could not resolve attribute '.$attribute.' in value '.$string);
363
            }
364 18
        }, $string);
365
    }
366
}
367