234 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			234 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| /**
 | |
|  * @package   FOF
 | |
|  * @copyright Copyright (c)2010-2021 Nicholas K. Dionysopoulos / Akeeba Ltd
 | |
|  * @license   GNU General Public License version 2, or later
 | |
|  */
 | |
| 
 | |
| namespace FOF30\Configuration;
 | |
| 
 | |
| defined('_JEXEC') || die;
 | |
| 
 | |
| use FOF30\Container\Container;
 | |
| 
 | |
| /**
 | |
|  * Reads and parses the fof.xml file in the back-end of a FOF-powered component,
 | |
|  * provisioning the data to the rest of the FOF framework
 | |
|  *
 | |
|  * @since    2.1
 | |
|  */
 | |
| class Configuration
 | |
| {
 | |
| 	/**
 | |
| 	 * Cache of FOF components' configuration variables
 | |
| 	 *
 | |
| 	 * @var array
 | |
| 	 */
 | |
| 	public static $configurations = [];
 | |
| 	/**
 | |
| 	 * The component's container
 | |
| 	 *
 | |
| 	 * @var  Container
 | |
| 	 */
 | |
| 	protected $container = null;
 | |
| 
 | |
| 	function __construct(Container $c)
 | |
| 	{
 | |
| 		$this->container = $c;
 | |
| 
 | |
| 		$this->parseComponent();
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Returns the value of a variable. Variables use a dot notation, e.g.
 | |
| 	 * view.config.whatever where the first part is the domain, the rest of the
 | |
| 	 * parts specify the path to the variable.
 | |
| 	 *
 | |
| 	 * @param   string  $variable  The variable name
 | |
| 	 * @param   mixed   $default   The default value, or null if not specified
 | |
| 	 *
 | |
| 	 * @return  mixed  The value of the variable
 | |
| 	 */
 | |
| 	public function get($variable, $default = null)
 | |
| 	{
 | |
| 		static $domains = null;
 | |
| 
 | |
| 		if (is_null($domains))
 | |
| 		{
 | |
| 			$domains = $this->getDomains();
 | |
| 		}
 | |
| 
 | |
| 		[$domain, $var] = explode('.', $variable, 2);
 | |
| 
 | |
| 		if (!in_array(ucfirst($domain), $domains))
 | |
| 		{
 | |
| 			return $default;
 | |
| 		}
 | |
| 
 | |
| 		$class = '\\FOF30\\Configuration\\Domain\\' . ucfirst($domain);
 | |
| 		/** @var   \FOF30\Configuration\Domain\DomainInterface $o */
 | |
| 		$o = new $class;
 | |
| 
 | |
| 		return $o->get(self::$configurations[$this->container->componentName], $var, $default);
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Parses the configuration of the specified component
 | |
| 	 *
 | |
| 	 * @return  void
 | |
| 	 */
 | |
| 	protected function parseComponent()
 | |
| 	{
 | |
| 		if ($this->container->platform->isCli())
 | |
| 		{
 | |
| 			$order = ['cli', 'backend'];
 | |
| 		}
 | |
| 		elseif ($this->container->platform->isBackend())
 | |
| 		{
 | |
| 			$order = ['backend'];
 | |
| 		}
 | |
| 		else
 | |
| 		{
 | |
| 			$order = ['frontend'];
 | |
| 		}
 | |
| 
 | |
| 		$order[] = 'common';
 | |
| 
 | |
| 		$order                                                 = array_reverse($order);
 | |
| 		self::$configurations[$this->container->componentName] = [];
 | |
| 
 | |
| 		foreach ([false, true] as $userConfig)
 | |
| 		{
 | |
| 			foreach ($order as $area)
 | |
| 			{
 | |
| 				$config                                                = $this->parseComponentArea($area, $userConfig);
 | |
| 				self::$configurations[$this->container->componentName] = array_replace_recursive(self::$configurations[$this->container->componentName], $config);
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Parses the configuration options of a specific component area
 | |
| 	 *
 | |
| 	 * @param   string  $area        Which area to parse (frontend, backend, cli)
 | |
| 	 * @param   bool    $userConfig  When true the user configuration (fof.user.xml) file will be read
 | |
| 	 *
 | |
| 	 * @return  array  A hash array with the configuration data
 | |
| 	 */
 | |
| 	protected function parseComponentArea($area, $userConfig = false)
 | |
| 	{
 | |
| 		$component = $this->container->componentName;
 | |
| 
 | |
| 		// Initialise the return array
 | |
| 		$ret = [];
 | |
| 
 | |
| 		// Get the folders of the component
 | |
| 		$componentPaths = $this->container->platform->getComponentBaseDirs($component);
 | |
| 		$filesystem     = $this->container->filesystem;
 | |
| 		$path           = $componentPaths['admin'];
 | |
| 
 | |
| 		if (isset($this->container['backEndPath']))
 | |
| 		{
 | |
| 			$path = $this->container['backEndPath'];
 | |
| 		}
 | |
| 
 | |
| 		// This line unfortunately doesn't work with Unit Tests because JPath depends on the JPATH_SITE constant :(
 | |
| 		// $path = $filesystem->pathCheck($path);
 | |
| 
 | |
| 		// Check that the path exists
 | |
| 		if (!$filesystem->folderExists($path))
 | |
| 		{
 | |
| 			return $ret;
 | |
| 		}
 | |
| 
 | |
| 		// Read the filename if it exists
 | |
| 		$filename = $path . '/fof.xml';
 | |
| 
 | |
| 		if ($userConfig)
 | |
| 		{
 | |
| 			$filename = $path . '/fof.user.xml';
 | |
| 		}
 | |
| 
 | |
| 		if (!$filesystem->fileExists($filename) && !file_exists($filename))
 | |
| 		{
 | |
| 			return $ret;
 | |
| 		}
 | |
| 
 | |
| 		$data = file_get_contents($filename);
 | |
| 
 | |
| 		// Load the XML data in a SimpleXMLElement object
 | |
| 		$xml = simplexml_load_string($data);
 | |
| 
 | |
| 		if (!($xml instanceof \SimpleXMLElement))
 | |
| 		{
 | |
| 			return $ret;
 | |
| 		}
 | |
| 
 | |
| 		// Get this area's data
 | |
| 		$areaData = $xml->xpath('//' . $area);
 | |
| 
 | |
| 		if (empty($areaData))
 | |
| 		{
 | |
| 			return $ret;
 | |
| 		}
 | |
| 
 | |
| 		$xml = array_shift($areaData);
 | |
| 
 | |
| 		// Parse individual configuration domains
 | |
| 		$domains = $this->getDomains();
 | |
| 
 | |
| 		foreach ($domains as $dom)
 | |
| 		{
 | |
| 			$class = '\\FOF30\\Configuration\\Domain\\' . ucfirst($dom);
 | |
| 
 | |
| 			if (class_exists($class, true))
 | |
| 			{
 | |
| 				/** @var   \FOF30\Configuration\Domain\DomainInterface $o */
 | |
| 				$o = new $class;
 | |
| 				$o->parseDomain($xml, $ret);
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		// Finally, return the result
 | |
| 		return $ret;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Gets a list of the available configuration domain adapters
 | |
| 	 *
 | |
| 	 * @return  array  A list of the available domains
 | |
| 	 */
 | |
| 	protected function getDomains()
 | |
| 	{
 | |
| 		static $domains = [];
 | |
| 
 | |
| 		if (empty($domains))
 | |
| 		{
 | |
| 			$filesystem = $this->container->filesystem;
 | |
| 
 | |
| 			$files = $filesystem->folderFiles(__DIR__ . '/Domain', '.php');
 | |
| 
 | |
| 			if (!empty($files))
 | |
| 			{
 | |
| 				foreach ($files as $file)
 | |
| 				{
 | |
| 					$domain = basename($file, '.php');
 | |
| 
 | |
| 					if ($domain == 'DomainInterface')
 | |
| 					{
 | |
| 						continue;
 | |
| 					}
 | |
| 
 | |
| 					$domain    = preg_replace('/[^A-Za-z0-9]/', '', $domain);
 | |
| 					$domains[] = $domain;
 | |
| 				}
 | |
| 
 | |
| 				$domains = array_unique($domains);
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		return $domains;
 | |
| 	}
 | |
| 
 | |
| }
 |