support for running .ext.phars without ext/phar
[pharext/pharext] / src / pharext / Task / PharBuild.php
1 <?php
2
3 namespace pharext\Task;
4
5 use pharext\Exception;
6 use pharext\SourceDir;
7 use pharext\Task;
8 use pharext\Tempname;
9
10 use Phar;
11
12 /**
13 * Build phar
14 */
15 class PharBuild implements Task
16 {
17 /**
18 * @var \pharext\SourceDir
19 */
20 private $source;
21
22 /**
23 * @var string
24 */
25 private $stub;
26
27 /**
28 * @var array
29 */
30 private $meta;
31
32 /**
33 * @var bool
34 */
35 private $readonly;
36
37 /**
38 * @param SourceDir $source extension source directory
39 * @param string $stub path to phar stub
40 * @param array $meta phar meta data
41 * @param bool $readonly whether the stub has -dphar.readonly=1 set
42 */
43 public function __construct(SourceDir $source = null, $stub, array $meta = null, $readonly = true) {
44 $this->source = $source;
45 $this->stub = $stub;
46 $this->meta = $meta;
47 $this->readonly = $readonly;
48 }
49
50 /**
51 * @param bool $verbose
52 * @return \pharext\Tempname
53 * @throws \pharext\Exception
54 */
55 public function run($verbose = false) {
56 /* Phar::compress() and ::convert*() use strtok("."), ugh!
57 * so, be sure to not use any other dots in the filename
58 * except for .phar
59 */
60 $temp = new Tempname("", "-pharext.phar");
61
62 $phar = new Phar($temp);
63 $phar->startBuffering();
64
65 if ($this->meta) {
66 $phar->setMetadata($this->meta);
67 }
68 if (is_file($this->stub)) {
69 $stub = preg_replace_callback('/^#include <([^>]+)>/m', function($includes) {
70 return file_get_contents($includes[1], true, null, 5);
71 }, file_get_contents($this->stub));
72 $phar->setStub($stub);
73 }
74
75 $phar->buildFromIterator((new Task\BundleGenerator)->run());
76
77 if ($this->source) {
78 if ($verbose) {
79 $bdir = $this->source->getBaseDir();
80 $blen = strlen($bdir);
81 foreach ($this->source as $index => $file) {
82 if (is_resource($file)) {
83 printf("Packaging %s ...\n", $index);
84 $phar[$index] = $file;
85 } else {
86 printf("Packaging %s ...\n", $index = trim(substr($file, $blen), "/"));
87 $phar->addFile($file, $index);
88 }
89 }
90 } else {
91 $phar->buildFromIterator($this->source, $this->source->getBaseDir());
92 }
93 }
94
95 $phar->stopBuffering();
96
97 if (!chmod($temp, fileperms($temp) | 0111)) {
98 throw new Exception;
99 }
100
101 return $temp;
102 }
103 }