<NME> ValueGenerator.php
<BEF> <?php
/**
 * Zend Framework (http://framework.zend.com/)
 *
 * @link      http://github.com/zendframework/zf2 for the canonical source repository
 * @copyright Copyright (c) 2005-2016 Zend Technologies USA Inc. (http://www.zend.com)
 * @license   http://framework.zend.com/license/new-bsd New BSD License
 */

namespace Zend\Code\Generator;

use ArrayObject as SplArrayObject;
use Zend\Code\Exception\InvalidArgumentException;
use Zend\Stdlib\ArrayObject as StdlibArrayObject;

use function addcslashes;
use function array_keys;
use function array_merge;
use function array_search;
use function count;
use function get_class;
use function get_defined_constants;
use function gettype;
 */
namespace Zend\Code\Generator;

class PhpValue extends AbstractPhp
{
    /**#@+
     * Constant values
use function str_repeat;
use function strpos;

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_ARRAY_SHORT = 'array_short';
    const TYPE_ARRAY_LONG  = 'array_long';
    /**
     * @var array of reflected constants
     */
    protected static $_constants = array();

    /**
     * @var mixed
     */
    protected $_value = null;

    /**
     * @var string
     */
    protected $_type  = self::TYPE_AUTO;

    /**
     * @var int
     */
    protected $_arrayDepth = 1;

    /**
     * @var string
     */
    protected $_outputMode = self::OUTPUT_MULTIPLE_LINE;

    /**
     * @var array
     */
    protected $_allowedTypes = null;

