FuelPHP クラス検索で使用しているソースコード閲覧クラスをオープンソースで公開します。(サイトでは jQuery 等を使用していますが、今回の公開部分にその部分は含まれていません)
PHP のビルトインクラス ReflectionClass を継承しています。
<?php
/**
* GNU Lesser General Public License
* http://www.gnu.org/copyleft/lesser.html
*/
/**
* Source_View
*
* @author Fumito MIZUNO <mizuno@php-web.net>
*/
class SourceView extends ReflectionClass
{
protected $data = array();
protected $methods_start_end = array();
protected $inherited_methods = array();
function __construct($reflect)
{
parent::__construct($reflect);
$this->_createFileData();
$this->_createMethodInfo();
}
/**
* createFileData
*
* @access public
* @return object
*/
function _createFileData()
{
$filename = $this->getFileName();
if(!file_exists($filename))
{
throw new Exception("Classname <b>" . $this->name . "</b> is not found in FuelPHP");
}
if(false === $this->data = file($filename))
{
throw new Exception("Failed to open file: " . $filename);
}
return $this;
}
/**
* outdata
*
* @param bool $escape
* @access public
* @return array
*/
function outData($escape=TRUE)
{
$startline = $this->getStartLine();
$endline = $this->getEndLine();
$out =array();
for($i=$startline-1;$i<$endline;$i++)
{
if ($escape)
{
$out[1+$i] = htmlspecialchars($this->data[$i],ENT_QUOTES,Config::get('encoding'));
}
else
{
$out[1+$i] = $this->data[$i];
}
}
return $out;
}
function getMethodStartEnd()
{
return $this->methods_start_end;
}
function getInheritedMethods()
{
return $this->inherited_methods;
}
function _createMethodInfo()
{
$methods = $this->getMethods();
if(!is_array($methods))
{
throw new Exception("getMethods not return array");
}
if(array() ==$methods)
{
throw new Exception("getMethods return empty array");
}
foreach ($methods as $method)
{
$methodobj = new reflectionMethod($method->class,$method->name);
if ($method->class == $this->name)
{
$this->methods_start_end[] = array(
'method'=>$method->name,
'start'=>$methodobj->getStartLine(),
'end'=>$methodobj->getEndLine(),
);
}
else
{
$this->inherited_methods[] = array(
'method'=>$method->name,
'class'=>$method->class,
);
}
}
return $this;
}
}
テストコードは下記です。FuelPHP では、コマンドラインで php oil t --group=App と入力すると phpunit を使ったテストが実行できます。テストクラスの直前にコメントで @group App と書いておく必要があります。
<?php
/**
* dummyclass
* Used for Tests
*/
class dummyclass
{
function outhtml()
{
return '<b>hello</b>';
}
function outtext()
{
return 'hello';
}
}
class dummysub extends dummyclass
{
function outnull()
{
return "";
}
}
/**
*
* @group App
*/
class Tests_SourceView extends TestCase
{
protected $reflect;
protected $sub;
public function setUp()
{
$this->reflect = new SourceView('dummyclass');
$this->sub = new SourceView('dummysub');
}
public function test_getMethodStartEnd()
{
$expected = array(
array(
'method'=>'outhtml',
'start'=>9,
'end'=>12
),
array(
'method'=>'outtext',
'start'=>13,
'end'=>16
),
);
$data = $this->reflect->getMethodStartEnd();
$this->assertEquals($expected,$data);
}
public function test_subgetMethodStartEnd()
{
$expected = array(
array(
'method'=>'outnull',
'start'=>21,
'end'=>24
),
);
$data = $this->sub->getMethodStartEnd();
$this->assertEquals($expected,$data);
}
public function test_subInherited_methods()
{
$expected = array(
array(
'method'=>'outhtml',
'class'=>'dummyclass',
),
array(
'method'=>'outtext',
'class'=>'dummyclass',
),
);
$data = $this->sub->getInheritedMethods();
$this->assertEquals($expected,$data);
}
public function test_outData_escape()
{
$expected = array(
7 =>'class dummyclass
',
8 =>'{
',
9 =>' function outhtml()
',
10 => ' {
',
11 =>' return '<b>hello</b>';
',
12 =>' }
',
13 =>' function outtext()
',
14 =>' {
',
15 =>' return 'hello';
',
16 =>' }
',
17 =>'}
',
);
$data = $this->reflect->outData();
$this->assertEquals($expected,$data);
}
public function test_outData_noescape()
{
$expected = array(
7 =>'class dummyclass
',
8 =>'{
',
9 =>' function outhtml()
',
10 => ' {
',
11 =>" return '<b>hello</b>';
",
12 =>' }
',
13 =>' function outtext()
',
14 =>' {
',
15 =>" return 'hello';
",
16 =>' }
',
17 =>'}
',
);
$data = $this->reflect->outData(false);
$this->assertEquals($expected,$data);
}
}