*/ // global flag needed for the error handling output $GLOBALS['errorStylesRendered'] = false; /** * The pat examples framework class - manages the navigation and * functionality of the examples collection of our tools. * * $Id: patExampleGen.php 373 2006-08-15 20:28:52Z gerd $ * * @package patExampleGen * @version 0.9 * @author Sebastian Mordziol * @license LGPL * @link http://www.php-tools.de */ class patExampleGen { /** * Stores all request variables * * @access private * @var array * @see setSections() */ var $vars = array(); /** * Stores the sections collection to generate * the examples navigation from * * @access private * @var array */ var $sections = array(); /** * The XML_Beautifier class - used if installed to display * XML output in a nice readable format with indentation. * * @access private * @var object */ var $beautifier = false; /** * Stores the tabs configuration used to create the tabnavigation * for each example. * * @access private * @var array * @see setTabs() */ var $tabs = array(); /** * Stores the name of the application * * @access private * @var string * @see setAppName() */ var $appName = 'Unknown'; /** * Stores the description of the application * * @access private * @var string * @see setAppDescription() */ var $appDescription = ''; /** * Stores the ID of the application's forum * * @access private * @var int * @see setAppForumId() */ var $appForumId = 0; /** * additional get parameter to be passed to each script * * @access private * @var array */ var $extraGet = array(); /** * custom naviagetion script * * @access private * @var string */ var $customNav = null; /** * Main process method that dispatches needed tasks according * to the given action. * * @access public */ function process() { $this->vars = $this->getRequestVars(); $action = 'frameset'; if( isset( $this->vars['action'] ) ) $action = strtolower( $this->vars['action'] ); switch( $action ) { case 'frameset': $this->displayFrameset(); break; case 'navigation': $this->displayNavigation(); break; case 'overview': $this->displayOverview(); break; case 'example': $this->displayExample(); break; } } /** * Retrieves the request variables from POST and GET * * @access public * @return array $requestVars The request vars */ function getRequestVars() { return array_merge( $_POST, $_GET ); } /** * Sets the default tab configuration that will be used for * each example page. Additional tabs can be defined for each * example within the section definition. * * @access public * @param array $tabs The tab configuration * @see $tabs */ function setTabs( $tabs ) { $this->tabs = $tabs; } /** * Sets the name of the application * * @access public * @param string $appName The name * @see $appName */ function setAppName( $appName ) { $this->appName = $appName; } /** * Sets the description of the application * * @access public * @param string $desc The description text * @see $appDescription */ function setAppDescription( $desc ) { $this->appDescription = $desc; } /** * Sets the ID of the application's forum. Needed to display * the correct link to the forum. * * @access public * @param int $id The forum ID * @see $appForumId */ function setAppForumId( $id ) { $this->appForumId = $id; } /** * Retrieves the default example view tab, the one * that is active when the page is loaded. * * @access public * @return string $tabId The ID of the tab */ function getDefaultTab( $tabs ) { foreach( $tabs as $tabId => $tabDef ) { if( $tabDef['default'] ) { return $tabId; } } reset( $tabs ); return key( $tabs ); } /** * Custom error handler that is set automatically to display * any patError error objets within the examples collection. * * Displays: * - Error level * - Error Message * - Error info * - Error file * - Error line * - plus the call stack that lead to the error * * @author Sebastian Mordziol * @access public * @static * @param object error object * @return object error object */ function &displayError( &$error ) { $prefix = 'arghDebug'; // display the needed styles and scripts, but only once. if( !$GLOBALS['errorStylesRendered'] ) { echo ''; echo ''; $GLOBALS['errorStylesRendered'] = true; } $errorID = md5( $error->getFile().$error->getLine() ); echo '
'; printf( '
%s: %s in %s on line %s
Details: %s (show backtrace)', patErrorManager::translateErrorLevel( $error->getLevel() ), $error->getMessage(), $error->getFile(), $error->getLine(), $error->getInfo() ); $backtrace = $error->getBacktrace(); if( is_array( $backtrace ) ) { $j = 1; echo ''; echo ' '; echo ' '; echo ' '; echo ' '; echo ' '; echo ' '; echo ' '; echo ' '; for( $i = count( $backtrace )-1; $i >= 0 ; $i-- ) { echo ' '; echo ' '; if( isset( $backtrace[$i]['class'] ) ) { echo ' '; } else { echo ' '; } if( isset( $backtrace[$i]['file'] ) ) { echo ' '; } else { echo ' '; } echo ' '; $j++; } echo ''; } echo '
'; $level = $error->getLevel(); if( $level != E_ERROR ) return $error; exit(); } /** * Displays an example page along with all defined tabs * * @access public */ function displayExample() { if( !isset( $this->vars['example'] ) ) die( 'No example selected.' ); $exampleId = $this->vars['example']; $section = $this->getExampleSection( $exampleId ); $example = $this->getExample( $exampleId ); $exampleFile = $exampleId.'.php'; $tabs = $this->getTabs( $exampleId ); $defaultTab = $this->getDefaultTab( $tabs ); $this->displayHead( 'Example', 'displayTab( \''.$defaultTab.'\' );' ); echo ''; echo '
'; echo '
'.$this->appName.' '.$section.' :: '.$example['title'].'
'; echo '
'.htmlentities( $example['descr'] ).'
'; echo '
'; // the tabs echo ''; echo ' '; echo ' '; foreach( $tabs as $tabId => $tabDef ) { echo ''; echo ''; } echo ' '; echo ' '; echo '
 '.$tabDef['title'].'  
