16
16
use Passbook \Certificate \P12 ;
17
17
use Passbook \Certificate \WWDR ;
18
18
use Passbook \Exception \FileException ;
19
+ use Passbook \Exception \PassInvalidException ;
19
20
use Passbook \Pass \Image ;
20
21
use RecursiveDirectoryIterator ;
21
22
use RecursiveIteratorIterator ;
@@ -83,6 +84,11 @@ class PassFactory
83
84
*/
84
85
protected $ skipSignature ;
85
86
87
+ /**
88
+ * @var PassValidatorInterface
89
+ */
90
+ private $ passValidator ;
91
+
86
92
/**
87
93
* Pass file extension
88
94
*
@@ -96,9 +102,13 @@ public function __construct($passTypeIdentifier, $teamIdentifier, $organizationN
96
102
$ this ->passTypeIdentifier = $ passTypeIdentifier ;
97
103
$ this ->teamIdentifier = $ teamIdentifier ;
98
104
$ this ->organizationName = $ organizationName ;
105
+
99
106
// Create certificate objects
100
107
$ this ->p12 = new P12 ($ p12File , $ p12Pass );
101
108
$ this ->wwdr = new WWDR ($ wwdrFile );
109
+
110
+ // By default use the PassValidator
111
+ $ this ->passValidator = new PassValidator ();
102
112
}
103
113
104
114
/**
@@ -125,6 +135,16 @@ public function getOutputPath()
125
135
return $ this ->outputPath ;
126
136
}
127
137
138
+ /**
139
+ * The output path with a directory separator on the end.
140
+ *
141
+ * @return string
142
+ */
143
+ public function getNormalizedOutputPath ()
144
+ {
145
+ return rtrim ($ this ->outputPath , DIRECTORY_SEPARATOR ) . DIRECTORY_SEPARATOR ;
146
+ }
147
+
128
148
/**
129
149
* Set overwrite
130
150
*
@@ -156,6 +176,7 @@ public function isOverwrite()
156
176
* be used for testing.
157
177
*
158
178
* @param boolean
179
+ *
159
180
* @return $this
160
181
*/
161
182
public function setSkipSignature ($ skipSignature )
@@ -166,14 +187,39 @@ public function setSkipSignature($skipSignature)
166
187
}
167
188
168
189
/**
169
- * Get overwrite
190
+ * Get skip signature
191
+ *
170
192
* @return boolean
171
193
*/
172
194
public function getSkipSignature ()
173
195
{
174
196
return $ this ->skipSignature ;
175
197
}
176
198
199
+ /**
200
+ * Set an implementation of PassValidatorInterface to validate the pass
201
+ * before packaging. When set to null, no validation is performed when
202
+ * packaging the pass.
203
+ *
204
+ * @param PassValidatorInterface|null $passValidator
205
+ *
206
+ * @return $this
207
+ */
208
+ public function setPassValidator (PassValidatorInterface $ passValidator = null )
209
+ {
210
+ $ this ->passValidator = $ passValidator ;
211
+
212
+ return $ this ;
213
+ }
214
+
215
+ /**
216
+ * @return PassValidatorInterface
217
+ */
218
+ public function getPassValidator ()
219
+ {
220
+ return $ this ->passValidator ;
221
+ }
222
+
177
223
/**
178
224
* Serialize pass
179
225
*
@@ -203,80 +249,31 @@ public function package(PassInterface $pass, $passName = '')
203
249
204
250
$ this ->populateRequiredInformation ($ pass );
205
251
206
- // Serialize pass
207
- $ json = self ::serialize ($ pass );
208
-
209
- $ outputPath = rtrim ($ this ->getOutputPath (), DIRECTORY_SEPARATOR ) . DIRECTORY_SEPARATOR ;
210
- $ passDir = $ outputPath . $ this ->getPassName ($ passName , $ pass ) . DIRECTORY_SEPARATOR ;
211
- $ passDirExists = file_exists ($ passDir );
212
- if ($ passDirExists && !$ this ->isOverwrite ()) {
213
- throw new FileException ("Temporary pass directory already exists " );
214
- } elseif (!$ passDirExists && !mkdir ($ passDir , 0777 , true )) {
215
- throw new FileException ("Couldn't create temporary pass directory " );
252
+ if ($ this ->passValidator ) {
253
+ if (!$ this ->passValidator ->validate ($ pass )){
254
+ throw new PassInvalidException ($ this ->passValidator ->getErrors ());
255
+ };
216
256
}
217
257
218
- // Pass.json
219
- $ passJSONFile = $ passDir . 'pass.json ' ;
220
- file_put_contents ($ passJSONFile , $ json );
258
+ $ passDir = $ this ->preparePassDirectory ($ pass );
259
+
260
+ // Serialize pass
261
+ file_put_contents ($ passDir . 'pass.json ' , self ::serialize ($ pass ));
221
262
222
263
// Images
223
- /** @var Image $image */
224
- foreach ($ pass ->getImages () as $ image ) {
225
- $ fileName = $ passDir . $ image ->getContext ();
226
- if ($ image ->isRetina ()) {
227
- $ fileName .= '@2x ' ;
228
- }
229
- $ fileName .= '. ' . $ image ->getExtension ();
230
- copy ($ image ->getPathname (), $ fileName );
231
- }
264
+ $ this ->prepareImages ($ pass , $ passDir );
232
265
233
266
// Localizations
234
- foreach ($ pass ->getLocalizations () as $ localization ) {
235
- // Create dir (LANGUAGE.lproj)
236
- $ localizationDir = $ passDir . $ localization ->getLanguage () . '.lproj ' . DIRECTORY_SEPARATOR ;
237
- mkdir ($ localizationDir , 0777 , true );
238
-
239
- // pass.strings File (Format: "token" = "value")
240
- $ localizationStringsFile = $ localizationDir . 'pass.strings ' ;
241
- file_put_contents ($ localizationStringsFile , $ localization ->getStringsFileOutput ());
242
-
243
- // Localization images
244
- foreach ($ localization ->getImages () as $ image ) {
245
- $ fileName = $ localizationDir . $ image ->getContext ();
246
- if ($ image ->isRetina ()) {
247
- $ fileName .= '@2x ' ;
248
- }
249
- $ fileName .= '. ' . $ image ->getExtension ();
250
- copy ($ image ->getPathname (), $ fileName );
251
- }
252
- }
267
+ $ this ->prepareLocalizations ($ pass , $ passDir );
253
268
254
269
// Manifest.json - recursive, also add files in sub directories
255
- $ manifestJSONFile = $ passDir . 'manifest.json ' ;
256
- $ manifest = array ();
257
- $ files = new RecursiveIteratorIterator (
258
- new RecursiveDirectoryIterator ($ passDir ),
259
- RecursiveIteratorIterator::SELF_FIRST
260
- );
261
- foreach ($ files as $ file ) {
262
- // Ignore "." and ".." folders
263
- if (in_array (substr ($ file , strrpos ($ file , '/ ' ) + 1 ), array ('. ' , '.. ' ))) {
264
- continue ;
265
- }
266
- //
267
- $ filePath = realpath ($ file );
268
- if (is_file ($ filePath ) === true ) {
269
- $ relativePathName = str_replace ($ passDir , '' , $ file ->getPathname ());
270
- $ manifest [$ relativePathName ] = sha1_file ($ filePath );
271
- }
272
- }
273
- file_put_contents ($ manifestJSONFile , $ this ->jsonEncode ($ manifest ));
270
+ $ manifestJSONFile = $ this ->prepareManifest ($ passDir );
274
271
275
272
// Signature
276
273
$ this ->sign ($ passDir , $ manifestJSONFile );
277
274
278
275
// Zip pass
279
- $ zipFile = $ outputPath . $ this ->getPassName ($ passName , $ pass ) . self ::PASS_EXTENSION ;
276
+ $ zipFile = $ this -> getNormalizedOutputPath () . $ this ->getPassName ($ passName , $ pass ) . self ::PASS_EXTENSION ;
280
277
$ this ->zip ($ passDir , $ zipFile );
281
278
282
279
// Remove temporary pass directory
@@ -311,7 +308,7 @@ private function sign($passDir, $manifestJSONFile)
311
308
$ this ->wwdr ->getRealPath ()
312
309
);
313
310
// Get signature content
314
- $ signature = @ file_get_contents ($ signatureFile );
311
+ $ signature = file_get_contents ($ signatureFile );
315
312
// Check signature content
316
313
if (!$ signature ) {
317
314
throw new FileException ("Couldn't read signature file. " );
@@ -432,4 +429,97 @@ public function getPassName($passName, PassInterface $pass)
432
429
return strlen ($ passNameSanitised ) != 0 ? $ passNameSanitised : $ pass ->getSerialNumber ();
433
430
}
434
431
432
+ /**
433
+ * @param $passDir
434
+ *
435
+ * @return string
436
+ */
437
+ private function prepareManifest ($ passDir )
438
+ {
439
+ $ manifestJSONFile = $ passDir . 'manifest.json ' ;
440
+ $ manifest = array ();
441
+ $ files = new RecursiveIteratorIterator (
442
+ new RecursiveDirectoryIterator ($ passDir ),
443
+ RecursiveIteratorIterator::SELF_FIRST
444
+ );
445
+ foreach ($ files as $ file ) {
446
+ // Ignore "." and ".." folders
447
+ if (in_array (substr ($ file , strrpos ($ file , '/ ' ) + 1 ), array ('. ' , '.. ' ))) {
448
+ continue ;
449
+ }
450
+ //
451
+ $ filePath = realpath ($ file );
452
+ if (is_file ($ filePath ) === true ) {
453
+ $ relativePathName = str_replace ($ passDir , '' , $ file ->getPathname ());
454
+ $ manifest [$ relativePathName ] = sha1_file ($ filePath );
455
+ }
456
+ }
457
+ file_put_contents ($ manifestJSONFile , $ this ->jsonEncode ($ manifest ));
458
+
459
+ return $ manifestJSONFile ;
460
+ }
461
+
462
+ /**
463
+ * @param PassInterface $pass
464
+ *
465
+ * @return string
466
+ */
467
+ private function preparePassDirectory (PassInterface $ pass )
468
+ {
469
+ $ passDir = $ this ->getNormalizedOutputPath () . $ pass ->getSerialNumber () . DIRECTORY_SEPARATOR ;
470
+ $ passDirExists = file_exists ($ passDir );
471
+ if ($ passDirExists && !$ this ->isOverwrite ()) {
472
+ throw new FileException ("Temporary pass directory already exists " );
473
+ } elseif (!$ passDirExists && !mkdir ($ passDir , 0777 , true )) {
474
+ throw new FileException ("Couldn't create temporary pass directory " );
475
+ }
476
+
477
+ return $ passDir ;
478
+ }
479
+
480
+ /**
481
+ * @param PassInterface $pass
482
+ * @param $passDir
483
+ */
484
+ private function prepareImages (PassInterface $ pass , $ passDir )
485
+ {
486
+ /** @var Image $image */
487
+ foreach ($ pass ->getImages () as $ image ) {
488
+ $ fileName = $ passDir . $ image ->getContext ();
489
+ if ($ image ->isRetina ()) {
490
+ $ fileName .= '@2x ' ;
491
+ }
492
+ $ fileName .= '. ' . $ image ->getExtension ();
493
+ copy ($ image ->getPathname (), $ fileName );
494
+ }
495
+ }
496
+
497
+ /**
498
+ * @param PassInterface $pass
499
+ * @param $passDir
500
+ */
501
+ private function prepareLocalizations (PassInterface $ pass , $ passDir )
502
+ {
503
+ foreach ($ pass ->getLocalizations () as $ localization ) {
504
+ // Create dir (LANGUAGE.lproj)
505
+ $ localizationDir = $ passDir . $ localization ->getLanguage () . '.lproj ' . DIRECTORY_SEPARATOR ;
506
+ mkdir ($ localizationDir , 0777 , true );
507
+
508
+ // pass.strings File (Format: "token" = "value")
509
+ $ localizationStringsFile = $ localizationDir . 'pass.strings ' ;
510
+ file_put_contents ($ localizationStringsFile , $ localization ->getStringsFileOutput ());
511
+
512
+ // Localization images
513
+ foreach ($ localization ->getImages () as $ image ) {
514
+ $ fileName = $ localizationDir . $ image ->getContext ();
515
+ if ($ image ->isRetina ()) {
516
+ $ fileName .= '@2x ' ;
517
+ }
518
+ $ fileName .= '. ' . $ image ->getExtension ();
519
+ copy ($ image ->getPathname (), $ fileName );
520
+ }
521
+ }
522
+ }
523
+
524
+
435
525
}
0 commit comments