Standing on the Shoulder of Linus

Home / 2012 / 5月 / 15 / ソースコード閲覧クラスを公開します

ソースコード閲覧クラスを公開します

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 &#039;&lt;b&gt;hello&lt;/b&gt;&#039;;
',
							12 =>'	}
',
							13 =>'	function outtext()
',
							14 =>'	{
',
									15 =>'		return &#039;hello&#039;;
',
									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);
	}
}

関連

Posted in fuelphp | Tagged PHP, テスト
← OSC 名古屋 2012 に参加しました。 WordPress が使用しているオープンソースライブラリを調べてみた →

アーカイブ

人気の投稿とページ

  • キンドル本を印刷する(PDFに変換する)方法
  • 名古屋駅から国際センターまでの道のり(徒歩)
  • AGPL ライセンス(GPLとは似ているが違いもある)
  • 6年使ったイーモバイル(Y!mobile)を解約手続。店頭でSIM返却
  • JP-Secure SiteGuard WP Pluginは不正ログイン防止に役立つか

プロフィール

水野史土:月70万PVホームページ制作会社のレスキューワーク株式会社で、PHPソフトウェアのサポートを行っている。concrete5コミュニティリーダー、Novius OSコアコード貢献者でもある。 詳しくは管理者詳細参照。
大好評WordPress書籍「WordPressユーザーのためのPHP入門 はじめから、ていねいに。」サポートページ

Copyright © 2015 Standing on the Shoulder of Linus.