'; // the tab contents foreach( $tabs as $tabId => $tabDef ) { // replace variables in the file string with // the corresponding local variables if( isset( $tabDef['file'] ) ) { // possible vars $needles = array( '$exampleFile', '$exampleId', ); // store values $replace = array(); foreach( $needles as $n ) array_push( $replace, ${substr( $n, 1 )} ); // replace $tabDef['file'] = str_replace( $needles, $replace, $tabDef['file'] ); } // what kind of tab is this? switch( strtolower( $tabDef['type'] ) ) { case 'phpsource': $this->displayPHPSource( $tabId, $tabDef['file'] ); break; case 'output': $this->displayOutput( $tabId, $tabDef['file'] ); break; case 'xmlsource': $this->displayXMLSource( $tabId, $tabDef['file'] ); break; case 'text': $this->displayText( $tabId, $tabDef['text'] ); break; case 'guide': $this->displayGuide( $tabId, $tabDef['file'], $tabDef['guide'] ); break; } } $this->displayFooter(); } function httpBuildQuery( $get ) { if( empty( $get ) ) { return ''; } $extra = array(); foreach( $get as $key => $value ) { $extra[] = $key . '=' . urlencode( $value ); } return implode( '&', $extra ); } /** * Display an example's output in an example tab via an iframe * * @access public * @param string $tabId The ID of the tab * @param string $file The file to show */ function displayOutput( $tabId, $file ) { $extra = $this->httpBuildQuery( $this->extraGet ); echo ''; } function displayGuide( $tabId, $file, $guide ) { $file = explode( "\n", $this->file_get_contents( $file ) ); echo '
'; foreach( $guide as $row => $entry ) { $slice = explode( '-', $entry['lines'] ); $hilight = implode( "\n", array_slice( $file, ( $slice[0] -1 ), ( $slice[1] - $slice[0] ) + 1 ) ); ob_start(); highlight_string( '' ); $content = ob_get_contents(); ob_end_clean(); $content = str_replace( '<?php', '', $content ); $content = str_replace( '?>', '', $content ); $numbers = ''; for( $i=$slice[0]; $i <= $slice[1]; $i++ ) { $numbers .= $i.'.
'; } echo '
'.$entry['text'].'
'.$numbers.' '.$content.'
'; } echo '
'; } /** * Display PHP source code in an example tab * * @access public * @param string $tabId The ID of the tab * @param string $file The file to hilight */ function displayPHPSource( $tabId, $file ) { echo '
'; highlight_file( $file ); echo '
'; } /** * Display a free text in a tab * * @access public * @param string $tabId The ID of the tab * @param string $text The text to display */ function displayText( $tabId, $text ) { echo '
'; echo $text; echo '
'; } /** * Display XML source code in an example tab * * @access public * @param string $tabId The ID of the tab * @param string $file The file to hilight */ function displayXMLSource( $tabId, $file ) { $url = str_replace( 'index.php', $file, 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'] ); $source = $this->url_get_contents( $url ); if( !$source ) die( 'Could not open XML source file for hilighting: "'.$url.'"' ); echo '
'; $this->displayXMLString( $source ); echo '
'; } /** * Hilights an xml string and displays it * * @access public * @param string $xml The XML string * @see highlightXML() */ function displayXMLString( $xml ) { echo $this->highlightXML( $xml ); } /** * Highlights an xml string and returns the highlighted source * * @access public * @param string $xml The XML string * @return string $xml The highlighted string */ function highlightXML( $xml ) { @include_once( 'XML/Beautifier.php' ); if( class_exists( 'XML_Beautifier' ) ) { if( !is_object( $this->beautifier ) ) { $this->beautifier =& new XML_Beautifier(); } $result = $this->beautifier->formatString( $xml ); if( !PEAR::isError( $result ) ) $xml = $result; } ob_start(); highlight_string( $xml ); $xml = ob_get_contents(); ob_end_clean(); return $xml; } /** * Displays the examples main frameset * * @access public */ function displayFrameset() { $extra = $this->httpBuildQuery( $this->extraGet ); echo ''; echo ''; echo ' '.$this->appName.': examples'; echo ''; echo ''; echo ' '; echo ' '; echo ''; echo ''; } /** * Sets the sections from which to generate the examples framework * * @access public * @param array &$sections The sections definition */ function setSections( $sections ) { $this->sections = $sections; } /** * set additional get parameter * * @access public * @param array $extra associative array of get parameter */ function setExtraGet( $extra ) { $this->extraGet = $extra; } /** * define additional naviagetion script * * @access public * @param array $script */ function addCustomNav( $script ) { $this->customNav = $script; } /** * Displays the main examples navigation * * @access public */ function displayNavigation() { $this->displayHead( 'Nav' ); if( $this->customNav ) { include $this->customNav; } $extra = $this->httpBuildQuery( $this->extraGet ); echo ''; echo '

