openssl signing
[pharext/pharext] / src / pharext / PeclSourceDir.php
1 <?php
2
3 namespace pharext;
4
5 /**
6 * A PECL extension source directory containing a v2 package.xml
7 */
8 class PeclSourceDir implements \IteratorAggregate, SourceDir
9 {
10 /**
11 * The Packager command
12 * @var pharext\Packager
13 */
14 private $cmd;
15
16 /**
17 * The package.xml
18 * @var SimpleXmlElement
19 */
20 private $sxe;
21
22 /**
23 * The base directory
24 * @var string
25 */
26 private $path;
27
28 /**
29 * @inheritdoc
30 * @see \pharext\SourceDir::__construct()
31 */
32 public function __construct(Command $cmd, $path) {
33 if (!realpath("$path/package.xml")) {
34 throw new \Exception("Missing package.xml in $path");
35 }
36 $sxe = simplexml_load_file("$path/package.xml");
37 $sxe->registerXPathNamespace("pecl", $sxe->getDocNamespaces()[""]);
38
39 $args = $cmd->getArgs();
40 if (!isset($args->name)) {
41 $name = (string) $sxe->xpath("/pecl:package/pecl:name")[0];
42 foreach ($args->parse(2, ["--name", $name]) as $error) {
43 $cmd->error("%s\n", $error);
44 }
45 }
46
47 if (!isset($args->release)) {
48 $release = (string) $sxe->xpath("/pecl:package/pecl:version/pecl:release")[0];
49 foreach ($args->parse(2, ["--release", $release]) as $error) {
50 $cmd->error("%s\n", $error);
51 }
52 }
53
54 $this->cmd = $cmd;
55 $this->sxe = $sxe;
56 $this->path = $path;
57 }
58
59 /**
60 * @inheritdoc
61 * @see \pharext\SourceDir::getBaseDir()
62 */
63 public function getBaseDir() {
64 return $this->path;
65 }
66
67 /**
68 * Compute the path of a file by parent dir nodes
69 * @param \SimpleXMLElement $ele
70 * @return string
71 */
72 private function dirOf($ele) {
73 $path = "";
74 while (($ele = current($ele->xpath(".."))) && $ele->getName() == "dir") {
75 $path = trim($ele["name"], "/") ."/". $path ;
76 }
77 return trim($path, "/");
78 }
79
80 /**
81 * Render installer hook
82 * @param array $configure
83 * @return string
84 */
85 private static function loadHook($configure, $dependencies) {
86 return include __DIR__."/../pharext_install.tpl.php";
87 }
88
89 /**
90 * Create installer hook
91 * @return resource
92 */
93 private function generateHooks() {
94 $dependencies = $this->sxe->xpath("/pecl:package/pecl:dependencies/pecl:required/pecl:package");
95 foreach ($dependencies as $key => $dep) {
96 if (($glob = glob("{$this->path}/{$dep->name}-*.ext.phar*"))) {
97 usort($glob, function($a, $b) {
98 return version_compare(
99 substr($a, strpos(".ext.phar", $a)),
100 substr($b, strpos(".ext.phar", $b))
101 );
102 });
103 yield realpath($this->path."/".end($glob));
104 } else {
105 unset($dependencies[$key]);
106 }
107 }
108 $configure = $this->sxe->xpath("/pecl:package/pecl:extsrcrelease/pecl:configureoption");
109 if ($configure) {
110 $fd = tmpfile();
111 ob_start(function($s) use($fd){
112 fwrite($fd, $s);
113 return null;
114 });
115 self::loadHook($configure, $dependencies);
116 ob_end_flush();
117 rewind($fd);
118 yield "pharext_install.php" => $fd;
119 }
120 }
121
122 /**
123 * Generate a list of files from the package.xml
124 * @return Generator
125 */
126 private function generateFiles() {
127 foreach ($this->generateHooks() as $file => $hook) {
128 if ($this->cmd->getArgs()->verbose) {
129 $this->cmd->info("Packaging %s\n", is_string($hook) ? $hook : $file);
130 }
131 yield $file => $hook;
132 }
133 foreach ($this->sxe->xpath("//pecl:file") as $file) {
134 $path = $this->path ."/". $this->dirOf($file) ."/". $file["name"];
135 if ($this->cmd->getArgs()->verbose) {
136 $this->cmd->info("Packaging %s\n", $path);
137 }
138 if (!($realpath = realpath($path))) {
139 $this->cmd->error("File %s does not exist", $path);
140 }
141 yield $realpath;
142 }
143 }
144
145 /**
146 * Implements IteratorAggregate
147 * @see IteratorAggregate::getIterator()
148 */
149 public function getIterator() {
150 return $this->generateFiles();
151 }
152 }