PHP Classes

File: doc.php

Recommend this page to a friend!
  Classes of Rubens Takiguti Ribeiro   Unicode Manipulation   doc.php   Download  
File: doc.php
Role: Auxiliary script
Content type: text/plain
Description: Class Documentation
Class: Unicode Manipulation
Manipulate text with Unicode encodings
Author: By
Last change: Missing file
Date: 15 years ago
Size: 20,151 bytes
 

Contents

Class file image Download
<?php /** * This file is part of unicode class. * It provides basic documentation. * * @autor Rubens Takiguti Ribeiro * @date 2008-06-19 * @version 0.52 2008-06-26 * @license http://www.gnu.org/licenses/lgpl-3.0.html LGPLv3 (LICENSE.TXT) * @copyright Copyright (C) 2008 Rubens Takiguti Ribeiro */ require_once(dirname(__FILE__).'/unicode.class.php'); /* BEGIN */ global $DOC; start_doc(); print_doc_page(); end_doc(); /* END */ /** * Start the doc script. Data used in this script are saved in session. * * @return void */ function start_doc() { global $DOC; if (!extension_loaded('reflection')) { die('Reflection extension is need to access this page.'); } $DOC = new stdClass(); session_start(); if (isset($_SESSION['DOC_CLASS'])) { $DOC = unserialize($_SESSION['DOC_CLASS']); } // Get filename if (!isset($DOC->file)) { $DOC->file = basename(__FILE__); } // Get action if (isset($_GET['action'])) { $DOC->action = $_GET['action']; } elseif (!isset($DOC->action)) { $DOC->action = 'main'; } // Get data if (!isset($DOC->data)) { $DOC->data = array(); } if (isset($_GET['data'])) { foreach ($_GET['data'] as $key => $value) { if ($value != 'null') { $DOC->data[$key] = $value; } else { unset($DOC->data[$key]); } } } } /** * End the doc script (save session). * * @return void */ function end_doc() { global $DOC; $_SESSION['DOC_CLASS'] = serialize($DOC); } /** * Print page based on user action. * * @return void */ function print_doc_page() { global $DOC; $last = 0; foreach (get_classes(false) as $class) { try { $ref_class = new ReflectionClass($class); } catch (Exception $e) { continue; } $data = parse_comment($ref_class->getDocComment()); list($version, $date) = explode(' ', $data['@version']); $date = date_parse($date); $last = max($last, mktime(0, 0, 0, $date['month'], $date['day'], $date['year'])); } header('Content-Type: text/html; charset=UTF-8'); echo "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n"; echo '<html lang="en">'; echo '<head>'; echo '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">'; echo '<title>Class Documentation</title>'; echo '<link rel="index" href="'.$DOC->file.'" title="Main" >'; echo '</head>'; echo '<body>'; echo '<h1 id="header">Class Documentation</h1>'; echo '<div id="content">'; echo '<hr />'; check_actions(); // Script Controller echo '<hr />'; echo '</div>'; echo '<p id="footer">'; echo 'Copyright &copy; 2008&nbsp;&nbsp;Rubens Takiguti Ribeiro<br />'; echo "Last update: \n"; echo '$Date '.gmstrftime('%Y/%m/%d %H:%M:%S', $last)." $\n"; echo '</p>'; echo '</body>'; echo '</html>'; } /** * Check and invoke action requests. * * @return void */ function check_actions() { global $DOC; switch ($DOC->action) { case 'open_class': case 'class_description': print_class_description(); break; case 'class_structure': print_class_structure(); break; case 'class_constants': print_class_constants(); break; case 'class_properties': print_class_properties(); break; case 'class_methods': print_class_methods(); break; case 'main': default: $DOC->data = array(); // Clear data print_main(); break; } } /** * Print the main page. * * @return void */ function print_main() { global $DOC; echo '<h2>Main Page</h2>'; echo '<p>Select a class below.</p>'; echo '<ol>'; foreach (get_classes() as $class => $name) { echo '<li><a href="'.$DOC->file.'?action=open_class&amp;data[class]='.$class.'">'.$name.'</a></li>'; } echo '</ol>'; } /** * Print class menu. * * @return void */ function print_class_menu() { global $DOC; $file = &$DOC->file; $actions = array('main' => 'Main', 'class_description' => 'Description', 'class_structure' => 'Structure', 'class_constants' => 'Constants', 'class_properties' => 'Properties', 'class_methods' => 'Methods'); echo '<h2>'.$DOC->data['class'].'</h2>'; echo '<ul class="navbar">'; foreach ($actions as $action => $name) { $class = $DOC->action == $action ? ' class="active"' : ''; echo '<li><a href="'.$file.'?action='.$action.'"'.$class.'>'.$name.'</a></li>'; } echo '</ul>'; } /** * Print class description. * * @return void; */ function print_class_description() { global $DOC; if (!isset($DOC->data['class'])) { echo '<p class="error">Class not defined</p>'; print_main(); return; } try { $ref_class = new ReflectionClass($DOC->data['class']); } catch (Exception $e) { echo '<p class="error">Class not defined: '.$e->getMessage().'</p>'; print_main(); return; } $data = parse_comment($ref_class->getDocComment()); $extension = $ref_class->getExtensionName(); if (empty($extension)) { $extension = null; } $interfaces = array(); foreach ($ref_class->getInterfaces() as $interface) { $interfaces[] = $interface->getName(); } $modifiers = implode(' ', Reflection::getModifierNames($ref_class->getModifiers())); if (empty($modifiers)) { $modifiers = null; } $data['@extension'] = $extension; $data['@class'] = $ref_class->getName(); $data['@file'] = $ref_class->getFileName(); $data['@lines'] = $ref_class->getStartLine().'-'.$ref_class->getEndLine(); $data['@implements'] = $interfaces; $data['@instantiable'] = (bool)$ref_class->isInstantiable(); $data['@interface'] = (bool)$ref_class->isInterface(); $data['@abstract'] = (bool)$ref_class->isAbstract(); $data['@final'] = (bool)$ref_class->isFinal(); $data['@iterateable'] = (bool)$ref_class->isIterateable(); $data['@modifiers'] = $modifiers; print_class_menu(); echo '<h3>Basic Class Description</h3>'; print_table($data, 'Basic Class Description'); } /** * Print class structure. * * @return void */ function print_class_structure() { global $DOC; if (!isset($DOC->data['class'])) { echo '<p class="error">Class not defined</p>'; print_main(); return; } $ref_class = new ReflectionClass($DOC->data['class']); $comments = get_category_comments($ref_class->getFileName()); print_class_menu(); echo '<h3>Class Structure</h3>'; if (count($comments)) { print_list($comments); } else { echo '<p>No structure specified in this file.</p>'; return; } } /** * Print class constants. * * @return void */ function print_class_constants() { global $DOC; if (!isset($DOC->data['class'])) { echo '<p class="error">Class not defined</p>'; print_main(); return; } $ref_class = new ReflectionClass($DOC->data['class']); $constants = $ref_class->getConstants(); print_class_menu(); echo '<h3>Class Constants</h3>'; if (!count($constants)) { echo '<p>No constants avaliable.</p>'; return; } echo '<table>'; echo '<caption>Class Constants</caption>'; echo '<thead>'; echo ' <tr>'; echo ' <th scope="col">Constant</th>'; echo ' <th scope="col">Value</th>'; echo ' <th scope="col">Type</th>'; echo ' </tr>'; echo '</thead>'; echo '<tbody>'; foreach ($constants as $constant => $value) { echo '<tr>'; echo ' <th scope="row">'.$DOC->data['class'].'::'.$constant.'</th>'; echo ' <td>'.convert_php_value($value).'</td>'; echo ' <td>'.gettype($value).'</td>'; echo '</tr>'; } echo '</tbody>'; echo '</table>'; } /** * Print class properties. * * @return void */ function print_class_properties() { global $DOC; if (!isset($DOC->data['class'])) { echo '<p class="error">Class not defined</p>'; print_main(); return; } $ref_class = new ReflectionClass($DOC->data['class']); $default_properties = $ref_class->getDefaultProperties(); print_class_menu(); if (!count($ref_class->getProperties())) { echo '<p>No properties avaliable.</p>'; return; } $properties = array(); echo '<h3>Class Properties</h3>'; echo '<ol>'; foreach ($ref_class->getProperties() as $property) { $data = parse_comment($property->getDocComment()); $data['@name'] = $property->getName(); if ($property->isPublic()) { $data['@visibility'] = 'public'; } elseif ($property->isProtected()) { $data['@visibility'] = 'protected'; } elseif ($property->isPrivate()) { $data['@visibility'] = 'private'; } else { $data['@visibility'] = 'undefined'; } $data['@static'] = $property->isStatic(); $default = $default_properties[$data['@name']]; $data['@default'] = convert_php_value($default).' ('.gettype($default).')'; echo ' <li><a href="#prop_'.$data['@name'].'">'.$data['@name'].'</a></li>'; $properties[] = $data; } echo '</ol>'; echo '<hr />'; echo '<h3>Properties Details</h3>'; foreach ($properties as $property) { echo '<div>'; echo '<h4><a id="prop_'.$property['@name'].'">'.$property['@name'].'</a></h4>'; print_table($property); echo '</div>'; } } /** * Print class methods. * * @return void */ function print_class_methods() { global $DOC; if (!isset($DOC->data['class'])) { echo '<p class="error">Class not defined</p>'; print_main(); return; } $ref_class = new ReflectionClass($DOC->data['class']); $comments = get_category_comments($ref_class->getFileName()); $first_method_line = false; foreach ($ref_class->getMethods() as $method) { $data = parse_comment($method->getDocComment()); $data['@name'] = $method->getName(); if ($method->isPublic()) { $data['@visibility'] = 'public'; } elseif ($method->isProtected()) { $data['@visibility'] = 'protected'; } elseif ($method->isPrivate()) { $data['@visibility'] = 'private'; } else { $data['@visibility'] = 'undefined'; } $data['@static'] = $method->isStatic(); $data['@final'] = $method->isFinal(); $data['@abstract'] = $method->isAbstract(); $data['@returns reference'] = $method->returnsReference(); $data['@lines'] = $method->getStartLine().'-'.$method->getEndLine(); $parameters = array(); foreach ($method->getParameters() as $parameter) { $p = '$'.$parameter->getName(); if ($parameter->isPassedByReference()) { $p = '&'.$p; } if ($parameter->isDefaultValueAvailable()) { $p .= ' = '.convert_php_value($parameter->getDefaultValue()); } $parameters[] = $p; } $data['@parameters'] = $parameters; if ($comments) { $data['@category'] = get_category($comments, $method->getStartLine()); } $methods[$data['@name']] = $data; } print_class_menu(); echo '<h3>Class Methods</h3>'; if (!count($methods)) { echo '<p>No methods avaliable.</p>'; return; } echo '<ul>'; if (!count($comments)) { foreach ($methods as $method) { echo '<li><a href="#method_'.$method['@name'].'">'.$method['@name'].'</a></li>'; } } else { $category = array(); foreach ($methods as $method) { if (!isset($category[$method['@category']])) { if (count($category)) { echo '</ul>'; } echo '<li><strong>'.$method['@category'].'</strong><ul>'; $category[$method['@category']] = true; } echo '<li><a href="#method_'.$method['@name'].'">'.$method['@name'].'</a></li>'; } echo '</ul>'; } echo '</ul>'; echo '<hr />'; echo '<h3>Methods Details</h3>'; foreach ($methods as $method) { echo '<div>'; echo '<h4<a id="method_'.$method['@name'].'">'.$method['@name'].'</a></h4>'; print_table($method); echo '</div>'; } } /** * Print a list hierarchically * * @param array $list * @return void */ function print_list($list) { echo '<ul>'; foreach ($list as $key => $value) { if (is_array($value)) { echo '<li>'.$key.print_list($value).'</li>'; } else { echo '<li>'.$value.'</li>'; } } echo '</ul>'; } /** * Print an associative array as an HTML table. * * @param array[string => string] $data * @param string $caption * @return void */ function print_table($data, $caption = '') { static $id = 0; $id++; $id_key = 't_key_'.$id; $id_value = 't_value_'.$id; if (!isset($data['description'])) { $data['description'] = '[No description]'; } echo '<table>'; if ($caption) { echo '<caption>'.$caption.'</caption>'; } echo '<thead>'; echo ' <tr>'; echo ' <th id="'.$id_key.'" scope="col">Key</th>'; echo ' <th id="'.$id_value.'" scope="col">Value</th>'; echo ' </tr>'; echo '</thead>'; echo '<tbody>'; $id_line = 't_desc_'.$id; echo ' <tr>'; echo ' <th id="'.$id_line.'" scope="row" headers="'.$id_key.'">Description</th>'; echo ' <td headers="'.$id_value.' '.$id_line.'">'.nl2br($data['description']).'</td>'; echo ' </tr>'; foreach ($data as $key => $value) { if ($key[0] == '@') { $key = substr($key, 1); list($key, $value) = convert_key_value($key, $value); $id_line = 't_'.strtolower($key).'_'.$id; echo ' <tr>'; echo ' <th id="'.$id_line.'" scope="row" headers="'.$id_key.'">'.ucfirst($key).'</th>'; echo ' <td headers="'.$id_value.' '.$id_line.'">'.$value.'</td>'; echo ' </tr>'; } } echo '</tbody>'; echo '</table>'; } /** * Convert a key value to be shown. * * @param string $key * @param mixed $value * @return array */ function convert_key_value($key, $value) { if (is_array($value)) { if (!count($value)) { return array($key, '[empty]'); } $first_key = current(array_keys($value)); $list_type = is_int($first_key) ? 'ol' : 'ul'; $return = '<'.$list_type.'>'; foreach ($value as $k => $v) { list($k, $v) = convert_key_value($k, $v); $return .= '<li>'.($list_type == 'ul' ? $k.': ' : '').$v.'</li>'; } $return .= '</'.$list_type.'>'; return array($key, $return); } switch ($key) { case 'license': case 'see': if (preg_match('/^(http[s]?:\/\/[^\040]+) (.+)$/', $value, $match)) { $value = '<a href="'.$match[1].'">'.convert_value($match[2]).'</a>'; } else { $value = convert_value($value); } break; default: $value = convert_value($value); break; } return array($key, $value); } /** * Convert a value to be shown. * * @param mixed $original * @return string */ function convert_value($original) { static $tr = array('(C)' => '&copy;', '(c)' => '&copy;', '(R)' => '&reg;', '(r)' => '&reg;', '(TM)' => '&trade;', '(tm)' => '&trade;'); if (is_string($original)) { return nl2br(strtr(utf8_encode($original), $tr)); } elseif (is_int($original)) { return number_format($original, 0, '.', ''); } elseif (is_double($original)) { return strval($original); } elseif (is_bool($original)) { return $original ? 'Yes' : 'No'; } elseif (is_null($original)) { return '[empty]'; } else { return '[value not printable]'; } } /** * Convert a PHP value to a human readeable format. * * @param mixed $original * @return string */ function convert_php_value($original) { if (is_string($original)) { return "'".$original."'"; } elseif (is_int($original)) { return number_format($original, 0, '.', ''); } elseif (is_double($original)) { return strval($original); } elseif (is_bool($original)) { return $original ? 'true' : 'false'; } elseif (is_null($original)) { return 'null'; } elseif (is_array($original)) { return '[array of size '.count($original).']'; } elseif (is_object($original)) { return '[object of type '.get_class($original).']'; } elseif (is_resource($original)) { return '[resource of type '.get_resource_type($original).']'; } else { return '[undefined value]'; } } /** * Parse a documentation comment and fill an associative array. * * @param string $comment * @return array[string => string] */ function parse_comment($comment) { $lines = explode("\n", $comment); array_shift($lines); $data = array('description' => ''); foreach ($lines as $line) { $line = substr(trim($line), 2); if ($line[0] == '@') { $pos_space = strpos($line, ' '); $attribute = substr($line, 0, $pos_space); $value = substr($line, $pos_space + 1); if (isset($data[$attribute])) { if (is_array($data[$attribute])) { $data[$attribute][] = $value; } else { $old_value = $data[$attribute]; $data[$attribute] = array($old_value, $value); } } else { $data[$attribute] = $value; } unset($pos_space, $attribute, $value); } else { $data['description'] .= $line."\n"; } } $data['description'] = trim($data['description']); return $data; } /** * Get category comments and its line. * * @param string $filename * @return array[int => string] */ function get_category_comments($filename) { $lines = file($filename); $comments = array(); foreach ($lines as $i => $line) { if (strpos($line, '///') === 0) { $comments[$i] = trim(substr($line, 3)); } } return $comments; } /** * Get category from an element of specific line. * * @param array $comments category comments * @param int $line line of element * @return string */ function get_category(&$comments, $line) { $last = ''; foreach ($comments as $l => $c) { if ($l > $line) { return $last; } $last = $c; } return $last; } /** * Get all classes/interfaces in current directory. * * @param bool $complete true returns "type classname" / false returns "classname" * @return array[string] */ function get_classes($complete = true) { $dirname = dirname(__FILE__).'/'; $dir = scandir($dirname); $classes = array(); $reg = '/^([a-z_]*)\.(class|interface)(\.php)$/'; foreach ($dir as $file) { if (is_file($dirname.$file) && preg_match($reg, $file, $match)) { if ($complete) { $classes[$match[1]] = $match[2].' '.$match[1]; } else { $classes[$match[1]] = $match[1]; } } } asort($classes); return $classes; }