<?php
/**
 * Joomla! Content Management System
 *
 * @copyright  (C) 2010 Open Source Matters, Inc. <https://www.joomla.org>
 * @license    GNU General Public License version 2 or later; see LICENSE.txt
 */

namespace Joomla\CMS\Cache;

\defined('JPATH_PLATFORM') or die;

use Joomla\CMS\Factory;
use Joomla\CMS\Filesystem\Path;

/**
 * Public cache handler
 *
 * @since  1.7.0
 * @note   As of 4.0 this class will be abstract
 */
class CacheController
{
	/**
	 * Cache object
	 *
	 * @var    Cache
	 * @since  1.7.0
	 */
	public $cache;

	/**
	 * Array of options
	 *
	 * @var    array
	 * @since  1.7.0
	 */
	public $options;

	/**
	 * Constructor
	 *
	 * @param   array  $options  Array of options
	 *
	 * @since   1.7.0
	 */
	public function __construct($options)
	{
		$this->cache = new Cache($options);
		$this->options = & $this->cache->_options;

		// Overwrite default options with given options
		foreach ($options as $option => $value)
		{
			if (isset($options[$option]))
			{
				$this->options[$option] = $options[$option];
			}
		}
	}

	/**
	 * Magic method to proxy CacheController method calls to Cache
	 *
	 * @param   string  $name       Name of the function
	 * @param   array   $arguments  Array of arguments for the function
	 *
	 * @return  mixed
	 *
	 * @since   1.7.0
	 */
	public function __call($name, $arguments)
	{
		return \call_user_func_array(array($this->cache, $name), $arguments);
	}

	/**
	 * Returns a reference to a cache adapter object, always creating it
	 *
	 * @param   string  $type     The cache object type to instantiate; default is output.
	 * @param   array   $options  Array of options
	 *
	 * @return  CacheController
	 *
	 * @since       1.7.0
	 * @throws      \RuntimeException
	 * @deprecated  5.0 Use the cache controller factory instead
	 */
	public static function getInstance($type = 'output', $options = array())
	{
		@trigger_error(
			sprintf(
				'%s() is deprecated. The cache controller should be fetched from the factory.',
				__METHOD__
			),
			E_USER_DEPRECATED
		);

		try
		{
			return Factory::getContainer()->get(CacheControllerFactoryInterface::class)->createCacheController($type, $options);
		}
		catch (\RuntimeException $e)
		{
			$type  = strtolower(preg_replace('/[^A-Z0-9_\.-]/i', '', $type));
			$class = 'JCacheController' . ucfirst($type);

			if (!class_exists($class))
			{
				// Search for the class file in the Cache include paths.
				$path = Path::find(self::addIncludePath(), strtolower($type) . '.php');

				if ($path !== false)
				{
					\JLoader::register($class, $path);
				}

				// The class should now be loaded
				if (!class_exists($class))
				{
					throw new \RuntimeException('Unable to load Cache Controller: ' . $type, 500);
				}

				// Only trigger a deprecation notice if the file and class are found
				@trigger_error(
					'Support for including cache controllers using path lookup is deprecated and will be removed in 5.0.'
					. ' Use a custom cache controller factory instead.',
					E_USER_DEPRECATED
				);
			}

			return new $class($options);
		}
	}

	/**
	 * Add a directory where Cache should search for controllers. You may either pass a string or an array of directories.
	 *
	 * @param   array|string  $path  A path to search.
	 *
	 * @return  array  An array with directory elements
	 *
	 * @since       1.7.0
	 * @deprecated  5.0 Use the cache controller factory instead
	 */
	public static function addIncludePath($path = '')
	{
		static $paths;

		if (!isset($paths))
		{
			$paths = array();
		}

		if (!empty($path) && !\in_array($path, $paths))
		{
			// Only trigger a deprecation notice when adding a lookup path
			@trigger_error(
				'Support for including cache controllers using path lookup is deprecated and will be removed in 5.0.'
				. ' Use a custom cache controller factory instead.',
				E_USER_DEPRECATED
			);

			array_unshift($paths, Path::clean($path));
		}

		return $paths;
	}
}
