Skip to content

Commit

Permalink
Merge pull request #8 from iannsp/master
Browse files Browse the repository at this point in the history
extract some methods
  • Loading branch information
Alexandre Gomes Gaigalas committed Mar 27, 2012
2 parents 58fb5f1 + f878378 commit b017996
Show file tree
Hide file tree
Showing 7 changed files with 311 additions and 125 deletions.
131 changes: 7 additions & 124 deletions library/Respect/Doc.php
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
<?php
namespace Respect;

use \SplObjectStorage;
use \ReflectionClass;
use \ReflectionMethod;
use \ReflectionProperty;

/**
* Generates docs that rocks your socks off.
Expand All @@ -21,9 +17,6 @@
class Doc
{
public $path;
protected $reflections=array();
protected $sections=array();

/** Receives the namespace or class to be documented */
public function __construct($classOrNamespace)
{
Expand All @@ -33,8 +26,9 @@ public function __construct($classOrNamespace)
/** Returns the documentation in markdown */
public function __toString()
{
return $this->getMarkdown($this->getContents($this->path));

$content = $this->getContents($this->path);
$markdown = new MarkDown();
return $markdown->get($content);
}

protected function getContents($path)
Expand All @@ -57,7 +51,6 @@ protected function getNamespaceContents($path)
return $sections;
}

//TODO: extract a lot of methods
protected function getClassContents($path)
{
if (!class_exists($path))
Expand All @@ -66,120 +59,10 @@ protected function getClassContents($path)
$sections = array();
$classes = array($path);
foreach ($classes as $class) {
$reflection = new ReflectionClass($class);
$class = $reflection->getName();
$sections[$class] = $reflection->getDocComment();

$reflectors = $this->getSections($reflection);
foreach ($reflectors as $sub) {

$tests = $reflectors[$sub];

if ($sub->isStatic())
$subName = 'static ';
else
$subName = '';

$subName .= $sub->getName();
$name = $class.'::'.$subName;

if ($sub instanceof ReflectionMethod)
if ($sub->getNumberOfRequiredParameters() <= 0)
$name .= '()';
else {
$params = $sub->getParameters();
$tmp = array();
foreach ($params as $param) {
if ($param->isArray())
$tmp[] = 'array ';
if ($param->isOptional())
$tmp[] = '$'.$param->getName().'=null';
elseif ($param->isDefaultValueAvailable())
$tmp[] = '$'.$param->getName().'='.$param->getDefaultValue();
else
$tmp[] = '$'.$param->getName();
}
$name .= '('.implode(', ', $tmp).')';
}

$sections[$name] = $sub->getDocComment();
// Fetch method content for examples
foreach ($tests as $n => $test) {
$testCaseContents = file($test->getFilename());
$testSectionName = "Example ".($n+1).":";
$testCaseLines = array_slice($testCaseContents, 1+$test->getStartLine(), -2+$test->getEndLine()-$test->getStartLine());
$testCaseLines = array_map(
function($line) {
if ($line{0} == "\t")
return substr($line, 1);
if ($line{0} == ' ')
return substr($line, 4);
else
return ' ' . $line;
},
$testCaseLines
);
$sections[$name] .= PHP_EOL.PHP_EOL.$testSectionName.PHP_EOL.PHP_EOL.implode($testCaseLines);
}

}

}
return $sections;
}

protected function getSections(ReflectionClass $reflection)
{
$testCaseClass = $reflection->getName().'Test';

if (class_exists($testCaseClass)) {
$testCaseReflection = new ReflectionClass($testCaseClass);
$testCaseMethods = $testCaseReflection->getMethods();
} else {
$testCaseMethods= array();
$docItem = new DocItem($class);
$class = $docItem->getName();
$sections = array_merge($sections,$docItem->getClassContent());
}
$sections = new SplObjectStorage;
$methods = $reflection->getMethods(ReflectionMethod::IS_PUBLIC ^ ReflectionMethod::IS_STATIC);
$properties = $reflection->getProperties(ReflectionProperty::IS_PUBLIC ^ ReflectionProperty::IS_STATIC);
$staticMethods = $reflection->getMethods(ReflectionMethod::IS_PUBLIC & ReflectionMethod::IS_STATIC);
$staticProperties = $reflection->getProperties(ReflectionProperty::IS_PUBLIC & ReflectionProperty::IS_STATIC);

$nameSort = function($a, $b) {
return strnatcasecmp($a->getName(), $b->getName());
};

usort($methods, $nameSort);
usort($properties, $nameSort);
usort($staticMethods, $nameSort);
usort($staticProperties, $nameSort);
foreach (array_merge($staticProperties, $properties, $staticMethods, $methods) as $method)
$sections[$method] = array_values(array_filter($testCaseMethods, function($test) use($method) {
return 0 === stripos($test->getName(), 'test_as_example_for_'.$method->getName().'_method');
}));
return $sections;
}

