travis: allow_failures
[m6w6/ext-http] / scripts / gen_stubs.php
1 #!/usr/bin/env php
2 <?php
3
4 function m($m, $c = null) {
5 $n = "";
6 if ($c && $c->isInterface()) {
7 $m ^= ReflectionMethod::IS_ABSTRACT;
8 }
9 foreach (Reflection::getModifierNames($m) as $mn) {
10 $n .= $mn . " ";
11 }
12 return $n;
13 }
14 function t($p) {
15 if ($c = $p->getClass()) return "\\" . $c->getName() . " ";
16 if ($p->isArray()) return "array ";
17 }
18 function c($n, $c) {
19 $_=$c;
20 while ($c = $c->getParentClass()) {
21 if (array_key_exists($n, $c->getConstants())) {
22 return false;
23 }
24 }
25 $c=$_;
26 foreach ((array) $c->getInterfaces() as $i) {
27 if (array_key_exists($n, $i->getConstants()) || !c($n, $i)) {
28 return false;
29 }
30 }
31 return true;
32 }
33
34 ob_start(function($s) {
35 // redirect any output to stderr
36 fwrite(STDERR, $s);
37 return true;
38 });
39
40 $out = STDOUT;
41 switch ($argc) {
42 default:
43 case 3:
44 $out = fopen($argv[2], "w") or die;
45 case 2:
46 $ext = $argv[1];
47 break;
48
49 case 1:
50 die(sprintf($out, "Usage: %s <ext>\n", $argv[0]));
51 }
52
53 fprintf($out, "<?php\n\n");
54
55 $ext = new ReflectionExtension($ext);
56
57 $constants = array();
58 $functions = array();
59 $structures = array();
60
61 // split up by namespace first
62 foreach ($ext->getConstants() as $constant => $value) {
63 $ns = ($nsend = strrpos($constant, "\\")) ? substr($constant, 0, $nsend++) : "";
64 $cn = substr($constant, $nsend);
65 $constants[$ns][$cn] = $value;
66 }
67 foreach ($ext->getFunctions() as $f) {
68 /* @var $f ReflectionFunction */
69 $ns = $f->inNamespace() ? $f->getNamespaceName() : "";
70 $functions[$ns][$f->getShortName()] = $f;
71 }
72 foreach ($ext->getClasses() as $c) {
73 /* @var $c ReflectionClass */
74 $ns = $c->inNamespace() ? $c->getNamespaceName() : "";
75 $structures[$ns][$c->getShortName()] = $c;
76 }
77
78 $namespaces = array_unique(array_merge(
79 array_keys($constants),
80 array_keys($functions),
81 array_keys($structures)
82 ));
83
84 // simple sort
85 natsort($namespaces);
86
87 foreach ($namespaces as $ns) {
88 fprintf($out, "namespace %s%s\n{\n", $ns, strlen($ns) ? " " : "");
89 //
90 if (isset($constants[$ns])) {
91 ksort($constants[$ns], SORT_NATURAL);
92 foreach ($constants[$ns] as $cn => $value) {
93 fprintf($out, "\tconst %s = %s;\n", $cn, var_export($value, true));
94 }
95 }
96 //
97 if (isset($functions[$ns])) {
98 ksort($functions[$ns], SORT_NATURAL);
99 foreach ($functions[$ns] as $fn => $f) {
100 /* @var $f ReflectionFunction */
101 fprintf($out, "\n\tfunction %s(", $fn);
102 $ps = array();
103 foreach ($f->getParameters() as $p) {
104 $p1 = sprintf("%s%s\$%s", t($p),
105 $p->isPassedByReference()?"&":"", trim($p->getName(), "\""));
106 if ($p->isOptional()) {
107 if ($p->isDefaultValueAvailable()) {
108 $p1 .= sprintf(" = %s",
109 var_export($p->getDefaultValue(), true));
110 } elseif (!($p->isArray() || $p->getClass()) || $p->allowsNull()) {
111 $p1 .= " = NULL";
112 } elseif ($p->isArray()) {
113 $p1 .= " = array()";
114 }
115 }
116 $ps[] = $p1;
117 }
118 fprintf($out, "%s) {\n\t}\n", implode(", ", $ps));
119 }
120 }
121 //
122 if (isset($structures[$ns])) {
123 uasort($structures[$ns], function ($a, $b) {
124 /* @var $a ReflectionClass */
125 /* @var $b ReflectionClass */
126 $score = array_sum([
127 -!$a->isInterface()+
128 -!$a->isAbstract()+
129 -!$a->isTrait()+
130 -!substr_compare($a->getShortName(), "Exception", -strlen("Exception")),
131 +!$b->isInterface()+
132 +!$b->isAbstract()+
133 +!$b->isTrait()+
134 -!substr_compare($b->getShortName(), "Exception", -strlen("Exception")),
135 ]);
136
137 if ($score) {
138 return -$score;
139 }
140 return strnatcmp($a->getShortName(), $b->getShortName());
141 });
142 foreach ($structures[$ns] as $cn => $c) {
143 fprintf($out, "\n\t%s%s %s ", m($c->getModifiers()),
144 $c->isInterface() ? "interface":"class", $c->getShortName());
145 if ($p = $c->getParentClass()) {
146 fprintf($out, "extends \\%s ", $p->getName());
147 }
148 if ($i = $c->getInterfaceNames()) {
149 fprintf($out, "implements \\%s ",
150 implode(", \\", array_filter($i, function($v) {
151 return $v != "Traversable";
152
153 }))
154 );
155 }
156 fprintf($out, "\n\t{\n");
157
158 $_=0;
159 foreach ($c->getConstants() as $n => $v) {
160 c($n, $c) and $_+=fprintf($out, "\t\tconst %s = %s;\n", $n,
161 var_export($v, true));
162 }
163 $_ and fprintf($out, "\n");
164 $_=0;
165 foreach ($c->getProperties() as $p) {
166 if ($p->getDeclaringClass()->getName() == $c->getName()) {
167 $_+=fprintf($out, "\t\t%s\$%s;\n", m($p->getModifiers()),
168 $p->getName());
169 }
170 }
171 $_ and fprintf($out, "\n");
172
173 foreach ($c->getMethods() as $m) {
174 if ($m->getDeclaringClass()->getName() == $c->getName()) {
175 fprintf($out, "\t\t%sfunction %s(", m($m->getModifiers(), $c),
176 $m->getName());
177 $ps = array();
178 foreach ($m->getParameters() as $p) {
179 $p1 = sprintf("%s%s\$%s", t($p),
180 $p->isPassedByReference()?"&":"", $p->getName());
181 if ($p->isOptional()) {
182 if ($p->isDefaultValueAvailable()) {
183 $p1 .= sprintf(" = %s",
184 var_export($p->getDefaultValue(), true));
185 } elseif (!($p->isArray() || $p->getClass()) || $p->allowsNull()) {
186 $p1 .= sprintf(" = NULL");
187 } elseif ($p->isArray()) {
188 $p1 .= " = array()";
189 }
190 }
191 $ps[] = $p1;
192 }
193 fprintf($out, "%s)", implode(", ", $ps));
194 if ($m->isAbstract()) {
195 fprintf($out, ";\n\n");
196 } else {
197 fprintf($out, " {\n\t\t}\n\n");
198 }
199 }
200 }
201
202 fprintf($out, "\t}\n");
203
204 }
205 }
206 //
207 fprintf($out, "}\n\n");
208 }