Examples navigation

'; echo '» Overview

'; foreach( $this->sections as $sectionName => $section ) { echo '

[+] '.$this->appName.'::'.$sectionName.' ('.count($section['pages']).')

'; echo '
'; foreach( $section['pages'] as $pageId => $pageData ) { $exampleFile = $section['basename'].$pageId; if( isset( $pageData['alias'] ) ) $exampleFile = $pageData['alias']; if( !file_exists( $exampleFile.'.php' ) ) { echo '» '.$pageData['title'].'
'; continue; } echo '» '.$pageData['title'].'
'; } echo '
'; } echo ''; echo ''; $this->displayFooter(); } /** * Displays the examples overview page * * @access public */ function displayOverview() { $this->displayHead( 'Overview' ); echo '

'.$this->appName.' examples overview

'; echo '

'; echo ' These examples show the functionality of '.$this->appName.' in detail. '; echo ' This overview lists all examples with a small description, and to '; echo ' navigate the examples, use the navigation on the left.'; echo '

'; if( !empty( $this->appDescription ) ) { echo '
'.$this->appDescription.'
'; } echo '
'; foreach( $this->sections as $section => $sectionData ) { echo '

'.$this->appName.'::'.$section.' ('.count($sectionData['pages']).')

'; echo '

'.$sectionData['descr'].'

'; echo '
'; } $this->displayFooter(); } /** * Displays the header for any example page * * @access public * @param string $area The area we are in - is added to the body style */ function displayHead( $area, $onload = null ) { echo ''; echo ''; echo ' '.$this->appName.' Examples'; echo ' '; echo ''; echo ''; } /** * Displays the footer for any example page * * @access public */ function displayFooter() { echo ''; echo ''; } /** * get the example section * * @access public * @param string example id * @return string section title */ function getExampleSection( $id ) { foreach( $this->sections as $title => $spec ) { if( strncmp( $spec['basename'], $id, strlen( $spec['basename'] ) ) === 0 ) return $title; } return false; } /** * Get an example's details * * @access public * @param string example id * @return string section title */ function getExample( $id ) { foreach( $this->sections as $title => $spec ) { if( strncmp( $spec['basename'], $id, strlen( $spec['basename'] ) ) !== 0 ) continue; foreach( $spec['pages'] as $name => $data ) { if( $id != $spec['basename'].$name ) continue; if( !isset( $data['templates'] ) ) { $data['templates'] = array( $id.'.tmpl' ); } return $data; } } return false; } /** * Get the tabs for an example (per example tabs can be modified/added). * * @access public * @param string $id The example id * @return array $tabs The tabs for the specified example */ function getTabs( $id ) { foreach( $this->sections as $title => $spec ) { if( strncmp( $spec['basename'], $id, strlen( $spec['basename'] ) ) !== 0 ) continue; foreach( $spec['pages'] as $name => $data ) { if( $id != $spec['basename'].$name ) continue; if( !isset( $data['tabs'] ) ) { return $this->tabs; } $tabs = $this->tabs; foreach( $data['tabs'] as $tabId => $tabDef ) { if( !isset( $tabDef['default'] ) ) $tabDef['default'] = false; $tabs[$tabId] = $tabDef; } return $tabs; } } return false; } /** * Replacement for file_get_contents * * @access public * @static * @param string filename * @return mixed content of the file or false */ function file_get_contents( $filename ) { if( !file_exists( $filename ) ) return false; if( function_exists( "file_get_contents" ) ) { return file_get_contents( $filename ); } $fp = @fopen( $filename, "rb" ); if( !$fp ) { return false; } flock( $fp, LOCK_SH ); $content = fread( $fp, filesize( $filename ) ); flock( $fp, LOCK_UN ); fclose( $fp ); return $content; } /** * Simple url content loader * * @access public * @static * @param string $url The Url to get the content from * @return mixed $content The content of the file or false */ function url_get_contents( $url ) { if( function_exists( "file_get_contents" ) ) { return file_get_contents( $url ); } $fp = @fopen( $url, "rb" ); if( !$fp ) { return false; } $content = ''; while( !feof( $fp ) ) { $content .= fread( $fp, 2000 ); } fclose( $fp ); return $content; } } ?>