protected function getMarkdown(array $sections)
{
$string = array();
foreach ($sections as $name=>$content) {

if (preg_match_all('/[\:]{1,2}(.*)/', $name, $matches))
$name = $matches[1][0];
else
$matches = 1;

$content = trim(preg_replace('#^(\s*[*]|[/][*]{2}|[\][*])[/*]*(.*?)[ /*]*$#m', '$2', $content));
$content = preg_replace("#\\n\\n[ ]*@#", "\n\nMore Info:\n\n@", $content);
$content = preg_replace_callback('#^[ ]*[@](\w+)[ ]+(.*)#mi',
function($matches){
$matches[1] = ucfirst($matches[1]);
return " - **{$matches[1]}:** {$matches[2]} ";
},
$content);
$char = count($matches) == 1 ? '=' : '-';
$string[] = trim($name . "\n" . str_repeat($char, strlen($name)) . "\n\n" . $content);
}
return implode("\n\n", $string);
}
}
}
138 changes: 138 additions & 0 deletions library/Respect/DocItem.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
<?php
namespace Respect;

use \SplObjectStorage;
use \ReflectionClass;
use \ReflectionMethod;
use \ReflectionProperty;


/**
* DocItem Reflection Class to speak where is the socks to rock it.
*
* @author Ivo Nascimento <[email protected]>
*/
class DocItem
{
private $item;
private $refItem;

/**
* __construct Construct a doc Item
*
* @access public
* @return void
*/
public function __construct($item)
{
$this->docItem = $item;
$this->refItem = new ReflectionClass($item);
}
private function getName()
{
return $this->refItem->getName();
}
private function getDocComment()
{
return $this->refItem->getDocComment();
}
public function __call($method, $parameters)
{
return call_user_func_array(array($this->refItem, $method),$parameters );
}
private function getMethods($scope=null)
{
if (is_null($scope))
return $this->refItem->getMethods();
return $this->refItem->getMethods($scope);
}
public function getSections()
{
$testCaseClass = $this->getName().'Test';

if (class_exists($testCaseClass)) {
$testCaseReflection = new ReflectionClass($testCaseClass);
$testCaseMethods = $testCaseReflection->getMethods();
} else {
$testCaseMethods= array();
}
$sections = new SplObjectStorage;
$methods = $this->getMethods(ReflectionMethod::IS_PUBLIC ^ ReflectionMethod::IS_STATIC);
$properties = $this->getProperties(ReflectionProperty::IS_PUBLIC ^ ReflectionProperty::IS_STATIC);
$staticMethods = $this->getMethods(ReflectionMethod::IS_PUBLIC & ReflectionMethod::IS_STATIC);
$staticProperties = $this->getProperties(ReflectionProperty::IS_PUBLIC & ReflectionProperty::IS_STATIC);

$nameSort = function($a, $b) {
return strnatcasecmp($a->getName(), $b->getName());
};

usort($methods, $nameSort);
usort($properties, $nameSort);
usort($staticMethods, $nameSort);
usort($staticProperties, $nameSort);
foreach (array_merge($staticProperties, $properties, $staticMethods, $methods) as $method)
$sections[$method] = array_values(array_filter($testCaseMethods, function($test) use($method) {
return 0 === stripos($test->getName(), 'test_as_example_for_'.$method->getName().'_method');
}));
return $sections;
}
public function getClassContent()
{
$sections = array();
$class = $this->getName();
$sections[$class] = $this->getDocComment();
$reflectors = $this->getSections();
foreach ($reflectors as $sub) {
$tests = $reflectors[$sub];
if ($sub->isStatic())
$subName = 'static ';
else
$subName = '';

$subName .= $sub->getName();
$name = $class.'::'.$subName;

if ($sub instanceof ReflectionMethod)
if ($sub->getNumberOfRequiredParameters() <= 0)
$name .= '()';
else {
$params = $sub->getParameters();
$tmp = array();
foreach ($params as $param) {
if ($param->isArray())
$tmp[] = 'array ';
if ($param->isOptional())
$tmp[] = '$'.$param->getName().'=null';
elseif ($param->isDefaultValueAvailable())
$tmp[] = '$'.$param->getName().'='.$param->getDefaultValue();
else
$tmp[] = '$'.$param->getName();
}
$name .= '('.implode(', ', $tmp).')';
}

$sections[$name] = $sub->getDocComment();
// Fetch method content for examples
foreach ($tests as $n => $test) {
$testCaseContents = file($test->getFilename());
$testSectionName = "Example ".($n+1).":";
$testCaseLines = array_slice($testCaseContents, 1+$test->getStartLine(), -2+$test->getEndLine()-$test->getStartLine());
$testCaseLines = array_map(
function($line) {
if ($line{0} == "\t")
return substr($line, 1);
if ($line{0} == ' ')
return substr($line, 4);
else
return ' ' . $line;
},
$testCaseLines
);
$sections[$name] .= PHP_EOL.PHP_EOL.$testSectionName.PHP_EOL.PHP_EOL.implode($testCaseLines);
}

}
return $sections;
}
}

