web/lib/Zend/Config/Json.php
changeset 64 162c1de6545a
parent 19 1c2f13fd785c
child 68 ecaf28ffe26e
equal deleted inserted replaced
63:5b37998e522e 64:162c1de6545a
       
     1 <?php
       
     2 /**
       
     3  * Zend Framework
       
     4  *
       
     5  * LICENSE
       
     6  *
       
     7  * This source file is subject to the new BSD license that is bundled
       
     8  * with this package in the file LICENSE.txt.
       
     9  * It is also available through the world-wide-web at this URL:
       
    10  * http://framework.zend.com/license/new-bsd
       
    11  * If you did not receive a copy of the license and are unable to
       
    12  * obtain it through the world-wide-web, please send an email
       
    13  * to license@zend.com so we can send you a copy immediately.
       
    14  *
       
    15  * @category  Zend
       
    16  * @package   Zend_Config
       
    17  * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
       
    18  * @license   http://framework.zend.com/license/new-bsd     New BSD License
       
    19  * @version   $Id: Json.php 23294 2010-11-05 00:27:34Z ramon $
       
    20  */
       
    21 
       
    22 /**
       
    23  * @see Zend_Config
       
    24  */
       
    25 require_once 'Zend/Config.php';
       
    26 
       
    27 /**
       
    28  * @see Zend_Json
       
    29  */
       
    30 require_once 'Zend/Json.php';
       
    31 
       
    32 /**
       
    33  * JSON Adapter for Zend_Config
       
    34  *
       
    35  * @category  Zend
       
    36  * @package   Zend_Config
       
    37  * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
       
    38  * @license   http://framework.zend.com/license/new-bsd     New BSD License
       
    39  */
       
    40 class Zend_Config_Json extends Zend_Config
       
    41 {
       
    42     /**
       
    43      * Name of object key indicating section current section extends
       
    44      */
       
    45     const EXTENDS_NAME = "_extends";
       
    46 
       
    47     /**
       
    48      * Whether or not to ignore constants in the JSON string
       
    49      *
       
    50      * Note: if you do not have constant names in quotations in your JSON
       
    51      * string, they may lead to syntax errors when parsing.
       
    52      *
       
    53      * @var bool
       
    54      */
       
    55     protected $_ignoreConstants = false;
       
    56 
       
    57     /**
       
    58      * Whether to skip extends or not
       
    59      *
       
    60      * @var boolean
       
    61      */
       
    62     protected $_skipExtends = false;
       
    63 
       
    64     /**
       
    65      * Loads the section $section from the config file encoded as JSON
       
    66      *
       
    67      * Sections are defined as properties of the main object
       
    68      *
       
    69      * In order to extend another section, a section defines the "_extends"
       
    70      * property having a value of the section name from which the extending
       
    71      * section inherits values.
       
    72      *
       
    73      * Note that the keys in $section will override any keys of the same
       
    74      * name in the sections that have been included via "_extends".
       
    75      *
       
    76      * @param  string  $json     JSON file or string to process
       
    77      * @param  mixed   $section Section to process
       
    78      * @param  boolean $options Whether modifiacations are allowed at runtime
       
    79      * @throws Zend_Config_Exception When JSON text is not set or cannot be loaded
       
    80      * @throws Zend_Config_Exception When section $sectionName cannot be found in $json
       
    81      */
       
    82     public function __construct($json, $section = null, $options = false)
       
    83     {
       
    84         if (empty($json)) {
       
    85             require_once 'Zend/Config/Exception.php';
       
    86             throw new Zend_Config_Exception('Filename is not set');
       
    87         }
       
    88 
       
    89         $allowModifications = false;
       
    90         if (is_bool($options)) {
       
    91             $allowModifications = $options;
       
    92         } elseif (is_array($options)) {
       
    93             foreach ($options as $key => $value) {
       
    94                 switch (strtolower($key)) {
       
    95                     case 'allow_modifications':
       
    96                     case 'allowmodifications':
       
    97                         $allowModifications = (bool) $value;
       
    98                         break;
       
    99                     case 'skip_extends':
       
   100                     case 'skipextends':
       
   101                         $this->_skipExtends = (bool) $value;
       
   102                         break;
       
   103                     case 'ignore_constants':
       
   104                     case 'ignoreconstants':
       
   105                         $this->_ignoreConstants = (bool) $value;
       
   106                         break;
       
   107                     default:
       
   108                         break;
       
   109                 }
       
   110             }
       
   111         }
       
   112 
       
   113         set_error_handler(array($this, '_loadFileErrorHandler')); // Warnings and errors are suppressed
       
   114         if ($json[0] != '{') {
       
   115             $json = file_get_contents($json);
       
   116         }
       
   117         restore_error_handler();
       
   118 
       
   119         // Check if there was a error while loading file
       
   120         if ($this->_loadFileErrorStr !== null) {
       
   121             require_once 'Zend/Config/Exception.php';
       
   122             throw new Zend_Config_Exception($this->_loadFileErrorStr);
       
   123         }
       
   124 
       
   125         // Replace constants
       
   126         if (!$this->_ignoreConstants) {
       
   127             $json = $this->_replaceConstants($json);
       
   128         }
       
   129 
       
   130         // Parse/decode
       
   131         $config = Zend_Json::decode($json);
       
   132 
       
   133         if (null === $config) {
       
   134             // decode failed
       
   135             require_once 'Zend/Config/Exception.php';
       
   136             throw new Zend_Config_Exception("Error parsing JSON data");
       
   137         }
       
   138 
       
   139         if ($section === null) {
       
   140             $dataArray = array();
       
   141             foreach ($config as $sectionName => $sectionData) {
       
   142                 $dataArray[$sectionName] = $this->_processExtends($config, $sectionName);
       
   143             }
       
   144 
       
   145             parent::__construct($dataArray, $allowModifications);
       
   146         } elseif (is_array($section)) {
       
   147             $dataArray = array();
       
   148             foreach ($section as $sectionName) {
       
   149                 if (!isset($config[$sectionName])) {
       
   150                     require_once 'Zend/Config/Exception.php';
       
   151                     throw new Zend_Config_Exception(sprintf('Section "%s" cannot be found', $sectionName));
       
   152                 }
       
   153 
       
   154                 $dataArray = array_merge($this->_processExtends($config, $sectionName), $dataArray);
       
   155             }
       
   156 
       
   157             parent::__construct($dataArray, $allowModifications);
       
   158         } else {
       
   159             if (!isset($config[$section])) {
       
   160                 require_once 'Zend/Config/Exception.php';
       
   161                 throw new Zend_Config_Exception(sprintf('Section "%s" cannot be found', $section));
       
   162             }
       
   163 
       
   164             $dataArray = $this->_processExtends($config, $section);
       
   165             if (!is_array($dataArray)) {
       
   166                 // Section in the JSON data contains just one top level string
       
   167                 $dataArray = array($section => $dataArray);
       
   168             }
       
   169 
       
   170             parent::__construct($dataArray, $allowModifications);
       
   171         }
       
   172 
       
   173         $this->_loadedSection = $section;
       
   174     }
       
   175 
       
   176     /**
       
   177      * Helper function to process each element in the section and handle
       
   178      * the "_extends" inheritance attribute.
       
   179      *
       
   180      * @param  array            $data Data array to process
       
   181      * @param  string           $section Section to process
       
   182      * @param  array            $config  Configuration which was parsed yet
       
   183      * @throws Zend_Config_Exception When $section cannot be found
       
   184      * @return array
       
   185      */
       
   186     protected function _processExtends(array $data, $section, array $config = array())
       
   187     {
       
   188         if (!isset($data[$section])) {
       
   189             require_once 'Zend/Config/Exception.php';
       
   190             throw new Zend_Config_Exception(sprintf('Section "%s" cannot be found', $section));
       
   191         }
       
   192 
       
   193         $thisSection  = $data[$section];
       
   194 
       
   195         if (is_array($thisSection) && isset($thisSection[self::EXTENDS_NAME])) {
       
   196             if (is_array($thisSection[self::EXTENDS_NAME])) {
       
   197                 require_once 'Zend/Config/Exception.php';
       
   198                 throw new Zend_Config_Exception('Invalid extends clause: must be a string; array received');
       
   199             }
       
   200             $this->_assertValidExtend($section, $thisSection[self::EXTENDS_NAME]);
       
   201 
       
   202             if (!$this->_skipExtends) {
       
   203                 $config = $this->_processExtends($data, $thisSection[self::EXTENDS_NAME], $config);
       
   204             }
       
   205             unset($thisSection[self::EXTENDS_NAME]);
       
   206         }
       
   207 
       
   208         $config = $this->_arrayMergeRecursive($config, $thisSection);
       
   209 
       
   210         return $config;
       
   211     }
       
   212 
       
   213     /**
       
   214      * Replace any constants referenced in a string with their values
       
   215      *
       
   216      * @param  string $value
       
   217      * @return string
       
   218      */
       
   219     protected function _replaceConstants($value)
       
   220     {
       
   221         foreach ($this->_getConstants() as $constant) {
       
   222             if (strstr($value, $constant)) {
       
   223                 $value = str_replace($constant, constant($constant), $value);
       
   224             }
       
   225         }
       
   226         return $value;
       
   227     }
       
   228 
       
   229     /**
       
   230      * Get (reverse) sorted list of defined constant names
       
   231      *
       
   232      * @return array
       
   233      */
       
   234     protected function _getConstants()
       
   235     {
       
   236         $constants = array_keys(get_defined_constants());
       
   237         rsort($constants, SORT_STRING);
       
   238         return $constants;
       
   239     }
       
   240 }