mirror of
https://github.com/torrentpier/torrentpier-lts.git
synced 2025-03-01 15:21:02 +03:00
436 lines
11 KiB
PHP
436 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-2015 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)
|
|
{
|
|
// strict check is important here if $type = AUTO
|
|
if ($value !== null) {
|
|
$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) {
|
|
if (count($outputParts) > 0) {
|
|
$output .= ',';
|
|
}
|
|
$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();
|
|
}
|
|
}
|