Completed
Push — master ( ea9cfc...8dc8d9 )
by Raffael
12:43 queued 03:57
created

Json::setup()   A

Complexity

Conditions 5
Paths 8

Size

Total Lines 31

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 30

Importance

Changes 0
Metric Value
dl 0
loc 31
ccs 0
cts 16
cp 0
rs 9.1128
c 0
b 0
f 0
cc 5
nc 8
nop 1
crap 30
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * tubee.io
7
 *
8
 * @copyright   Copryright (c) 2017-2018 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 Psr\Log\LoggerInterface;
16
use Tubee\AttributeMap\AttributeMapInterface;
17
use Tubee\Collection\CollectionInterface;
18
use Tubee\Endpoint\Json\Exception as JsonException;
19
use Tubee\EndpointObject\EndpointObjectInterface;
20
use Tubee\Storage\StorageInterface;
21
use Tubee\Workflow\Factory as WorkflowFactory;
22
23
class Json extends AbstractFile
24
{
25
    /**
26
     * Kind.
27
     */
28
    public const KIND = 'JsonEndpoint';
29
30
    /**
31
     * Init endpoint.
32
     */
33
    public function __construct(string $name, string $type, string $file, StorageInterface $storage, CollectionInterface $collection, WorkflowFactory $workflow, LoggerInterface $logger, array $resource = [])
34
    {
35
        if ($type === EndpointInterface::TYPE_DESTINATION) {
36
            $this->flush = true;
37
        }
38
39
        parent::__construct($name, $type, $file, $storage, $collection, $workflow, $logger, $resource);
40
    }
41
42
    /**
43
     * {@inheritdoc}
44
     */
45
    public function setup(bool $simulate = false): EndpointInterface
46
    {
47
        if ($this->type === EndpointInterface::TYPE_DESTINATION) {
48
            $streams = [$this->file => $this->storage->openWriteStream($this->file)];
49
        } else {
50
            $streams = $this->storage->openReadStreams($this->file);
51
        }
52
53
        foreach ($streams as $path => $stream) {
54
            $content = [];
0 ignored issues
show
Unused Code introduced by
$content 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...
55
            // if ($this->type === EndpointInterface::TYPE_SOURCE) {
56
            $content = json_decode(stream_get_contents($stream), true);
57
58
            if ($err = json_last_error() !== JSON_ERROR_NONE) {
59
                throw new JsonException\InvalidJson('failed decode json '.$this->file.', json error '.$err);
60
            }
61
62
            if (!is_array($content)) {
63
                throw new JsonException\ArrayExpected('json file contents must be an array');
64
            }
65
            // }
66
67
            $this->files[] = [
68
                'stream' => $stream,
69
                'content' => $content,
70
                'path' => $path,
71
            ];
72
        }
73
74
        return $this;
75
    }
76
77
    /**
78
     * {@inheritdoc}
79
     */
80
    public function shutdown(bool $simulate = false): EndpointInterface
81
    {
82
        foreach ($this->files as $resource) {
83
            if ($simulate === false && $this->type === EndpointInterface::TYPE_DESTINATION) {
84
                $json = json_encode($resource['content'], JSON_PRETTY_PRINT);
85
86
                if (fwrite($resource['stream'], $json) === false) {
87
                    throw new Exception\WriteOperationFailed('failed create json file '.$resource['path']);
88
                }
89
90
                $this->storage->syncWriteStream($resource['stream'], $resource['path']);
91
            }
92
93
            fclose($resource['stream']);
94
        }
95
96
        $this->files = [];
97
98
        return $this;
99
    }
100
101
    /**
102
     * {@inheritdoc}
103
     */
104
    public function transformQuery(?array $query = null)
105
    {
106
        $result = null;
107
        if ($this->filter_all !== null) {
108
            $result = json_decode(stripslashes($this->filter_all), true);
109
        }
110
111
        if (!empty($query)) {
112
            if ($this->filter_all === null) {
113
                $result = json_decode($query, true);
114
            } else {
115
                $result = array_merge($result, $query);
116
            }
117
        }
118
119
        return $result;
120
    }
121
122
    /**
123
     * {@inheritdoc}
124
     */
125
    public function getAll(?array $query = null): Generator
126
    {
127
        $filter = $this->transformQuery($query);
128
        $i = 0;
129
130
        foreach ($this->files as $resource_key => $json) {
131
            foreach ($json['content'] as $object) {
132
                if (!is_array($object)) {
133
                    throw new JsonException\ArrayExpected('json must contain an array of objects');
134
                }
135
136
                if (count(array_intersect_assoc($object, $filter)) !== count($filter)) {
137
                    $this->logger->debug('json object does not match filter [{filter}], skip it', [
138
                        'category' => get_class($this),
139
                        'filter' => $filter,
140
                    ]);
141
142
                    continue;
143
                }
144
145
                yield $this->build($object);
146
                ++$i;
147
            }
148
        }
149
150
        return $i;
151
    }
152
153
    /**
154
     * {@inheritdoc}
155
     */
156
    public function create(AttributeMapInterface $map, array $object, bool $simulate = false): ?string
157
    {
158
        foreach ($this->files as $resource_key => $xml) {
159
            $this->files[$resource_key]['content'][] = $object;
160
161
            $this->logger->debug('create new json object on endpoint ['.$this->name.'] with values [{values}]', [
162
                'category' => get_class($this),
163
                'values' => $object,
164
            ]);
165
        }
166
167
        return null;
168
    }
169
170
    /**
171
     * {@inheritdoc}
172
     */
173
    public function getDiff(AttributeMapInterface $map, array $diff): array
174
    {
175
        throw new Exception\UnsupportedEndpointOperation('endpoint '.get_class($this).' does not support getDiff(), use flush=true');
176
    }
177
178
    /**
179
     * {@inheritdoc}
180
     */
181
    public function change(AttributeMapInterface $map, array $diff, array $object, array $endpoint_object, bool $simulate = false): ?string
182
    {
183
        throw new Exception\UnsupportedEndpointOperation('endpoint '.get_class($this).' does not support change(), use flush=true');
184
    }
185
186
    /**
187
     * {@inheritdoc}
188
     */
189
    public function delete(AttributeMapInterface $map, array $object, array $endpoint_object, bool $simulate = false): bool
190
    {
191
        throw new Exception\UnsupportedEndpointOperation('endpoint '.get_class($this).' does not support delete(), use flush=true');
192
    }
193
194
    /**
195
     * {@inheritdoc}
196
     */
197
    public function getOne(array $object, array $attributes = []): EndpointObjectInterface
198
    {
199
        $elements = [];
200
        $filter = json_decode($this->getFilterOne($object), true);
201
202
        foreach ($this->files as $json) {
203
            if (isset($json['content'])) {
204
                foreach ($json['content'] as $object) {
205
                    if (!is_array($object)) {
206
                        throw new JsonException\ArrayExpected('json must contain an array of objects');
207
                    }
208
209
                    if (count(array_intersect_assoc($object, $filter)) !== count($filter)) {
210
                        continue;
211
                    }
212
                    $elements[] = $object;
213
                }
214
            }
215
216
            if (count($elements) > 1) {
217
                throw new Exception\ObjectMultipleFound('found more than one object with filter '.json_encode($filter));
218
            }
219
            if (count($elements) === 0) {
220
                throw new Exception\ObjectNotFound('no object found with filter '.json_encode($filter));
221
            }
222
223
            return $this->build(array_shift($elements));
224
        }
225
    }
226
}
227