File indexing completed on 2024-04-28 06:00:00

0001 <?php
0002 /**
0003  * Zend Framework
0004  *
0005  * LICENSE
0006  *
0007  * This source file is subject to the new BSD license that is bundled
0008  * with this package in the file LICENSE.txt.
0009  * It is also available through the world-wide-web at this URL:
0010  * http://framework.zend.com/license/new-bsd
0011  * If you did not receive a copy of the license and are unable to
0012  * obtain it through the world-wide-web, please send an email
0013  * to license@zend.com so we can send you a copy immediately.
0014  *
0015  * @category   Zend
0016  * @package    Zend_Application
0017  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
0018  * @license    http://framework.zend.com/license/new-bsd     New BSD License
0019  * @version    $Id$
0020  */
0021 
0022 /**
0023  * @category   Zend
0024  * @package    Zend_Application
0025  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
0026  * @license    http://framework.zend.com/license/new-bsd     New BSD License
0027  */
0028 class Zend_Application
0029 {
0030     /**
0031      * Autoloader to use
0032      *
0033      * @var Zend_Loader_Autoloader
0034      */
0035     protected $_autoloader;
0036 
0037     /**
0038      * Bootstrap
0039      *
0040      * @var Zend_Application_Bootstrap_BootstrapAbstract
0041      */
0042     protected $_bootstrap;
0043 
0044     /**
0045      * Application environment
0046      *
0047      * @var string
0048      */
0049     protected $_environment;
0050 
0051     /**
0052      * Flattened (lowercase) option keys
0053      *
0054      * @var array
0055      */
0056     protected $_optionKeys = array();
0057 
0058     /**
0059      * Options for Zend_Application
0060      *
0061      * @var array
0062      */
0063     protected $_options = array();
0064 
0065     /**
0066      * Constructor
0067      *
0068      * Initialize application. Potentially initializes include_paths, PHP
0069      * settings, and bootstrap class.
0070      *
0071      * @param  string                   $environment
0072      * @param  string|array|Zend_Config $options String path to configuration file, or array/Zend_Config of configuration options
0073      * @param bool $suppressNotFoundWarnings Should warnings be suppressed when a file is not found during autoloading?
0074      * @throws Zend_Application_Exception When invalid options are provided
0075      * @return void
0076      */
0077     public function __construct($environment, $options = null, $suppressNotFoundWarnings = null)
0078     {
0079         $this->_environment = (string) $environment;
0080 
0081         require_once 'Zend/Loader/Autoloader.php';
0082         $this->_autoloader = Zend_Loader_Autoloader::getInstance();
0083         $this->_autoloader->suppressNotFoundWarnings($suppressNotFoundWarnings);
0084 
0085         if (null !== $options) {
0086             if (is_string($options)) {
0087                 $options = $this->_loadConfig($options);
0088             } elseif ($options instanceof Zend_Config) {
0089                 $options = $options->toArray();
0090             } elseif (!is_array($options)) {
0091                 throw new Zend_Application_Exception(
0092                     'Invalid options provided; must be location of config file,'
0093                     . ' a config object, or an array'
0094                 );
0095             }
0096 
0097             $this->setOptions($options);
0098         }
0099     }
0100 
0101     /**
0102      * Retrieve current environment
0103      *
0104      * @return string
0105      */
0106     public function getEnvironment()
0107     {
0108         return $this->_environment;
0109     }
0110 
0111     /**
0112      * Retrieve autoloader instance
0113      *
0114      * @return Zend_Loader_Autoloader
0115      */
0116     public function getAutoloader()
0117     {
0118         return $this->_autoloader;
0119     }
0120 
0121     /**
0122      * Set application options
0123      *
0124      * @param  array $options
0125      * @throws Zend_Application_Exception When no bootstrap path is provided
0126      * @throws Zend_Application_Exception When invalid bootstrap information are provided
0127      * @return Zend_Application
0128      */
0129     public function setOptions(array $options)
0130     {
0131         if (!empty($options['config'])) {
0132             if (is_array($options['config'])) {
0133                 $_options = array();
0134                 foreach ($options['config'] as $tmp) {
0135                     $_options = $this->mergeOptions(
0136                         $_options, $this->_loadConfig($tmp)
0137                     );
0138                 }
0139                 $options = $this->mergeOptions($_options, $options);
0140             } else {
0141                 $options = $this->mergeOptions(
0142                     $this->_loadConfig($options['config']), $options
0143                 );
0144             }
0145         }
0146 
0147         $this->_options = $options;
0148 
0149         $options = array_change_key_case($options, CASE_LOWER);
0150 
0151         $this->_optionKeys = array_keys($options);
0152 
0153         if (!empty($options['phpsettings'])) {
0154             $this->setPhpSettings($options['phpsettings']);
0155         }
0156 
0157         if (!empty($options['includepaths'])) {
0158             $this->setIncludePaths($options['includepaths']);
0159         }
0160 
0161         if (!empty($options['autoloadernamespaces'])) {
0162             $this->setAutoloaderNamespaces($options['autoloadernamespaces']);
0163         }
0164 
0165         if (!empty($options['autoloaderzfpath'])) {
0166             $autoloader = $this->getAutoloader();
0167             if (method_exists($autoloader, 'setZfPath')) {
0168                 $zfPath    = $options['autoloaderzfpath'];
0169                 $zfVersion = !empty($options['autoloaderzfversion'])
0170                            ? $options['autoloaderzfversion']
0171                            : 'latest';
0172                 $autoloader->setZfPath($zfPath, $zfVersion);
0173             }
0174         }
0175 
0176         if (!empty($options['bootstrap'])) {
0177             $bootstrap = $options['bootstrap'];
0178 
0179             if (is_string($bootstrap)) {
0180                 $this->setBootstrap($bootstrap);
0181             } elseif (is_array($bootstrap)) {
0182                 if (empty($bootstrap['path'])) {
0183                     throw new Zend_Application_Exception(
0184                         'No bootstrap path provided'
0185                     );
0186                 }
0187 
0188                 $path  = $bootstrap['path'];
0189                 $class = null;
0190 
0191                 if (!empty($bootstrap['class'])) {
0192                     $class = $bootstrap['class'];
0193                 }
0194 
0195                 $this->setBootstrap($path, $class);
0196             } else {
0197                 throw new Zend_Application_Exception(
0198                     'Invalid bootstrap information provided'
0199                 );
0200             }
0201         }
0202 
0203         return $this;
0204     }
0205 
0206     /**
0207      * Retrieve application options (for caching)
0208      *
0209      * @return array
0210      */
0211     public function getOptions()
0212     {
0213         return $this->_options;
0214     }
0215 
0216     /**
0217      * Is an option present?
0218      *
0219      * @param  string $key
0220      * @return bool
0221      */
0222     public function hasOption($key)
0223     {
0224         return in_array(strtolower($key), $this->_optionKeys);
0225     }
0226 
0227     /**
0228      * Retrieve a single option
0229      *
0230      * @param  string $key
0231      * @return mixed
0232      */
0233     public function getOption($key)
0234     {
0235         if ($this->hasOption($key)) {
0236             $options = $this->getOptions();
0237             $options = array_change_key_case($options, CASE_LOWER);
0238             return $options[strtolower($key)];
0239         }
0240         return null;
0241     }
0242 
0243     /**
0244      * Merge options recursively
0245      *
0246      * @param  array $array1
0247      * @param  mixed $array2
0248      * @return array
0249      */
0250     public function mergeOptions(array $array1, $array2 = null)
0251     {
0252         if (is_array($array2)) {
0253             foreach ($array2 as $key => $val) {
0254                 if (is_array($array2[$key])) {
0255                     $array1[$key] = (array_key_exists($key, $array1) && is_array($array1[$key]))
0256                                   ? $this->mergeOptions($array1[$key], $array2[$key])
0257                                   : $array2[$key];
0258                 } else {
0259                     $array1[$key] = $val;
0260                 }
0261             }
0262         }
0263         return $array1;
0264     }
0265 
0266     /**
0267      * Set PHP configuration settings
0268      *
0269      * @param  array $settings
0270      * @param  string $prefix Key prefix to prepend to array values (used to map . separated INI values)
0271      * @return Zend_Application
0272      */
0273     public function setPhpSettings(array $settings, $prefix = '')
0274     {
0275         foreach ($settings as $key => $value) {
0276             $key = empty($prefix) ? $key : $prefix . $key;
0277             if (is_scalar($value)) {
0278                 ini_set($key, $value);
0279             } elseif (is_array($value)) {
0280                 $this->setPhpSettings($value, $key . '.');
0281             }
0282         }
0283 
0284         return $this;
0285     }
0286 
0287     /**
0288      * Set include path
0289      *
0290      * @param  array $paths
0291      * @return Zend_Application
0292      */
0293     public function setIncludePaths(array $paths)
0294     {
0295         $path = implode(PATH_SEPARATOR, $paths);
0296         set_include_path($path . PATH_SEPARATOR . get_include_path());
0297         return $this;
0298     }
0299 
0300     /**
0301      * Set autoloader namespaces
0302      *
0303      * @param  array $namespaces
0304      * @return Zend_Application
0305      */
0306     public function setAutoloaderNamespaces(array $namespaces)
0307     {
0308         $autoloader = $this->getAutoloader();
0309 
0310         foreach ($namespaces as $namespace) {
0311             $autoloader->registerNamespace($namespace);
0312         }
0313 
0314         return $this;
0315     }
0316 
0317     /**
0318      * Set bootstrap path/class
0319      *
0320      * @param  string $path
0321      * @param  string $class
0322      * @return Zend_Application
0323      */
0324     public function setBootstrap($path, $class = null)
0325     {
0326         // setOptions() can potentially send a null value; specify default
0327         // here
0328         if (null === $class) {
0329             $class = 'Bootstrap';
0330         }
0331 
0332         if (!class_exists($class, false)) {
0333             require_once $path;
0334             if (!class_exists($class, false)) {
0335                 throw new Zend_Application_Exception(
0336                     'Bootstrap class not found'
0337                 );
0338             }
0339         }
0340         $this->_bootstrap = new $class($this);
0341 
0342         if (!$this->_bootstrap instanceof Zend_Application_Bootstrap_Bootstrapper) {
0343             throw new Zend_Application_Exception(
0344                 'Bootstrap class does not implement'
0345                 . ' Zend_Application_Bootstrap_Bootstrapper'
0346             );
0347         }
0348 
0349         return $this;
0350     }
0351 
0352     /**
0353      * Get bootstrap object
0354      *
0355      * @return Zend_Application_Bootstrap_BootstrapAbstract
0356      */
0357     public function getBootstrap()
0358     {
0359         if (null === $this->_bootstrap) {
0360             $this->_bootstrap = new Zend_Application_Bootstrap_Bootstrap($this);
0361         }
0362         return $this->_bootstrap;
0363     }
0364 
0365     /**
0366      * Bootstrap application
0367      *
0368      * @param  null|string|array $resource
0369      * @return Zend_Application
0370      */
0371     public function bootstrap($resource = null)
0372     {
0373         $this->getBootstrap()->bootstrap($resource);
0374         return $this;
0375     }
0376 
0377     /**
0378      * Run the application
0379      *
0380      * @return void
0381      */
0382     public function run()
0383     {
0384         $this->getBootstrap()->run();
0385     }
0386 
0387     /**
0388      * Load configuration file of options
0389      *
0390      * @param  string $file
0391      * @throws Zend_Application_Exception When invalid configuration file is provided
0392      * @return array
0393      */
0394     protected function _loadConfig($file)
0395     {
0396         $environment = $this->getEnvironment();
0397         $suffix      = pathinfo($file, PATHINFO_EXTENSION);
0398         $suffix      = ($suffix === 'dist')
0399                      ? pathinfo(basename($file, ".$suffix"), PATHINFO_EXTENSION)
0400                      : $suffix;
0401 
0402         switch (strtolower($suffix)) {
0403             case 'ini':
0404                 $config = new Zend_Config_Ini($file, $environment);
0405                 break;
0406 
0407             case 'xml':
0408                 $config = new Zend_Config_Xml($file, $environment);
0409                 break;
0410 
0411             case 'json':
0412                 $config = new Zend_Config_Json($file, $environment);
0413                 break;
0414 
0415             case 'yaml':
0416             case 'yml':
0417                 $config = new Zend_Config_Yaml($file, $environment);
0418                 break;
0419 
0420             case 'php':
0421             case 'inc':
0422                 $config = include $file;
0423                 if (!is_array($config)) {
0424                     throw new Zend_Application_Exception(
0425                         'Invalid configuration file provided; PHP file does not'
0426                         . ' return array value'
0427                     );
0428                 }
0429                 return $config;
0430                 break;
0431 
0432             default:
0433                 throw new Zend_Application_Exception(
0434                     'Invalid configuration file provided; unknown config type'
0435                 );
0436         }
0437 
0438         return $config->toArray();
0439     }
0440 }