Skip to content

Instantly share code, notes, and snippets.

@sasezaki
Last active December 17, 2015 09:09
Show Gist options
  • Select an option

  • Save sasezaki/5585215 to your computer and use it in GitHub Desktop.

Select an option

Save sasezaki/5585215 to your computer and use it in GitHub Desktop.
just a note
<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\Code\Scanner;
use Zend\Code\Annotation;
use Zend\Code\Exception;
use Zend\Code\NameInformation;
class PropertyScanner implements ScannerInterface
{
/**
* @var bool
*/
protected $isScanned = false;
/**
* @var array
*/
protected $tokens;
/**
* @var NameInformation
*/
protected $nameInformation;
/**
* @var string
*/
protected $class;
/**
* @var ClassScanner
*/
protected $scannerClass;
/**
* @var int
*/
protected $lineStart;
/**
* @var bool
*/
protected $isProtected = false;
/**
* @var bool
*/
protected $isPublic = true;
/**
* @var bool
*/
protected $isPrivate = false;
/**
* @var bool
*/
protected $isStatic = false;
/**
* @var string
*/
protected $docComment;
/**
* @var string
*/
protected $name;
/**
* @var string
*/
protected $value;
/**
* Constructor
*
* @param array $propertyTokens
* @param NameInformation $nameInformation
*/
public function __construct(array $propertyTokens, NameInformation $nameInformation = null)
{
$this->tokens = $propertyTokens;
$this->nameInformation = $nameInformation;
}
/**
* @param string $class
*/
public function setClass($class)
{
$this->class = $class;
}
/**
* @param ClassScanner $scannerClass
*/
public function setScannerClass(ClassScanner $scannerClass)
{
$this->scannerClass = $scannerClass;
}
/**
* @return ClassScanner
*/
public function getClassScanner()
{
return $this->scannerClass;
}
/**
* @return string
*/
public function getName()
{
$this->scan();
return $this->name;
}
/**
* @return bool
*/
public function isPublic()
{
$this->scan();
return $this->isPublic;
}
/**
* @return bool
*/
public function isPrivate()
{
$this->scan();
return $this->isPrivate;
}
/**
* @return bool
*/
public function isProtected()
{
$this->scan();
return $this->isProtected;
}
/**
* @return bool
*/
public function isStatic()
{
$this->scan();
return $this->isStatic;
}
/**
* @return string
*/
public function getValue()
{
$this->scan();
return $this->value;
}
/**
* @return string
*/
public function getDocComment()
{
$this->scan();
return $this->docComment;
}
/**
* @param Annotation\AnnotationManager $annotationManager
* @return AnnotationScanner
*/
public function getAnnotations(Annotation\AnnotationManager $annotationManager)
{
if (($docComment = $this->getDocComment()) == '') {
return false;
}
return new AnnotationScanner($annotationManager, $docComment, $this->nameInformation);
}
/**
* @return string
*/
public function __toString()
{
$this->scan();
return var_export($this, true);
}
/**
* Scan tokens
*
* @throws \Zend\Code\Exception\RuntimeException
*/
protected function scan()
{
if ($this->isScanned) {
return;
}
if (!$this->tokens) {
throw new Exception\RuntimeException('No tokens were provided');
}
/**
* Variables & Setup
*/
$tokens = &$this->tokens;
reset($tokens);
$tokenValueLoop = false;
$scanValueStart = false;
SCANNER_TOP:
$token = current($tokens);
if (!is_string($token)) {
list($tokenType, $tokenContent, $tokenLine) = $token;
switch ($tokenType) {
case T_DOC_COMMENT:
if ($this->docComment === null && $this->name === null) {
$this->docComment = $tokenContent;
}
$tokenValueLoop = false;
goto SCANNER_CONTINUE;
case T_VARIABLE:
$this->name = ltrim($tokenContent, '$');
$tokenValueLoop = false;
goto SCANNER_CONTINUE;
case T_PUBLIC:
// use defaults
$tokenValueLoop = false;
goto SCANNER_CONTINUE;
case T_PROTECTED:
$this->isProtected = true;
$this->isPublic = false;
$tokenValueLoop = false;
goto SCANNER_CONTINUE;
case T_PRIVATE:
$this->isPrivate = true;
$this->isPublic = false;
$tokenValueLoop = false;
goto SCANNER_CONTINUE;
case T_STATIC:
$this->isStatic = true;
$tokenValueLoop = false;
goto SCANNER_CONTINUE;
default:
if ($scanValueStart === false && $tokenType === T_WHITESPACE) {
goto SCANNER_CONTINUE;
}
$scanValueStart = true;
if ($tokenValueLoop === false) {
$propertyValue = new PropertyValue;
}
$propertyValue->add($token);
// old
if ($this->name !== null && trim($tokenContent) !== '') {
//var_dump(__METHOD__, $token, token_name($token[0]), $tokenContent, $tokenLine);
$this->value .= (is_string($token)) ? $token : $tokenContent;
if (substr($this->value, 0, 1) === '"' || substr($this->value, 0, 1) === "'") {
$this->value = substr($this->value, 1, -1); // Remove quotes
}
}
$tokenValueLoop = true;
goto SCANNER_CONTINUE;
}
} else {
if (isset($propertyValue)) {
if ($token !== ';') {
$propertyValue->add($token);
}
}
}
SCANNER_CONTINUE:
if (next($this->tokens) === false) {
if (isset($propertyValue)) {
//var_dump($propertyValue);
//$propertyValue->scan();
$propertyValue->debug();
};
goto SCANNER_END;
}
goto SCANNER_TOP;
SCANNER_END:
$this->isScanned = true;
}
}
class PropertyValueArray implements \Iterator
{
private $position = 0;
private $tokenPosition = 0;
private $numerical_count = 0;
private $tokens;
private $current;
public function __construct($tokens)
{
var_dump($tokens);
$this->tokens = $tokens;
}
public function current()
{
return $this->current;
}
public function next()
{
++$this->position;
++$this->tokenPosition;
$this->fetch();
}
protected function fetch()
{
do {
if (!isset($this->tokens[$this->tokenPosition])) {
break;
}
if (is_array($this->tokens[$this->tokenPosition])) {
if ($this->tokens[$this->tokenPosition][0] === T_WHITESPACE) {
++$this->tokenPosition;
continue;
}
if ($this->tokens[$this->tokenPosition][1] === '=>') {
++$this->tokenPosition;
continue;
}
if ($this->tokens[$this->tokenPosition][1] === 'array') {
if ($this->tokenPosition == 0) {
++$this->tokenPosition;
continue;
} else {
// multidimentional
$multi_start = $this->tokenPosition;
do {
if ($this->tokens[$this->tokenPosition] === ')') {
$tokens = $this->tokens;
$tokens = array_slice($tokens, $multi_start, $this->tokenPosition + 1 - $multi_start);
++$this->tokenPosition;
break;
}
++$this->tokenPosition;
} while (true);
$this->current = new self($tokens);
}
}
// is key or value ?
if (isset($this->tokens[$this->tokenPosition + 1])) {
if (
$this->tokens[$this->tokenPosition + 1] === ',' ||
$this->tokens[$this->tokenPosition + 1] === ')'
) {
$value = $this->tokens[$this->tokenPosition][1];
break;
}
if (
(
is_array($this->tokens[$this->tokenPosition + 1]) &&
$this->tokens[$this->tokenPosition + 1][0] === T_WHITESPACE)
&&
(
$this->tokens[$this->tokenPosition + 2] === ',' ||
$this->tokens[$this->tokenPosition + 2] === ')'
)
) {
$value = $this->tokens[$this->tokenPosition][1];
break;
}
}
if (is_array($this->tokens[$this->tokenPosition])) {
$key = $this->tokens[$this->tokenPosition][1];
} else {
goto FETCH_END;
}
}
++$this->tokenPosition;
} while (true);
if (!isset($value)) {
goto FETCH_END;
}
$this->current = array('key' => (isset($key))? $key : $this->numerical_count, 'value' => $value);
if (!isset($key)) ++$this->numerical_count;
FETCH_END:
}
public function key()
{
return $this->position;
}
public function valid()
{
return $this->tokenPosition < count($this->tokens);
}
public function rewind()
{
$this->position = 0;
$this->tokenPosition = 0;
$this->fetch();
}
public function scan(){
$count_current_tokens = count($this->tokens);
$array_token = array();
$left_count = 0; // (
for ($i = 0; $i < $count_current_tokens; $i++) {
if ($this->tokens[$i] === '(') {
$left_count++;
}
if ($this->tokens[$i] === ')') {
$left_count--;
}
if (is_array($this->tokens[$i])) {
$array_token;
}
}
}
}
class PropertyValue
{
private $scanned;
private $tokens = array();
private $value;
public function add($token)
{
$this->tokens[] = $token;
}
public function debug(){
//var_dump(count($this->tokens));
//var_dump($this->tokens[0][1]);
if (count($this->tokens) === 1) { //just a string or boolean or CONST
$serializer = new \Zend\Serializer\Adapter\PhpCode;
var_dump($serializer->unserialize($this->tokens[0][1]));
} else {
$propertyValueArray = new PropertyValueArray($this->tokens);
foreach ($propertyValueArray as $a) {
var_dump($a);
}
/**
$propertyValueArray->rewind();
//var_dump($propertyValueArray);
var_dump($propertyValueArray->current());
$propertyValueArray->next();
var_dump($propertyValueArray->current());
$propertyValueArray->next();
var_dump($propertyValueArray->current());*/
}
}
public function getTokens()
{
return $this->tokens;
}
public function getValue()
{
$this->scan();
return $this->value;
}
public function scan()
{
if ($this->scanned) {
return; //already scanned;
}
$tokens = $this->tokens;
return;
foreach ($tokens as $token) {
//if (in_array($token[0], array(T_WHITESPACE))) { //ignore
// continue;
//}
if ($token[0] === T_ARRAY) {
$value = new PropertyValue($token);
$value->scan();
$this->value[] = $value->getValue();
} else {
$this->value[] = $token;
}
}
return;
$token_start = current($tokens);
if ($token_start[0] === T_ARRAY) {
array_shift($tokens);
$this->tokens = $tokens;
$this->scan();
/**
array_shift($tokens);
$value = new PropertyValue();
foreach ($tokens as $token) {
if ($token[0] === T_ARRAY) {
}
$value->add($token);
}
$this->value = $value;
return;
*/
}
if (!$this->value) {
$this->value = new PropertyValue();
}
$this->value->add($tokens);
$this->scanned = true;
}
}
<?php
use Zend\Code\Scanner;
spl_autoload_register(function($class){
if ($class === 'Zend\Code\Scanner\PropertyScanner') {
include __DIR__.'/PropertyScanner_patch.php';
}
});
require dirname( __DIR__).'/tests/_autoload.php';
$code = <<<'CODE'
<?php
class Abc
{
protected $boolean = false;
protected $fo = array('a' => 1, 'b', 'c' => 3);
protected $foo = array('x' => 9 ,array(3,6), 2);
protected $string = 'xx';
protected $bar2, $bar3;
}
CODE;
////syntax check
eval(substr($code, 5));
$property = (isset($argv[1])) ? $argv[1] : 'foo';
$scanner = new Scanner\TokenArrayScanner(token_get_all($code));
var_dump($scanner->getClass('Abc')->getProperty($property)->getValue());
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment