torrentpier-lts/library/Zend/Code/Generator/ValueGenerator.php

432 lines
11 KiB
PHP

<?php
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the canonical source repository
* @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
namespace Zend\Code\Generator;
use Zend\Stdlib\ArrayObject;
class ValueGenerator extends AbstractGenerator
{
/**#@+
* Constant values
*/
const TYPE_AUTO = 'auto';
const TYPE_BOOLEAN = 'boolean';
const TYPE_BOOL = 'bool';
const TYPE_NUMBER = 'number';
const TYPE_INTEGER = 'integer';
const TYPE_INT = 'int';
const TYPE_FLOAT = 'float';
const TYPE_DOUBLE = 'double';
const TYPE_STRING = 'string';
const TYPE_ARRAY = 'array';
const TYPE_CONSTANT = 'constant';
const TYPE_NULL = 'null';
const TYPE_OBJECT = 'object';
const TYPE_OTHER = 'other';
/**#@-*/
const OUTPUT_MULTIPLE_LINE = 'multipleLine';
const OUTPUT_SINGLE_LINE = 'singleLine';
/**
* @var mixed
*/
protected $value = null;
/**
* @var string
*/
protected $type = self::TYPE_AUTO;
/**
* @var int
*/
protected $arrayDepth = 0;
/**
* @var string
*/
protected $outputMode = self::OUTPUT_MULTIPLE_LINE;
/**
* @var array
*/
protected $allowedTypes = null;
/**
* Autodetectable constants
* @var ArrayObject
*/
protected $constants = null;
/**
* @param mixed $value
* @param string $type
* @param string $outputMode
* @param ArrayObject $constants
*/
public function __construct($value = null, $type = self::TYPE_AUTO, $outputMode = self::OUTPUT_MULTIPLE_LINE, ArrayObject $constants = null)
{
if ($value !== null) { // strict check is important here if $type = AUTO
$this->setValue($value);
}
if ($type !== self::TYPE_AUTO) {
$this->setType($type);
}
if ($outputMode !== self::OUTPUT_MULTIPLE_LINE) {
$this->setOutputMode($outputMode);
}
if ($constants !== null) {
$this->constants = $constants;
} else {
$this->constants = new ArrayObject();
}
}
/**
* Init constant list by defined and magic constants
*/
public function initEnvironmentConstants()
{
$constants = array(
'__DIR__',
'__FILE__',
'__LINE__',
'__CLASS__',
'__TRAIT__',
'__METHOD__',
'__FUNCTION__',
'__NAMESPACE__',
'::'
);
$constants = array_merge($constants, array_keys(get_defined_constants()), $this->constants->getArrayCopy());
$this->constants->exchangeArray($constants);
}
/**
* Add constant to list
*
* @param string $constant
*
* @return $this
*/
public function addConstant($constant)
{
$this->constants->append($constant);
return $this;
}
/**
* Delete constant from constant list
*
* @param string $constant
*
* @return bool
*/
public function deleteConstant($constant)
{
if (($index = array_search($constant, $this->constants->getArrayCopy())) !== false) {
$this->constants->offsetUnset($index);
}
return $index !== false;
}
/**
* Return constant list
*
* @return ArrayObject
*/
public function getConstants()
{
return $this->constants;
}
/**
* @return bool
*/
public function isValidConstantType()
{
if ($this->type == self::TYPE_AUTO) {
$type = $this->getAutoDeterminedType($this->value);
} else {
$type = $this->type;
}
// valid types for constants
$scalarTypes = array(
self::TYPE_BOOLEAN,
self::TYPE_BOOL,
self::TYPE_NUMBER,
self::TYPE_INTEGER,
self::TYPE_INT,
self::TYPE_FLOAT,
self::TYPE_DOUBLE,
self::TYPE_STRING,
self::TYPE_CONSTANT,
self::TYPE_NULL
);
return in_array($type, $scalarTypes);
}
/**
* @param mixed $value
* @return ValueGenerator
*/
public function setValue($value)
{
$this->value = $value;
return $this;
}
/**
* @return mixed
*/
public function getValue()
{
return $this->value;
}
/**
* @param string $type
* @return ValueGenerator
*/
public function setType($type)
{
$this->type = (string) $type;
return $this;
}
/**
* @return string
*/
public function getType()
{
return $this->type;
}
/**
* @param int $arrayDepth
* @return ValueGenerator
*/
public function setArrayDepth($arrayDepth)
{
$this->arrayDepth = (int) $arrayDepth;
return $this;
}
/**
* @return int
*/
public function getArrayDepth()
{
return $this->arrayDepth;
}
/**
* @param string $type
* @return string
*/
protected function getValidatedType($type)
{
$types = array(
self::TYPE_AUTO,
self::TYPE_BOOLEAN,
self::TYPE_BOOL,
self::TYPE_NUMBER,
self::TYPE_INTEGER,
self::TYPE_INT,
self::TYPE_FLOAT,
self::TYPE_DOUBLE,
self::TYPE_STRING,
self::TYPE_ARRAY,
self::TYPE_CONSTANT,
self::TYPE_NULL,
self::TYPE_OBJECT,
self::TYPE_OTHER
);
if (in_array($type, $types)) {
return $type;
}
return self::TYPE_AUTO;
}
/**
* @param mixed $value
* @return string
*/
public function getAutoDeterminedType($value)
{
switch (gettype($value)) {
case 'boolean':
return self::TYPE_BOOLEAN;
case 'string':
foreach ($this->constants as $constant) {
if (strpos($value, $constant) !== false) {
return self::TYPE_CONSTANT;
}
}
return self::TYPE_STRING;
case 'double':
case 'float':
case 'integer':
return self::TYPE_NUMBER;
case 'array':
return self::TYPE_ARRAY;
case 'NULL':
return self::TYPE_NULL;
case 'object':
case 'resource':
case 'unknown type':
default:
return self::TYPE_OTHER;
}
}
/**
* @throws Exception\RuntimeException
* @return string
*/
public function generate()
{
$type = $this->type;
if ($type != self::TYPE_AUTO) {
$type = $this->getValidatedType($type);
}
$value = $this->value;
if ($type == self::TYPE_AUTO) {
$type = $this->getAutoDeterminedType($value);
}
if ($type == self::TYPE_ARRAY) {
foreach ($value as &$curValue) {
if ($curValue instanceof self) {
continue;
}
$curValue = new self($curValue, self::TYPE_AUTO, self::OUTPUT_MULTIPLE_LINE, $this->getConstants());
}
}
$output = '';
switch ($type) {
case self::TYPE_BOOLEAN:
case self::TYPE_BOOL:
$output .= ($value ? 'true' : 'false');
break;
case self::TYPE_STRING:
$output .= self::escape($value);
break;
case self::TYPE_NULL:
$output .= 'null';
break;
case self::TYPE_NUMBER:
case self::TYPE_INTEGER:
case self::TYPE_INT:
case self::TYPE_FLOAT:
case self::TYPE_DOUBLE:
case self::TYPE_CONSTANT:
$output .= $value;
break;
case self::TYPE_ARRAY:
$output .= 'array(';
if ($this->outputMode == self::OUTPUT_MULTIPLE_LINE) {
$output .= self::LINE_FEED . str_repeat($this->indentation, $this->arrayDepth + 1);
}
$outputParts = array();
$noKeyIndex = 0;
foreach ($value as $n => $v) {
/* @var $v ValueGenerator */
$v->setArrayDepth($this->arrayDepth + 1);
$partV = $v->generate();
$short = false;
if (is_int($n)) {
if ($n === $noKeyIndex) {
$short = true;
$noKeyIndex++;
} else {
$noKeyIndex = max($n + 1, $noKeyIndex);
}
}
if ($short) {
$outputParts[] = $partV;
} else {
$outputParts[] = (is_int($n) ? $n : self::escape($n)) . ' => ' . $partV;
}
}
$padding = ($this->outputMode == self::OUTPUT_MULTIPLE_LINE)
? self::LINE_FEED . str_repeat($this->indentation, $this->arrayDepth + 1)
: ' ';
$output .= implode(',' . $padding, $outputParts);
if ($this->outputMode == self::OUTPUT_MULTIPLE_LINE) {
$output .= self::LINE_FEED . str_repeat($this->indentation, $this->arrayDepth);
}
$output .= ')';
break;
case self::TYPE_OTHER:
default:
throw new Exception\RuntimeException(
sprintf('Type "%s" is unknown or cannot be used as property default value.', get_class($value))
);
}
return $output;
}
/**
* Quotes value for PHP code.
*
* @param string $input Raw string.
* @param bool $quote Whether add surrounding quotes or not.
* @return string PHP-ready code.
*/
public static function escape($input, $quote = true)
{
$output = addcslashes($input, "\\'");
// adds quoting strings
if ($quote) {
$output = "'" . $output . "'";
}
return $output;
}
/**
* @param string $outputMode
* @return ValueGenerator
*/
public function setOutputMode($outputMode)
{
$this->outputMode = (string) $outputMode;
return $this;
}
/**
* @return string
*/
public function getOutputMode()
{
return $this->outputMode;
}
public function __toString()
{
return $this->generate();
}
}