34 changes: 34 additions & 0 deletions library/Respect/MarkDown.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php
namespace Respect;

/**
* speak Markdownish
*
* @author Ivo Nascimento <[email protected]>
*/
class MarkDown
{
public function get(array $sections)
{
$string = array();
foreach ($sections as $name=>$content) {

if (preg_match_all('/[\:]{1,2}(.*)/', $name, $matches))
$name = $matches[1][0];
else
$matches = 1;

$content = trim(preg_replace('#^(\s*[*]|[/][*]{2}|[\][*])[/*]*(.*?)[ /*]*$#m', '$2', $content));
$content = preg_replace("#\\n\\n[ ]*@#", "\n\nMore Info:\n\n@", $content);
$content = preg_replace_callback('#^[ ]*[@](\w+)[ ]+(.*)#mi',
function($matches){
$matches[1] = ucfirst($matches[1]);
return " - **{$matches[1]}:** {$matches[2]} ";
},
$content);
$char = count($matches) == 1 ? '=' : '-';
$string[] = trim($name . "\n" . str_repeat($char, strlen($name)) . "\n\n" . $content);
}
return implode("\n\n", $string);
}
}
56 changes: 56 additions & 0 deletions tests/library/Respect/DocItemTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?php
namespace respect;

class DocItemTest extends \phpunit_framework_testcase
{
private $docItem;
public function setUp()
{
$this->docItem = New DocItem( 'Respect\DocItem');
}
public function tearDown()
{
$this->docItem = null;
}
public function test_getName()
{
$this->AssertEquals('Respect\DocItem', $this->docItem->getName());
}
public function test_getDocComment()
{
$returnValue = "/**
* DocItem Reflection Class to speak where is the socks to rock it.
*
* @author Ivo Nascimento <[email protected]>
*/";
$this->AssertEquals($returnValue, $this->docItem->getDocComment());
}

public function getMethodsDataprovider()
{
return array(
array(0,'__construct'),
array(1,'getName'),
array(2,'getDocComment'),
array(3,'__call')
);
}
/**
* @dataProvider getMethodsDataprovider
*/
public function test_getMethods($idx, $name)
{
$methods = $this->docItem->getMethods();
$this->AssertEquals($methods[$idx]->name, $name );
}
public function test_getSections()
{
$this->AssertInstanceOf('SplObjectStorage',$this->docItem->getSections());
}
public function test_getClassContents()
{
$doc = new Doc('\Respect\Doc');
$content = \file_get_contents (__DIR__."/../../output/RespectDoc_output.txt");
$this->AssertEquals($content, (string)$doc);
}
}
Loading

0 comments on commit b017996

Please sign in to comment.