Pelzini

This is the code documentation for the Pelzini project

source of /viewer/functions.php

Various useful functions
  1. <?php
  2. /*
  3. Copyright 2008 Josh Heidenreich
  4.  
  5. This file is part of Pelzini.
  6.  
  7. Pelzini is free software: you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation, either version 3 of the License, or
  10. (at your option) any later version.
  11.  
  12. Pelzini is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. GNU General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with Pelzini. If not, see <http://www.gnu.org/licenses/>.
  19. */
  20.  
  21. /**
  22.  * Various useful functions
  23.  *
  24.  * @package Viewer
  25.  * @author Josh Heidenreich
  26.  * @since 0.1
  27.  * @tag i18n-done
  28.  **/
  29.  
  30.  
  31. require_once 'geshi/geshi.php';
  32.  
  33. /**
  34.  * Fixes all magically quoted strings in the given array or string
  35.  *
  36.  * @param mixed &$item The string or array in which to fix magic quotes
  37.  * @return mixed The resultant string or array
  38.  */
  39. function fix_magic_quotes(&$item)
  40. {
  41. if (is_array($item)) {
  42. // if a key is magically quoted, it needs to be modified - do key modifications after the loop is done,
  43. // so that the same data does not get fixed twice
  44. $key_replacements = array ();
  45. foreach ($item as $key => $val) {
  46. $new_key = stripslashes($key);
  47. if ($new_key != $key) $key_replacements[$key] = $new_key;
  48. $item[$key] = fix_magic_quotes ($val);
  49. }
  50.  
  51. foreach ($key_replacements as $old_key => $new_key) {
  52. $item[$new_key] = $item[$old_key];
  53. unset ($item[$old_key]);
  54. }
  55.  
  56. } else {
  57. $item = stripslashes($item);
  58. }
  59.  
  60. return $item;
  61. }
  62.  
  63.  
  64. /**
  65.  * Determines the link for a specified name (might be a class, an interface or a function)
  66.  *
  67.  * @param string $name The name to check
  68.  * @return string A piece of HTML usable to represent the object, as a link if possible
  69.  **/
  70. function get_object_link($name)
  71. {
  72. global $project;
  73. $sql_name = db_escape($name);
  74.  
  75. // check classes
  76. $q = "SELECT id FROM classes WHERE name = '{$sql_name}' AND projectid = {$project['id']}";
  77. $res = db_query($q);
  78. if (db_num_rows($res) != 0) {
  79. return get_class_link($name);
  80. }
  81.  
  82. // check interfaces
  83. $q = "SELECT id FROM interfaces WHERE name = '{$sql_name}' AND projectid = {$project['id']}";
  84. $res = db_query($q);
  85. if (db_num_rows($res) != 0) {
  86. return get_interface_link($name);
  87. }
  88.  
  89. // check functions
  90. $q = "SELECT id FROM functions WHERE name = '{$sql_name}' AND classid IS NULL AND interfaceid IS NULL AND projectid = {$project['id']}";
  91. $res = db_query($q);
  92. if (db_num_rows($res) != 0) {
  93. return '<a href="function?name=' . urlencode($name) . '">' . htmlspecialchars($name) . '</a>';
  94. }
  95.  
  96. return $name;
  97. }
  98.  
  99.  
  100. /**
  101.  * Echos a list of all of the authors of a specifc item
  102.  **/
  103. function show_authors($link_id, $link_type)
  104. {
  105. global $project;
  106.  
  107. $q = "SELECT name, email, description FROM item_authors WHERE linkid = {$link_id} AND linktype = {$link_type} AND projectid = {$project['id']}";
  108. $res = db_query($q);
  109.  
  110. if (db_num_rows($res) > 0) {
  111. echo '<h3>', str(STR_AUTHORS), '</h3>';
  112.  
  113. echo '<ul>';
  114. while ($row = db_fetch_assoc ($res)) {
  115. $row['name'] = htmlspecialchars($row['name']);
  116. $row['email'] = htmlspecialchars($row['email']);
  117.  
  118. echo "<li><a href=\"author?name={$row['name']}\">{$row['name']}</a>";
  119.  
  120. if ($row['email']) {
  121. echo "<br><a href=\"mailto:{$row['email']}\">{$row['email']}</a>";
  122. }
  123.  
  124. if ($row['description']) {
  125. echo "<br><small>{$row['description']}</small>";
  126. }
  127.  
  128. echo '</li>';
  129. }
  130. echo '</ul>';
  131. }
  132. }
  133.  
  134.  
  135. /**
  136.  * Shows the tables used by a specific file, function or class
  137.  **/
  138. function show_tables($link_id, $link_type)
  139. {
  140. global $project;
  141.  
  142. $q = "SELECT name, action, description FROM item_tables WHERE linkid = {$link_id} AND linktype = {$link_type} AND projectid = {$project['id']}";
  143. $res = db_query($q);
  144.  
  145. if (db_num_rows($res) > 0) {
  146. echo '<h3>', str(STR_TABLES), '</h3>';
  147.  
  148. echo '<ul>';
  149. while ($row = db_fetch_assoc ($res)) {
  150. $name_url = urlencode($row['name']);
  151. $row['name'] = htmlspecialchars($row['name']);
  152.  
  153. echo "<li><i>{$row['action']}</i> <a href=\"table?name={$name_url}\">{$row['name']}</a>";
  154.  
  155. if ($row['description']) {
  156. echo "<br><small>{$row['description']}</small>";
  157. }
  158.  
  159. echo '</li>';
  160. }
  161. echo '</ul>';
  162. }
  163. }
  164.  
  165.  
  166. /**
  167.  * Shows the 'see also' things for a specific file, function or class
  168.  **/
  169. function show_see_also($link_id, $link_type)
  170. {
  171. global $project;
  172.  
  173. $q = "SELECT name FROM item_see WHERE linkid = {$link_id} AND linktype = {$link_type} AND projectid = {$project['id']}";
  174. $res = db_query($q);
  175.  
  176. if (db_num_rows($res) > 0) {
  177. echo '<h3>', str(STR_SEE_ALSO), '</h3>';
  178.  
  179. echo '<ul>';
  180. while ($row = db_fetch_assoc ($res)) {
  181. echo '<li>', process_inline_link(array(1 => $row['name'])), '</li>';
  182. }
  183. echo '</ul>';
  184. }
  185. }
  186.  
  187.  
  188. /**
  189.  * Shows the examples a specific file, function or class
  190.  **/
  191. function show_examples($link_id, $link_type)
  192. {
  193. global $project;
  194.  
  195. $q = "SELECT description FROM item_example WHERE linkid = {$link_id} AND linktype = {$link_type} AND projectid = {$project['id']}";
  196. $res = db_query($q);
  197.  
  198. while ($row = db_fetch_assoc ($res)) {
  199. echo '<h3>', str(STR_EXAMPLE), '</h3>';
  200.  
  201. $geshi = new GeSHi($row['description'], 'php');
  202. $geshi->enable_classes();
  203. $geshi->set_line_style('background: #f8f8f8;');
  204.  
  205. echo '<style type="text/css">', $geshi->get_stylesheet(), '</style>';
  206. echo $geshi->parse_code();
  207. }
  208. }
  209.  
  210.  
  211. /**
  212.  * Echos a list of all of the authors of a specifc item
  213.  **/
  214. function show_tags($link_id, $link_type)
  215. {
  216. global $project;
  217.  
  218. $q = "SELECT name FROM item_info_tags WHERE linkid = {$link_id} AND linktype = {$link_type} AND projectid = {$project['id']}";
  219. $res = db_query($q);
  220.  
  221. if (db_num_rows($res) > 0) {
  222. echo '<p class="tags">', str(STR_TAGS);
  223.  
  224. while ($row = db_fetch_assoc ($res)) {
  225. $row['name'] = htmlspecialchars($row['name']);
  226.  
  227. echo " &nbsp; <a href=\"tag?name={$row['name']}\">{$row['name']}</a>";
  228. }
  229. }
  230. }
  231.  
  232.  
  233. /**
  234.  * Gets HTML for a version, based on the version id
  235.  *
  236.  * @table select versions Will only select once, results are stored in a static array
  237.  **/
  238. function get_since_version($version_id)
  239. {
  240. global $project;
  241.  
  242. $version_id = (int) $version_id;
  243.  
  244. $q = "SELECT name FROM versions WHERE id = {$version_id} AND projectid = {$project['id']}";
  245. $res = db_query($q);
  246. $row = db_fetch_assoc($res);
  247.  
  248. return $row['name'];
  249. }
  250.  
  251.  
  252. /**
  253.  * Processes inline tags within text
  254.  *
  255.  * @param string $text the input text
  256.  * @return string The output, with inline text replaced
  257.  **/
  258. function process_inline($text)
  259. {
  260. $callback = 'process_inline_link';
  261. $text = preg_replace_callback('/{@link ([^}]*?)}/i', $callback, $text);
  262. $text = preg_replace_callback('/{@see ([^}]*?)}/i', $callback, $text);
  263. return $text;
  264. }
  265.  
  266.  
  267. /**
  268.  * Replaces the content of a @link or @see tag with its actual link.
  269.  * The content is defines as the part after @link or @see, up to the closing curly bracket
  270.  *
  271.  * @param array $matches Matches produced by a preg_* function
  272.  * @return string HTML for the link to the item, or plain text if no link could be found
  273.  **/
  274. function process_inline_link(array $matches)
  275. {
  276. global $project;
  277.  
  278. $original_text = $matches[1];
  279.  
  280. @list($text, $link_text) = explode(' ', $original_text, 2);
  281. if ($link_text == '') $link_text = $text;
  282.  
  283. $text = trim($text);
  284. $text_sql = db_quote($text);
  285.  
  286. if (preg_match('/^(?:https?|ftp|mailto|telnet|ssh|rsync):/', $text)) {
  287. // It's a URL
  288. return "<a href=\"{$text}\">{$link_text}</a>";
  289.  
  290. } else if (strpos($text, '::') !== false) {
  291. // It's a class member
  292. list ($class, $member) = explode('::', $text, 2);
  293.  
  294. $class_sql = db_quote($class);
  295. $q = "SELECT id, name FROM classes WHERE name LIKE {$class_sql} AND projectid = {$project['id']}";
  296. $res = db_query($q);
  297. if ($row = db_fetch_assoc($res)) {
  298. $class_id = $row['id'];
  299. $class_name = $row['name'];
  300.  
  301. if (substr($member, -2) == '()') {
  302. $member = trim(substr($member, 0, -2));
  303. }
  304. $text_sql = db_quote($member);
  305.  
  306. // member functions
  307. $q = "SELECT id, name FROM functions WHERE name LIKE {$text_sql} AND classid = {$class_id}";
  308. $res = db_query($q);
  309. if ($row = db_fetch_assoc($res)) {
  310. return get_function_link($class_name, $row['name'], $link_text);
  311. }
  312.  
  313. // member variables
  314. $q = "SELECT id, name FROM variables WHERE name LIKE {$text_sql} AND classid = {$class_id}";
  315. $res = db_query($q);
  316. if ($row = db_fetch_assoc($res)) {
  317. return get_class_link($class, null, $link_text);
  318. }
  319.  
  320. return $link_text;
  321. }
  322. }
  323.  
  324. // Look for classes
  325. $q = "SELECT id, name FROM classes WHERE name LIKE {$text_sql} AND projectid = {$project['id']}";
  326. $res = db_query($q);
  327. if ($row = db_fetch_assoc($res)) {
  328. return get_class_link($row['name'], null, $link_text);
  329. }
  330.  
  331. // Look for files
  332. $file = $text;
  333. if ($file[0] != '/') $file = '/' . $file;
  334. $file_sql = db_quote($file);
  335. $q = "SELECT id, name FROM files WHERE name LIKE {$file_sql} AND projectid = {$project['id']}";
  336. $res = db_query($q);
  337. if ($row = db_fetch_assoc($res)) {
  338. return "<a href=\"file?id={$row['id']}\">{$link_text}</a>";
  339. }
  340.  
  341. // Look for constants
  342. $q = "SELECT id, name, fileid FROM constants WHERE name LIKE {$text_sql} AND projectid = {$project['id']}";
  343. $res = db_query($q);
  344. if ($row = db_fetch_assoc($res)) {
  345. return "<a href=\"file?id={$row['fileid']}#constants\">{$link_text}</a>";
  346. }
  347.  
  348. if (substr($text, -2) == '()') {
  349. $text = trim(substr($text, 0, -2));
  350. $text_sql = db_quote($text);
  351. }
  352.  
  353. // Look for functions
  354. $q = "SELECT id, name FROM functions WHERE name LIKE {$text_sql} AND classid IS NULL AND interfaceid IS NULL AND projectid = {$project['id']}";
  355. $res = db_query($q);
  356. if ($row = db_fetch_assoc($res)) {
  357. return get_function_link(null, $row['name'], $link_text);
  358. }
  359.  
  360. // Look for documents
  361. // This is very last, and is done against the original full text (you cannot define an alternate name for the link of a document)
  362. $orig_text = db_quote($original_text);
  363. $q = "SELECT id, name FROM documents WHERE name LIKE {$orig_text}";
  364. $res = db_query($q);
  365. if ($row = db_fetch_assoc($res)) {
  366. $row['name'] = urlencode($row['name']);
  367. return "<a href=\"document?name={$row['name']}\">{$original_text}</a>";
  368. }
  369.  
  370. return $original_text;
  371. }
  372.  
  373.  
  374. /**
  375.  * Replaces an inline @link or @see with the plain-text version of that @link or @see.
  376.  * This is used in places where excessive links are overkill.
  377.  *
  378.  * @param string $text the input text
  379.  * @return string The output, with inline text replaced
  380.  **/
  381. function delink_inline($text)
  382. {
  383. $callback = 'process_inline_delink';
  384. $text = preg_replace_callback('/{@link ([^}]*?)}/i', $callback, $text);
  385. $text = preg_replace_callback('/{@see ([^}]*?)}/i', $callback, $text);
  386. return $text;
  387. }
  388.  
  389.  
  390. /**
  391.  * Replaces the content of a @link or @see tag with the plain text version of the link
  392.  * The content is defines as the part after @link or @see, up to the closing curly bracket
  393.  *
  394.  * @param array $matches Matches produced by a preg_* function
  395.  * @return string The plain text version of a link
  396.  **/
  397. function process_inline_delink(array $matches)
  398. {
  399. $original_text = $matches[1];
  400. $link = explode(' ', $original_text, 2);
  401.  
  402. return isset($link[1]) ? $link[1] : $link[0];
  403. }
  404.  
  405.  
  406. function show_function_usage($function_id)
  407. {
  408. $q = "SELECT functions.name, functions.static, GROUP_CONCAT(returns.type SEPARATOR '|') AS returntypes,
  409. classes.name AS class
  410. FROM functions
  411. LEFT JOIN classes ON functions.classid = classes.id
  412. LEFT JOIN returns ON returns.functionid = functions.id
  413. WHERE functions.id = {$function_id}";
  414. $res = db_query ($q);
  415. $function = db_fetch_assoc($res);
  416.  
  417. echo '<div class="function-usage">';
  418.  
  419. if ($function['returntypes']) {
  420. echo htmlspecialchars($function['returntypes']), ' ';
  421. } else {
  422. echo 'unknown ';
  423. }
  424.  
  425. if ($function['class']) {
  426. if ($function['static']) {
  427. echo "{$function['class']}::";
  428. } else {
  429. echo "\${$function['class']}->";
  430. }
  431. }
  432.  
  433. echo '<b>', $function['name'], '</b> ( ';
  434.  
  435. $q = "SELECT name, type, byref, defaultvalue FROM arguments WHERE functionid = {$function_id} ORDER BY id";
  436. $res = db_query($q);
  437. $j = 0;
  438. $num_close = 0;
  439. while ($row = db_fetch_assoc ($res)) {
  440. $row['name'] = htmlspecialchars($row['name']);
  441. $row['type'] = htmlspecialchars($row['type']);
  442. if ($row['type'] == '') $row['type'] = 'mixed';
  443.  
  444. if ($row['defaultvalue'] !== null) echo '[';
  445. if ($j++ > 0) echo ', ';
  446.  
  447. echo " {$row['type']} ";
  448. if ($row['byref']) echo '&';
  449. echo "{$row['name']} ";
  450. if ($row['defaultvalue'] !== null) $num_close++;
  451. }
  452. echo str_repeat(']', $num_close);
  453. echo ' );';
  454. echo '</div>';
  455. }
  456.  
  457.  
  458. /**
  459. * Return a link to a given file
  460. *
  461. * @param string $filename The file to return a link for
  462. * @return string HTML of a complete A link to the file
  463. **/
  464. function get_file_link($filename)
  465. {
  466. return '<a href="file?name=' . urlencode($filename) . '">' . htmlspecialchars($filename) . '</a>';
  467. }
  468.  
  469.  
  470. /**
  471. * Return a link to the source view for a file
  472. *
  473. * @param string $filename The file to return a link for
  474. * @param int $linenum Line number to highlight
  475. * @return string HTML of a complete A link to the file
  476. **/
  477. function get_source_link($filename, $linenum = null)
  478. {
  479. $source_url = 'file_source?name=' . urlencode($filename);
  480. $out = '<a href="' . htmlspecialchars($source_url) . '">' . htmlspecialchars($filename) . '</a>';
  481.  
  482. if ($linenum) {
  483. $source_url .= '&highlight=' . $linenum;
  484. if ($linenum > 5) {
  485. $source_url .= '#src-lines-' . ($linenum - 5);
  486. }
  487. $out .= ' line ';
  488. $out .= '<a href="' . htmlspecialchars($source_url) . '">' . $linenum . '</a>';
  489. }
  490.  
  491. return $out;
  492. }
  493.  
  494.  
  495. /**
  496. * Return a link to a given class
  497. *
  498. * @param string $class The name of the class to return a link for
  499. * @param string $link_text Text to show on the link; defaults to the class name
  500. * @return string HTML of a complete A link to the class
  501. **/
  502. function get_class_link($class, $filename = null, $link_text = null)
  503. {
  504. $url = 'class?name=' . urlencode($class);
  505. if ($filename) $url .= '&file=' . urlencode($filename);
  506. return '<a href="' . htmlspecialchars($url) . '">' . htmlspecialchars($link_text ?: $class) . '</a>';
  507. }
  508.  
  509.  
  510. /**
  511. * Return a link to a given interface
  512. *
  513. * @param string $interface The name of the interface to return a link for
  514. * @return string HTML of a complete A link to the interface
  515. **/
  516. function get_interface_link($interface)
  517. {
  518. return '<a href="interface?name=' . urlencode($interface) . '">' . htmlspecialchars($interface) . '</a>';
  519. }
  520.  
  521.  
  522. /**
  523. * Return a link to a given namespace
  524. *
  525. * @param string $namespace The name of the namespace to return a link for
  526. **/
  527. function get_namespace_link($namespace)
  528. {
  529. return '<a href="namespace?name=' . urlencode($namespace) . '">' . htmlspecialchars($namespace) . '</a>';
  530. }
  531.  
  532.  
  533. /**
  534. * Return a link to a given function
  535. *
  536. * @param string $class The name of the class or interface a function is a member of. Use NULL for non-class functions
  537. * @param string $function The name of the function to return a link for
  538. * @param string $link_text Text to show on the link; defaults to the function name
  539. * @return string HTML of a complete A link to the function
  540. **/
  541. function get_function_link($class, $function, $link_text = null)
  542. {
  543. $out = '';
  544. if ($class) {
  545. $out .= '<a href="function?name=' . urlencode($function) . '&memberof=' . urlencode($class) . '">';
  546. } else {
  547. $out .= '<a href="function?name=' . urlencode($function) . '">';
  548. }
  549. $out .= htmlspecialchars($link_text ?: $function);
  550. $out .= '</a>';
  551. return $out;
  552. }
  553.  
  554.  
  555. function redirect($url)
  556. {
  557. header('Location: ' . $url);
  558. exit(0);
  559. }
  560.