| Viewing file:  AbstractConfigLoader.php (5.86 KB)      -rw-r--r-- Select action/file-type:
 
  (+) |  (+) |  (+) | Code (+) | Session (+) |  (+) | SDB (+) |  (+) |  (+) |  (+) |  (+) |  (+) | 
 
<?php
 namespace Guzzle\Service;
 
 use Guzzle\Common\Exception\InvalidArgumentException;
 use Guzzle\Common\Exception\RuntimeException;
 
 /**
 * Abstract config loader
 */
 abstract class AbstractConfigLoader implements ConfigLoaderInterface
 {
 /** @var array Array of aliases for actual filenames */
 protected $aliases = array();
 
 /** @var array Hash of previously loaded filenames */
 protected $loadedFiles = array();
 
 /** @var array JSON error code mappings */
 protected static $jsonErrors = array(
 JSON_ERROR_NONE => 'JSON_ERROR_NONE - No errors',
 JSON_ERROR_DEPTH => 'JSON_ERROR_DEPTH - Maximum stack depth exceeded',
 JSON_ERROR_STATE_MISMATCH => 'JSON_ERROR_STATE_MISMATCH - Underflow or the modes mismatch',
 JSON_ERROR_CTRL_CHAR => 'JSON_ERROR_CTRL_CHAR - Unexpected control character found',
 JSON_ERROR_SYNTAX => 'JSON_ERROR_SYNTAX - Syntax error, malformed JSON',
 JSON_ERROR_UTF8 => 'JSON_ERROR_UTF8 - Malformed UTF-8 characters, possibly incorrectly encoded'
 );
 
 public function load($config, array $options = array())
 {
 // Reset the array of loaded files because this is a new config
 $this->loadedFiles = array();
 
 if (is_string($config)) {
 $config = $this->loadFile($config);
 } elseif (!is_array($config)) {
 throw new InvalidArgumentException('Unknown type passed to configuration loader: ' . gettype($config));
 } else {
 $this->mergeIncludes($config);
 }
 
 return $this->build($config, $options);
 }
 
 /**
 * Add an include alias to the loader
 *
 * @param string $filename Filename to alias (e.g. _foo)
 * @param string $alias    Actual file to use (e.g. /path/to/foo.json)
 *
 * @return self
 */
 public function addAlias($filename, $alias)
 {
 $this->aliases[$filename] = $alias;
 
 return $this;
 }
 
 /**
 * Remove an alias from the loader
 *
 * @param string $alias Alias to remove
 *
 * @return self
 */
 public function removeAlias($alias)
 {
 unset($this->aliases[$alias]);
 
 return $this;
 }
 
 /**
 * Perform the parsing of a config file and create the end result
 *
 * @param array $config  Configuration data
 * @param array $options Options to use when building
 *
 * @return mixed
 */
 protected abstract function build($config, array $options);
 
 /**
 * Load a configuration file (can load JSON or PHP files that return an array when included)
 *
 * @param string $filename File to load
 *
 * @return array
 * @throws InvalidArgumentException
 * @throws RuntimeException when the JSON cannot be parsed
 */
 protected function loadFile($filename)
 {
 if (isset($this->aliases[$filename])) {
 $filename = $this->aliases[$filename];
 }
 
 switch (pathinfo($filename, PATHINFO_EXTENSION)) {
 case 'js':
 case 'json':
 $level = error_reporting(0);
 $json = file_get_contents($filename);
 error_reporting($level);
 
 if ($json === false) {
 $err = error_get_last();
 throw new InvalidArgumentException("Unable to open {$filename}: " . $err['message']);
 }
 
 $config = json_decode($json, true);
 // Throw an exception if there was an error loading the file
 if ($error = json_last_error()) {
 $message = isset(self::$jsonErrors[$error]) ? self::$jsonErrors[$error] : 'Unknown error';
 throw new RuntimeException("Error loading JSON data from {$filename}: ({$error}) - {$message}");
 }
 break;
 case 'php':
 if (!is_readable($filename)) {
 throw new InvalidArgumentException("Unable to open {$filename} for reading");
 }
 $config = require $filename;
 if (!is_array($config)) {
 throw new InvalidArgumentException('PHP files must return an array of configuration data');
 }
 break;
 default:
 throw new InvalidArgumentException('Unknown file extension: ' . $filename);
 }
 
 // Keep track of this file being loaded to prevent infinite recursion
 $this->loadedFiles[$filename] = true;
 
 // Merge include files into the configuration array
 $this->mergeIncludes($config, dirname($filename));
 
 return $config;
 }
 
 /**
 * Merges in all include files
 *
 * @param array  $config   Config data that contains includes
 * @param string $basePath Base path to use when a relative path is encountered
 *
 * @return array Returns the merged and included data
 */
 protected function mergeIncludes(&$config, $basePath = null)
 {
 if (!empty($config['includes'])) {
 foreach ($config['includes'] as &$path) {
 // Account for relative paths
 if ($path[0] != DIRECTORY_SEPARATOR && !isset($this->aliases[$path]) && $basePath) {
 $path = "{$basePath}/{$path}";
 }
 // Don't load the same files more than once
 if (!isset($this->loadedFiles[$path])) {
 $this->loadedFiles[$path] = true;
 $config = $this->mergeData($this->loadFile($path), $config);
 }
 }
 }
 }
 
 /**
 * Default implementation for merging two arrays of data (uses array_merge_recursive)
 *
 * @param array $a Original data
 * @param array $b Data to merge into the original and overwrite existing values
 *
 * @return array
 */
 protected function mergeData(array $a, array $b)
 {
 return array_merge_recursive($a, $b);
 }
 }
 
 |