1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/* |
4
|
|
|
* This file is part of the puli/manager package. |
5
|
|
|
* |
6
|
|
|
* (c) Bernhard Schussek <[email protected]> |
7
|
|
|
* |
8
|
|
|
* For the full copyright and license information, please view the LICENSE |
9
|
|
|
* file that was distributed with this source code. |
10
|
|
|
*/ |
11
|
|
|
|
12
|
|
|
namespace Puli\Manager\Package; |
13
|
|
|
|
14
|
|
|
use Puli\Manager\Api\Config\Config; |
15
|
|
|
use Puli\Manager\Api\Factory\FactoryManager; |
16
|
|
|
use Puli\Manager\Api\FileNotFoundException; |
17
|
|
|
use Puli\Manager\Api\InvalidConfigException; |
18
|
|
|
use Puli\Manager\Api\Package\PackageFile; |
19
|
|
|
use Puli\Manager\Api\Package\RootPackageFile; |
20
|
|
|
use Puli\Manager\Api\Storage\ReadException; |
21
|
|
|
use Puli\Manager\Api\Storage\Storage; |
22
|
|
|
use Puli\Manager\Api\Storage\WriteException; |
23
|
|
|
use stdClass; |
24
|
|
|
use Webmozart\Json\Conversion\ConversionFailedException; |
25
|
|
|
use Webmozart\Json\Conversion\JsonConverter; |
26
|
|
|
use Webmozart\Json\DecodingFailedException; |
27
|
|
|
use Webmozart\Json\EncodingFailedException; |
28
|
|
|
use Webmozart\Json\JsonDecoder; |
29
|
|
|
use Webmozart\Json\JsonEncoder; |
30
|
|
|
|
31
|
|
|
/** |
32
|
|
|
* Loads and saves package files. |
33
|
|
|
* |
34
|
|
|
* @since 1.0 |
35
|
|
|
* |
36
|
|
|
* @author Bernhard Schussek <[email protected]> |
37
|
|
|
*/ |
38
|
|
|
class PackageFileStorage |
39
|
|
|
{ |
40
|
|
|
/** |
41
|
|
|
* @var Storage |
42
|
|
|
*/ |
43
|
|
|
private $storage; |
44
|
|
|
|
45
|
|
|
/** |
46
|
|
|
* @var JsonConverter |
47
|
|
|
*/ |
48
|
|
|
private $packageFileConverter; |
49
|
|
|
|
50
|
|
|
/** |
51
|
|
|
* @var JsonConverter |
52
|
|
|
*/ |
53
|
|
|
private $rootPackageFileConverter; |
54
|
|
|
|
55
|
|
|
/** |
56
|
|
|
* @var JsonEncoder |
57
|
|
|
*/ |
58
|
|
|
private $jsonEncoder; |
59
|
|
|
|
60
|
|
|
/** |
61
|
|
|
* @var JsonDecoder |
62
|
|
|
*/ |
63
|
|
|
private $jsonDecoder; |
64
|
|
|
|
65
|
|
|
/** |
66
|
|
|
* @var FactoryManager |
67
|
|
|
*/ |
68
|
|
|
private $factoryManager; |
69
|
|
|
|
70
|
|
|
/** |
71
|
|
|
* Creates a new storage. |
72
|
|
|
* |
73
|
|
|
* @param Storage $storage The file storage. |
74
|
|
|
* @param JsonConverter $packageFileConverter The JSON converter for |
75
|
|
|
* {@link PackageFile} |
76
|
|
|
* instances. |
77
|
|
|
* @param JsonConverter $rootPackageFileConverter The JSON converter |
78
|
|
|
* for {@link RootPackageFile} |
79
|
|
|
* instances. |
80
|
|
|
* @param JsonEncoder $jsonEncoder The JSON encoder. |
81
|
|
|
* @param JsonDecoder $jsonDecoder The JSON decoder. |
82
|
|
|
* @param FactoryManager|null $factoryManager The manager used to |
83
|
|
|
* regenerate the factory |
84
|
|
|
* class after saving |
85
|
|
|
* the root package file. |
86
|
|
|
*/ |
87
|
40 |
View Code Duplication |
public function __construct( |
|
|
|
|
88
|
|
|
Storage $storage, |
89
|
|
|
JsonConverter $packageFileConverter, |
90
|
|
|
JsonConverter $rootPackageFileConverter, |
91
|
|
|
JsonEncoder $jsonEncoder, |
92
|
|
|
JsonDecoder $jsonDecoder, |
93
|
|
|
FactoryManager $factoryManager = null |
94
|
|
|
) { |
95
|
40 |
|
$this->storage = $storage; |
96
|
40 |
|
$this->packageFileConverter = $packageFileConverter; |
97
|
40 |
|
$this->rootPackageFileConverter = $rootPackageFileConverter; |
98
|
40 |
|
$this->jsonEncoder = $jsonEncoder; |
99
|
40 |
|
$this->jsonDecoder = $jsonDecoder; |
100
|
40 |
|
$this->factoryManager = $factoryManager; |
101
|
40 |
|
} |
102
|
|
|
|
103
|
|
|
/** |
104
|
|
|
* Loads a package file from a file path. |
105
|
|
|
* |
106
|
|
|
* If the file does not exist, an empty configuration is returned. |
107
|
|
|
* |
108
|
|
|
* Loaded package files must have a package name set. If none is set, an |
109
|
|
|
* exception is thrown. |
110
|
|
|
* |
111
|
|
|
* @param string $path The path to the package file. |
112
|
|
|
* |
113
|
|
|
* @return PackageFile The loaded package file. |
114
|
|
|
* |
115
|
|
|
* @throws FileNotFoundException If the file does not exist. |
116
|
|
|
* @throws ReadException If the file cannot be read. |
117
|
|
|
* @throws InvalidConfigException If the file contains invalid configuration. |
118
|
|
|
*/ |
119
|
17 |
View Code Duplication |
public function loadPackageFile($path) |
|
|
|
|
120
|
|
|
{ |
121
|
17 |
|
$json = $this->storage->read($path); |
122
|
17 |
|
$jsonData = $this->decode($json, $path); |
123
|
|
|
|
124
|
|
|
try { |
125
|
16 |
|
return $this->packageFileConverter->fromJson($jsonData, array( |
126
|
16 |
|
'path' => $path, |
127
|
|
|
)); |
128
|
1 |
|
} catch (ConversionFailedException $e) { |
129
|
1 |
|
throw new InvalidConfigException(sprintf( |
130
|
1 |
|
'The JSON in %s could not be converted: %s', |
131
|
|
|
$path, |
132
|
1 |
|
$e->getMessage() |
133
|
1 |
|
), 0, $e); |
134
|
|
|
} |
135
|
|
|
} |
136
|
|
|
|
137
|
|
|
/** |
138
|
|
|
* Saves a package file. |
139
|
|
|
* |
140
|
|
|
* The package file is saved to the same path that it was read from. |
141
|
|
|
* |
142
|
|
|
* @param PackageFile $packageFile The package file to save. |
143
|
|
|
* |
144
|
|
|
* @throws WriteException If the file cannot be written. |
145
|
|
|
* @throws InvalidConfigException If the file contains invalid configuration. |
146
|
|
|
*/ |
147
|
3 |
|
public function savePackageFile(PackageFile $packageFile) |
148
|
|
|
{ |
149
|
|
|
try { |
150
|
3 |
|
$jsonData = $this->packageFileConverter->toJson($packageFile, array( |
151
|
3 |
|
'targetVersion' => $packageFile->getVersion(), |
152
|
|
|
)); |
153
|
1 |
|
} catch (ConversionFailedException $e) { |
154
|
1 |
|
throw new InvalidConfigException(sprintf( |
155
|
1 |
|
'The data written to %s could not be converted: %s', |
156
|
1 |
|
$packageFile->getPath(), |
157
|
1 |
|
$e->getMessage() |
158
|
1 |
|
), 0, $e); |
159
|
|
|
} |
160
|
|
|
|
161
|
2 |
|
$json = $this->encode($jsonData, $packageFile->getPath()); |
162
|
|
|
|
163
|
1 |
|
$this->storage->write($packageFile->getPath(), $json); |
164
|
1 |
|
} |
165
|
|
|
|
166
|
|
|
/** |
167
|
|
|
* Loads a root package file from a file path. |
168
|
|
|
* |
169
|
|
|
* If the file does not exist, an empty configuration is returned. |
170
|
|
|
* |
171
|
|
|
* @param string $path The path to the package configuration file. |
172
|
|
|
* @param Config $baseConfig The configuration that the package will inherit |
173
|
|
|
* its configuration values from. |
174
|
|
|
* |
175
|
|
|
* @return RootPackageFile The loaded package file. |
176
|
|
|
* |
177
|
|
|
* @throws FileNotFoundException If the file does not exist. |
178
|
|
|
* @throws ReadException If the file cannot be read. |
179
|
|
|
* @throws InvalidConfigException If the file contains invalid configuration. |
180
|
|
|
*/ |
181
|
30 |
View Code Duplication |
public function loadRootPackageFile($path, Config $baseConfig) |
|
|
|
|
182
|
|
|
{ |
183
|
30 |
|
$json = $this->storage->read($path); |
184
|
29 |
|
$jsonData = $this->decode($json, $path); |
185
|
|
|
|
186
|
|
|
try { |
187
|
28 |
|
return $this->rootPackageFileConverter->fromJson($jsonData, array( |
188
|
28 |
|
'path' => $path, |
189
|
28 |
|
'baseConfig' => $baseConfig, |
190
|
|
|
)); |
191
|
1 |
|
} catch (ConversionFailedException $e) { |
192
|
1 |
|
throw new InvalidConfigException(sprintf( |
193
|
1 |
|
'The JSON in %s could not be converted: %s', |
194
|
|
|
$path, |
195
|
1 |
|
$e->getMessage() |
196
|
1 |
|
), 0, $e); |
197
|
|
|
} |
198
|
|
|
} |
199
|
|
|
|
200
|
|
|
/** |
201
|
|
|
* Saves a root package file. |
202
|
|
|
* |
203
|
|
|
* The package file is saved to the same path that it was read from. |
204
|
|
|
* |
205
|
|
|
* @param RootPackageFile $packageFile The package file to save. |
206
|
|
|
* |
207
|
|
|
* @throws WriteException If the file cannot be written. |
208
|
|
|
* @throws InvalidConfigException If the file contains invalid configuration. |
209
|
|
|
*/ |
210
|
4 |
View Code Duplication |
public function saveRootPackageFile(RootPackageFile $packageFile) |
|
|
|
|
211
|
|
|
{ |
212
|
|
|
try { |
213
|
4 |
|
$jsonData = $this->rootPackageFileConverter->toJson($packageFile, array( |
214
|
4 |
|
'targetVersion' => $packageFile->getVersion(), |
215
|
|
|
)); |
216
|
1 |
|
} catch (ConversionFailedException $e) { |
217
|
1 |
|
throw new InvalidConfigException(sprintf( |
218
|
1 |
|
'The data written to %s could not be converted: %s', |
219
|
1 |
|
$packageFile->getPath(), |
220
|
1 |
|
$e->getMessage() |
221
|
1 |
|
), 0, $e); |
222
|
|
|
} |
223
|
|
|
|
224
|
3 |
|
$json = $this->encode($jsonData, $packageFile->getPath()); |
225
|
|
|
|
226
|
2 |
|
$this->storage->write($packageFile->getPath(), $json); |
227
|
|
|
|
228
|
2 |
|
if ($this->factoryManager) { |
229
|
1 |
|
$this->factoryManager->autoGenerateFactoryClass(); |
230
|
|
|
} |
231
|
2 |
|
} |
232
|
|
|
|
233
|
5 |
View Code Duplication |
private function encode(stdClass $jsonData, $path) |
|
|
|
|
234
|
|
|
{ |
235
|
|
|
try { |
236
|
5 |
|
return $this->jsonEncoder->encode($jsonData); |
237
|
2 |
|
} catch (EncodingFailedException $e) { |
238
|
2 |
|
throw new InvalidConfigException(sprintf( |
239
|
2 |
|
'The configuration in %s could not be encoded: %s', |
240
|
|
|
$path, |
241
|
2 |
|
$e->getMessage() |
242
|
2 |
|
), 0, $e); |
243
|
|
|
} |
244
|
|
|
} |
245
|
|
|
|
246
|
32 |
View Code Duplication |
private function decode($json, $path) |
|
|
|
|
247
|
|
|
{ |
248
|
|
|
try { |
249
|
32 |
|
return $this->jsonDecoder->decode($json); |
250
|
2 |
|
} catch (DecodingFailedException $e) { |
251
|
2 |
|
throw new InvalidConfigException(sprintf( |
252
|
2 |
|
'The configuration in %s could not be decoded: %s', |
253
|
|
|
$path, |
254
|
2 |
|
$e->getMessage() |
255
|
2 |
|
), 0, $e); |
256
|
|
|
} |
257
|
|
|
} |
258
|
|
|
} |
259
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.