Completed
Branch master (7d7b3f)
by Ori
01:38
created

BaseResource::getInlineDataStream()

Size

Total Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
nc 1
dl 0
loc 1
c 0
b 0
f 0
1
<?php
2
3
namespace frictionlessdata\datapackage\Resources;
4
5
use frictionlessdata\datapackage\DataStreams\BaseDataStream;
6
use frictionlessdata\datapackage\Registry;
7
use frictionlessdata\datapackage\Validators\ResourceValidationError;
8
use frictionlessdata\datapackage\Validators\ResourceValidator;
9
use frictionlessdata\datapackage\Exceptions\ResourceValidationFailedException;
10
use frictionlessdata\datapackage\Utils;
11
12
abstract class BaseResource implements \Iterator
13
{
14
    /**
15
     * BaseResource constructor.
16
     *
17
     * @param object      $descriptor
18
     * @param null|string $basePath
19
     *
20
     * @throws ResourceValidationFailedException
21
     */
22
    public function __construct($descriptor, $basePath, $skipValidations = false)
23
    {
24
        $this->basePath = $basePath;
25
        $this->descriptor = Utils::objectify($descriptor);
26
        $this->skipValidations = $skipValidations;
27
        if (!$this->skipValidations) {
28
            $validationErrors = $this->validateResource();
29
            if (count($validationErrors) > 0) {
30
                throw new ResourceValidationFailedException($validationErrors);
31
            }
32
        }
33
    }
34
35
    public static function handlesDescriptor($descriptor)
36
    {
37
        return static::handlesProfile(Registry::getResourceValidationProfile($descriptor));
38
    }
39
40
    public function read($options = null)
0 ignored issues
show
Unused Code introduced by
The parameter $options is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
41
    {
42
        $rows = [];
43
        foreach ($this as $row) {
44
            $rows[] = $row;
45
        }
46
47
        return $rows;
48
    }
49
50
    public function dataStreams()
51
    {
52
        if (is_null($this->dataStreams)) {
53
            $this->dataStreams = [];
54
            foreach ($this->path() as $path) {
55
                $this->dataStreams[] = $this->getDataStream($path);
56
            }
57
            $data = $this->data();
58
            if ($data) {
59
                $this->dataStreams[] = $this->getInlineDataStream($data);
60
            }
61
        }
62
63
        return $this->dataStreams;
64
    }
65
66
    /**
67
     * @return object
68
     */
69
    public function descriptor()
70
    {
71
        return $this->descriptor;
72
    }
73
74
    /**
75
     * @return string
76
     */
77
    public function name()
78
    {
79
        return $this->descriptor()->name;
80
    }
81
82
    public function path()
83
    {
84
        if (isset($this->descriptor()->path)) {
85
            $path = $this->descriptor()->path;
86
            if (!is_array($path)) {
87
                $path = [$path];
88
            }
89
90
            return $path;
91
        } else {
92
            return [];
93
        }
94
    }
95
96
    public function data()
97
    {
98
        return isset($this->descriptor()->data) ? $this->descriptor()->data : null;
99
    }
100
101
    // standard iterator functions - to iterate over the data sources
102
    public function rewind()
103
    {
104
        $this->dataStreams = null;
105
        $this->currentDataStream = 0;
106
        foreach ($this->dataStreams() as $dataStream) {
107
            $dataStream->rewind();
108
        }
109
    }
110
111
    public function current()
112
    {
113
        return $this->dataStreams()[$this->currentDataStream]->current();
114
    }
115
116
    public function key()
117
    {
118
        return $this->dataStreams()[$this->currentDataStream]->key();
119
    }
120
121
    public function next()
122
    {
123
        return $this->dataStreams()[$this->currentDataStream]->next();
124
    }
125
126
    public function valid()
127
    {
128
        $dataStreams = $this->dataStreams();
129
        if ($dataStreams[$this->currentDataStream]->valid()) {
130
            // current data stream is still valid
131
            return true;
132
        } else {
133
            ++$this->currentDataStream;
134
            if (isset($dataStreams[$this->currentDataStream])) {
135
                // current data stream is done, but we have another data stream
136
                return true;
137
            } else {
138
                // no more data and no more data streams
139
                return false;
140
            }
141
        }
142
    }
143
144
    public static function validateDataSource($dataSource, $basePath = null)
145
    {
146
        $errors = [];
147
        $dataSource = static::normalizeDataSource($dataSource, $basePath);
148
        if (!Utils::isHttpSource($dataSource) && !file_exists($dataSource)) {
149
            $errors[] = new ResourceValidationError(
150
                ResourceValidationError::SCHEMA_VIOLATION,
151
                "data source file does not exist or is not readable: {$dataSource}"
152
            );
153
        }
154
155
        return $errors;
156
    }
157
158
    /**
159
     * allows extending classes to add custom sources
160
     * used by unit tests to add a mock http source.
161
     *
162
     * @param string $dataSource
163
     * @param string $basePath
164
     *
165
     * @return string
166
     */
167
    public static function normalizeDataSource($dataSource, $basePath = null)
168
    {
169
        if (!empty($basePath) && !Utils::isHttpSource($dataSource)) {
170
            // TODO: support JSON pointers
171
            $absPath = $basePath.DIRECTORY_SEPARATOR.$dataSource;
172
            if (file_exists($absPath)) {
173
                $dataSource = $absPath;
174
            }
175
        }
176
177
        return $dataSource;
178
    }
179
180
    protected $descriptor;
181
    protected $basePath;
182
    protected $skipValidations = false;
183
    protected $currentDataPosition = 0;
184
    protected $currentDataStream = 0;
185
    protected $dataStreams = null;
186
187
    protected function validateResource()
188
    {
189
        return ResourceValidator::validate($this->descriptor(), $this->basePath);
190
    }
191
192
    /**
193
     * @param string $dataSource
194
     *
195
     * @return BaseDataStream
196
     */
197
    abstract protected function getDataStream($dataSource);
198
199
    abstract protected function getInlineDataStream($data);
200
201
    protected static function handlesProfile($profile)
202
    {
203
        return false;
204
    }
205
}
206