PageRenderTime 59ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/plugins/com.aptana.editor.php.epl/Resources/language/generate.php

https://github.com/haegyung/aptana-php
PHP | 933 lines | 726 code | 69 blank | 138 comment | 105 complexity | 0ff79dfcc1732694decf768666320ada MD5 | raw file
  1. <?php
  2. /**
  3. * This script can be used for generating PHP model for PDT.
  4. * It builds PHP functions according to the loaded extensions in running PHP,
  5. * using complementary information gathered from PHP.net documentation
  6. *
  7. * @author Michael Spector <michael@zend.com>
  8. */
  9. if (version_compare(phpversion(), "5.0.0") < 0) {
  10. die ("This script requires PHP 5.0.0 or higher!\n");
  11. }
  12. $splitFiles = true;
  13. $phpdocDir = null;
  14. $phpDir = "php5";
  15. if (strstr(phpversion(), "5.3")) {
  16. $phpDir = "php5.3";
  17. }
  18. // Parse arguments:
  19. $argv = $_SERVER["argv"];
  20. $argv0 = array_shift ($argv);
  21. for ($i = 0; $i < count($argv); ++$i) {
  22. switch ($argv[$i]) {
  23. case "-nosplit":
  24. $splitFiles = false;
  25. break;
  26. case "-help":
  27. show_help();
  28. break;
  29. default:
  30. $phpdocDir = $argv[$i];
  31. }
  32. }
  33. if (!$phpdocDir) {
  34. show_help();
  35. }
  36. $functionsDoc = parse_phpdoc_functions ($phpdocDir);
  37. $classesDoc = parse_phpdoc_classes ($phpdocDir);
  38. $constantsDoc = parse_phpdoc_constants ($phpdocDir);
  39. $processedFunctions = array();
  40. $processedClasses = array();
  41. $processedConstants = array();
  42. @mkdir ($phpDir);
  43. if (!$splitFiles) {
  44. begin_file_output();
  45. }
  46. $extensions = get_loaded_extensions();
  47. foreach ($extensions as $extName) {
  48. if ($splitFiles) {
  49. begin_file_output();
  50. }
  51. print_extension (new ReflectionExtension ($extName));
  52. if ($splitFiles) {
  53. finish_file_output("{$phpDir}/{$extName}.php");
  54. }
  55. }
  56. if ($splitFiles) {
  57. begin_file_output();
  58. }
  59. $intFunctions = get_defined_functions();
  60. foreach ($intFunctions["internal"] as $intFunction) {
  61. if (!@$processedFunctions[strtolower($intFunction)]) {
  62. print_function (new ReflectionFunction ($intFunction));
  63. }
  64. }
  65. $intClasses = array_merge (get_declared_classes(), get_declared_interfaces());
  66. foreach ($intClasses as $intClass) {
  67. if (!@$processedClasses[strtolower($intClass)]) {
  68. print_class (new ReflectionClass ($intClass));
  69. }
  70. }
  71. print "\n";
  72. $constants = get_defined_constants(true);
  73. $intConstants = $constants["internal"];
  74. // add magic constants:
  75. $intConstants['__FILE__'] = null;
  76. $intConstants['__LINE__'] = null;
  77. $intConstants['__CLASS__'] = null;
  78. $intConstants['__FUNCTION__'] = null;
  79. $intConstants['__METHOD__'] = null;
  80. if (version_compare(phpversion(), "5.3.0") >= 0) {
  81. $intConstants['__DIR__'] = null;
  82. $intConstants['__NAMESPACE__'] = null;
  83. }
  84. foreach ($intConstants as $name => $value) {
  85. if (!@$processedConstants[$name]) {
  86. print_constant ($name, $value);
  87. }
  88. }
  89. finish_file_output("{$phpDir}/basic.php");
  90. // Create .list file
  91. $fp = fopen ("{$phpDir}/.list", "w");
  92. foreach (glob("{$phpDir}/*.php") as $f) {
  93. fwrite ($fp, basename($f));
  94. fwrite ($fp, "\n");
  95. }
  96. fclose($fp);
  97. echo 'Finished...';
  98. // === Functions ===
  99. /**
  100. * Makes generic key from given function name
  101. * @param name string Function name
  102. * @return string generic key
  103. */
  104. function make_funckey_from_str ($name) {
  105. $name = str_replace ("->", "::", $name);
  106. $name = str_replace ("()", "", $name);
  107. $name = strtolower ($name);
  108. return $name;
  109. }
  110. /**
  111. * Replaces all invalid charaters with '_' in PHP identifier
  112. * @param name PHP identifier
  113. * @return string PHP identifier with stripped invalid characters
  114. */
  115. function clean_php_identifier ($name) {
  116. $name = preg_replace('/[^\$\w\_]+/', '_', $name);
  117. return $name;
  118. }
  119. /**
  120. * Makes generic key from given function reference
  121. * @param name ReflectionMethod function reference
  122. * @return string generic key
  123. */
  124. function make_funckey_from_ref ($ref) {
  125. if ($ref instanceof ReflectionMethod) {
  126. $funckey = strtolower($ref->getDeclaringClass()->getName())."::".strtolower($ref->getName());
  127. } else {
  128. $funckey = strtolower($ref->getName());
  129. }
  130. return $funckey;
  131. }
  132. /**
  133. * Parses PHP documentation
  134. * @param phpdocDir string PHP.net documentation directory
  135. * @return array Function information gathered from the PHP.net documentation by parsing XML files
  136. */
  137. function parse_phpdoc_functions ($phpdocDir) {
  138. $xml_files = array_merge (
  139. glob ("{$phpdocDir}/reference/*/*/*.xml")
  140. );
  141. foreach ($xml_files as $xml_file) {
  142. $xml = file_get_contents ($xml_file);
  143. if (preg_match ('@<refentry.*?xml:id=["\'](.*?)["\'].*?>.*?<refname>(.*?)</refname>.*?<refpurpose>(.*?)</refpurpose>@s', $xml, $match)) {
  144. $refname = make_funckey_from_str ($match[2]);
  145. $functionsDoc[$refname]['id'] = $match[1];
  146. $functionsDoc[$refname]['quickref'] = trim($match[3]);
  147. if (preg_match ('@<refsect1\s+role=["\']description["\']>(.*?)</refsect1>@s', $xml, $match)) {
  148. $description = $match[1];
  149. $function_alias = null;
  150. $parameters = null;
  151. $has_object_style = false;
  152. if (preg_match ('@^(.*?)<classsynopsis>.*?<classname>(.*)</classname>.*?<methodsynopsis>.*?<type>(.*?)</type>.*?<methodname>(.*?)</methodname>(.*?)</methodsynopsis>.*?</classsynopsis>(.*)$@s', $description, $match)) {
  153. $functionsDoc[$refname]['classname'] = trim($match[2]);
  154. $functionsDoc[$refname]['returntype'] = trim($match[3]);
  155. $functionsDoc[$refname]['methodname'] = trim($match[4]);
  156. $parameters = $match[5];
  157. $description = $match[1].$match[6];
  158. $has_object_style = true;
  159. }
  160. if (preg_match ('@<methodsynopsis>.*?<type>(.*?)</type>.*?<methodname>(.*?)</methodname>(.*?)</methodsynopsis>@s', $description, $match)) {
  161. if ($has_object_style) {
  162. $function_alias = trim($match[2]);
  163. } else {
  164. $functionsDoc[$refname]['returntype'] = trim($match[1]);
  165. $functionsDoc[$refname]['methodname'] = trim($match[2]);
  166. $parameters = $match[3];
  167. }
  168. }
  169. if ($parameters) {
  170. if (preg_match_all ('@<methodparam\s*(.*?)>.*?<type>(.*?)</type>.*?<parameter\s*(.*?)>(.*?)</parameter>.*?</methodparam>@s', $parameters, $match)) {
  171. for ($i = 0; $i < count($match[0]); ++$i) {
  172. $parameter = array (
  173. 'type' => trim($match[2][$i]),
  174. 'name' => clean_php_identifier(trim($match[4][$i])),
  175. );
  176. if (preg_match ('@choice=[\'"]opt[\'"]@', $match[1][$i])) {
  177. $parameter['isoptional'] = true;
  178. }
  179. if (preg_match ('@role=[\'"]reference[\'"]@', $match[3][$i])) {
  180. $parameter['isreference'] = true;
  181. }
  182. $functionsDoc[$refname]['parameters'][] = $parameter;
  183. }
  184. }
  185. }
  186. }
  187. if (preg_match ('@<refsect1\s+role=["\']parameters["\']>(.*?)</refsect1>@s', $xml, $match)) {
  188. $parameters = $match[1];
  189. if (preg_match_all('@<varlistentry\s*.*?>.*?<parameter>(.*?)</parameter>.*?<listitem\s*.*?>(.*?)</listitem>.*?</varlistentry>@s', $parameters, $match)) {
  190. for ($i = 0; $i < count($match[0]); $i++) {
  191. for ($j = 0; $j < count(@$functionsDoc[$refname]['parameters']); $j++) {
  192. if ($match[1][$i] == $functionsDoc[$refname]['parameters'][$j]['name']) {
  193. $functionsDoc[$refname]['parameters'][$j]['paramdoc'] = xml_to_phpdoc ($match[2][$i]);
  194. break;
  195. }
  196. }
  197. }
  198. }
  199. }
  200. if (preg_match ('@<refsect1\s+role=["\']returnvalues["\']>(.*?)</refsect1>@s', $xml, $match)) {
  201. $returnvalues = $match[1];
  202. if (preg_match ('@<para>\s*(Returns)?(.*)</para>?@s', $returnvalues, $match)) {
  203. $functionsDoc[$refname]['returndoc'] = xml_to_phpdoc ($match[2]);
  204. }
  205. }
  206. // Create information for function alias
  207. if ($function_alias) {
  208. $functionsDoc[$function_alias] = $functionsDoc[$refname];
  209. }
  210. }
  211. }
  212. return $functionsDoc;
  213. }
  214. /**
  215. * Parses PHP documentation
  216. * @param phpdocDir string PHP.net documentation directory
  217. * @return array Class information gathered from the PHP.net documentation by parsing XML files
  218. */
  219. function parse_phpdoc_classes ($phpdocDir) {
  220. $xml_files = array_merge (
  221. glob ("{$phpdocDir}/reference/*/reference.xml"),
  222. glob ("{$phpdocDir}/reference/*/classes.xml"),
  223. glob ("{$phpdocDir}/language/*/*.xml"),
  224. glob ("{$phpdocDir}/language/*.xml")
  225. );
  226. global $fields_doc;
  227. foreach ($xml_files as $xml_file) {
  228. $xml = file_get_contents ($xml_file);
  229. if (preg_match ('@xml:id=["\'](.*?)["\']@', $xml, $match)) {
  230. $id = $match[1];
  231. if (preg_match_all ('@<title><classname>(.*?)</classname></title>@', $xml, $match)) {
  232. for ($i = 0; $i < count($match[0]); ++$i) {
  233. $class = $match[1][$i];
  234. $refname = strtolower ($class);
  235. $classesDoc[$refname]['id'] = $id;
  236. $classesDoc[$refname]['name'] = $class;
  237. if (preg_match ("@<title><classname>{$class}</classname></title>\s*<para>(.*?)</para>@s", $xml, $match2)) {
  238. $classesDoc[$refname]['doc'] = xml_to_phpdoc($match2[1]);
  239. }
  240. //pass over class fields here
  241. $fields_xml_file = array_merge (
  242. glob ("{$phpdocDir}/reference/*/" . $refname . ".xml")
  243. );
  244. if($fields_xml_file[0] != null) {
  245. $xml_field_data = file_get_contents ($fields_xml_file[0]);
  246. if($xml_field_data != null) {
  247. if(preg_match_all ('@<fieldsynopsis>((\w|\W|\s)*?)</fieldsynopsis>@', $xml_field_data, $fieldsynopsis_list)) {
  248. foreach ($fieldsynopsis_list[1] as $fieldsynopsis) {
  249. if(preg_match_all("@<varname\s*linkend=\"{$refname}.props.(.*?)\">(.*?)</varname>@", $fieldsynopsis, $varname)) {
  250. $field_name = $varname[2][0];
  251. $fields_doc[$refname][$field_name]['name'] = $field_name;
  252. }
  253. // <varlistentry xml:id="domdocument.props.formatoutput">
  254. // <term><varname>formatOutput</varname></term>
  255. // <listitem>
  256. // <para>Nicely formats output with indentation and extra space.</para>
  257. // </listitem>
  258. // </varlistentry>
  259. if (preg_match ("@<varlistentry.*?<term><varname>{$field_name}</varname></term>.*?<para>(.*?)</para>@s", $xml_field_data, $doc)) {
  260. if(preg_match ("@<emphasis>Deprecated</emphasis>@s", $doc[1], $deprecated)) {
  261. $fields_doc[$refname][$field_name]['deprecated'] = true;
  262. }else {
  263. $fields_doc[$refname][$field_name]['deprecated'] = false;
  264. }
  265. $fields_doc[$refname][$field_name]['doc'] = xml_to_phpdoc($doc[1]);
  266. }
  267. if(preg_match_all("@<modifier>(.*?)</modifier>@", $fieldsynopsis, $modifier_list)) {
  268. foreach ($modifier_list[1] as $current_modifier) {
  269. if($current_modifier == "readonly") {
  270. continue;
  271. }else {
  272. $modifier = $current_modifier;
  273. break;
  274. }
  275. }
  276. //go to the next field if not public ???
  277. if($modifier == "private") {
  278. continue;
  279. }
  280. $fields_doc[$refname][$field_name]['modifier'] = $modifier;
  281. }
  282. if(preg_match_all("@<type>(.*?)</type>@", $fieldsynopsis, $type)) {
  283. $field_type = $type[1][0];
  284. $fields_doc[$refname][$field_name]['type'] = $field_type;
  285. }
  286. }
  287. }
  288. }
  289. }
  290. }
  291. }
  292. }
  293. }
  294. return $classesDoc;
  295. }
  296. /**
  297. * Parses PHP documentation
  298. * @param phpdocDir string PHP.net documentation directory
  299. * @return array Constant information gathered from the PHP.net documentation by parsing XML files
  300. */
  301. function parse_phpdoc_constants ($phpdocDir) {
  302. exec ("find ".addslashes($phpdocDir)." -name \"*constants.xml\"", $xml_files);
  303. foreach ($xml_files as $xml_file) {
  304. $xml = file_get_contents ($xml_file);
  305. if (preg_match ('@xml:id=["\'](.*?)["\']@', $xml, $match)) {
  306. $id = $match[1];
  307. if (preg_match_all ('@<term>\s*<constant>([a-zA-Z_][a-zA-Z0-9_]*)</constant>.*?</term>.*?<listitem>(.*?)</listitem>@s', $xml, $match)) {
  308. for ($i = 0; $i < count($match[0]); ++$i) {
  309. $constant = $match[1][$i];
  310. $constantsDoc[$constant]['id'] = $id;
  311. $constantsDoc[$constant]['doc'] = xml_to_phpdoc($match[2][$i]);
  312. }
  313. }
  314. if (preg_match_all (
  315. '@<entry>\s*<constant>([a-zA-Z_][a-zA-Z0-9_]*)</constant>.*?</entry>\s*<entry>\d+</entry>\s*<entry>(.*?)</entry>@s', $xml, $match)
  316. || preg_match_all ('@<entry>\s*<constant>([a-zA-Z_][a-zA-Z0-9_]*)</constant>.*?</entry>\s*<entry>(.*?)</entry>@s', $xml, $match)) {
  317. for ($i = 0; $i < count($match[0]); ++$i) {
  318. $constant = $match[1][$i];
  319. $constantsDoc[$constant]['id'] = $id;
  320. $constantsDoc[$constant]['doc'] = xml_to_phpdoc($match[2][$i]);
  321. }
  322. }
  323. }
  324. }
  325. return $constantsDoc;
  326. }
  327. /**
  328. * Prints ReflectionExtension in format of PHP code
  329. * @param extRef ReflectionExtension object
  330. */
  331. function print_extension ($extRef) {
  332. print "\n// Start of {$extRef->getName()} v.{$extRef->getVersion()}\n";
  333. // process classes:
  334. $classesRef = $extRef->getClasses();
  335. if (count ($classesRef) > 0) {
  336. foreach ($classesRef as $classRef) {
  337. print_class ($classRef);
  338. }
  339. }
  340. // process functions
  341. $funcsRef = $extRef->getFunctions();
  342. if (count ($funcsRef) > 0) {
  343. foreach ($funcsRef as $funcRef) {
  344. print_function ($funcRef);
  345. }
  346. print "\n";
  347. }
  348. // process constants
  349. $constsRef = $extRef->getConstants();
  350. if (count ($constsRef) > 0) {
  351. print_constants ($constsRef);
  352. print "\n";
  353. }
  354. print "// End of {$extRef->getName()} v.{$extRef->getVersion()}\n";
  355. }
  356. /**
  357. * Prints ReflectionClass in format of PHP code
  358. * @param classRef ReflectionClass object
  359. * @param tabs integer[optional] number of tabs for indentation
  360. */
  361. function print_class ($classRef, $tabs = 0) {
  362. global $processedClasses;
  363. $processedClasses [strtolower($classRef->getName())] = true;
  364. print "\n";
  365. print_doccomment ($classRef, $tabs);
  366. print_tabs ($tabs);
  367. if ($classRef->isFinal()) print "final ";
  368. print $classRef->isInterface() ? "interface " : "class ";
  369. print clean_php_identifier($classRef->getName())." ";
  370. // print out parent class
  371. $parentClassRef = $classRef->getParentClass();
  372. if ($parentClassRef) {
  373. print "extends {$parentClassRef->getName()} ";
  374. }
  375. // print out interfaces
  376. $interfacesRef = $classRef->getInterfaces();
  377. if (count ($interfacesRef) > 0) {
  378. print $classRef->isInterface() ? "extends " : "implements ";
  379. $i = 0;
  380. foreach ($interfacesRef as $interfaceRef) {
  381. if ($i++ > 0) {
  382. print ", ";
  383. }
  384. print "{$interfaceRef->getName()}";
  385. }
  386. }
  387. print " {\n";
  388. // process constants
  389. $constsRef = $classRef->getConstants();
  390. if (count ($constsRef) > 0) {
  391. print_class_constants ($constsRef, $tabs + 1);
  392. print "\n";
  393. }
  394. global $classesDoc;
  395. // process properties
  396. $propertiesRef = $classRef->getProperties();
  397. if (count ($propertiesRef) > 0) {
  398. foreach ($propertiesRef as $propertyRef) {
  399. print_property ($propertyRef, $tabs + 1);
  400. $printedFields[$propertyRef->getName()] = true;
  401. }
  402. print "\n";
  403. }
  404. $className = strtolower($classRef->getName());
  405. if($className == "DomDocument") {
  406. echo "DomDocument";
  407. }
  408. global $fields_doc;
  409. if (@$fields_doc[$className]) {
  410. $fields = @$fields_doc[$className];
  411. foreach ($fields as $field) {
  412. if(!$printedFields[$field['name']]) {
  413. //print doc here
  414. print("\n");
  415. $doc = $field['doc'];
  416. if ($doc) {
  417. print_tabs ($tabs + 1);
  418. print "/**\n";
  419. print_tabs ($tabs + 1);
  420. print " * ".newline_to_phpdoc($doc, $tabs + 1)."\n";
  421. print_tabs ($tabs + 1);
  422. print " * @var ".$field['type']."\n";
  423. if($field['deprecated'] == true) {
  424. print_tabs ($tabs + 1);
  425. print " * @deprecated "."\n";
  426. }
  427. print_Tabs ($tabs + 1);
  428. // http://www.php.net/manual/en/class.domdocument.php#domdocument.props.actualencoding
  429. $refname = strtolower($classRef->getName());
  430. $class_url = make_url ("class." . $refname);
  431. $field_name = strtolower($field['name']);
  432. $field_url = $class_url . '#' . $className . ".props." . $field_name;
  433. print " * @link {$field_url}\n";
  434. print_tabs ($tabs + 1);
  435. print " */\n";
  436. }
  437. print_tabs ($tabs + 1);
  438. print implode(' ', array($field['modifier']));
  439. print " ";
  440. print "\${$field['name']};\n";
  441. }
  442. }
  443. }
  444. // process methods
  445. $methodsRef = $classRef->getMethods();
  446. if (count ($methodsRef) > 0) {
  447. foreach ($methodsRef as $methodRef) {
  448. print_function ($methodRef, $tabs + 1);
  449. }
  450. print "\n";
  451. }
  452. print_tabs ($tabs);
  453. print "}\n";
  454. }
  455. /**
  456. * Prints ReflectionProperty in format of PHP code
  457. * @param propertyRef ReflectionProperty object
  458. * @param tabs integer[optional] number of tabs for indentation
  459. */
  460. function print_property ($propertyRef, $tabs = 0) {
  461. print_doccomment ($propertyRef, $tabs);
  462. print_tabs ($tabs);
  463. print_modifiers ($propertyRef);
  464. print "\${$propertyRef->getName()};\n";
  465. }
  466. function print_function ($functionRef, $tabs = 0) {
  467. global $functionsDoc;
  468. global $processedFunctions;
  469. $funckey = make_funckey_from_ref ($functionRef);
  470. $processedFunctions[$funckey] = true;
  471. print "\n";
  472. print_doccomment ($functionRef, $tabs);
  473. print_tabs ($tabs);
  474. if (!($functionRef instanceof ReflectionFunction)) {
  475. print_modifiers ($functionRef);
  476. }
  477. print "function ";
  478. if ($functionRef->returnsReference()) {
  479. print "&";
  480. }
  481. print "{$functionRef->getName()} (";
  482. $parameters = @$functionsDoc[$funckey]['parameters'];
  483. if ($parameters) {
  484. print_parameters ($parameters);
  485. } else {
  486. print_parameters_ref ($functionRef->getParameters());
  487. }
  488. print ") {}\n";
  489. }
  490. /**
  491. * Prints ReflectionParameter in format of PHP code
  492. * @param parameters array information from PHP.net documentation
  493. */
  494. function print_parameters ($parameters) {
  495. $i = 0;
  496. foreach ($parameters as $parameter) {
  497. if ($parameter['name'] != "...") {
  498. if ($i++ > 0) {
  499. print ", ";
  500. }
  501. $type = $parameter['type'];
  502. if ($type && (class_exists ($type) || $type == "array")) {
  503. print "{$type} ";
  504. }
  505. if (@$parameter['isreference']) {
  506. print "&";
  507. }
  508. print "\${$parameter['name']}";
  509. if (@$parameter['isoptional']) {
  510. if (@$parameter['defaultvalue']) {
  511. $value = $parameter['defaultvalue'];
  512. if (!is_numeric ($value)) {
  513. $value = "'{$value}'";
  514. }
  515. print " = {$value}";
  516. } else {
  517. print " = null";
  518. }
  519. }
  520. }
  521. }
  522. }
  523. /**
  524. * Prints ReflectionParameter in format of PHP code
  525. * @param paramsRef ReflectionParameter[] array of objects
  526. */
  527. function print_parameters_ref ($paramsRef) {
  528. $i = 0;
  529. foreach ($paramsRef as $paramRef) {
  530. if ($paramRef->isArray()) {
  531. print "array ";
  532. } else {
  533. if ($className = get_parameter_classname($paramRef)) {
  534. print "{$className} ";
  535. }
  536. }
  537. $name = $paramRef->getName() ? $paramRef->getName() : "var".($i+1);
  538. if ($name != "...") {
  539. if ($i++ > 0) {
  540. print ", ";
  541. }
  542. if ($paramRef->isPassedByReference()) {
  543. print "&";
  544. }
  545. print "\${$name}";
  546. if ($paramRef->allowsNull()) {
  547. print " = null";
  548. } else if ($paramRef->isDefaultValueAvailable()) {
  549. $value = $paramRef->getDefaultValue();
  550. if (!is_numeric ($value)) {
  551. $value = "'{$value}'";
  552. }
  553. print " = {$value}";
  554. }
  555. }
  556. }
  557. }
  558. /**
  559. * Prints constants in format of PHP code
  560. * @param constants array containing constants, where key is a name of constant
  561. * @param tabs integer[optional] number of tabs for indentation
  562. */
  563. function print_constants ($constants, $tabs = 0) {
  564. foreach ($constants as $name => $value) {
  565. print_constant ($name, $value, $tabs);
  566. }
  567. }
  568. function print_constant ($name, $value = null, $tabs = 0) {
  569. global $constantsDoc;
  570. global $processedConstants;
  571. $processedConstants [$name] = true;
  572. if ($value === null) {
  573. $value = @constant ($name);
  574. }
  575. $value = escape_const_value ($value);
  576. $doc = @$constantsDoc[$name]['doc'];
  577. if ($doc) {
  578. print "\n";
  579. print_tabs ($tabs);
  580. print "/**\n";
  581. print_tabs ($tabs);
  582. print " * ".newline_to_phpdoc($doc, $tabs)."\n";
  583. print_tabs ($tabs);
  584. print " * @link ".make_url($constantsDoc[$name]['id'])."\n";
  585. print_tabs ($tabs);
  586. print " */\n";
  587. }
  588. print_tabs ($tabs);
  589. print "define ('{$name}', {$value});\n";
  590. }
  591. function escape_const_value ($value) {
  592. if (is_resource($value)) {
  593. $value = "\"${value}\"";
  594. } else if (!is_numeric ($value) && !is_bool ($value) && $value !== null) {
  595. if($value=== '\\'){
  596. $value = '"'.addcslashes ($value, "\\\"\r\n\t").'"';
  597. }
  598. else{
  599. $value = '"'.addcslashes ($value, "\"\r\n\t").'"';
  600. }
  601. } else if ($value === null) {
  602. $value = "null";
  603. } else if ($value === false) {
  604. $value = "false";
  605. } else if ($value === true) {
  606. $value = "true";
  607. }
  608. return $value;
  609. }
  610. /**
  611. * Prints class constants in format of PHP code
  612. * @param constants array containing constants, where key is a name of constant
  613. * @param tabs integer[optional] number of tabs for indentation
  614. */
  615. function print_class_constants ($constants, $tabs = 0) {
  616. foreach ($constants as $name => $value) {
  617. $value = escape_const_value ($value);
  618. print_tabs ($tabs);
  619. print "const {$name} = {$value};\n";
  620. }
  621. }
  622. /**
  623. * Prints modifiers of reflection object in format of PHP code
  624. * @param ref Reflection some reflection object
  625. */
  626. function print_modifiers ($ref) {
  627. $modifiers = Reflection::getModifierNames ($ref->getModifiers());
  628. if (count ($modifiers) > 0) {
  629. print implode(' ', $modifiers);
  630. print " ";
  631. }
  632. }
  633. /**
  634. * Makes PHP Manual URL from the given ID
  635. * @param id PHP Element ID
  636. * @return URL
  637. */
  638. function make_url ($id) {
  639. return "http://www.php.net/manual/en/{$id}.php";
  640. }
  641. /**
  642. * Prints PHPDOC comment before specified reflection object
  643. * @param ref Reflection some reflection object
  644. * @param tabs integer[optional] number of tabs for indentation
  645. */
  646. function print_doccomment ($ref, $tabs = 0) {
  647. global $functionsDoc;
  648. global $classesDoc;
  649. $docComment = $ref->getDocComment();
  650. if ($docComment) {
  651. print_tabs ($tabs);
  652. print "{$docComment}\n";
  653. }
  654. else if ($ref instanceof ReflectionClass) {
  655. $refname = strtolower($ref->getName());
  656. if (@$classesDoc[$refname]) {
  657. print_tabs ($tabs);
  658. print "/**\n";
  659. $doc = @$classesDoc[$refname]['doc'];
  660. if ($doc) {
  661. $doc = newline_to_phpdoc ($doc, $tabs);
  662. print_tabs ($tabs);
  663. print " * {$doc}\n";
  664. }
  665. if (@$classesDoc[$refname]['id']) {
  666. print_Tabs ($tabs);
  667. $url = make_url ("class." . $refname);
  668. print " * @link {$url}\n";
  669. }
  670. print_tabs ($tabs);
  671. print " */\n";
  672. }
  673. }
  674. else if ($ref instanceof ReflectionFunctionAbstract) {
  675. $funckey = make_funckey_from_ref ($ref);
  676. $returntype = @$functionsDoc[$funckey]['returntype'];
  677. $desc = @$functionsDoc[$funckey]['quickref'];
  678. $returndoc = newline_to_phpdoc (@$functionsDoc[$funckey]['returndoc'], $tabs);
  679. $paramsRef = $ref->getParameters();
  680. $parameters = @$functionsDoc[$funckey]['parameters'];
  681. if ($desc || count ($paramsRef) > 0 || $parameters || $returntype) {
  682. print_tabs ($tabs);
  683. print "/**\n";
  684. if ($desc) {
  685. print_tabs ($tabs);
  686. print " * {$desc}\n";
  687. }
  688. if (@$functionsDoc[$funckey]['id']) {
  689. print_tabs ($tabs);
  690. $url = make_url ($functionsDoc[$funckey]['id']);
  691. print " * @link {$url}\n";
  692. }
  693. if ($parameters) {
  694. foreach ($parameters as $parameter) {
  695. print_tabs ($tabs);
  696. print " * @param {$parameter['name']} {$parameter['type']}";
  697. if (@$parameter['isoptional']) {
  698. print "[optional]";
  699. }
  700. $paramdoc = newline_to_phpdoc (@$parameter['paramdoc'], $tabs);
  701. print " {$paramdoc}";
  702. print "\n";
  703. }
  704. } else {
  705. $i = 0;
  706. foreach ($paramsRef as $paramRef) {
  707. print_tabs ($tabs);
  708. $name = $paramRef->getName() ? $paramRef->getName() : "var".++$i;
  709. print " * @param {$name}";
  710. if ($className = get_parameter_classname($paramRef)) {
  711. print " {$className}";
  712. if ($paramRef->isArray()) {
  713. print "[]";
  714. }
  715. }
  716. if ($paramRef->isOptional()) {
  717. print "[optional]";
  718. }
  719. print "\n";
  720. }
  721. }
  722. if ($returntype) {
  723. print_tabs ($tabs);
  724. print " * @return {$returntype} {$returndoc}\n";
  725. }
  726. print_tabs ($tabs);
  727. print " */\n";
  728. }
  729. } else if ($ref instanceof ReflectionProperty) {
  730. //TODO complete phpdoc for fields detected by reflection
  731. }
  732. }
  733. /**
  734. * Converts XML entities to human readable string for PHPDOC
  735. * @param str string
  736. * @return string
  737. */
  738. function xml_to_phpdoc ($str) {
  739. $str = str_replace ("&return.success;", "Returns true on success or false on failure.", $str);
  740. $str = str_replace ("&return.void;", "", $str);
  741. $str = str_replace ("&true;", "true", $str);
  742. $str = str_replace ("&false;", "false", $str);
  743. $str = strip_tags_special ($str);
  744. $str = preg_replace ("/ */", " ", $str);
  745. $str = preg_replace ("/[\r\n][\t ]/", "\n", $str);
  746. $str = trim ($str);
  747. return $str;
  748. }
  749. /**
  750. * Converts newlines to PHPDOC prefixes in the given string
  751. * @param str string
  752. * @param tabs integer[optional] number of tabs for indentation
  753. * @return string PHPDOC string
  754. */
  755. function newline_to_phpdoc ($str, $tabs = 0) {
  756. $str = preg_replace ("@[\r\n]+@", "\n".str_repeat("\t", $tabs)." * ", $str);
  757. return $str;
  758. }
  759. /**
  760. * Prints specified number of tabs
  761. * @param tabs integer number of tabs to print
  762. */
  763. function print_tabs ($tabs) {
  764. print str_repeat("\t", $tabs);
  765. }
  766. /**
  767. * Returns class name from given parameter reference, this method is a workaround
  768. * for the case when exception is thrown from getClass() when such classname does not exist.
  769. */
  770. function get_parameter_classname(ReflectionParameter $paramRef) {
  771. try {
  772. if ($classRef = $paramRef->getClass()) {
  773. return $classRef->getName();
  774. }
  775. } catch (Exception $e) {
  776. if (preg_match('/Class (\w+) does not exist/', $e->getMessage(), $matches)) {
  777. return $matches[1];
  778. }
  779. }
  780. return null;
  781. }
  782. /**
  783. * Starts outputing to the new file
  784. */
  785. function begin_file_output() {
  786. ob_start();
  787. print "<?php\n";
  788. }
  789. /**
  790. * Ends outputing, and dumps the output to the specified file
  791. * @param filename File to dump the output
  792. */
  793. function finish_file_output($filename) {
  794. //if (file_exists ($filename)) {
  795. // rename ($filename, "{$filename}.bak");
  796. //}
  797. print "?>\n";
  798. file_put_contents ($filename, ob_get_contents());
  799. ob_end_clean();
  800. }
  801. /**
  802. * Strips xml tags from the string like the standard strip_tags() function
  803. * would do, but also translates some of the docbook tags (such as tables
  804. * an paragraphs) to proper html tags
  805. * @param str string
  806. * @return string
  807. */
  808. function strip_tags_special ($str) {
  809. // first mask and translate the tags to preseve
  810. $str = preg_replace ("/<(\/?)table>/", "###($1table)###", $str);
  811. $str = str_replace ("<row>", "###(tr valign=\"top\")###", $str);
  812. $str = str_replace ("</row>", "###(/tr)###", $str);
  813. $str = preg_replace ("/<(\/?)entry>/", "###($1td)###", $str);
  814. $str = preg_replace ("/<(\/?)para>/", "###($1p)###", $str);
  815. // now strip the remaining tags
  816. $str = strip_tags ($str);
  817. // and restore the translated ones
  818. $str = str_replace ("###(", "<", $str);
  819. $str = str_replace (")###", ">", $str);
  820. return $str;
  821. }
  822. /**
  823. * Prints usage help to the screen, and exits from program
  824. */
  825. function show_help() {
  826. global $argv0;
  827. die (<<<EOF
  828. USAGE: {$argv0} [options] <PHP.net documentation directory>
  829. Where options are:
  830. -help Show this help.
  831. -split Split output to different files (one file per PHP extension).
  832. EOF
  833. );
  834. }
  835. ?>