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); } }