From e262a291933636b32b5133e28ceb0f01c7ba85b6 Mon Sep 17 00:00:00 2001 From: Mateusz Uzdowski Date: Tue, 17 Apr 2012 14:45:26 +1200 Subject: [PATCH] ENHANCEMENT: move code introspection functions to the silverstripe-codeviz module --- css/CodeViewer.css | 3 - css/TestViewer.css | 3 - dev/CodeViewer.php | 351 -------------------------------- dev/DevelopmentAdmin.php | 11 +- dev/ModelViewer.php | 213 ------------------- dev/TestViewer.php | 257 ----------------------- scss/CodeViewer.scss | 14 -- scss/TestViewer.scss | 14 -- templates/CodeViewer.ss | 9 - templates/ModelViewer.ss | 34 ---- templates/ModelViewer_dotsrc.ss | 20 -- templates/TestViewer.ss | 9 - 12 files changed, 1 insertion(+), 937 deletions(-) delete mode 100644 css/CodeViewer.css delete mode 100644 css/TestViewer.css delete mode 100644 dev/CodeViewer.php delete mode 100644 dev/ModelViewer.php delete mode 100644 dev/TestViewer.php delete mode 100755 scss/CodeViewer.scss delete mode 100755 scss/TestViewer.scss delete mode 100644 templates/CodeViewer.ss delete mode 100644 templates/ModelViewer.ss delete mode 100644 templates/ModelViewer_dotsrc.ss delete mode 100644 templates/TestViewer.ss diff --git a/css/CodeViewer.css b/css/CodeViewer.css deleted file mode 100644 index 2cd9f3493..000000000 --- a/css/CodeViewer.css +++ /dev/null @@ -1,3 +0,0 @@ -pre { border: 1px #777 solid; background-color: #CCC; color: #333; margin: 0.5em 2em; padding: 1em; line-height: 120%; } - -pre strong { background-color: #FFC; color: #000; padding: 2px; } diff --git a/css/TestViewer.css b/css/TestViewer.css deleted file mode 100644 index 2cd9f3493..000000000 --- a/css/TestViewer.css +++ /dev/null @@ -1,3 +0,0 @@ -pre { border: 1px #777 solid; background-color: #CCC; color: #333; margin: 0.5em 2em; padding: 1em; line-height: 120%; } - -pre strong { background-color: #FFC; color: #000; padding: 2px; } diff --git a/dev/CodeViewer.php b/dev/CodeViewer.php deleted file mode 100644 index a2546da35..000000000 --- a/dev/CodeViewer.php +++ /dev/null @@ -1,351 +0,0 @@ - 'browse', - '$Class' => 'viewClass' - ); - - static $allowed_actions = array( - 'index', - 'browse', - 'viewClass' - ); - - /** - * Define a simple finite state machine. - * Top keys are the state names. 'start' is the first state, and 'die' is the error state. - * Inner keys are token names/codes. The values are either a string, new state, or an array(new state, handler method). - * The handler method will be passed the PHP token as an argument, and is expected to populate a property of the object. - */ - static $fsm = array( - 'start' => array( - T_CLASS => array('className','createClass'), - T_DOC_COMMENT => array('', 'saveClassComment'), - ), - 'className' => array( - T_STRING => array('classSpec', 'setClassName'), - ), - 'classSpec' => array( - '{' => 'classBody', - ), - 'classBody' => array( - T_FUNCTION => array('methodName','createBodyMethod'), - '}' => array('start', 'completeClass'), - T_DOC_COMMENT => array('', 'saveMethodComment'), - ), - 'methodName' => array( - T_STRING => array('methodSpec', 'setMethodName'), - ), - 'methodSpec' => array( - '{' => 'methodBody', - ), - 'methodBody' => array( - '{' => array('!push','appendMethodContent'), - '}' => array( - 'hasstack' => array('!pop', 'appendMethodContent'), - 'nostack' => array('classBody', 'completeMethod'), - ), - T_VARIABLE => array('variable', 'potentialMethodCall'), - T_COMMENT => array('', 'appendMethodComment'), - T_DOC_COMMENT => array('', 'appendMethodComment'), - '*' => array('', 'appendMethodContent'), - ), - 'variable' => array( - T_OBJECT_OPERATOR => array('variableArrow', 'potentialMethodCall'), - '*' => array('methodBody', 'appendMethodContent'), - ), - 'variableArrow' => array( - T_STRING => array('methodOrProperty', 'potentialMethodCall'), - T_WHITESPACE => array('', 'potentialMethodCall'), - '*' => array('methodBody', 'appendMethodContent'), - ), - 'methodOrProperty' => array( - '(' => array('methodCall', 'potentialMethodCall'), - T_WHITESPACE => array('', 'potentialMethodCall'), - '*' => array('methodBody', 'appendMethodContent'), - ), - 'methodCall' => array( - '(' => array('!push/nestedInMethodCall', 'potentialMethodCall'), - ')' => array('methodBody', 'completeMethodCall'), - '*' => array('', 'potentialMethodCall'), - ), - 'nestedInMethodCall' => array( - '(' => array('!push', 'potentialMethodCall'), - ')' => array('!pop', 'potentialMethodCall'), - '*' => array('', 'potentialMethodCall'), - ), - ); - - function init() { - parent::init(); - - if(!Permission::check('ADMIN')) return Security::permissionFailure(); - TestRunner::use_test_manifest(); - } - - public function browse() { - $classes = ClassInfo::subclassesFor('SapphireTest'); - - array_shift($classes); - ksort($classes); - - $result ='

View any of the following test classes

'; - $result .=''; - - $result .='

View any of the following other classes

'; - - $classes = array_keys(ClassInfo::allClasses()); - sort($classes); - - $result .=''; - - return $this->customise(array ( - 'Content' => $result - ))->renderWith('CodeViewer'); - } - - public function viewClass(SS_HTTPRequest $request) { - $class = $request->param('Class'); - - if(!class_exists($class)) { - throw new Exception('CodeViewer->viewClass(): not passed a valid class to view (does the class exist?)'); - } - - return $this->customise(array ( - 'Content' => $this->testAnalysis(getClassFile($class)) - ))->renderWith('CodeViewer'); - } - - public function Link($action = null) { - return Controller::join_links(Director::absoluteBaseURL(), 'dev/viewcode/', $action); - } - - protected $classComment, $methodComment; - - function saveClassComment($token) { - $this->classComment = $this->parseComment($token); - } - function saveMethodComment($token) { - $this->methodComment = $this->parseComment($token); - } - - function createClass($token) { - $this->currentClass = array( - "description" => $this->classComment['pretty'], - "heading" => isset($this->classComment['heading']) ? $this->classComment['heading'] : null, - ); - $ths->classComment = null; - } - function setClassName($token) { - $this->currentClass['name'] = $token[1]; - if(!$this->currentClass['heading']) $this->currentClass['heading'] = $token[1]; - } - function completeClass($token) { - $this->classes[] = $this->currentClass; - } - - function createBodyMethod($token) { - $this->currentMethod = array(); - $this->currentMethod['content'] = "
";
-		$this->currentMethod['description'] = $this->methodComment['pretty'];
-		$this->currentMethod['heading'] = isset($this->methodComment['heading']) ? $this->methodComment['heading'] : null;
-		$this->methodComment = null;
-
-	}
-	function setMethodName($token) {
-		$this->currentMethod['name'] = $token[1];
-		if(!$this->currentMethod['heading']) $this->currentMethod['heading'] = $token[1];
-	}
-	function appendMethodComment($token) {
-		if(substr($token[1],0,2) == '/*') {
-			$this->closeOffMethodContentPre();
-			$this->currentMethod['content'] .= $this->prettyComment($token) . "
";
-		} else {
-			$this->currentMethod['content'] .= $this->renderToken($token);
-		}
-	} 
-
-	function prettyComment($token) {
-		$comment = preg_replace('/^\/\*/','',$token[1]);
-		$comment = preg_replace('/\*\/$/','',$comment);
-		$comment = preg_replace('/(^|\n)[\t ]*\* */m',"\n",$comment);
-		$comment = htmlentities($comment, ENT_COMPAT, 'UTF-8');
-		$comment = str_replace("\n\n", "

", $comment); - return "

$comment

"; - } - - function parseComment($token) { - $parsed = array(); - - $comment = preg_replace('/^\/\*/','',$token[1]); - $comment = preg_replace('/\*\/$/','',$comment); - $comment = preg_replace('/(^|\n)[\t ]*\* */m',"\n",$comment); - - foreach(array('heading','nav') as $var) { - if(preg_match('/@' . $var . '\s+([^\n]+)\n/', $comment, $matches)) { - $parsed[$var] = $matches[1]; - $comment = preg_replace('/@' . $var . '\s+([^\n]+)\n/','', $comment); - } - } - - $parsed['pretty'] = "

" . str_replace("\n\n", "

", htmlentities($comment, ENT_COMPAT, 'UTF-8')). "

"; - return $parsed; - } - - protected $isNewLine = true; - - function appendMethodContent($token) { - if($this->potentialMethodCall) { - $this->currentMethod['content'] .= $this->potentialMethodCall; - $this->potentialMethodCall = ""; - } - //if($this->isNewLine && isset($token[2])) $this->currentMethod['content'] .= $token[2] . ": "; - $this->isNewLine = false; - $this->currentMethod['content'] .= $this->renderToken($token); - } - function completeMethod($token) { - $this->closeOffMethodContentPre(); - $this->currentMethod['content'] = str_replace("\n\t\t","\n",$this->currentMethod['content']); - $this->currentClass['methods'][] = $this->currentMethod; - } - - protected $potentialMethodCall = ""; - function potentialMethodCall($token) { - $this->potentialMethodCall .= $this->renderToken($token); - } - function completeMethodCall($token) { - $this->potentialMethodCall .= $this->renderToken($token); - if(strpos($this->potentialMethodCall, '->assert') !== false) { - $this->currentMethod['content'] .= "" . $this->potentialMethodCall . ""; - } else { - $this->currentMethod['content'] .= $this->potentialMethodCall; - } - $this->potentialMethodCall = ""; - } - - /** - * Finish the "pre" block in method content. - * Will remove whitespace and empty "pre" blocks - */ - function closeOffMethodContentPre() { - $this->currentMethod['content'] = trim($this->currentMethod['content']); - if(substr($this->currentMethod['content'],-5) == '
') $this->currentMethod['content'] = substr($this->currentMethod['content'], 0,-5);
-		else $this->currentMethod['content'] .= '
'; - } - - /** - * Render the given token as HTML - */ - function renderToken($token) { - $tokenContent = htmlentities( - is_array($token) ? $token[1] : $token, - ENT_COMPAT, - 'UTF-8' - ); - $tokenName = is_array($token) ? token_name($token[0]) : 'T_PUNCTUATION'; - - switch($tokenName) { - case "T_WHITESPACE": - if(strpos($tokenContent, "\n") !== false) $this->isNewLine = true; - return $tokenContent; - default: - return "$tokenContent"; - } - } - - protected $classes = array(); - protected $currentMethod, $currentClass; - - function testAnalysis($file) { - $content = file_get_contents($file); - $tokens = token_get_all($content); - - // Execute a finite-state-machine with a built-in state stack - // This FSM+stack gives us enough expressive power for simple PHP parsing - $state = "start"; - $stateStack = array(); - - //echo "
  • state $state"; - foreach($tokens as $token) { - // Get token name - some tokens are arrays, some arent' - if(is_array($token)) $tokenName = $token[0]; else $tokenName = $token; - //echo "
  • token '$tokenName'"; - - // Find the rule for that token in the current state - if(isset(self::$fsm[$state][$tokenName])) $rule = self::$fsm[$state][$tokenName]; - else if(isset(self::$fsm[$state]['*'])) $rule = self::$fsm[$state]['*']; - else $rule = null; - - // Check to see if we have specified multiple rules depending on whether the stack is populated - if(is_array($rule) && array_keys($rule) == array('hasstack', 'nostack')) { - if($stateStack) $rule = $rule['hasstack']; - else $rule = $rule = $rule['nostack']; - } - - if(is_array($rule)) { - list($destState, $methodName) = $rule; - $this->$methodName($token); - } else if($rule) { - $destState = $rule; - } else { - $destState = null; - } - //echo "
  • ->state $destState"; - - if(preg_match('/!(push|pop)(\/[a-zA-Z0-9]+)?/', $destState, $parts)) { - $action = $parts[1]; - $argument = isset($parts[2]) ? substr($parts[2],1) : null; - $destState = null; - - switch($action) { - case "push": - $stateStack[] = $state; - if($argument) $destState = $argument; - break; - - case "pop": - if($stateStack) $destState = array_pop($stateStack); - else if($argument) $destState = $argument; - else user_error("State transition '!pop' was attempted with an empty state-stack and no default option specified.", E_USER_ERROR); - } - } - - if($destState) $state = $destState; - if(!isset(self::$fsm[$state])) user_error("Transition to unrecognised state '$state'", E_USER_ERROR); - } - - $subclasses = ClassInfo::subclassesFor('SapphireTest'); - foreach($this->classes as $classDef) { - if(true ||in_array($classDef['name'], $subclasses)) { - echo "

    $classDef[heading]

    "; - echo "
    $classDef[description]
    "; - if(isset($classDef['methods'])) foreach($classDef['methods'] as $method) { - if(true || substr($method['name'],0,4) == 'test') { - //$title = ucfirst(strtolower(preg_replace('/([a-z])([A-Z])/', '$1 $2', substr($method['name'], 4)))); - $title = $method['heading']; - - echo "

    $title

    "; - echo "
    $method[description]
    "; - echo $method['content']; - } - } - } - - } - } -} diff --git a/dev/DevelopmentAdmin.php b/dev/DevelopmentAdmin.php index 5e43a0e62..eecb54dda 100644 --- a/dev/DevelopmentAdmin.php +++ b/dev/DevelopmentAdmin.php @@ -83,8 +83,7 @@ class DevelopmentAdmin extends Controller { "tests/endsession" => "Ends a test session", "jstests" => "See a list of JavaScript tests to run", "jstests/all" => "Run all JavaScript tests", - "tasks" => "See a list of build tasks to run", - "viewcode" => "Read source code in a literate programming style", + "tasks" => "See a list of build tasks to run" ); // Web mode @@ -127,10 +126,6 @@ class DevelopmentAdmin extends Controller { return TaskRunner::create(); } - function viewmodel() { - return ModelViewer::create(); - } - function build($request) { if(Director::is_cli()) { $da = DatabaseAdmin::create(); @@ -187,8 +182,4 @@ class DevelopmentAdmin extends Controller { function errors() { Director::redirect("Debug_"); } - - function viewcode($request) { - return CodeViewer::create(); - } } diff --git a/dev/ModelViewer.php b/dev/ModelViewer.php deleted file mode 100644 index c385adb53..000000000 --- a/dev/ModelViewer.php +++ /dev/null @@ -1,213 +0,0 @@ - 'handleModule', - ); - - protected $module = null; - - function handleModule($request) { - return new ModelViewer_Module($request->param('Module')); - } - - function init() { - parent::init(); - - $canAccess = (Director::isDev() || Director::is_cli() || Permission::check("ADMIN")); - if(!$canAccess) return Security::permissionFailure($this); - - // check for graphviz dependencies - $returnCode = 0; - $output = array(); - exec("which neato", $output, $returnCode); - if($returnCode != 0) { - user_error( - 'You don\'t seem to have the GraphViz library (http://graphviz.org/) and the "neato" command-line utility available', - E_USER_ERROR - ); - } - } - - /** - * Model classes - */ - function Models() { - $classes = ClassInfo::subclassesFor('DataObject'); - array_shift($classes); - $output = new ArrayList(); - foreach($classes as $class) { - $output->push(new ModelViewer_Model($class)); - } - return $output; - } - - /** - * Model classes, grouped by Module - */ - function Modules() { - $classes = ClassInfo::subclassesFor('DataObject'); - array_shift($classes); - - $modules = array(); - foreach($classes as $class) { - $model = new ModelViewer_Model($class); - if(!isset($modules[$model->Module])) $modules[$model->Module] = new ArrayList(); - $modules[$model->Module]->push($model); - } - ksort($modules); - unset($modules['userforms']); - - if($this->module) { - $modules = array($this->module => $modules[$this->module]); - } - - $output = new ArrayList(); - foreach($modules as $moduleName => $models) { - $output->push(new ArrayData(array( - 'Link' => 'dev/viewmodel/' . $moduleName, - 'Name' => $moduleName, - 'Models' => $models, - ))); - } - - return $output; - } -} - -/** - * @package framework - * @subpackage tools - */ -class ModelViewer_Module extends ModelViewer { - static $url_handlers = array( - 'graph' => 'graph', - ); - - /** - * ModelViewer can be optionally constructed to restrict its output to a specific module - */ - function __construct($module = null) { - $this->module = $module; - - parent::__construct(); - } - - function graph() { - SSViewer::set_source_file_comments(false); - $dotContent = $this->renderWith("ModelViewer_dotsrc"); - $CLI_dotContent = escapeshellarg($dotContent); - - $output= `echo $CLI_dotContent | neato -Tpng:gd &> /dev/stdout`; - if(substr($output,1,3) == 'PNG') header("Content-type: image/png"); - else header("Content-type: text/plain"); - echo $output; - } -} - -/** - * Represents a single model in the model viewer - * - * @package framework - * @subpackage tools - */ -class ModelViewer_Model extends ViewableData { - protected $className; - - function __construct($className) { - $this->className = $className; - parent::__construct(); - } - - function getModule() { - $classes = SS_ClassLoader::instance()->getManifest()->getClasses(); - $className = strtolower($this->className); - - if(($pos = strpos($className,'_')) !== false) $className = substr($className,0,$pos); - if(isset($classes[$className])) { - if(preg_match('/^'.str_replace('/','\/',preg_quote(BASE_PATH)).'\/([^\/]+)\//', $classes[$className], $matches)) { - return $matches[1]; - } - } - } - - function getName() { - return $this->className; - } - - function getParentModel() { - $parentClass = get_parent_class($this->className); - if($parentClass != "DataObject") return $parentClass; - } - - function Fields() { - $output = new ArrayList(); - - $output->push(new ModelViewer_Field($this,'ID', 'PrimaryKey')); - if(!$this->ParentModel) { - $output->push(new ModelViewer_Field($this,'Created', 'Datetime')); - $output->push(new ModelViewer_Field($this,'LastEdited', 'Datetime')); - } - - $db = singleton($this->className)->uninherited('db',true); - if($db) foreach($db as $k => $v) { - $output->push(new ModelViewer_Field($this, $k, $v)); - } - return $output; - } - - function Relations() { - $output = new ArrayList(); - - foreach(array('has_one','has_many','many_many') as $relType) { - $items = singleton($this->className)->uninherited($relType,true); - if($items) foreach($items as $k => $v) { - $output->push(new ModelViewer_Relation($this, $k, $v, $relType)); - } - } - return $output; - } -} - -/** - * @package framework - * @subpackage tools - */ -class ModelViewer_Field extends ViewableData { - public $Model, $Name, $Type; - - function __construct($model, $name, $type) { - $this->Model = $model; - $this->Name = $name; - $this->Type = $type; - - parent::__construct(); - } -} - -/** - * @package framework - * @subpackage tools - */ -class ModelViewer_Relation extends ViewableData { - public $Model, $Name, $RelationType, $RelatedClass; - - function __construct($model, $name, $relatedClass, $relationType) { - $this->Model = $model; - $this->Name = $name; - $this->RelatedClass = $relatedClass; - $this->RelationType = $relationType; - - parent::__construct(); - } - -} - diff --git a/dev/TestViewer.php b/dev/TestViewer.php deleted file mode 100644 index 7792b0ab0..000000000 --- a/dev/TestViewer.php +++ /dev/null @@ -1,257 +0,0 @@ - array( - T_CLASS => array('className','createClass'), - ), - 'className' => array( - T_STRING => array('classSpec', 'setClassName'), - ), - 'classSpec' => array( - '{' => 'classBody', - ), - 'classBody' => array( - T_FUNCTION => array('methodName','createBodyMethod'), - '}' => array('start', 'completeClass'), - ), - 'methodName' => array( - T_STRING => array('methodSpec', 'setMethodName'), - ), - 'methodSpec' => array( - '{' => 'methodBody', - ), - 'methodBody' => array( - '{' => array('!push','appendMethodContent'), - '}' => array( - 'hasstack' => array('!pop', 'appendMethodContent'), - 'nostack' => array('classBody', 'completeMethod'), - ), - T_VARIABLE => array('variable', 'potentialMethodCall'), - T_COMMENT => array('', 'appendMethodComment'), - '*' => array('', 'appendMethodContent'), - ), - 'variable' => array( - T_OBJECT_OPERATOR => array('variableArrow', 'potentialMethodCall'), - '*' => array('methodBody', 'appendMethodContent'), - ), - 'variableArrow' => array( - T_STRING => array('methodOrProperty', 'potentialMethodCall'), - T_WHITESPACE => array('', 'potentialMethodCall'), - '*' => array('methodBody', 'appendMethodContent'), - ), - 'methodOrProperty' => array( - '(' => array('methodCall', 'potentialMethodCall'), - T_WHITESPACE => array('', 'potentialMethodCall'), - '*' => array('methodBody', 'appendMethodContent'), - ), - 'methodCall' => array( - '(' => array('!push/nestedInMethodCall', 'potentialMethodCall'), - ')' => array('methodBody', 'completeMethodCall'), - '*' => array('', 'potentialMethodCall'), - ), - 'nestedInMethodCall' => array( - '(' => array('!push', 'potentialMethodCall'), - ')' => array('!pop', 'potentialMethodCall'), - '*' => array('', 'potentialMethodCall'), - ), - ); - - function init() { - parent::init(); - - $canAccess = (Director::isDev() || Director::is_cli() || Permission::check("ADMIN")); - if(!$canAccess) return Security::permissionFailure($this); - } - - function createClass($token) { - $this->currentClass = array(); - } - function setClassName($token) { - $this->currentClass['name'] = $token[1]; - } - function completeClass($token) { - $this->classes[] = $this->currentClass; - } - - function createBodyMethod($token) { - $this->currentMethod = array(); - $this->currentMethod['content'] = "
    ";
    -	}
    -	function setMethodName($token) {
    -		$this->currentMethod['name'] = $token[1];
    -	}
    -	function appendMethodComment($token) {
    -		if(substr($token[1],0,2) == '/*') {
    -			$comment = preg_replace('/^\/\*/','',$token[1]);
    -			$comment = preg_replace('/\*\/$/','',$comment);
    -			$comment = preg_replace('/\n[\t ]*\* */m',"\n",$comment);
    -			
    -			$this->closeOffMethodContentPre();
    -			$this->currentMethod['content'] .= "

    $comment

    ";
    -		} else {
    -			$this->currentMethod['content'] .= $this->renderToken($token);
    -		}
    -		
    -	} 
    -	function appendMethodContent($token) {
    -		if($this->potentialMethodCall) {
    -			$this->currentMethod['content'] .= $this->potentialMethodCall;
    -			$this->potentialMethodCall = "";
    -		}
    -		$this->currentMethod['content'] .= $this->renderToken($token);
    -	}
    -	function completeMethod($token) {
    -		$this->closeOffMethodContentPre();
    -		$this->currentMethod['content'] = str_replace("\n\t\t","\n",$this->currentMethod['content']);
    -		$this->currentClass['methods'][] = $this->currentMethod;
    -	}
    -	
    -	protected $potentialMethodCall = "";
    -	function potentialMethodCall($token) {
    -		$this->potentialMethodCall .= $this->renderToken($token);
    -	}
    -	function completeMethodCall($token) {
    -		$this->potentialMethodCall .= $this->renderToken($token);
    -		if(strpos($this->potentialMethodCall, '->assert') !== false) {
    -			$this->currentMethod['content'] .= "" . $this->potentialMethodCall . "";
    -		} else {
    -			$this->currentMethod['content'] .= $this->potentialMethodCall;
    -		}
    -		$this->potentialMethodCall = "";
    -	}
    -	
    -	/**
    -	 * Finish the "pre" block in method content.
    -	 * Will remove whitespace and empty "pre" blocks
    -	 */
    -	function closeOffMethodContentPre() {
    -		$this->currentMethod['content'] = trim($this->currentMethod['content']);
    -		if(substr($this->currentMethod['content'],-5) == '
    ') $this->currentMethod['content'] = substr($this->currentMethod['content'], 0,-5);
    -		else $this->currentMethod['content'] .= '
    '; - } - - /** - * Render the given token as HTML - */ - function renderToken($token) { - $tokenContent = htmlentities( - is_array($token) ? $token[1] : $token, - ENT_COMPAT, - 'UTF-8' - ); - $tokenName = is_array($token) ? token_name($token[0]) : 'T_PUNCTUATION'; - - switch($tokenName) { - case "T_WHITESPACE": - return $tokenContent; - default: - return "$tokenContent"; - } - } - - protected $classes = array(); - protected $currentMethod, $currentClass; - - function Content() { - $className = $this->urlParams['ID']; - if($className && ClassInfo::exists($className)) { - return $this->testAnalysis(getClassFile($className)); - } else { - $result = "

    View any of the following test classes

    "; - $classes = ClassInfo::subclassesFor('SapphireTest'); - ksort($classes); - foreach($classes as $className) { - if($className == 'SapphireTest') continue; - $result .= "
  • $className
  • "; - } - return $result; - } - } - - function testAnalysis($file) { - $content = file_get_contents($file); - $tokens = token_get_all($content); - - // Execute a finite-state-machine with a built-in state stack - // This FSM+stack gives us enough expressive power for simple PHP parsing - $state = "start"; - $stateStack = array(); - - //echo "
  • state $state"; - foreach($tokens as $token) { - // Get token name - some tokens are arrays, some arent' - if(is_array($token)) $tokenName = $token[0]; else $tokenName = $token; - //echo "
  • token '$tokenName'"; - - // Find the rule for that token in the current state - if(isset(self::$fsm[$state][$tokenName])) $rule = self::$fsm[$state][$tokenName]; - else if(isset(self::$fsm[$state]['*'])) $rule = self::$fsm[$state]['*']; - else $rule = null; - - // Check to see if we have specified multiple rules depending on whether the stack is populated - if(is_array($rule) && array_keys($rule) == array('hasstack', 'nostack')) { - if($stateStack) $rule = $rule['hasstack']; - else $rule = $rule = $rule['nostack']; - } - - if(is_array($rule)) { - list($destState, $methodName) = $rule; - $this->$methodName($token); - } else if($rule) { - $destState = $rule; - } else { - $destState = null; - } - //echo "
  • ->state $destState"; - - if(preg_match('/!(push|pop)(\/[a-zA-Z0-9]+)?/', $destState, $parts)) { - $action = $parts[1]; - $argument = isset($parts[2]) ? substr($parts[2],1) : null; - $destState = null; - - switch($action) { - case "push": - $stateStack[] = $state; - if($argument) $destState = $argument; - break; - - case "pop": - if($stateStack) $destState = array_pop($stateStack); - else if($argument) $destState = $argument; - else user_error("State transition '!pop' was attempted with an empty state-stack and no default option specified.", E_USER_ERROR); - } - } - - if($destState) $state = $destState; - if(!isset(self::$fsm[$state])) user_error("Transition to unrecognised state '$state'", E_USER_ERROR); - } - - $subclasses = ClassInfo::subclassesFor('SapphireTest'); - foreach($this->classes as $classDef) { - if(in_array($classDef['name'], $subclasses)) { - echo "

    $classDef[name]

    "; - if($classDef['methods']) foreach($classDef['methods'] as $method) { - if(substr($method['name'],0,4) == 'test') { - //$title = ucfirst(strtolower(preg_replace('/([a-z])([A-Z])/', '$1 $2', substr($method['name'], 4)))); - $title = $method['name']; - - echo "

    $title

    "; - echo $method['content']; - } - } - } - - } - } -} diff --git a/scss/CodeViewer.scss b/scss/CodeViewer.scss deleted file mode 100755 index 621ee4318..000000000 --- a/scss/CodeViewer.scss +++ /dev/null @@ -1,14 +0,0 @@ -pre { - border: 1px #777 solid; - background-color: #CCC; - color: #333; - margin: 0.5em 2em; - padding: 1em; - line-height: 120%; -} - -pre strong { - background-color: #FFC; - color: #000; - padding: 2px; -} \ No newline at end of file diff --git a/scss/TestViewer.scss b/scss/TestViewer.scss deleted file mode 100755 index 621ee4318..000000000 --- a/scss/TestViewer.scss +++ /dev/null @@ -1,14 +0,0 @@ -pre { - border: 1px #777 solid; - background-color: #CCC; - color: #333; - margin: 0.5em 2em; - padding: 1em; - line-height: 120%; -} - -pre strong { - background-color: #FFC; - color: #000; - padding: 2px; -} \ No newline at end of file diff --git a/templates/CodeViewer.ss b/templates/CodeViewer.ss deleted file mode 100644 index e87b0648b..000000000 --- a/templates/CodeViewer.ss +++ /dev/null @@ -1,9 +0,0 @@ - - -<% base_tag %> - - - - $Content - - diff --git a/templates/ModelViewer.ss b/templates/ModelViewer.ss deleted file mode 100644 index a155caadb..000000000 --- a/templates/ModelViewer.ss +++ /dev/null @@ -1,34 +0,0 @@ - - - <% base_tag %> - Data Model - - - -

    Data Model for your project

    - - <% control Modules %> -

    Module $Name

    - - - - <% control Models %> -

    $Name <% if ParentModel %> (subclass of $ParentModel)<% end_if %>

    -

    Fields

    -
      - <% control Fields %> -
    • $Name - $Type
    • - <% end_control %> -
    - -

    Relations

    -
      - <% control Relations %> -
    • $Name $RelationType $RelatedClass
    • - <% end_control %> -
    - <% end_control %> - <% end_control %> - - - diff --git a/templates/ModelViewer_dotsrc.ss b/templates/ModelViewer_dotsrc.ss deleted file mode 100644 index a7070a6f2..000000000 --- a/templates/ModelViewer_dotsrc.ss +++ /dev/null @@ -1,20 +0,0 @@ -digraph g { - orientation=portrait; - overlap=false; - splines=true; - - edge[fontsize=8,len=1.5]; - node[fontsize=10,shape=box]; - - <% control Modules %> - <% control Models %> - $Name [shape=record,label="{$Name|<% control Fields %>$Name\\n<% end_control %>}"]; - <% if ParentModel %> - $Name -> $ParentModel [style=dotted]; - <% end_if %> - <% control Relations %> - $Model.Name -> $RelatedClass [label="$Name\\n$RelationType"]; - <% end_control %> - <% end_control %> - <% end_control %> -} diff --git a/templates/TestViewer.ss b/templates/TestViewer.ss deleted file mode 100644 index e14ea0878..000000000 --- a/templates/TestViewer.ss +++ /dev/null @@ -1,9 +0,0 @@ - - -<% base_tag %> - - - - $Content - -