216 lines
4.8 KiB
PHP
216 lines
4.8 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\Utils;
|
|
|
|
defined('_JEXEC') || die;
|
|
|
|
use Exception;
|
|
use FOF30\Container\Container;
|
|
use JDatabaseDriver;
|
|
use Joomla\CMS\Factory;
|
|
use Joomla\Registry\Registry;
|
|
|
|
/**
|
|
* Class MediaVersion
|
|
* @package FOF30\Utils
|
|
*
|
|
* @since 3.5.3
|
|
*/
|
|
class MediaVersion
|
|
{
|
|
/**
|
|
* Cached the version and date of FOF-powered components
|
|
*
|
|
* @var array
|
|
* @since 3.5.3
|
|
*/
|
|
protected static $componentVersionCache = [];
|
|
|
|
/**
|
|
* The current component's container
|
|
*
|
|
* @var Container
|
|
* @since 3.5.3
|
|
*/
|
|
protected $container;
|
|
|
|
/**
|
|
* The configured media query version
|
|
*
|
|
* @var string|null;
|
|
* @since 3.5.3
|
|
*/
|
|
protected $mediaVersion;
|
|
|
|
/**
|
|
* MediaVersion constructor.
|
|
*
|
|
* @param Container $c The component container
|
|
*
|
|
* @since 3.5.3
|
|
*/
|
|
public function __construct(Container $c)
|
|
{
|
|
$this->container = $c;
|
|
}
|
|
|
|
/**
|
|
* Get a component's version and date
|
|
*
|
|
* @param string $component
|
|
* @param JDatabaseDriver $db
|
|
*
|
|
* @return array
|
|
* @since 3.5.3
|
|
*/
|
|
protected static function getComponentVersionAndDate($component, $db)
|
|
{
|
|
if (array_key_exists($component, self::$componentVersionCache))
|
|
{
|
|
return self::$componentVersionCache[$component];
|
|
}
|
|
|
|
$version = '0.0.0';
|
|
$date = date('Y-m-d H:i:s');
|
|
|
|
try
|
|
{
|
|
$query = $db->getQuery(true)
|
|
->select([
|
|
$db->qn('manifest_cache'),
|
|
])->from($db->qn('#__extensions'))
|
|
->where($db->qn('type') . ' = ' . $db->q('component'))
|
|
->where($db->qn('name') . ' = ' . $db->q($component));
|
|
|
|
$db->setQuery($query);
|
|
|
|
$json = $db->loadResult();
|
|
|
|
if (class_exists('JRegistry'))
|
|
{
|
|
$params = new Registry($json);
|
|
}
|
|
else
|
|
{
|
|
$params = new Registry($json);
|
|
}
|
|
|
|
$version = $params->get('version', $version);
|
|
$date = $params->get('creationDate', $date);
|
|
}
|
|
catch (Exception $e)
|
|
{
|
|
}
|
|
|
|
self::$componentVersionCache[$component] = [$version, $date];
|
|
|
|
return self::$componentVersionCache[$component];
|
|
}
|
|
|
|
/**
|
|
* Serialization helper
|
|
*
|
|
* This is for the benefit of legacy components which might use Joomla's JS/CSS inclusion directly passing
|
|
* $container->mediaVersion as the version argument. In FOF 3.5.2 and lower that was always string or null, making
|
|
* it a safe bet. In FOF 3.5.3 and later it's an object. It's not converted to a string until Joomla builds its
|
|
* template header. However, Joomla's cache system will try to serialize all CSS and JS definitions, including their
|
|
* parameters of which version is one. Therefore, for those legacy applications, Joomla would be trying to serialize
|
|
* the MediaVersion object which would try to serialize the container. That would cause an immediate failure since
|
|
* we protect the Container from being serialized.
|
|
*
|
|
* Our Template service knows about this and stringifies the MediaVersion before passing it to Joomla. Legacy apps
|
|
* may not do that. Using the __sleep and __wakeup methods in this class we make sure that we are essentially
|
|
* storing nothing but strings in the serialized representation and we reconstruct the container upon
|
|
* unseralization. That said, it's a good idea to use the Template service instead of $container->mediaVersion
|
|
* directly or, at the very least, use (string) $container->mediaVersion when using the Template service is not a
|
|
* viable option.
|
|
*
|
|
* @return string[]
|
|
*/
|
|
public function __sleep()
|
|
{
|
|
$this->componentName = $this->container->componentName;
|
|
|
|
return [
|
|
'mediaVersion',
|
|
'componentName',
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Unserialization helper
|
|
*
|
|
* @return void
|
|
* @see __sleep
|
|
*/
|
|
public function __wakeup()
|
|
{
|
|
if (isset($this->componentName))
|
|
{
|
|
$this->container = Container::getInstance($this->componentName);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns the media query version string
|
|
*
|
|
* @return string
|
|
* @since 3.5.3
|
|
*/
|
|
public function __toString()
|
|
{
|
|
if (empty($this->mediaVersion))
|
|
{
|
|
$this->mediaVersion = $this->getDefaultMediaVersion();
|
|
}
|
|
|
|
return $this->mediaVersion;
|
|
}
|
|
|
|
/**
|
|
* Sets the media query version string
|
|
*
|
|
* @param mixed $mediaVersion
|
|
*
|
|
* @since 3.5.3
|
|
*/
|
|
public function setMediaVersion($mediaVersion)
|
|
{
|
|
$this->mediaVersion = $mediaVersion;
|
|
}
|
|
|
|
/**
|
|
* Returns the default media query version string if none is already defined
|
|
*
|
|
* @return string
|
|
* @since 3.5.3
|
|
*/
|
|
protected function getDefaultMediaVersion()
|
|
{
|
|
// Initialise
|
|
[$version, $date] = self::getComponentVersionAndDate($this->container->componentName, $this->container->db);
|
|
|
|
// Get the site's secret
|
|
try
|
|
{
|
|
$app = Factory::getApplication();
|
|
|
|
if (method_exists($app, 'get'))
|
|
{
|
|
$secret = $app->get('secret');
|
|
}
|
|
}
|
|
catch (Exception $e)
|
|
{
|
|
}
|
|
|
|
// Generate the version string
|
|
return md5($version . $date . $secret);
|
|
}
|
|
}
|