license helper
[pharext/pharext] / src / pharext / SourceDir / Pecl.php
1 <?php
2
3 namespace pharext\SourceDir;
4
5 use pharext\Cli\Args;
6 use pharext\Exception;
7 use pharext\SourceDir;
8 use pharext\License;
9
10 /**
11 * A PECL extension source directory containing a v2 package.xml
12 */
13 class Pecl implements \IteratorAggregate, SourceDir
14 {
15 use License;
16
17 /**
18 * The package.xml
19 * @var SimpleXmlElement
20 */
21 private $sxe;
22
23 /**
24 * The base directory
25 * @var string
26 */
27 private $path;
28
29 /**
30 * The package.xml
31 * @var string
32 */
33 private $file;
34
35 /**
36 * @inheritdoc
37 * @see \pharext\SourceDir::__construct()
38 */
39 public function __construct($path) {
40 if (is_file("$path/package2.xml")) {
41 $sxe = simplexml_load_file($this->file = "$path/package2.xml");
42 } elseif (is_file("$path/package.xml")) {
43 $sxe = simplexml_load_file($this->file = "$path/package.xml");
44 } else {
45 throw new Exception("Missing package.xml in $path");
46 }
47
48 $sxe->registerXPathNamespace("pecl", $sxe->getDocNamespaces()[""]);
49
50 $this->sxe = $sxe;
51 $this->path = realpath($path);
52 }
53
54 /**
55 * @inheritdoc
56 * @see \pharext\SourceDir::getBaseDir()
57 */
58 public function getBaseDir() {
59 return $this->path;
60 }
61
62 /**
63 * Retrieve gathered package info
64 * @return Generator
65 */
66 public function getPackageInfo() {
67 if (($name = $this->sxe->xpath("/pecl:package/pecl:name"))) {
68 yield "name" => (string) $name[0];
69 }
70 if (($release = $this->sxe->xpath("/pecl:package/pecl:version/pecl:release"))) {
71 yield "release" => (string) $release[0];
72 }
73 if ($this->sxe->xpath("/pecl:package/pecl:zendextsrcrelease")) {
74 yield "zend" => true;
75 }
76 }
77
78 /**
79 * @inheritdoc
80 * @return string
81 */
82 public function getLicense() {
83 if (($license = $this->sxe->xpath("/pecl:package/pecl:license"))) {
84 if (($file = $this->findLicense($this->getBaseDir(), $license[0]["filesource"]))) {
85 return $this->readLicense($file);
86 }
87 }
88 if (($file = $this->findLicense($this->getBaseDir()))) {
89 return $this->readLicense($file);
90 }
91 if ($license) {
92 return $license[0] ." ". $license[0]["uri"];
93 }
94 return "UNKNOWN";
95 }
96
97 /**
98 * @inheritdoc
99 * @see \pharext\SourceDir::getArgs()
100 */
101 public function getArgs() {
102 $configure = $this->sxe->xpath("/pecl:package/pecl:extsrcrelease/pecl:configureoption");
103 foreach ($configure as $cfg) {
104 yield [null, $cfg["name"], ucfirst($cfg["prompt"]), Args::OPTARG,
105 strlen($cfg["default"]) ? $cfg["default"] : null];
106 }
107 $configure = $this->sxe->xpath("/pecl:package/pecl:zendextsrcrelease/pecl:configureoption");
108 foreach ($configure as $cfg) {
109 yield [null, $cfg["name"], ucfirst($cfg["prompt"]), Args::OPTARG,
110 strlen($cfg["default"]) ? $cfg["default"] : null];
111 }
112 }
113
114 /**
115 * @inheritdoc
116 * @see \pharext\SourceDir::setArgs()
117 */
118 public function setArgs(Args $args) {
119 $configure = $this->sxe->xpath("/pecl:package/pecl:extsrcrelease/pecl:configureoption");
120 foreach ($configure as $cfg) {
121 if (isset($args[$cfg["name"]])) {
122 $args->configure = "--{$cfg["name"]}={$args[$cfg["name"]]}";
123 }
124 }
125 $configure = $this->sxe->xpath("/pecl:package/pecl:zendextsrcrelease/pecl:configureoption");
126 foreach ($configure as $cfg) {
127 if (isset($args[$cfg["name"]])) {
128 $args->configure = "--{$cfg["name"]}={$args[$cfg["name"]]}";
129 }
130 }
131 }
132
133 /**
134 * Compute the path of a file by parent dir nodes
135 * @param \SimpleXMLElement $ele
136 * @return string
137 */
138 private function dirOf($ele) {
139 $path = "";
140 while (($ele = current($ele->xpath(".."))) && $ele->getName() == "dir") {
141 $path = trim($ele["name"], "/") ."/". $path ;
142 }
143 return trim($path, "/");
144 }
145
146 /**
147 * Generate a list of files from the package.xml
148 * @return Generator
149 */
150 private function generateFiles() {
151 /* hook */
152 $temp = tmpfile();
153 fprintf($temp, "<?php\nreturn new %s(__DIR__);\n", get_class($this));
154 rewind($temp);
155 yield "pharext_package.php" => $temp;
156
157 /* deps */
158 $dependencies = $this->sxe->xpath("/pecl:package/pecl:dependencies/pecl:required/pecl:package");
159 foreach ($dependencies as $key => $dep) {
160 if (($glob = glob("{$this->path}/{$dep->name}-*.ext.phar*"))) {
161 usort($glob, function($a, $b) {
162 return version_compare(
163 substr($a, strpos(".ext.phar", $a)),
164 substr($b, strpos(".ext.phar", $b))
165 );
166 });
167 yield end($glob);
168 }
169 }
170
171 /* files */
172 yield realpath($this->file);
173 foreach ($this->sxe->xpath("//pecl:file") as $file) {
174 yield realpath($this->path ."/". $this->dirOf($file) ."/". $file["name"]);
175 }
176 }
177
178 /**
179 * Implements IteratorAggregate
180 * @see IteratorAggregate::getIterator()
181 */
182 public function getIterator() {
183 return $this->generateFiles();
184 }
185 }