PageRenderTime 33ms CodeModel.GetById 27ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/utilities.class.php

http://github.com/vanity/vanity
PHP | 680 lines | 576 code | 64 blank | 40 comment | 43 complexity | 1810e95870ff6c1c5bec9c1203e62550 MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-3.0
  1. <?php
  2. class Util
  3. {
  4. /**
  5. *
  6. */
  7. public static function normalize_path($path)
  8. {
  9. $path = preg_replace('/\w+\/\.\.\//', '', $path);
  10. $path = str_replace(array('//', '/./'), '/', $path);
  11. return $path;
  12. }
  13. /**
  14. *
  15. */
  16. public static function access($o)
  17. {
  18. $accesses = array();
  19. if (method_exists($o, 'isFinal'))
  20. {
  21. if ($o->isFinal()) $accesses[] = 'final';
  22. }
  23. if (method_exists($o, 'isAbstract'))
  24. {
  25. if ($o->isAbstract()) $accesses[] = 'abstract';
  26. }
  27. if (method_exists($o, 'isPrivate'))
  28. {
  29. if ($o->isPrivate()) $accesses[] = 'private';
  30. }
  31. if (method_exists($o, 'isProtected'))
  32. {
  33. if ($o->isProtected()) $accesses[] = 'protected';
  34. }
  35. if (method_exists($o, 'isPublic'))
  36. {
  37. if ($o->isPublic()) $accesses[] = 'public';
  38. }
  39. if (method_exists($o, 'isStatic'))
  40. {
  41. if ($o->isStatic()) $accesses[] = 'static';
  42. }
  43. return $accesses;
  44. }
  45. /**
  46. *
  47. */
  48. public static function get_reference_xml($function)
  49. {
  50. $function = preg_replace('/::__/', '::', $function);
  51. $function = str_replace('::', DIRECTORY_SEPARATOR, $function);
  52. $function = str_replace('_', '-', $function);
  53. $letters = str_split($function);
  54. $pattern = array();
  55. foreach ($letters as $letter)
  56. {
  57. if (preg_match('/[a-z]/i', $letter))
  58. {
  59. $pattern[] = '[' . strtolower($letter) . strtoupper($letter) . ']';
  60. }
  61. else
  62. {
  63. $pattern[] = $letter;
  64. }
  65. }
  66. $pattern = implode('', $pattern);
  67. $results = self::rglob(PHPREF_DIR . '**' . DIRECTORY_SEPARATOR . $pattern . '.*');
  68. $filepath = array_shift($results);
  69. if ($filepath)
  70. {
  71. $contents = file_get_contents($filepath);
  72. $contents = str_replace('xmlns=', 'ns=', $contents);
  73. // Handle entities embedded inside entities
  74. while (preg_match('/&([^;]*);/i', $contents))
  75. {
  76. $contents = preg_replace_callback('/&([^;]*);/i', function($matches)
  77. {
  78. if (strpos($matches[1], '#') === false)
  79. {
  80. $ENTITY_MAP = $GLOBALS['ENTITY_MAP'];
  81. return $ENTITY_MAP[$matches[1]];
  82. }
  83. return $matches[1];
  84. }, $contents);
  85. }
  86. return simplexml_load_string($contents, 'Vanity_SimpleXMLExtended', LIBXML_NOCDATA & LIBXML_NOBLANKS & LIBXML_NOENT);
  87. }
  88. // Null if we can't find anything (e.g. SimpleXMLElement::__toString()).
  89. return null;
  90. }
  91. /**
  92. *
  93. */
  94. public static function rglob($pattern, $flags = 0, $path = '')
  95. {
  96. if (!$path && ($dir = dirname($pattern)) != '.')
  97. {
  98. if ($dir == '\\' || $dir == '/')
  99. {
  100. $dir = '';
  101. }
  102. return self::rglob(basename($pattern), $flags, $dir . '/');
  103. }
  104. $paths = glob($path . '*', GLOB_ONLYDIR | GLOB_NOSORT);
  105. $files = glob($path . $pattern, $flags);
  106. foreach ($paths as $p)
  107. {
  108. $files = array_merge($files, self::rglob($pattern, $flags, $p . '/'));
  109. }
  110. return $files;
  111. }
  112. /**
  113. *
  114. */
  115. public static function indent($content)
  116. {
  117. $contents = explode("\n", $content);
  118. $contents = array_map(function($line)
  119. {
  120. if (trim($line) !== '')
  121. {
  122. return TAB . '| ' . $line;
  123. }
  124. }, $contents);
  125. return implode("\n", $contents);
  126. }
  127. /**
  128. *
  129. */
  130. public static function regex_token($token)
  131. {
  132. $token = str_replace('/', '\/', $token);
  133. $token = quotemeta($token);
  134. return str_replace('\\\\', '\\', $token);
  135. }
  136. /**
  137. *
  138. */
  139. public static function line_numbers($lnum, $content)
  140. {
  141. return str_pad($lnum + 1, strlen((string) sizeof($content)), '0', STR_PAD_LEFT);
  142. }
  143. /**
  144. *
  145. */
  146. public static function entitize($s)
  147. {
  148. return htmlspecialchars($s, ENT_COMPAT, 'UTF-8');
  149. }
  150. /**
  151. *
  152. */
  153. public static function size_readable($size, $unit = null, $default = null)
  154. {
  155. // Units
  156. $sizes = array('B', 'kB', 'MB', 'GB', 'TB', 'PB');
  157. $mod = 1024;
  158. $ii = count($sizes) - 1;
  159. // Max unit
  160. $unit = array_search((string) $unit, $sizes);
  161. if ($unit === null || $unit === false)
  162. {
  163. $unit = $ii;
  164. }
  165. // Return string
  166. if ($default === null)
  167. {
  168. $default = '%01.2f %s';
  169. }
  170. // Loop
  171. $i = 0;
  172. while ($unit != $i && $size >= 1024 && $i < $ii)
  173. {
  174. $size /= $mod;
  175. $i++;
  176. }
  177. return sprintf($default, $size, $sizes[$i]);
  178. }
  179. /**
  180. *
  181. */
  182. public static function unwrap_array($array)
  183. {
  184. $out = 'array(';
  185. $collect = array();
  186. foreach ($array as $k => $v)
  187. {
  188. $key = '';
  189. if (!is_int($k))
  190. {
  191. $key = '"' . $k . '" => ';
  192. }
  193. switch (gettype($v))
  194. {
  195. case 'integer':
  196. $collect[] = $key . $v;
  197. break;
  198. case 'string':
  199. $collect[] = $key . '"' . $v . '"';
  200. break;
  201. case 'array':
  202. $collect[] = $key . Util::unwrap_array($v);
  203. break;
  204. case 'object':
  205. $collect[] = $key . get_class($v);
  206. break;
  207. default:
  208. $collect[] = $key . gettype($v);
  209. }
  210. }
  211. $values = implode(', ', $collect);
  212. $out .= $values ? ' ' : '';
  213. $out .= $values;
  214. $out .= $values ? ' ' : '';
  215. $out .= ')';
  216. return $out;
  217. }
  218. /**
  219. *
  220. */
  221. public static function time_hms($seconds)
  222. {
  223. $time = '';
  224. // First pass
  225. $hours = (integer) ($seconds / 3600);
  226. $seconds = $seconds % 3600;
  227. $minutes = (integer) ($seconds / 60);
  228. $seconds = $seconds % 60;
  229. // Cleanup
  230. $time .= ($hours) ? $hours . ':' : '';
  231. $time .= ($minutes < 10 && $hours > 0) ? '0' . $minutes : $minutes;
  232. $time .= ':';
  233. $time .= ($seconds < 10) ? '0' . $seconds : $seconds;
  234. return $time;
  235. }
  236. /**
  237. *
  238. */
  239. public static function read_examples($yml = 'examples.yml')
  240. {
  241. $examples = array();
  242. $all_examples = Util::rglob($yml);
  243. foreach ($all_examples as $example)
  244. {
  245. $example = realpath($example);
  246. $yaml = spyc_load_file($example);
  247. foreach ($yaml as $class => $methods)
  248. {
  249. if ($methods)
  250. {
  251. foreach ($methods as $method => $tests)
  252. {
  253. if ($tests)
  254. {
  255. foreach ($tests as $index => $test)
  256. {
  257. $yaml[$class][$method][$index] = dirname($example) . DIRECTORY_SEPARATOR . $test;
  258. }
  259. }
  260. }
  261. }
  262. }
  263. $examples = array_merge($examples, $yaml);
  264. }
  265. return $examples;
  266. }
  267. /**
  268. *
  269. */
  270. public static function get_parent_classes($rclass)
  271. {
  272. $class_list = array();
  273. $rclass = new ReflectionClass($rclass);
  274. while ($parent_class = $rclass->getParentClass())
  275. {
  276. $class_list[] = $parent_class->getName();
  277. $rclass = $parent_class;
  278. }
  279. return $class_list;
  280. }
  281. /**
  282. *
  283. */
  284. public static function htmlify_text($text)
  285. {
  286. if (strpos(trim($text), '<') !== 0)
  287. {
  288. return trim(Markdown($text));
  289. }
  290. return trim($text);
  291. }
  292. /**
  293. *
  294. */
  295. public static function clean_docbook($content)
  296. {
  297. $content = preg_replace('/(\s+)/m', ' ', $content);
  298. $content = preg_replace('/\s?<(\/?)(para)([^>]*)>\s?/i', '<\\1p\\3>', $content);
  299. $content = preg_replace('/<(\/?)(literal)([^>]*)>/i', '<\\1code\\3>', $content);
  300. $content = preg_replace('/<(\/?)(orderedlist)([^>]*)>/i', '<\\1ol\\3>', $content);
  301. $content = preg_replace('/<(\/?)(itemizedlist)([^>]*)>/i', '<\\1ul\\3>', $content);
  302. $content = preg_replace('/<(\/?)(listitem)([^>]*)>/i', '<\\1li\\3>', $content);
  303. $content = preg_replace('/<constant([^>]*)>(\w*)<\/constant>/i', '<code>\\2</code>', $content);
  304. $content = preg_replace('/<type([^>]*)>(\w*)<\/type>/i', '<a href="http://php.net/\\2"><code>\\2</code></a>', $content);
  305. $content = preg_replace('/<classname([^>]*)>(\w*)<\/classname>/i', '<a href="http://php.net/\\2"><code>\\2</code></a>', $content);
  306. $content = preg_replace('/<methodname([^>]*)>(\w*)::(\w*)<\/methodname>/i', '<a href="http://php.net/\\2.\\3"><code>\\2::\\3</code></a>', $content);
  307. $content = preg_replace('/<link linkend="([^"]*)">([^>]*)<\/link>/i', '<a href="http://php.net/\\1"><code>\\2</code></a>', $content);
  308. $content = str_replace('<pmeter>', ' <code>', $content);
  309. $content = str_replace('</pmeter>', '</code> ', $content);
  310. $content = str_replace('<row>', '<tr>', $content);
  311. $content = str_replace('</row>', '</tr>', $content);
  312. $content = str_replace('<entry>', '<td>', $content);
  313. $content = str_replace('</entry>', '</td>', $content);
  314. return trim($content);
  315. }
  316. /**
  317. *
  318. */
  319. public static function elongate_type($type)
  320. {
  321. $types = array(
  322. 'int' => 'integer',
  323. 'bool' => 'boolean',
  324. );
  325. if (isset($types[strtolower($type)]))
  326. {
  327. return $types[strtolower($type)];
  328. }
  329. return $type;
  330. }
  331. /**
  332. *
  333. */
  334. public static function strip_root_element($xml, $element = 'listitem')
  335. {
  336. $xml = preg_replace('/^<' . $element . '>/i', '', trim($xml));
  337. $xml = preg_replace('/<\/' . $element . '>$/i', '', $xml);
  338. return trim($xml);
  339. }
  340. /**
  341. *
  342. */
  343. public static function generate_entity_map()
  344. {
  345. $master_map = array();
  346. $glob = array_merge(
  347. Util::rglob(ENTITY_GLOBAL_DIR . '**.ent'),
  348. Util::rglob(ENTITY_LANG_DIR . '**.ent')
  349. );
  350. foreach ($glob as $file)
  351. {
  352. $entities = file_get_contents($file);
  353. preg_match_all('/<!ENTITY\s+([^\s]*)\s+("|\')([^\\2]*)\\2\s*>/Ui', $entities, $m);
  354. for ($i = 0, $max = count($m[0]); $i < $max; $i++)
  355. {
  356. $v = str_replace(array("\r\n", "\n"), ' ', $m[3][$i]);
  357. $map[$m[1][$i]] = $v;
  358. }
  359. $master_map = array_merge($master_map, $map);
  360. }
  361. ksort($master_map);
  362. return $master_map;
  363. }
  364. /**
  365. *
  366. */
  367. public static function content_partials($paths)
  368. {
  369. $map = array();
  370. foreach ($paths as $full_path)
  371. {
  372. $path = str_replace(PARTIALS_DIR, '', $full_path);
  373. $path = explode(DIRECTORY_SEPARATOR, strtolower($path));
  374. if (count($path) === 3)
  375. {
  376. $class = $path[0];
  377. $method = $path[1];
  378. $content = $path[2];
  379. }
  380. elseif (count($path) === 2)
  381. {
  382. $class = $path[0];
  383. $method = null;
  384. $content = $path[1];
  385. }
  386. if (!isset($map[$class]))
  387. {
  388. $map[$class] = array();
  389. }
  390. if ($method && !isset($map[$class][$method]))
  391. {
  392. $map[$class][$method] = array();
  393. }
  394. $content = explode('.', $content);
  395. if (is_array($content))
  396. {
  397. $filename = $content[0];
  398. $extension = $content[1];
  399. }
  400. else
  401. {
  402. $filename = $content;
  403. $extension = '';
  404. }
  405. if (!isset($map[$path[0]][$path[1]][$content[0]]))
  406. {
  407. if (!$method) $method = '';
  408. $map[$class][$method][$filename] = Util::convert_to_html($full_path);
  409. }
  410. }
  411. return $map;
  412. }
  413. public static function convert_to_html($path)
  414. {
  415. $pathinfo = pathinfo($path);
  416. $extension = strtolower($pathinfo['extension']);
  417. switch ($extension)
  418. {
  419. // Markdown
  420. case 'md':
  421. case 'mdown':
  422. case 'markdown':
  423. return trim(SmartyPants(Markdown(file_get_contents($path))));
  424. break;
  425. // PHP-infused HTML
  426. case 'phtml':
  427. Generator::start();
  428. include $path;
  429. $phtml_content = Generator::end();
  430. return SmartyPants(trim($phtml_content));
  431. break;
  432. // Pre-formatted text
  433. case '':
  434. case 'txt':
  435. case 'text':
  436. return '<pre>' . trim(file_get_contents($path)) . '</pre>';
  437. break;
  438. // Plain ol' HTML
  439. default:
  440. return trim(SmartyPants(file_get_contents($path)));
  441. break;
  442. }
  443. }
  444. /**
  445. *
  446. */
  447. public static function apply_linkmap($current, $s, $linkmap = null)
  448. {
  449. $i = 0;
  450. $map = $linkmap ? $linkmap : $GLOBALS['LINKMAP'];
  451. $matches = preg_match_all('/<([^>]*)>/', $s, $m);
  452. foreach ($m[1] as $match)
  453. {
  454. if (preg_match('/(https?|ftp):\/\//', $match)) continue; // Don't match links.
  455. elseif (strpos($match, '::'))
  456. {
  457. $pieces = explode('::', $match);
  458. if (strpos($pieces[0], 'php:') !== false)
  459. {
  460. $pieces[0] = str_replace('php:', '', $pieces[0]);
  461. $s = str_replace($m[0][$i], '<a href="http://php.net/' . strtolower($pieces[0]) . '.' . str_replace('()', '', strtolower($pieces[1])) . '"><code>' . $pieces[0] . '::' . $pieces[1] . '</code></a>', $s);
  462. }
  463. elseif (isset($map['map'][$pieces[0]][$pieces[1]]))
  464. {
  465. $s = str_replace($m[0][$i], '<a href="../' . strtolower($map['map'][$pieces[0]][$pieces[1]]) . '" rel="../../index.html' . strtolower($map['altmap'][$pieces[0]][$pieces[1]]) . '"><code>' . $pieces[0] . '::' . $pieces[1] . '</code></a>', $s);
  466. }
  467. }
  468. else
  469. {
  470. if (strpos($match, 'php:') !== false)
  471. {
  472. $match = str_replace('php:', '', $match);
  473. $s = str_replace($m[0][$i], '<a href="http://php.net/' . str_replace('()', '', strtolower($match)) . '"><code>' . $match . '</code></a>', $s);
  474. }
  475. elseif (isset($map['map'][$current][$match])) // Match same-class methods
  476. {
  477. $s = str_replace($m[0][$i], '<a href="../' . strtolower($map['map'][$current][$match]) . '" rel="../../index.html' . strtolower($map['altmap'][$current][$match]) . '"><code>' . $match . '</code></a>', $s);
  478. }
  479. elseif (isset($map['map'][$match]['index'])) // Match same class index
  480. {
  481. $s = str_replace($m[0][$i], '<a href="../' . strtolower($map['map'][$match]['index']) . '" rel="../../index.html' . strtolower($map['altmap'][$match]['index']) . '"><code>' . $match . '</code></a>', $s);
  482. }
  483. }
  484. $i++;
  485. }
  486. return $s;
  487. }
  488. /**
  489. *
  490. */
  491. public static function parse_groups()
  492. {
  493. if (file_exists(CONFIG_DIR . 'groups.yml'))
  494. {
  495. $groups = spyc_load_file(CONFIG_DIR . 'groups.yml');
  496. $out = array();
  497. foreach ($groups as $group)
  498. {
  499. foreach ($group as $k => $v)
  500. {
  501. if (is_int($k))
  502. {
  503. $group[$k] = str_replace('.', '::', $v);
  504. }
  505. }
  506. foreach ($group as $k => $v)
  507. {
  508. if (is_int($k))
  509. {
  510. $t = explode('::', $v);
  511. $class = $t[0];
  512. $method = $t[1];
  513. if (!isset($out[$class]))
  514. {
  515. $out[$class] = array();
  516. }
  517. if (!isset($out[$class][$method]))
  518. {
  519. $out[$class][$method] = array();
  520. }
  521. $out[$class][$method] = array_merge($out[$class][$method], $group);
  522. $a = array();
  523. foreach ($out[$class][$method] as $m)
  524. {
  525. $x = str_replace($class . '::', '', $m);
  526. if (strpos($m, '()') === false)
  527. {
  528. $x .= '()';
  529. }
  530. $a[] = $x;
  531. }
  532. $out[$class][$method] = $a;
  533. $out[$class][$method] = array_unique($out[$class][$method]);
  534. sort($out[$class][$method]);
  535. }
  536. else
  537. {
  538. $class = $k;
  539. $methods = str_replace('()', '', $v);
  540. foreach ($methods as $method)
  541. {
  542. if (!isset($out[$class]))
  543. {
  544. $out[$class] = array();
  545. }
  546. if (!isset($out[$class][$method]))
  547. {
  548. $out[$class][$method] = array();
  549. }
  550. $out[$class][$method] = array_merge($out[$class][$method], $methods);
  551. $out[$class][$method] = array_map(function($method)
  552. {
  553. if (strpos($method, '()') === false)
  554. {
  555. $method .= '()';
  556. }
  557. return $method;
  558. }, $out[$class][$method]);
  559. $out[$class][$method] = array_unique($out[$class][$method]);
  560. sort($out[$class][$method]);
  561. }
  562. }
  563. }
  564. }
  565. return $out;
  566. }
  567. return array();
  568. }
  569. /**
  570. *
  571. */
  572. public static function strip_whitespace($buffer)
  573. {
  574. // return HTMLCompressor::compress($buffer);
  575. return $buffer;
  576. }
  577. }