    /**
     * _init()
    protected $allowedTypes;

     */
    protected function _init()
    {
        if(count(self::$_constants) == 0) {
            $reflect = new \ReflectionClass(get_class($this));
            foreach ($reflect->getConstants() as $name => $value) {
                if (substr($name, 0, 4) == 'TYPE') {
                    self::$_constants[$name] = $value;
                }
            }
            unset($reflect);
     * @param null|SplArrayObject|StdlibArrayObject $constants
     */
    public function __construct(
        $value = null,
        $type = self::TYPE_AUTO,
        $outputMode = self::OUTPUT_MULTIPLE_LINE,
        $constants = null
     */
    public function isValidConstantType()
    {
        if ($this->_type == self::TYPE_AUTO) {
            $type = $this->_getAutoDeterminedType($this->_value);
        } else {
            $type = $this->_type;
        }

        // valid types for constants
        }
        if ($constants === null) {
            $constants = new SplArrayObject();
        } elseif (! ($constants instanceof SplArrayObject || $constants instanceof StdlibArrayObject)) {
            throw new InvalidArgumentException(
                '$constants must be an instance of ArrayObject or Zend\Stdlib\ArrayObject'
            );
        }
        $this->constants = $constants;
    }

    /**
     * Init constant list by defined and magic constants
     */
    public function initEnvironmentConstants()
    {
        $constants   = [
     * setValue()
     *
     * @param mixed $value
     * @return \Zend\Code\Generator\PhpPropertyValue
     */
    public function setValue($value)
    {
        $this->_value = $value;
        return $this;
    }

        $this->constants->exchangeArray($constants);
    }

    /**
     */
    public function getValue()
    {
        return $this->_value;
    }

    /**
     * setType()
     *
     * @param string $type
     * @return \Zend\Code\Generator\PhpPropertyValue
     */
    public function setType($type)
    {
        $this->_type = $type;
        return $this;
    }

     * @return bool
     */
    public function deleteConstant($constant)
    {
     */
    public function getType()
    {
        return $this->_type;
    }

    /**
     * setArrayDepth()
     *
     * @param int $arrayDepth
     * @return \Zend\Code\Generator\PhpPropertyValue
     */
    public function setArrayDepth($arrayDepth)
    {
        $this->_arrayDepth = $arrayDepth;
        return $this;
    }

     * @return bool
     */
    public function isValidConstantType()
    {
     */
    public function getArrayDepth()
    {
        return $this->_arrayDepth;
    }

    /**
            self::TYPE_ARRAY,
            self::TYPE_ARRAY_LONG,
            self::TYPE_ARRAY_SHORT,
            self::TYPE_BOOLEAN,
     */
    protected function _getValidatedType($type)
    {
        if (($constName = array_search($type, self::$_constants)) !== false) {
            return $type;
        }

            self::TYPE_CONSTANT,
            self::TYPE_NULL,
        ];

        return in_array($type, $validConstantTypes);
    }

    /**
     * @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 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);
    }

    /**
     * @return int
     */
    public function getArrayDepth()
    {
        return $this->arrayDepth;
    }

    /**
     * @param  string $type
     * @return string
     */
    protected function getValidatedType($type)
    {
        $types = [
            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_ARRAY_SHORT,
            self::TYPE_ARRAY_LONG,
            self::TYPE_CONSTANT,
            self::TYPE_NULL,
            self::TYPE_OBJECT,
            self::TYPE_OTHER,
        ];

        if (in_array($type, $types)) {
            return $type;
        }

        return self::TYPE_AUTO;
    }
                $curArrayMultiblock = false;
                if (count($value) > 1) {
                    $curArrayMultiblock = true;
                    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) {
                    $v->setArrayDepth($this->_arrayDepth + 1);
                    $partV = $v->generate();
                    if ($n === $noKeyIndex) {
                        $outputParts[] = $partV;
                    }
                }
                        $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 ($curArrayMultiblock == true && $this->_outputMode == self::OUTPUT_MULTIPLE_LINE) {
                    $output .= self::LINE_FEED . str_repeat($this->_indentation, $this->_arrayDepth + 1);
                }
                $output .= ')';
                break;
            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);
        }

        $isArrayType = in_array($type, [self::TYPE_ARRAY, self::TYPE_ARRAY_LONG, self::TYPE_ARRAY_SHORT]);

        if ($isArrayType) {
            foreach ($value as &$curValue) {
                if ($curValue instanceof self) {
                    continue;
                }

                if (is_array($curValue)) {
                    $newType = $type;
                } else {
                    $newType = self::TYPE_AUTO;
                }

                $curValue = new self($curValue, $newType, self::OUTPUT_MULTIPLE_LINE, $this->getConstants());
                $curValue->setIndentation($this->indentation);
            }
        }

        $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:
            case self::TYPE_ARRAY_LONG:
            case self::TYPE_ARRAY_SHORT:
                if ($type === self::TYPE_ARRAY_LONG) {
                    $startArray = 'array(';
                    $endArray   = ')';
                } else {
                    $startArray = '[';
                    $endArray = ']';
                }

                $output .= $startArray;
                if ($this->outputMode == self::OUTPUT_MULTIPLE_LINE) {
                    $output .= self::LINE_FEED . str_repeat($this->indentation, $this->arrayDepth + 1);
                }
                $outputParts = [];
                $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 .= $endArray;
                break;
            case self::TYPE_OTHER:
            default:
                throw new Exception\RuntimeException(sprintf(
                    'Type "%s" is unknown or cannot be used as property default value.',
                    is_object($value) ? get_class($value) : gettype($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();
    }
}

<MSG> Zend\Code
  - More generator refactoring

<DFF> @@ -24,7 +24,7 @@
  */
 namespace Zend\Code\Generator;
 
-class PhpValue extends AbstractPhp
+class ValueGenerator extends AbstractPhp
 {
     /**#@+
      * Constant values
@@ -51,32 +51,32 @@ class PhpValue extends AbstractPhp
     /**
      * @var array of reflected constants
      */
-    protected static $_constants = array();
+    protected static $constants = array();
 
     /**
      * @var mixed
      */
-    protected $_value = null;
+    protected $value = null;
 
     /**
      * @var string
      */
-    protected $_type  = self::TYPE_AUTO;
+    protected $type  = self::TYPE_AUTO;
 
     /**
      * @var int
      */
-    protected $_arrayDepth = 1;
+    protected $arrayDepth = 1;
 
     /**
      * @var string
      */
-    protected $_outputMode = self::OUTPUT_MULTIPLE_LINE;
+    protected $outputMode = self::OUTPUT_MULTIPLE_LINE;
 
     /**
      * @var array
      */
-    protected $_allowedTypes = null;
+    protected $allowedTypes = null;
 
     /**
      * _init()
@@ -85,11 +85,11 @@ class PhpValue extends AbstractPhp
      */
     protected function _init()
     {
-        if(count(self::$_constants) == 0) {
+        if(count(self::$constants) == 0) {
             $reflect = new \ReflectionClass(get_class($this));
             foreach ($reflect->getConstants() as $name => $value) {
                 if (substr($name, 0, 4) == 'TYPE') {
-                    self::$_constants[$name] = $value;
+                    self::$constants[$name] = $value;
                 }
             }
             unset($reflect);
@@ -103,10 +103,10 @@ class PhpValue extends AbstractPhp
      */
     public function isValidConstantType()
     {
-        if ($this->_type == self::TYPE_AUTO) {
-            $type = $this->_getAutoDeterminedType($this->_value);
+        if ($this->type == self::TYPE_AUTO) {
+            $type = $this->_getAutoDeterminedType($this->value);
         } else {
-            $type = $this->_type;
+            $type = $this->type;
         }
 
         // valid types for constants
@@ -130,11 +130,11 @@ class PhpValue extends AbstractPhp
      * setValue()
      *
      * @param mixed $value
-     * @return \Zend\Code\Generator\PhpPropertyValue
+     * @return ValueGenerator
      */
     public function setValue($value)
     {
-        $this->_value = $value;
+        $this->value = $value;
         return $this;
     }
 
@@ -145,18 +145,18 @@ class PhpValue extends AbstractPhp
      */
     public function getValue()
     {
-        return $this->_value;
+        return $this->value;
     }
 
     /**
      * setType()
      *
      * @param string $type
-     * @return \Zend\Code\Generator\PhpPropertyValue
+     * @return ValueGenerator
      */
     public function setType($type)
     {
-        $this->_type = $type;
+        $this->type = $type;
         return $this;
     }
 
@@ -167,18 +167,18 @@ class PhpValue extends AbstractPhp
      */
     public function getType()
     {
-        return $this->_type;
+        return $this->type;
     }
 
     /**
      * setArrayDepth()
      *
      * @param int $arrayDepth
-     * @return \Zend\Code\Generator\PhpPropertyValue
+     * @return ValueGenerator
      */
     public function setArrayDepth($arrayDepth)
     {
-        $this->_arrayDepth = $arrayDepth;
+        $this->arrayDepth = $arrayDepth;
         return $this;
     }
 
@@ -189,7 +189,7 @@ class PhpValue extends AbstractPhp
      */
     public function getArrayDepth()
     {
-        return $this->_arrayDepth;
+        return $this->arrayDepth;
     }
 
     /**
@@ -200,7 +200,7 @@ class PhpValue extends AbstractPhp
      */
     protected function _getValidatedType($type)
     {
-        if (($constName = array_search($type, self::$_constants)) !== false) {
+        if (($constName = array_search($type, self::$constants)) !== false) {
             return $type;
         }
 
@@ -245,13 +245,13 @@ class PhpValue extends AbstractPhp
      */
     public function generate()
     {
-        $type = $this->_type;
+        $type = $this->type;
 
         if ($type != self::TYPE_AUTO) {
             $type = $this->_getValidatedType($type);
         }
 
-        $value = $this->_value;
+        $value = $this->value;
 
         if ($type == self::TYPE_AUTO) {
             $type = $this->_getAutoDeterminedType($value);
@@ -299,14 +299,14 @@ class PhpValue extends AbstractPhp
                 $curArrayMultiblock = false;
                 if (count($value) > 1) {
                     $curArrayMultiblock = true;
-                    if ($this->_outputMode == self::OUTPUT_MULTIPLE_LINE) {
-                        $output .= self::LINE_FEED . str_repeat($this->_indentation, $this->_arrayDepth + 1);
+                    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) {
-                    $v->setArrayDepth($this->_arrayDepth + 1);
+                    $v->setArrayDepth($this->arrayDepth + 1);
                     $partV = $v->generate();
                     if ($n === $noKeyIndex) {
                         $outputParts[] = $partV;
@@ -315,12 +315,12 @@ class PhpValue extends AbstractPhp
                         $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)
+                $padding = ($this->outputMode == self::OUTPUT_MULTIPLE_LINE)
+                    ? self::LINE_FEED . str_repeat($this->_indentation, $this->arrayDepth + 1)
                     : ' ';
                 $output .= implode(',' . $padding, $outputParts);
-                if ($curArrayMultiblock == true && $this->_outputMode == self::OUTPUT_MULTIPLE_LINE) {
-                    $output .= self::LINE_FEED . str_repeat($this->_indentation, $this->_arrayDepth + 1);
+                if ($curArrayMultiblock == true && $this->outputMode == self::OUTPUT_MULTIPLE_LINE) {
+                    $output .= self::LINE_FEED . str_repeat($this->_indentation, $this->arrayDepth + 1);
                 }
                 $output .= ')';
                 break;

Zend\Code   - More generator refactoring