Current File : /home/pacjaorg/wpt.pacja.org/cop/media/fef/script.fef.php |
<?php
/**
* Akeeba Frontend Framework (FEF)
*
* @package fef
* @copyright (c) 2017-2022 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU General Public License version 3, or later
*/
defined('_JEXEC') or die();
use Joomla\CMS\Date\Date as JDate;
use Joomla\CMS\Factory as JFactory;
use Joomla\CMS\Filesystem\File;
use Joomla\CMS\Filesystem\Folder;
use Joomla\CMS\Installer\Adapter\FileAdapter as JInstallerAdapterFile;
use Joomla\CMS\Installer\Installer as JInstaller;
use Joomla\CMS\Log\Log as JLog;
if (class_exists('file_fefInstallerScript'))
{
// WTAF?!
return;
}
/**
* Akeeba FEF Installation Script
*
* @noinspection PhpUnused
*/
class file_fefInstallerScript
{
/**
* The minimum PHP version required to install this extension
*
* @var string
*/
protected $minimumPHPVersion = '7.2.0';
/**
* The minimum Joomla! version required to install this extension
*
* @var string
*/
protected $minimumJoomlaVersion = '3.9.0';
/**
* The maximum Joomla! version this extension can be installed on
*
* @var string
*/
protected $maximumJoomlaVersion = '4.999.999';
/**
* Joomla! pre-flight event. This runs before Joomla! installs or updates the component. This is our last chance to
* tell Joomla! if it should abort the installation.
*
* @param string $type Installation type (install, update, discover_install)
* @param JInstaller|JInstallerAdapterFile $parent Parent object
*
* @return boolean True to let the installation proceed, false to halt the installation
*/
public function preflight($type, $parent)
{
// Do not run on uninstall.
if ($type === 'uninstall')
{
return true;
}
// Check the minimum PHP version
if (!empty($this->minimumPHPVersion))
{
if (defined('PHP_VERSION'))
{
$version = PHP_VERSION;
}
elseif (function_exists('phpversion'))
{
$version = phpversion();
}
else
{
$version = '5.0.0'; // all bets are off!
}
if (!version_compare($version, $this->minimumPHPVersion, 'ge'))
{
$msg = "<p>You need PHP $this->minimumPHPVersion or later to install this package but you are currently using PHP $version</p>";
JLog::add($msg, JLog::WARNING, 'jerror');
return false;
}
}
// Check the minimum Joomla! version
if (!empty($this->minimumJoomlaVersion) && !version_compare(JVERSION, $this->minimumJoomlaVersion, 'ge'))
{
$jVersion = JVERSION;
$msg = "<p>You need Joomla! $this->minimumJoomlaVersion or later to install this package but you only have $jVersion installed.</p>";
JLog::add($msg, JLog::WARNING, 'jerror');
return false;
}
// Check the maximum Joomla! version
if (!empty($this->maximumJoomlaVersion) && !version_compare(JVERSION, $this->maximumJoomlaVersion, 'le'))
{
$jVersion = JVERSION;
$msg = <<< HTML
<h3>FEF is no longer needed on Joomla 5</h3>
<p>
<strong>Summary: FEF is no longer used on Joomla 5. Please uninstall it.</strong>
</p>
<hr/>
<p>
Akeeba FEF a.k.a. the Akeeba Front-End Framework was a CSS and JavaScript framework used by Akeeba Ltd with the Joomla 3 versions of our software.
</p>
<p>
Akeeba Ltd has stopped using the FEF framework for developing extensions. All of our extensions have new, Joomla 4 and later native versions which use the Bootstrap library, included in Joomla itself.
</p>
<p>
You can no longer install or update FEF on Joomla 5.0 and later (you have {$jVersion}). In fact, you just need to uninstall it.
</p>
HTML;
JLog::add($msg, JLog::WARNING, 'jerror');
return false;
}
// In case of an update, discovery etc I need to check if I am an update
if (($type == 'update') && !$this->amIAnUpdate($parent))
{
$msg = "<p>You already have a newer version of Akeeba Frontend Framework installed. If you want to downgrade please uninstall Akeeba Frontend Framework and install the older version.</p><p>If you see this message during the installation or update of an Akeeba extension please ignore it <em>and</em> the immediately following “Files Install: Custom install routine failure” message. They are expected but Joomla! won't allow us to prevent them from showing up.</p>";
JLog::add($msg, JLog::WARNING, 'jerror');
return false;
}
// Delete obsolete font files and folders
if ($type == 'update')
{
// Use pathnames relative to your site's root
$removeFiles = [
'files' => [
// Non-WOFF fonts are not shipped as of 1.0.1 since all modern browsers we target use WOFF
'media/fef/fonts/akeeba/Akeeba-Products.eot',
'media/fef/fonts/akeeba/Akeeba-Products.svg',
'media/fef/fonts/akeeba/Akeeba-Products.ttf',
'media/fef/fonts/Ionicon/ionicons.eot',
'media/fef/fonts/Ionicon/ionicons.svg',
'media/fef/fonts/Ionicon/ionicons.ttf',
// Files renamed in 1.0.8
'css/reset.min.css',
'css/style.min.css',
// JavaScript: Irrelevant for Joomla
'js/darkmode.js',
'js/darkmode.min.js',
'js/darkmode.map',
'js/Darkmode.min.js',
'js/Darkmode.map',
'js/menu.js',
'js/menu.min.js',
'js/menu.map',
'js/Menu.min.js',
'js/Menu.map',
// JavaScript: Uncompressed and map files
'js/dropdown.js',
'js/dropdown.map',
'js/Dropdown.map',
'js/loader.js',
'js/loader.map',
'js/Loader.map',
'js/tabs.js',
'js/tabs.map',
'js/Tabs.map',
],
'folders' => [
],
];
// Remove obsolete files and folders
$this->removeFilesAndFolders($removeFiles);
}
return true;
}
/**
* Runs after install, update or discover_update. In other words, it executes after Joomla! has finished installing
* or updating your component. This is the last chance you've got to perform any additional installations, clean-up,
* database updates and similar housekeeping functions.
*
* @param string $type install, update or discover_update
* @param JInstallerAdapterFile $parent Parent object
*
* @throws Exception
*
* @noinspection PhpUnusedParameterInspection
*/
public function postflight($type, JInstallerAdapterFile $parent)
{
// Do not run on uninstall.
if ($type === 'uninstall')
{
return true;
}
// Auto-uninstall this package when it is no longer needed.
if (($type != 'install') && ($this->countHardcodedDependencies() === 0))
{
$this->uninstallSelf($parent);
return true;
}
$this->bugfixFilesNotCopiedOnUpdate($parent);
return true;
}
/**
* Runs on uninstallation
*
* @param JInstallerAdapterFile $parent The parent object
*
* @throws RuntimeException If the uninstallation is not allowed
*
* @noinspection PhpUnusedParameterInspection
*/
public function uninstall($parent)
{
if (version_compare(JVERSION, '4.1.0', 'ge'))
{
return false;
}
// Check dependencies on FEF
$dependencyCount = $this->countHardcodedDependencies();
if ($dependencyCount)
{
$msg = "<p>You have $dependencyCount extension(s) depending on Akeeba Frontend Framework. The package cannot be uninstalled unless these extensions are uninstalled first.</p>";
JLog::add($msg, JLog::WARNING, 'jerror');
throw new RuntimeException($msg, 500);
}
Folder::delete(JPATH_SITE . '/media/fef');
return true;
}
/**
* Removes obsolete files and folders
*
* @param array $removeList The files and directories to remove
*/
protected function removeFilesAndFolders($removeList)
{
// Remove files
if (isset($removeList['files']) && !empty($removeList['files']))
{
foreach ($removeList['files'] as $file)
{
$f = JPATH_ROOT . '/' . $file;
if (!is_file($f))
{
continue;
}
File::delete($f);
}
}
// Remove folders
if (isset($removeList['folders']) && !empty($removeList['folders']))
{
foreach ($removeList['folders'] as $folder)
{
$f = JPATH_ROOT . '/' . $folder;
if (!is_dir($f))
{
continue;
}
Folder::delete($f);
}
}
}
/**
* Is this package an update to the currently installed FEF? If not (we're a downgrade) we will return false
* and prevent the installation from going on.
*
* @param JInstallerAdapterFile $parent The parent object
*
* @return bool Am I an update to an existing version>
*/
protected function amIAnUpdate($parent)
{
$grandpa = $parent->getParent();
$source = $grandpa->getPath('source');
$target = JPATH_ROOT . '/media/fef';
if (!Folder::exists($source))
{
// WTF? I can't find myself. I can't install anything.
return false;
}
// If FEF is not really installed (someone removed the directory instead of uninstalling?) I have to install it.
if (!Folder::exists($target))
{
return true;
}
$fefVersion = [];
if (File::exists($target . '/version.txt'))
{
$rawData = @file_get_contents($target . '/version.txt');
$rawData = ($rawData === false) ? "0.0.0\n2011-01-01\n" : $rawData;
$info = explode("\n", $rawData);
$fefVersion['installed'] = [
'version' => trim($info[0]),
'date' => new JDate(trim($info[1])),
];
}
else
{
$fefVersion['installed'] = [
'version' => '0.0',
'date' => new JDate('2011-01-01'),
];
}
$rawData = @file_get_contents($source . '/version.txt');
$rawData = ($rawData === false) ? "0.0.0\n2011-01-01\n" : $rawData;
$info = explode("\n", $rawData);
$fefVersion['package'] = [
'version' => trim($info[0]),
'date' => new JDate(trim($info[1])),
];
return $fefVersion['package']['date']->toUNIX() >= $fefVersion['installed']['date']->toUNIX();
}
/**
* Fix for Joomla bug: sometimes files are not copied on update.
*
* We have observed that ever since Joomla! 1.5.5, when Joomla! is performing an extension update some files /
* folders are not copied properly. This seems to be a bit random and seems to be more likely to happen the more
* added / modified files and folders you have. We are trying to work around it by retrying the copy operation
* ourselves WITHOUT going through the manifest, based entirely on the conventions we follow.
*
* @param \Joomla\CMS\Installer\Adapter\FileAdapter $parent
*/
protected function bugfixFilesNotCopiedOnUpdate($parent)
{
$source = $parent->getParent()->getPath('source');
$target = JPATH_SITE . '/media/fef';
$this->recursiveConditionalCopy($source, $target);
}
/**
* Recursively copy a bunch of files, but only if the source and target file have a different size.
*
* @param string $source Path to copy FROM
* @param string $dest Path to copy TO
* @param array $ignored List of entries to ignore (first level entries are taken into account)
*
* @return void
*/
protected function recursiveConditionalCopy($source, $dest, $ignored = [])
{
// Make sure source and destination exist
if (!@is_dir($source))
{
return;
}
if (!@is_dir($dest))
{
if (!@mkdir($dest, 0755))
{
Folder::create($dest, 0755);
}
}
if (!@is_dir($dest))
{
// Cannot create folder $dest
return;
}
// List the contents of the source folder
try
{
$di = new DirectoryIterator($source);
}
catch (Exception $e)
{
return;
}
// Process each entry
foreach ($di as $entry)
{
// Ignore dot dirs (. and ..)
if ($entry->isDot())
{
continue;
}
$sourcePath = $entry->getPathname();
$fileName = $entry->getFilename();
// Do not copy ignored files
if (!empty($ignored) && in_array($fileName, $ignored))
{
continue;
}
// If it's a directory do a recursive copy
if ($entry->isDir())
{
$this->recursiveConditionalCopy($sourcePath, $dest . DIRECTORY_SEPARATOR . $fileName);
continue;
}
// If it's a file check if it's missing or identical
$mustCopy = false;
$targetPath = $dest . DIRECTORY_SEPARATOR . $fileName;
if (!@is_file($targetPath))
{
$mustCopy = true;
}
else
{
$sourceSize = @filesize($sourcePath);
$targetSize = @filesize($targetPath);
$mustCopy = $sourceSize != $targetSize;
if ((substr($targetPath, -4) === '.php') && function_exists('opcache_invalidate'))
{
opcache_invalidate($targetPath);
}
}
if (!$mustCopy)
{
continue;
}
if (!@copy($sourcePath, $targetPath))
{
File::copy($sourcePath, $targetPath);
}
}
}
/**
* Count the number of old FOF + FEF based extensions installed on this site
*
* @return int
*/
private function countHardcodedDependencies()
{
// Look for fof.xml in the backend directories of the following components
$hardcodedDependencies = [
'com_admintools',
'com_akeeba',
'com_ars',
'com_ats',
'com_compatibility',
'com_datacompliance',
'com_contactus',
'com_docimport',
'com_loginguard',
];
$count = 0;
foreach ($hardcodedDependencies as $component)
{
$filePath = JPATH_ADMINISTRATOR . '/components/' . $component . '/fof.xml';
if (@file_exists($filePath))
{
$count++;
}
}
return $count;
}
/**
* Uninstall this package.
*
* This runs on update when there are no more dependencies left.
*
* @param \Joomla\CMS\Installer\Adapter\FileAdapter $adapter
*
* @return void
*/
private function uninstallSelf($adapter)
{
$parent = $adapter->getParent();
if (empty($parent) || !property_exists($parent, 'extension'))
{
return;
}
if (version_compare(JVERSION, '4.0', 'lt'))
{
$db = \Joomla\CMS\Factory::getDbo();
}
else
{
$db = \Joomla\CMS\Factory::getContainer()->get('DatabaseDriver');
}
try
{
$query = $db->getQuery(true)
->select($db->quoteName('extension_id'))
->from($db->quoteName('#__extensions'))
->where($db->quoteName('type') . ' = ' . $db->quote('file'))
->where($db->quoteName('name') . ' = ' . $db->quote('file_fef'));
$id = $db->setQuery($query)->loadResult();
}
catch (Exception $e)
{
return;
}
if (empty($id))
{
return;
}
$msg = 'Automatically uninstalling FEF; this package is no longer required on your site.';
\Joomla\CMS\Log\Log::add($msg, \Joomla\CMS\Log\Log::INFO, 'jerror');
$parent->uninstall('file', $id);
}
}