Completed
Pull Request — master (#42)
by
unknown
01:30
created

BaseDatapackage::copy()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace frictionlessdata\datapackage\Datapackages;
4
5
use frictionlessdata\datapackage\Factory;
6
use frictionlessdata\datapackage\Registry;
7
use frictionlessdata\datapackage\Utils;
8
use frictionlessdata\datapackage\Validators\DatapackageValidator;
9
use frictionlessdata\datapackage\Exceptions\DatapackageValidationFailedException;
10
use Chumper\Zipper\Zipper;
11
12
abstract class BaseDatapackage implements \Iterator
13
{
14
    /**
15
     * BaseDatapackage constructor.
16
     *
17
     * @param object      $descriptor
18
     * @param null|string $basePath
19
     *
20
     * @throws DatapackageValidationFailedException
21
     */
22
    public function __construct($descriptor, $basePath = null, $skipValidations = false)
23
    {
24
        $this->descriptor = $descriptor;
25
        $this->basePath = $basePath;
26
        $this->skipValidations = $skipValidations;
27
        if (!$this->skipValidations) {
28
            $this->revalidate();
29
        }
30
    }
31
32
    public static function create($name, $resources, $basePath = null)
33
    {
34
        $datapackage = new static((object) [
35
            'name' => $name,
36
            'resources' => [],
37
        ], $basePath, true);
38
        foreach ($resources as $resource) {
39
            $datapackage->addResource($resource);
0 ignored issues
show
Bug introduced by
The call to addResource() misses a required argument $resource.

This check looks for function calls that miss required arguments.

Loading history...
40
        }
41
42
        return $datapackage;
43
    }
44
45
    public function revalidate()
46
    {
47
        $this->rewind();
48
        $validationErrors = $this->datapackageValidate();
49
        if (count($validationErrors) > 0) {
50
            throw new DatapackageValidationFailedException($validationErrors);
51
        }
52
    }
53
54
    public static function handlesDescriptor($descriptor)
55
    {
56
        return static::handlesProfile(Registry::getDatapackageValidationProfile($descriptor));
57
    }
58
59
    /**
60
     * returns the descriptor as-is, without adding default values or normalizing.
61
     *
62
     * @return object
63
     */
64
    public function descriptor()
65
    {
66
        return $this->descriptor;
67
    }
68
69
    public function resources()
70
    {
71
        $resources = [];
72
        foreach ($this->descriptor->resources as $resourceDescriptor) {
73
            $resources[$resourceDescriptor->name] = $this->initResource($resourceDescriptor);
74
        }
75
76
        return $resources;
77
    }
78
79
    public function getResource($name)
80
    {
81
        foreach ($this->descriptor->resources as $resourceDescriptor) {
82
            if ($resourceDescriptor->name == $name) {
83
                return $this->initResource($resourceDescriptor);
84
            }
85
        }
86
        throw new \Exception("couldn't find matching resource with name =  '{$name}'");
87
    }
88
89
    public function addResource($name, $resource)
90
    {
91
        if (is_a($resource, 'frictionlessdata\\datapackage\\Resources\\BaseResource')) {
92
            $resource = $resource->descriptor();
93
        } else {
94
            $resource = Utils::objectify($resource);
95
        }
96
        $resource->name = $name;
97
        $resourceDescriptors = [];
98
        $gotMatch = false;
99
        foreach ($this->descriptor->resources as $resourceDescriptor) {
100
            if ($resourceDescriptor->name == $resource->name) {
101
                $resourceDescriptors[] = $resource;
102
                $gotMatch = true;
103
            } else {
104
                $resourceDescriptors[] = $resourceDescriptor;
105
            }
106
        }
107
        if (!$gotMatch) {
108
            $resourceDescriptors[] = $resource;
109
        }
110
        $this->descriptor->resources = $resourceDescriptors;
111
        if (!$this->skipValidations) {
112
            $this->revalidate();
113
        }
114
    }
115
116
    // TODO: remove this function and use the getResource / addResource directly (will need to modify a lot of tests code)
117
    public function resource($name, $resource = null)
118
    {
119
        if ($resource) {
120
            $this->addResource($name, $resource);
121
        } else {
122
            return $this->getResource($name);
123
        }
124
    }
125
126
    public function removeResource($name)
127
    {
128
        $resourceDescriptors = [];
129
        foreach ($this->descriptor->resources as $resourceDescriptor) {
130
            if ($resourceDescriptor->name != $name) {
131
                $resourceDescriptors[] = $resourceDescriptor;
132
            }
133
        }
134
        $this->descriptor->resources = $resourceDescriptors;
135
        if (!$this->skipValidations) {
136
            $this->revalidate();
137
        }
138
    }
139
140
    public function saveDescriptor($filename)
141
    {
142
        return file_put_contents($filename, json_encode($this->descriptor()));
143
    }
144
145
    // standard iterator functions - to iterate over the resources
146
    public function rewind()
147
    {
148
        $this->currentResourcePosition = 0;
149
    }
150
151
    public function current()
152
    {
153
        return $this->initResource($this->descriptor()->resources[$this->currentResourcePosition]);
154
    }
155
156
    public function key()
157
    {
158
        return $this->currentResourcePosition;
159
    }
160
161
    public function next()
162
    {
163
        ++$this->currentResourcePosition;
164
    }
165
166
    public function valid()
167
    {
168
        return isset($this->descriptor()->resources[$this->currentResourcePosition]);
169
    }
170
171
    public function save($zip_filename)
172
    {
173
        $zipper = new Zipper();
174
175
        $packageCopy = $this->copy();
176
177
        $base = tempnam(sys_get_temp_dir(), 'datapackage-zip-');
178
        $files = [
179
            'datapackage.json' => $base.'datapackage.json',
180
        ];
181
        $ri = 0;
182
183
        foreach ($packageCopy->resources() as $resource) {
184
            $resourceFiles = [];
185
            $fileNames = $resource->save($base.'resource-'.$ri);
186
            foreach ($fileNames as $fileName) {
187
                $relname = str_replace($base.'resource-'.$ri, '', $fileName);
188
                $files['resource-'.$ri.$relname] = $fileName;
189
                $resourceFiles []= 'resource-'.$ri.$relname;
190
            }
191
            $resource->descriptor()->path = count($resourceFiles) == 1 ? $resourceFiles[0] : $resourceFiles;
192
            ++$ri;
193
        }
194
195
        $packageCopy->saveDescriptor($files['datapackage.json']);
196
197
        /* @noinspection PhpUnhandledExceptionInspection Never occurs with our args */
198
        $zipper->make($zip_filename)->add($files)->close();
199
        foreach (array_values($files) as $file) {
200
            unlink($file);
201
        }
202
    }
203
204
    public function copy()
205
    {
206
        return new static($this->descriptor, $this->basePath, true);
207
    }
208
209
    protected $descriptor;
210
    protected $currentResourcePosition = 0;
211
    protected $basePath;
212
    protected $skipValidations = false;
213
214
    /**
215
     * called by the resources iterator for each iteration.
216
     *
217
     * @param object $descriptor
218
     *
219
     * @return \frictionlessdata\datapackage\Resources\BaseResource
220
     */
221
    protected function initResource($descriptor)
222
    {
223
        return Factory::resource($descriptor, $this->basePath, $this->skipValidations);
224
    }
225
226
    protected function datapackageValidate()
227
    {
228
        return DatapackageValidator::validate($this->descriptor(), $this->basePath);
229
    }
230
231
    protected static function handlesProfile($profile)
232
    {
233
        return false;
234
    }
235
}
236