Implement packager and installer hooks
[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 * Installer hook
30 * @var string
31 */
32 private $hook;
33
34 /**
35 * @inheritdoc
36 * @see \pharext\SourceDir::__construct()
37 */
38 public function __construct(Command $cmd, $path) {
39 $sxe = simplexml_load_file("$path/package.xml");
40 $sxe->registerXPathNamespace("pecl", $sxe->getDocNamespaces()[""]);
41
42 $args = $cmd->getArgs();
43 if (!isset($args->name)) {
44 $name = (string) $sxe->xpath("/pecl:package/pecl:name")[0];
45 foreach ($args->parse(2, ["--name", $name]) as $error) {
46 $cmd->error("%s\n", $error);
47 }
48 }
49
50 if (!isset($args->release)) {
51 $release = (string) $sxe->xpath("/pecl:package/pecl:version/pecl:release")[0];
52 foreach ($args->parse(2, ["--release", $release]) as $error) {
53 $cmd->error("%s\n", $error);
54 }
55 }
56
57 if (($configure = $sxe->xpath("/pecl:package/pecl:extsrcrelease/pecl:configureoption"))) {
58 $this->hook = tmpfile();
59 ob_start(function($s) {
60 fwrite($this->hook, $s);
61 return null;
62 });
63 call_user_func(function() use ($configure) {
64 include __DIR__."/../pharext_install.tpl.php";
65 });
66 ob_end_flush();
67 }
68
69 $this->cmd = $cmd;
70 $this->sxe = $sxe;
71 $this->path = $path;
72 }
73
74 /**
75 * @inheritdoc
76 * @see \pharext\SourceDir::getBaseDir()
77 */
78 public function getBaseDir() {
79 return $this->path;
80 }
81
82 /**
83 * Compute the path of a file by parent dir nodes
84 * @param \SimpleXMLElement $ele
85 * @return string
86 */
87 private function dirOf($ele) {
88 $path = "";
89 while (($ele = current($ele->xpath(".."))) && $ele->getName() == "dir") {
90 $path = trim($ele["name"], "/") ."/". $path ;
91 }
92 return trim($path, "/");
93 }
94
95 /**
96 * Generate a list of files from the package.xml
97 * @return Generator
98 */
99 private function generateFiles() {
100 if ($this->hook) {
101 rewind($this->hook);
102 yield "pharext_install.php" => $this->hook;
103 }
104 foreach ($this->sxe->xpath("//pecl:file") as $file) {
105 $path = $this->path ."/". $this->dirOf($file) ."/". $file["name"];
106 if ($this->cmd->getArgs()->verbose) {
107 $this->cmd->info("Packaging %s\n", $path);
108 }
109 if (!($realpath = realpath($path))) {
110 $this->cmd->error("File %s does not exist", $path);
111 }
112 yield $realpath;
113 }
114 }
115
116 /**
117 * Implements IteratorAggregate
118 * @see IteratorAggregate::getIterator()
119 */
120 public function getIterator() {
121 return $this->generateFiles();
122 }
123 }