Файловый менеджер - Редактировать - /home/wuectly/www/03cbe/fof40.zip
Назад
PK gi"]��` ` Cli/Joomla4.phpnu &1i� <?php /** * @package FOF * @copyright Copyright (c)2010-2022 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ // Do not put the JEXEC or die check on this file use FOF40\Cli\Traits\CGIModeAware; use FOF40\Cli\Traits\CustomOptionsAware; use FOF40\Cli\Traits\JoomlaConfigAware; use FOF40\Cli\Traits\MemStatsAware; use FOF40\Cli\Traits\TimeAgoAware; use Joomla\CMS\Application\CliApplication; use Joomla\CMS\Application\ExtensionNamespaceMapper; use Joomla\CMS\Factory; use Joomla\Event\Dispatcher; use Joomla\Registry\Registry; use Joomla\Session\SessionInterface; /** * Load the legacy Joomla! include files * * Despite Joomla complaining about it with an E_DEPRECATED notice, if you use bootstrap.php instead of * import.legacy.php you get an HTML error page (yes, under CLI!) which is kinda daft. */ if (function_exists('error_reporting')) { $oldErrorReporting = @error_reporting(E_ERROR | E_NOTICE | E_DEPRECATED); } include_once JPATH_LIBRARIES . '/import.legacy.php'; if (function_exists('error_reporting')) { @error_reporting($oldErrorReporting); } // Load the Framework (J4 beta 1 and later) or CMS import file (J4 a12 and lower) $cmsImportFilePath = JPATH_BASE . '/includes/framework.php'; $cmsImportFilePathOld = JPATH_LIBRARIES . '/cms.php'; if (@file_exists($cmsImportFilePath)) { @include_once $cmsImportFilePath; // Boot the DI container $container = \Joomla\CMS\Factory::getContainer(); /* * Alias the session service keys to the CLI session service as that is the primary session backend for this application * * In addition to aliasing "common" service keys, we also create aliases for the PHP classes to ensure autowiring objects * is supported. This includes aliases for aliased class names, and the keys for aliased class names should be considered * deprecated to be removed when the class name alias is removed as well. */ $container->alias('session', 'session.cli') ->alias('JSession', 'session.cli') ->alias(\Joomla\CMS\Session\Session::class, 'session.cli') ->alias(\Joomla\Session\Session::class, 'session.cli') ->alias(\Joomla\Session\SessionInterface::class, 'session.cli'); } elseif (@file_exists($cmsImportFilePathOld)) { @include_once $cmsImportFilePathOld; } /** * Base class for a Joomla! command line application. Adapted from JCli / JApplicationCli */ abstract class FOFCliApplicationJoomla4 extends CliApplication { use CGIModeAware, CustomOptionsAware, JoomlaConfigAware, MemStatsAware, TimeAgoAware, ExtensionNamespaceMapper; private $allowedToClose = false; public static function getInstance($name = null) { $instance = parent::getInstance($name); Factory::$application = $instance; /** * Load FOF. * * In Joomla 4 this must happen after we have set up the application in the factory because Factory::getLanguage * goes through the application object to retrieve the configuration. */ if (!defined('FOF40_INCLUDED') && !@include_once(JPATH_LIBRARIES . '/fof40/include.php')) { throw new RuntimeException('Cannot load FOF', 500); } return $instance; } public function __construct(\Joomla\Input\Input $input = null, Registry $config = null, \Joomla\CMS\Application\CLI\CliOutput $output = null, \Joomla\CMS\Application\CLI\CliInput $cliInput = null, \Joomla\Event\DispatcherInterface $dispatcher = null, \Joomla\DI\Container $container = null) { // Some servers only provide a CGI executable. While not ideal for running CLI applications we can make do. $this->detectAndWorkAroundCGIMode(); // We need to tell Joomla to register its default namespace conventions $this->createExtensionNamespaceMap(); // Initialize custom options handling which is a bit more straightforward than Input\Cli. $this->initialiseCustomOptions(); // Default configuration: Joomla Global Configuration if (empty($config)) { $config = new Registry($this->fetchConfigurationData()); } if (empty($dispatcher)) { $dispatcher = new Dispatcher(); } parent::__construct($input, $config, $output, $cliInput, $dispatcher, $container); /** * Allow the application to close. * * This is required to allow CliApplication to execute under CGI mode. The checks performed in the parent * constructor will call close() if the application does not run pure CLI mode. However, some hosts only provide * the PHP CGI binary for executing CLI scripts. While wrong it will work in most cases. By default close() will * do nothing, thereby allowing the parent constructor to call it without a problem. Finally, we set this flag * to true to allow doExecute() to call close() and actually close the application properly. Yeehaw! */ $this->allowedToClose = true; } /** * Method to close the application. * * See the constructor for details on why it works the way it works. * * @param integer $code The exit code (optional; default is 0). * * @return void * * @codeCoverageIgnore * @since 1.0 */ public function close($code = 0) { // See the constructor for details if (!$this->allowedToClose) { return; } exit($code); } /** * Gets the name of the current running application. * * @return string The name of the application. * * @since 4.0.0 */ public function getName() { return get_class($this); } /** * Get the menu object. * * @param string $name The application name for the menu * @param array $options An array of options to initialise the menu with * * @return \Joomla\CMS\Menu\AbstractMenu|null A AbstractMenu object or null if not set. * * @since 4.0.0 */ public function getMenu($name = null, $options = []) { return null; } /** * Method to get the application session object. * * @return SessionInterface The session object * * @since 4.0.0 */ public function getSession() { return $this->getContainer()->get('session.cli'); } } PK gi"]�t$�9 9 Cli/Joomla3.phpnu &1i� <?php /** * @package FOF * @copyright Copyright (c)2010-2022 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ // Do not put the JEXEC or die check on this file use FOF40\Cli\Traits\CGIModeAware; use FOF40\Cli\Traits\CustomOptionsAware; use FOF40\Cli\Traits\JoomlaConfigAware; use FOF40\Cli\Traits\MemStatsAware; use FOF40\Cli\Traits\MessageAware; use FOF40\Cli\Traits\TimeAgoAware; use FOF40\Utils\CliSessionHandler; use Joomla\CMS\Application\CliApplication; use Joomla\CMS\Input\Cli; // Load the legacy Joomla! include files (Joomla! 3 only) include_once JPATH_LIBRARIES . '/import.legacy.php'; // Load the CMS import file if it exists (newer Joomla! 3 versions and Joomla! 4) $cmsImportFilePath = JPATH_LIBRARIES . '/cms.php'; if (@file_exists($cmsImportFilePath)) { @include_once $cmsImportFilePath; } /** * Base class for a Joomla! command line application. Adapted from JCli / JApplicationCli */ abstract class FOFCliApplicationJoomla3 extends CliApplication { use CGIModeAware, CustomOptionsAware, JoomlaConfigAware, MemStatsAware, MessageAware, TimeAgoAware; private $allowedToClose = false; public static function getInstance($name = null) { // Load the Joomla global configuration in JFactory. This must happen BEFORE loading FOF. JFactory::getConfig(JPATH_CONFIGURATION . '/configuration.php'); // Load FOF if (!defined('FOF40_INCLUDED') && !@include_once(JPATH_LIBRARIES . '/fof40/include.php')) { throw new RuntimeException('Cannot load FOF', 500); } // Create a CLI-specific session JFactory::$session = JSession::getInstance('none', [ 'expire' => 84400, ], new CliSessionHandler()); $instance = parent::getInstance($name); JFactory::$application = $instance; return $instance; } public function __construct(Cli $input = null, \Joomla\Registry\Registry $config = null, \JEventDispatcher $dispatcher = null) { // Some servers only provide a CGI executable. While not ideal for running CLI applications we can make do. $this->detectAndWorkAroundCGIMode(); // Initialize custom options handling which is a bit more straightforward than Input\Cli. $this->initialiseCustomOptions(); parent::__construct($input, $config, $dispatcher); /** * Allow the application to close. * * This is required to allow CliApplication to execute under CGI mode. The checks performed in the parent * constructor will call close() if the application does not run pure CLI mode. However, some hosts only provide * the PHP CGI binary for executing CLI scripts. While wrong it will work in most cases. By default close() will * do nothing, thereby allowing the parent constructor to call it without a problem. Finally, we set this flag * to true to allow doExecute() to call close() and actually close the application properly. Yeehaw! */ $this->allowedToClose = true; } /** * Method to close the application. * * See the constructor for details on why it works the way it works. * * @param integer $code The exit code (optional; default is 0). * * @return void * * @codeCoverageIgnore * @since 1.0 */ public function close($code = 0) { // See the constructor for details if (!$this->allowedToClose) { return; } exit($code); } /** * Gets the name of the current running application. * * @return string The name of the application. * * @since 4.0.0 */ public function getName() { return get_class($this); } /** * Get the menu object. * * @param string $name The application name for the menu * @param array $options An array of options to initialise the menu with * * @return \Joomla\CMS\Menu\AbstractMenu|null A AbstractMenu object or null if not set. * * @since 4.0.0 */ public function getMenu($name = null, $options = []) { return null; } } PK gi"]�d�� � Cli/Traits/CGIModeAware.phpnu &1i� <?php /** * @package FOF * @copyright Copyright (c)2010-2022 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace FOF40\Cli\Traits; defined('_JEXEC') || die; /** * CGI Mode detection and workaround * * Some hosts only give access to the PHP CGI binary, even for running CLI scripts. While problematic, it mostly works. * This trait detects PHP-CGI and manipulates $_GET in such a way that we populate the $argv and $argc global variables * in the same way that PHP-CLI would set them. This allows the CLI input object to work. Moreover, we unset the PHP * execution time limit, if possible, to prevent accidental timeouts. * * @package FOF40\Cli\Traits */ trait CGIModeAware { /** * Detect if we are running under CGI mode. In this case it populates the global $argv and $argc parameters off the * CGI input ($_GET superglobal). */ private function detectAndWorkAroundCGIMode() { // This code only executes when running under CGI. So let's detect it first. $cgiMode = (!defined('STDOUT') || !defined('STDIN') || !isset($_SERVER['argv'])); if (!$cgiMode) { return; } // CGI mode has a time limit. Unset it to prevent timeouts. if (function_exists('set_time_limit')) { set_time_limit(0); } // Convert $_GET into the appropriate $argv representation. This allows Input\Cli to work under PHP-CGI. $query = ""; if (!empty($_GET)) { foreach ($_GET as $k => $v) { $query .= " $k"; if ($v != "") { $query .= "=$v"; } } } $query = ltrim($query); global $argv, $argc; $argv = explode(' ', $query); $argc = count($argv); $_SERVER['argv'] = $argv; } }PK gi"]�Ĺe Cli/Traits/TimeAgoAware.phpnu &1i� <?php /** * @package FOF * @copyright Copyright (c)2010-2022 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace FOF40\Cli\Traits; defined('_JEXEC') || die; /** * Allows the developer to show the relative time difference between two timestamps. * * @package FOF40\Cli\Traits */ trait TimeAgoAware { /** * Returns the relative time difference between two timestamps in a human readable format * * @param int $referenceTimestamp Timestamp of the reference date/time * @param int|null $currentTimestamp Timestamp of the current date/time. Null for time(). * @param string $timeUnit Time unit. One of s, m, h, d, or y. * @param bool $autoSuffix Add "ago" / "from now" suffix? * * @return string For example, "10 seconds ago" */ protected function timeAgo($referenceTimestamp = 0, $currentTimestamp = null, $timeUnit = '', $autoSuffix = true) { if (is_null($currentTimestamp)) { $currentTimestamp = time(); } // Raw time difference $raw = $currentTimestamp - $referenceTimestamp; $clean = abs($raw); $calcNum = [ ['s', 60], ['m', 60 * 60], ['h', 60 * 60 * 60], ['d', 60 * 60 * 60 * 24], ['y', 60 * 60 * 60 * 24 * 365], ]; $calc = [ 's' => [1, 'second'], 'm' => [60, 'minute'], 'h' => [60 * 60, 'hour'], 'd' => [60 * 60 * 24, 'day'], 'y' => [60 * 60 * 24 * 365, 'year'], ]; $effectiveTimeUnit = $timeUnit; if ($timeUnit == '') { $effectiveTimeUnit = 's'; for ($i = 0; $i < count($calcNum); $i++) { if ($clean <= $calcNum[$i][1]) { $effectiveTimeUnit = $calcNum[$i][0]; $i = count($calcNum); } } } $timeDifference = floor($clean / $calc[$effectiveTimeUnit][0]); $textSuffix = ''; if ($autoSuffix == true && ($currentTimestamp == time())) { if ($raw < 0) { $textSuffix = ' from now'; } else { $textSuffix = ' ago'; } } if ($referenceTimestamp != 0) { if ($timeDifference == 1) { return $timeDifference . ' ' . $calc[$effectiveTimeUnit][1] . ' ' . $textSuffix; } return $timeDifference . ' ' . $calc[$effectiveTimeUnit][1] . 's ' . $textSuffix; } return '(no reference timestamp was provided).'; } }PK gi"]��,v� � Cli/Traits/MessageAware.phpnu &1i� <?php /** * @package FOF * @copyright Copyright (c)2010-2022 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace FOF40\Cli\Traits; defined('_JEXEC') || die; /** * Sometimes other extensions will try to enqueue messages to the application. Methods for those tasks only exists in * web applications, so we have to replicate their behavior in CLI environment or fatal errors will occur * * @package FOF40\Cli\Traits */ trait MessageAware { /** @var array Queue holding all messages */ protected $messageQueue = []; /** * @param $msg * @param $type * * @return void */ public function enqueueMessage($msg, $type) { // Don't add empty messages. if (trim($msg) === '') { return; } $message = ['message' => $msg, 'type' => strtolower($type)]; if (!in_array($message, $this->messageQueue)) { // Enqueue the message. $this->messageQueue[] = $message; } } /** * Loosely based on Joomla getMessageQueue * * @param bool $clear * * @return array */ public function getMessageQueue($clear = false) { $messageQueue = $this->messageQueue; if ($clear) { $this->messageQueue = []; } return $messageQueue; } } PK gi"]9�վ� � Cli/Traits/MemStatsAware.phpnu &1i� <?php /** * @package FOF * @copyright Copyright (c)2010-2022 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace FOF40\Cli\Traits; defined('_JEXEC') || die; /** * Memory statistics * * This is an optional trait which allows the developer to print memory usage statistics and format byte sizes into * human-readable strings. * * @package FOF40\Cli\Traits */ trait MemStatsAware { /** * Formats a number of bytes in human readable format * * @param int $size The size in bytes to format, e.g. 8254862 * * @return string The human-readable representation of the byte size, e.g. "7.87 Mb" */ protected function formatByteSize($size) { $unit = ['b', 'KB', 'MB', 'GB', 'TB', 'PB']; return @round($size / pow(1024, ($i = floor(log($size, 1024)))), 2) . ' ' . $unit[$i]; } /** * Returns the current memory usage, formatted * * @return string */ protected function memUsage() { if (function_exists('memory_get_usage')) { $size = memory_get_usage(); return $this->formatByteSize($size); } else { return "(unknown)"; } } /** * Returns the peak memory usage, formatted * * @return string */ protected function peakMemUsage() { if (function_exists('memory_get_peak_usage')) { $size = memory_get_peak_usage(); return $this->formatByteSize($size); } else { return "(unknown)"; } } }PK gi"]u�^� � ! Cli/Traits/CustomOptionsAware.phpnu &1i� <?php /** * @package FOF * @copyright Copyright (c)2010-2022 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace FOF40\Cli\Traits; defined('_JEXEC') || die; use JFilterInput; use Joomla\CMS\Filter\InputFilter; /** * Implements a simpler, more straightforward options parser than the Joomla CLI input object. It supports short options * when the Joomla CLI input object doesn't. Eventually this will go away and we can use something like Symfony Console * instead. * * @package FOF40\Cli\Traits */ trait CustomOptionsAware { /** * POSIX-style CLI options. Access them with through the getOption method. * * @var array */ protected static $cliOptions = []; /** * Filter object to use for custom options parsing. * * @var JFilterInput|InputFilter */ protected $filter = null; /** * Initializes the custom CLI options parsing * * @return void */ protected function initialiseCustomOptions() { // Create a new JFilterInput if (class_exists('JFilterInput')) { $this->filter = JFilterInput::getInstance(); } else { $this->filter = InputFilter::getInstance(); } // Parse the POSIX options $this->parseOptions(); } /** * Parses POSIX command line options and sets the self::$cliOptions associative array. Each array item contains * a single dimensional array of values. Arguments without a dash are silently ignored. * * This works much better than JInputCli since it allows you to use all valid POSIX ways of defining CLI parameters. * * @return void */ protected function parseOptions() { global $argc, $argv; // Workaround for PHP-CGI if (!isset($argc) && !isset($argv)) { $query = ""; if (!empty($_GET)) { foreach ($_GET as $k => $v) { $query .= " $k"; if ($v != "") { $query .= "=$v"; } } } $query = ltrim($query); $argv = explode(' ', $query); $argc = count($argv); } $currentName = ""; $options = []; for ($i = 1; $i < $argc; $i++) { $argument = $argv[$i]; $value = $argument; if (strpos($argument, "-") === 0) { $argument = ltrim($argument, '-'); $name = $argument; $value = null; if (strstr($argument, '=')) { list($name, $value) = explode('=', $argument, 2); } $currentName = $name; if (!isset($options[$currentName]) || ($options[$currentName] == null)) { $options[$currentName] = []; } } if ((!is_null($value)) && (!is_null($currentName))) { $key = null; if (strstr($value, '=')) { $parts = explode('=', $value, 2); $key = $parts[0]; $value = $parts[1]; } $values = $options[$currentName]; if (is_null($values)) { $values = []; } if (is_null($key)) { array_push($values, $value); } else { $values[$key] = $value; } $options[$currentName] = $values; } } self::$cliOptions = $options; } /** * Returns the value of a command line option. This does NOT use JInputCLI. You MUST run parseOptions before. * * @param string $key The full name of the option, e.g. "foobar" * @param mixed $default The default value to return * @param string $type Joomla! filter type, e.g. cmd, int, bool and so on. * * @return mixed The value of the option */ protected function getOption($key, $default = null, $type = 'raw') { // If the key doesn't exist set it to the default value if (!array_key_exists($key, self::$cliOptions)) { self::$cliOptions[$key] = is_array($default) ? $default : [$default]; } $type = strtolower($type); if ($type == 'array') { return self::$cliOptions[$key]; } $value = null; if (!empty(self::$cliOptions[$key])) { $value = self::$cliOptions[$key][0]; } return $this->filterVariable($value, $type); } /** * Filter a variable using JInputFilter * * @param mixed $var The variable to filter * @param string $type The filter type, default 'cmd' * * @return mixed The filtered value */ protected function filterVariable($var, $type = 'cmd') { return $this->filter->clean($var, $type); } }PK gi"]�x)�~ ~ Cli/Traits/JoomlaConfigAware.phpnu &1i� <?php /** * @package FOF * @copyright Copyright (c)2010-2022 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace FOF40\Cli\Traits; defined('_JEXEC') || die; /** * Allows the CLI application to use the Joomla Global Configuration parameters as its own configuration. * * @package FOF40\Cli\Traits */ trait JoomlaConfigAware { /** * Method to load the application configuration, returning it as an object or array * * This can be overridden in subclasses if you don't want to fetch config from a PHP class file. * * @param string|null $file The filepath to the file containing the configuration class. Default: Joomla's * configuration.php * @param string $className The name of the PHP class holding the configuration. Default: JConfig * * @return mixed Either an array or object to be loaded into the configuration object. */ protected function fetchConfigurationData($file = null, $className = 'JConfig') { // Set the configuration file name. if (empty($file)) { $file = JPATH_BASE . '/configuration.php'; } // Import the configuration file. if (!is_file($file)) { return []; } include_once $file; // Instantiate the configuration object. if (!class_exists('JConfig')) { return []; } return new $className(); } }PK gi"]P�� Cli/wrong_php.phpnu &1i� <?php /** * @package FOF * @copyright Copyright (c)2010-2022 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ /** @var string $minphp */ if (!isset($minphp)) { die; } ?> ================================================================================ WARNING! Incompatible PHP version <?php echo PHP_VERSION ?> (required: <?php echo $minphp ?> or later) ================================================================================ This script must be run using PHP version <?php echo $minphp ?> or later. Your server is currently using a much older version which would cause this script to crash. As a result we have aborted execution of the script. Please contact your host and ask them for the correct path to the PHP CLI binary for PHP <?php echo $minphp ?> or later, then edit your CRON job and replace your current path to PHP with the one your host gave you. For your information, the current PHP version information is as follows. PATH: <?php echo PHP_BINDIR ?> VERSION: <?php echo PHP_VERSION ?> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ IMPORTANT! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PHP version numbers are NOT decimals! Trailing zeros do matter. For example, PHP 5.3.28 is twenty four versions newer (greater than) than PHP 5.3.4. Please consult https://www.akeeba.com/how-do-version-numbers-work.html Further clarifications: 1. There is no possible way that you are receiving this message in error. We are using the PHP_VERSION constant to detect the PHP version you are currently using. This is what PHP itself reports as its own version. It simply cannot lie. 2. Even though your *site* may be running in a higher PHP version that the one reported above, your CRON scripts will most likely not be running under it. This has to do with the fact that your site DOES NOT run under the command line and there are different executable files (binaries) for the web and command line versions of PHP. 3. Please note that we cannot provide support about this error as the solution depends only on your server setup. The only people who know how your server is set up are your host's technicians. Therefore we can only advise you to contact your host and request them the correct path to the PHP CLI binary. Let us stress out that only your host knows and can give this information to you. 4. The latest published versions of PHP can be found at http://www.php.net/ Any older version is considered insecure and must not be used on a production site. If your server uses a much older version of PHP than those published in the URL above please notify your host that their servers are insecure and in need of an update. This script will now terminate. Goodbye. PK gi"]V�uT�$ �$ Cli/Application.phpnu &1i� <?php /** * @package FOF * @copyright Copyright (c)2010-2022 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ // Do not put the JEXEC or die check on this file /** * FOF-powered Joomla! CLI application implementation. * * Get all the power of Joomla in CLI without all the awkward decisions which make CLI scripts fail on many common, * commercial hosting environments. We've been doing that in our software before Joomla got CLI support. We know of all * the pitfalls and this little gem here will work around most of them (or at least fail gracefully). * * Your CLI script must begin with the following boilerplate code: * * // Boilerplate -- START * define('_JEXEC', 1); * * foreach ([__DIR__, getcwd()] as $curdir) * { * if (file_exists($curdir . '/defines.php')) * { * define('JPATH_BASE', realpath($curdir . '/..')); * require_once $curdir . '/defines.php'; * * break; * } * * if (file_exists($curdir . '/../includes/defines.php')) * { * define('JPATH_BASE', realpath($curdir . '/..')); * require_once $curdir . '/../includes/defines.php'; * * break; * } * } * * defined('JPATH_LIBRARIES') || die ('This script must be placed in or run from the cli folder of your site.'); * * require_once JPATH_LIBRARIES . '/fof40/Cli/Application.php'; * // Boilerplate -- END * * Create a class which extends FOFCliApplication and implements doExecute, e.g. * * // Class definition -- START * class YourClassName extends FOFCliApplication * { * protected function doExecute() * { * // Do something useful * } * } * // Class definition -- END * * Finally, execute your script with: * * // Execute script -- START * FOFCliApplication::getInstance('YourClassName')->execute(); * // Execute script -- END * * You can optionally define $minphp before the boilerplate code to enforce a different minimum PHP version. */ // Abort immediately when this file is executed from a web SAPI if (array_key_exists('REQUEST_METHOD', $_SERVER)) { die('This is a command line script. You are not allowed to access it over the web.'); } // Work around some badly configured servers which print out notices if (function_exists('error_reporting')) { $oldLevel = error_reporting(E_ERROR | E_NOTICE | E_DEPRECATED); } // Minimum PHP version check if (!isset($minphp)) { $minphp = '5.6.0'; } if (version_compare(PHP_VERSION, $minphp, 'lt')) { require_once __DIR__ . '/wrong_php.php'; die; } // Required by scripts written for old Joomla! versions. define('DS', DIRECTORY_SEPARATOR); /** * Timezone fix * * This piece of code was originally put here because some PHP 5.3 servers forgot to declare a default timezone. * Unfortunately it's still required because some hosts STILL forget to provide a timezone in their php.ini files or, * worse, use invalid timezone names. */ if (function_exists('date_default_timezone_get') && function_exists('date_default_timezone_set')) { $serverTimezone = @date_default_timezone_get(); // Do I have no timezone set? if (empty($serverTimezone) || !is_string($serverTimezone)) { $serverTimezone = 'UTC'; } // Do I have an invalid timezone? try { $testTimeZone = new DateTimeZone($serverTimezone); } catch (\Exception $e) { $serverTimezone = 'UTC'; } // Set the default timezone to a correct thing @date_default_timezone_set($serverTimezone); } // This is not necessary if you have used the boilerplate code. if (!isset($curdir) && !defined('JPATH_ROOT')) { foreach ([__DIR__ . '/../../../cli', getcwd()] as $curdir) { if (file_exists($curdir . '/defines.php')) { define('JPATH_BASE', realpath($curdir . '/..')); require_once $curdir . '/defines.php'; break; } if (file_exists($curdir . '/../includes/defines.php')) { define('JPATH_BASE', realpath($curdir . '/..')); require_once $curdir . '/../includes/defines.php'; break; } } defined('JPATH_LIBRARIES') || die ('This script must be placed in or run from the cli folder of your site.'); } // Restore the error reporting before importing Joomla core code if (function_exists('error_reporting')) { error_reporting($oldLevel); } // Awkward Joomla version detection before we can actually load Joomla! itself $joomlaMajorVersion = 3; $joomlaMinorVersion = 0; $jVersionFile = JPATH_LIBRARIES . '/src/Version.php'; if ($versionFileContents = @file_get_contents($jVersionFile)) { preg_match("/MAJOR_VERSION\s*=\s*(\d*)\s*;/", $versionFileContents, $versionMatches); $joomlaMajorVersion = (int) $versionMatches[1]; preg_match("/MINOR_VERSION\s*=\s*(\d*)\s*;/", $versionFileContents, $versionMatches); $joomlaMinorVersion = (int) $versionMatches[1]; } // Load the Trait files include_once __DIR__ . '/Traits/CGIModeAware.php'; include_once __DIR__ . '/Traits/CustomOptionsAware.php'; include_once __DIR__ . '/Traits/JoomlaConfigAware.php'; include_once __DIR__ . '/Traits/MemStatsAware.php'; include_once __DIR__ . '/Traits/MessageAware.php'; include_once __DIR__ . '/Traits/TimeAgoAware.php'; // The actual implementation of the CliApplication depends on the Joomla version we're running under switch ($joomlaMajorVersion) { case 3: default: require_once __DIR__ . '/Joomla3.php'; abstract class FOFApplicationCLI extends FOFCliApplicationJoomla3 { } ; break; case 4: require_once __DIR__ . '/Joomla4.php'; abstract class FOFApplicationCLI extends FOFCliApplicationJoomla4 { } ; break; } /** * A default exception handler. Catches all unhandled exceptions, displays debug information about them and sets the * error level to 254. * * @param Throwable $ex The Exception / Error being handled */ function FOFCliExceptionHandler($ex) { echo "\n\n"; echo "********** ERROR! **********\n\n"; echo $ex->getMessage(); echo "\n\nTechnical information:\n\n"; echo "Code: " . $ex->getCode() . "\n"; echo "File: " . $ex->getFile() . "\n"; echo "Line: " . $ex->getLine() . "\n"; echo "\nStack Trace:\n\n" . $ex->getTraceAsString(); echo "\n\n"; exit(254); } /** * Timeout handler * * This function is registered as a shutdown script. If a catchable timeout occurs it will detect it and print a helpful * error message instead of just dying cold. The error level is set to 253 in this case. * * @return void */ function FOFCliTimeoutHandler() { $connection_status = connection_status(); if ($connection_status == 0) { // Normal script termination, do not report an error. return; } echo "\n\n"; echo "********** ERROR! **********\n\n"; if ($connection_status == 1) { echo <<< END The process was aborted on user's request. This usually means that you pressed CTRL-C to terminate the script (if you're running it from a terminal / SSH session), or that your host's CRON daemon aborted the execution of this script. If you are running this script through a CRON job and saw this message, please contact your host and request an increase in the timeout limit for CRON jobs. Moreover you need to ask them to increase the max_execution_time in the php.ini file or, even better, set it to 0. END; } else { echo <<< END This script has timed out. As a result, the process has FAILED to complete. Your host applies a maximum execution time for CRON jobs which is too low for this script to work properly. Please contact your host and request an increase in the timeout limit for CRON jobs. Moreover you need to ask them to increase the max_execution_time in the php.ini file or, even better, set it to 0. END; if (!function_exists('php_ini_loaded_file')) { echo "\n\n"; return; } $ini_location = php_ini_loaded_file(); echo <<<END The php.ini file your host will need to modify is located at: $ini_location Info for the host: the location above is reported by PHP's php_ini_loaded_file() method. END; echo "\n\n"; exit(253); } } /** * Error handler. It tries to catch fatal errors and report them in a meaningful way. Obviously it only works for * catchable fatal errors. It sets the error level to 252. * * IMPORTANT! Under PHP 7 the default exception handler will be called instead, including when there is a non-catchable * fatal error. * * @param int $errno Error number * @param string $errstr Error string, tells us what went wrong * @param string $errfile Full path to file where the error occurred * @param int $errline Line number where the error occurred * * @return void */ function FOFCliErrorHandler($errno, $errstr, $errfile, $errline) { switch ($errno) { case E_ERROR: case E_USER_ERROR: echo "\n\n"; echo "********** ERROR! **********\n\n"; echo "PHP Fatal Error: $errstr"; echo "\n\nTechnical information:\n\n"; echo "File: " . $errfile . "\n"; echo "Line: " . $errline . "\n"; echo "\nStack Trace:\n\n" . debug_backtrace(); echo "\n\n"; exit(252); break; default: break; } } /** * Custom default handlers for otherwise unhandled exceptions and PHP catchable errors. * * Moreover, we register a shutdown function to catch timeouts and SIGTERM signals, because some hosts *are* monsters. */ set_exception_handler('FOFCliExceptionHandler'); set_error_handler('FOFCliErrorHandler', E_ERROR | E_USER_ERROR); register_shutdown_function('FOFCliTimeoutHandler');PK gi"]�0�nU nU Container/Container.phpnu &1i� <?php /** * @package FOF * @copyright Copyright (c)2010-2022 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace FOF40\Container; defined('_JEXEC') || die; use FOF40\Autoloader\Autoloader; use FOF40\Configuration\Configuration; use FOF40\Dispatcher\Dispatcher; use FOF40\Encrypt\EncryptService; use FOF40\Factory\FactoryInterface; use FOF40\Inflector\Inflector; use FOF40\Input\Input as FOFInput; use FOF40\Params\Params; use FOF40\Platform\FilesystemInterface; use FOF40\Platform\Joomla\Filesystem as JoomlaFilesystem; use FOF40\Platform\PlatformInterface; use FOF40\Render\RenderInterface; use FOF40\Template\Template; use FOF40\Toolbar\Toolbar; use FOF40\TransparentAuthentication\TransparentAuthentication as TransparentAuth; use FOF40\Utils\MediaVersion; use FOF40\View\Compiler\Blade; use JDatabaseDriver; use Joomla\CMS\Factory as JoomlaFactory; use Joomla\CMS\Session\Session; use Joomla\Input\Input as JoomlaInput; /** * Dependency injection container for FOF-powered components. * * The properties below (except componentName, bareComponentName and the ones marked with property-read) can be * configured in the fof.xml component configuration file. * * Sample fof.xml: * * <fof> * <common> * <container> * <option name="componentNamespace"><![CDATA[MyCompany\MyApplication]]></option> * <option name="frontEndPath"><![CDATA[%PUBLIC%\components\com_application]]></option> * <option name="factoryClass">magic</option> * </container> * </common> * </fof> * * The paths can use the variables %ROOT%, %PUBLIC%, %ADMIN%, %TMP%, %LOG% i.e. all the path keys returned by * Platform's * getPlatformBaseDirs() method in uppercase and surrounded by percent signs. * * * @property string $componentName The name of the component (com_something) * @property string $bareComponentName The name of the component without com_ (something) * @property string $componentNamespace The namespace of the component's classes (\Foobar) * @property string $frontEndPath The absolute path to the front-end files * @property string $backEndPath The absolute path to the back-end files * @property string $thisPath The preferred path (e.g. backEndPath for Admin * application) * @property string $rendererClass View renderer classname. Must implement * RenderInterface * @property string $factoryClass MVC Factory classname, default * FOF40\Factory\BasicFactory * @property string $platformClass Platform classname, default * FOF40\Platform\Joomla\Platform * @property MediaVersion $mediaVersion A version string for media files in forms. * * @property-read Configuration $appConfig The application configuration registry * @property-read Blade $blade The Blade view template compiler engine * @property-read JDatabaseDriver $db The database connection object * @property-read Dispatcher $dispatcher The component's dispatcher * @property-read FactoryInterface $factory The MVC object factory * @property-read FilesystemInterface $filesystem The filesystem abstraction layer object * @property-read Inflector $inflector The English word inflector * @property-read Params $params The component's params * @property-read FOFInput $input The input object * @property-read PlatformInterface $platform The platform abstraction layer object * @property-read RenderInterface $renderer The view renderer * @property-read Session $session Joomla! session storage * @property-read Template $template The template helper * @property-read TransparentAuth $transparentAuth Transparent authentication handler * @property-read Toolbar $toolbar The component's toolbar * @property-read EncryptService $crypto The component's data encryption service */ class Container extends ContainerBase { /** * Cache of created container instances * * @var array */ protected static $instances = []; /** * Public constructor. This does NOT go through the fof.xml file. You are advised to use getInstance() instead. * * @param array $values Overrides for the container configuration and services * * @throws \FOF40\Container\Exception\NoComponent If no component name is specified */ public function __construct(array $values = []) { // Initialise $this->bareComponentName = ''; $this->componentName = ''; $this->componentNamespace = ''; $this->frontEndPath = ''; $this->backEndPath = ''; $this->thisPath = ''; $this->factoryClass = 'FOF40\\Factory\\BasicFactory'; $this->platformClass = 'FOF40\\Platform\\Joomla\\Platform'; $initMediaVersion = null; if (isset($values['mediaVersion']) && !is_object($values['mediaVersion'])) { $initMediaVersion = $values['mediaVersion']; unset($values['mediaVersion']); } // Try to construct this container object parent::__construct($values); // Make sure we have a component name if (empty($this['componentName'])) { throw new Exception\NoComponent; } $bareComponent = substr($this->componentName, 4); $this['bareComponentName'] = $bareComponent; // Try to guess the component's namespace if (empty($this['componentNamespace'])) { $this->componentNamespace = ucfirst($bareComponent); } else { $this->componentNamespace = trim($this->componentNamespace, '\\'); } // Make sure we have front-end and back-end paths if (empty($this['frontEndPath'])) { $this->frontEndPath = JPATH_SITE . '/components/' . $this->componentName; } if (empty($this['backEndPath'])) { $this->backEndPath = JPATH_ADMINISTRATOR . '/components/' . $this->componentName; } // Get the namespaces for the front-end and back-end parts of the component $frontEndNamespace = '\\' . $this->componentNamespace . '\\Site\\'; $backEndNamespace = '\\' . $this->componentNamespace . '\\Admin\\'; // Special case: if the frontend and backend paths are identical, we don't use the Site and Admin namespace // suffixes after $this->componentNamespace (so you may use FOF with WebApplication apps) if ($this->frontEndPath == $this->backEndPath) { $frontEndNamespace = '\\' . $this->componentNamespace . '\\'; $backEndNamespace = '\\' . $this->componentNamespace . '\\'; } // Do we have to register the component's namespaces with the autoloader? $autoloader = Autoloader::getInstance(); if (!$autoloader->hasMap($frontEndNamespace)) { $autoloader->addMap($frontEndNamespace, $this->frontEndPath); } if (!$autoloader->hasMap($backEndNamespace)) { $autoloader->addMap($backEndNamespace, $this->backEndPath); } // Inflector service if (!isset($this['inflector'])) { $this['inflector'] = function (Container $c) { return new Inflector(); }; } // Filesystem abstraction service if (!isset($this['filesystem'])) { $this['filesystem'] = function (Container $c) { return new JoomlaFilesystem($c); }; } // Platform abstraction service if (!isset($this['platform'])) { if (empty($c['platformClass'])) { $c['platformClass'] = 'FOF40\\Platform\\Joomla\\Platform'; } $this['platform'] = function (Container $c) { $className = $c['platformClass']; return new $className($c); }; } if (empty($this['thisPath'])) { $this['thisPath'] = $this['frontEndPath']; if ($this->platform->isBackend()) { $this['thisPath'] = $this['backEndPath']; } } // MVC Factory service if (!isset($this['factory'])) { $this['factory'] = function (Container $c) { if (empty($c['factoryClass'])) { $c['factoryClass'] = 'FOF40\\Factory\\BasicFactory'; } if (strpos($c['factoryClass'], '\\') === false) { $class = $c->getNamespacePrefix() . 'Factory\\' . $c['factoryClass']; $c['factoryClass'] = class_exists($class) ? $class : '\\FOF40\\Factory\\' . ucfirst($c['factoryClass']) . 'Factory'; } if (!class_exists($c['factoryClass'], true)) { $c['factoryClass'] = 'FOF40\\Factory\\BasicFactory'; } $factoryClass = $c['factoryClass']; /** @var FactoryInterface $factory */ $factory = new $factoryClass($c); if (isset($c['section'])) { $factory->setSection($c['section']); } return $factory; }; } // Component Configuration service if (!isset($this['appConfig'])) { $this['appConfig'] = function (Container $c) { $class = $c->getNamespacePrefix() . 'Configuration\\Configuration'; if (!class_exists($class, true)) { $class = '\\FOF40\\Configuration\\Configuration'; } return new $class($c); }; } // Component Params service if (!isset($this['params'])) { $this['params'] = function (Container $c) { return new Params($c); }; } // Blade view template compiler service if (!isset($this['blade'])) { $this['blade'] = function (Container $c) { return new Blade($c); }; } // Database Driver service if (!isset($this['db'])) { $this['db'] = function (Container $c) { return $c->platform->getDbo(); }; } // Request Dispatcher service if (!isset($this['dispatcher'])) { $this['dispatcher'] = function (Container $c) { return $c->factory->dispatcher(); }; } // Component toolbar provider if (!isset($this['toolbar'])) { $this['toolbar'] = function (Container $c) { return $c->factory->toolbar(); }; } // Component toolbar provider if (!isset($this['transparentAuth'])) { $this['transparentAuth'] = function (Container $c) { return $c->factory->transparentAuthentication(); }; } // View renderer if (!isset($this['renderer'])) { $this['renderer'] = function (Container $c) { if (isset($c['rendererClass']) && class_exists($c['rendererClass'])) { $class = $c['rendererClass']; $renderer = new $class($c); if ($renderer instanceof RenderInterface) { return $renderer; } } $filesystem = $c->filesystem; // Try loading the stock renderers shipped with FOF $path = __DIR__ . '/../Render/'; $renderFiles = $filesystem->folderFiles($path, '.php'); $renderer = null; $priority = 0; foreach ($renderFiles as $filename) { if ($filename == 'RenderBase.php') { continue; } if ($filename == 'RenderInterface.php') { continue; } $className = 'FOF40\\Render\\' . basename($filename, '.php'); if (!class_exists($className, true)) { continue; } /** @var RenderInterface $o */ $o = new $className($c); $info = $o->getInformation(); if (($info->enabled ?? []) === []) { continue; } if ($info->priority > $priority) { $priority = $info->priority; $renderer = $o; } } return $renderer; }; } // Input Access service if (isset($this['input']) && is_array($this['input'])) { if (empty($this['input'])) { $this['input'] = []; } // This swap is necessary to prevent infinite recursion $this['rawInputData'] = array_merge($this['input']); unset($this['input']); $this['input'] = function (Container $c) { $input = new FOFInput($c['rawInputData']); unset($c['rawInputData']); return $input; }; } if (!isset($this['input'])) { $this['input'] = function () { return new FOFInput(); }; } // Session service if (!isset($this['session'])) { $this['session'] = function (Container $c) { return JoomlaFactory::getSession(); }; } // Template service if (!isset($this['template'])) { $this['template'] = function (Container $c) { return new Template($c); }; } // Media version string if (!isset($this['mediaVersion'])) { $this['mediaVersion'] = function (Container $c) { return new MediaVersion($c); }; if (!is_null($initMediaVersion)) { $this['mediaVersion']->setMediaVersion($initMediaVersion); } } // Encryption / cryptography service if (!isset($this['crypto'])) { $this['crypto'] = function (Container $c) { return new EncryptService($c); }; } } /** * Returns a container instance for a specific component. This method goes through fof.xml to read the default * configuration values for the container. You are advised to use this unless you have a specific reason for * instantiating a Container without going through the fof.xml file. * * Pass the value 'tempInstance' => true in the $values array to get a temporary instance. Otherwise you will get * the cached instance of the previously created container. * * @param string $component The component you want to get a container for, e.g. com_foobar. * @param array $values Container configuration overrides you want to apply. Optional. * @param string $section The application section (site, admin) you want to fetch. Any other value results in * auto-detection. * * @return \FOF40\Container\Container */ public static function &getInstance($component, array $values = [], $section = 'auto') { $tempInstance = false; if (isset($values['tempInstance'])) { $tempInstance = $values['tempInstance']; unset($values['tempInstance']); } if ($tempInstance) { return self::makeInstance($component, $values, $section); } $signature = md5($component . '@' . $section); if (!isset(self::$instances[$signature])) { self::$instances[$signature] = self::makeInstance($component, $values, $section); } return self::$instances[$signature]; } /** * Returns a temporary container instance for a specific component. * * @param string $component The component you want to get a container for, e.g. com_foobar. * @param array $values Container configuration overrides you want to apply. Optional. * @param string $section The application section (site, admin) you want to fetch. Any other value results in * auto-detection. * * @return \FOF40\Container\Container * * @throws Exception\NoComponent */ protected static function &makeInstance($component, array $values = [], $section = 'auto') { // Try to auto-detect some defaults $tmpConfig = array_merge($values, ['componentName' => $component]); $tmpContainer = new Container($tmpConfig); if (!in_array($section, ['site', 'admin'])) { $section = $tmpContainer->platform->isBackend() ? 'admin' : 'site'; } $appConfig = $tmpContainer->appConfig; // Get the namespace from fof.xml $namespace = $appConfig->get('container.componentNamespace', null); // $values always overrides $namespace and fof.xml if (isset($values['componentNamespace'])) { $namespace = $values['componentNamespace']; } // If there is no namespace set, try to guess it. if (empty($namespace)) { $bareComponent = $component; if (substr($component, 0, 4) == 'com_') { $bareComponent = substr($component, 4); } $namespace = ucfirst($bareComponent); } // Get the default front-end/back-end paths $frontEndPath = $appConfig->get('container.frontEndPath', JPATH_SITE . '/components/' . $component); $backEndPath = $appConfig->get('container.backEndPath', JPATH_ADMINISTRATOR . '/components/' . $component); // Parse path variables if necessary $frontEndPath = $tmpContainer->parsePathVariables($frontEndPath); $backEndPath = $tmpContainer->parsePathVariables($backEndPath); // Apply path overrides if (isset($values['frontEndPath'])) { $frontEndPath = $values['frontEndPath']; } if (isset($values['backEndPath'])) { $backEndPath = $values['backEndPath']; } $thisPath = ($section == 'admin') ? $backEndPath : $frontEndPath; // Get the namespaces for the front-end and back-end parts of the component $frontEndNamespace = '\\' . $namespace . '\\Site\\'; $backEndNamespace = '\\' . $namespace . '\\Admin\\'; // Special case: if the frontend and backend paths are identical, we don't use the Site and Admin namespace // suffixes after $this->componentNamespace (so you may use FOF with WebApplication apps) if ($frontEndPath == $backEndPath) { $frontEndNamespace = '\\' . $namespace . '\\'; $backEndNamespace = '\\' . $namespace . '\\'; } // Do we have to register the component's namespaces with the autoloader? $autoloader = Autoloader::getInstance(); if (!$autoloader->hasMap($frontEndNamespace)) { $autoloader->addMap($frontEndNamespace, $frontEndPath); } if (!$autoloader->hasMap($backEndNamespace)) { $autoloader->addMap($backEndNamespace, $backEndPath); } // Get the Container class name $classNamespace = ($section == 'admin') ? $backEndNamespace : $frontEndNamespace; $class = $classNamespace . 'Container'; // Get the values overrides from fof.xml $values = array_merge([ 'factoryClass' => '\\FOF40\\Factory\\BasicFactory', 'platformClass' => '\\FOF40\\Platform\\Joomla\\Platform', 'section' => $section, ], $values); $values = array_merge($values, [ 'componentName' => $component, 'componentNamespace' => $namespace, 'frontEndPath' => $frontEndPath, 'backEndPath' => $backEndPath, 'thisPath' => $thisPath, 'rendererClass' => $appConfig->get('container.rendererClass', null), 'factoryClass' => $appConfig->get('container.factoryClass', $values['factoryClass']), 'platformClass' => $appConfig->get('container.platformClass', $values['platformClass']), ]); if (empty($values['rendererClass'])) { unset ($values['rendererClass']); } $mediaVersion = $appConfig->get('container.mediaVersion', null); unset($appConfig); unset($tmpConfig); unset($tmpContainer); $container = class_exists($class, true) ? new $class($values) : new Container($values); if (!is_null($mediaVersion)) { $container->mediaVersion->setMediaVersion($mediaVersion); } return $container; } /** * The container SHOULD NEVER be serialised. If this happens, it means that any of the installed version is doing * something REALLY BAD, so let's die and inform the user of what it's going on. */ public function __sleep() { // If the site is in debug mode we die and let the user figure it out if (defined('JDEBUG') && JDEBUG) { $msg = <<< END Something on your site is broken and tries to save the plugin state in the cache. This is a major security issue and will cause your site to not work properly. Go to your site's backend, Global Configuration and set Caching to OFF as a temporary solution. Possible causes: older versions of JoomlaShine templates, JomSocial, BetterPreview and other third party Joomla! extensions. END; die($msg); } // Otherwise we serialise the Container return ['values', 'factories', 'protected', 'frozen', 'raw', 'keys']; } /** * Get the applicable namespace prefix for a component section. Possible sections: * auto Auto-detect which is the current component section * inverse The inverse area than auto * site Frontend * admin Backend * * @param string $section The section you want to get information for * * @return string The namespace prefix for the component's classes, e.g. \Foobar\Example\Site\ */ public function getNamespacePrefix(string $section = 'auto'): string { // Get the namespaces for the front-end and back-end parts of the component $frontEndNamespace = '\\' . $this->componentNamespace . '\\Site\\'; $backEndNamespace = '\\' . $this->componentNamespace . '\\Admin\\'; // Special case: if the frontend and backend paths are identical, we don't use the Site and Admin namespace // suffixes after $this->componentNamespace (so you may use FOF with WebApplication apps) if ($this->frontEndPath === $this->backEndPath) { $frontEndNamespace = '\\' . $this->componentNamespace . '\\'; $backEndNamespace = '\\' . $this->componentNamespace . '\\'; } switch ($section) { default: case 'auto': if ($this->platform->isBackend()) { return $backEndNamespace; } else { return $frontEndNamespace; } break; case 'inverse': if ($this->platform->isBackend()) { return $frontEndNamespace; } return $backEndNamespace; case 'site': return $frontEndNamespace; case 'admin': return $backEndNamespace; } } /** * Replace the path variables in the $path string. * * The recognized variables are: * * %root% Path to the site root * * %public% Path to the public area of the site * * %admin% Path to the administrative area of the site * * %api% Path to the API application area of the site * * %tmp% Path to the temp directory * * %log% Path to the log directory * * @param string $path * * @return mixed */ public function parsePathVariables(string $path) { $platformDirs = $this->platform->getPlatformBaseDirs(); // root public admin tmp log $search = array_map(function ($x) { return '%' . strtoupper($x) . '%'; }, array_keys($platformDirs)); $replace = array_values($platformDirs); return str_replace($search, $replace, $path); } } PK gi"]C�#N N # Container/Exception/NoComponent.phpnu &1i� <?php /** * @package FOF * @copyright Copyright (c)2010-2022 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace FOF40\Container\Exception; defined('_JEXEC') || die; use Exception; class NoComponent extends \Exception { public function __construct(string $message = "", int $code = 0, Exception $previous = null) { if (empty($message)) { $message = 'No component specified building the Container object'; } if (empty($code)) { $code = 500; } parent::__construct($message, $code, $previous); } } PK gi"]D�� � Container/ContainerBase.phpnu &1i� <?php /** * @package FOF * @copyright Copyright (c)2010-2022 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace FOF40\Container; defined('_JEXEC') || die; use FOF40\Pimple\Container; class ContainerBase extends Container { /** * Magic getter for alternative syntax, e.g. $container->foo instead of $container['foo'] * * @param string $name * * @return mixed * * @throws \InvalidArgumentException if the identifier is not defined */ function __get(string $name) { return $this->offsetGet($name); } /** * Magic setter for alternative syntax, e.g. $container->foo instead of $container['foo'] * * @param string $name The unique identifier for the parameter or object * @param mixed $value The value of the parameter or a closure for a service * * @throws \RuntimeException Prevent override of a frozen service */ function __set(string $name, $value) { // Special backwards compatible handling for the mediaVersion service if ($name == 'mediaVersion') { $this[$name]->setMediaVersion($value); return; } $this->offsetSet($name, $value); } } PK gi"]�{�p� � Configuration/Configuration.phpnu &1i� <?php /** * @package FOF * @copyright Copyright (c)2010-2022 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace FOF40\Configuration; use FOF40\Container\Container; defined('_JEXEC') || die; /** * 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; private $domains = 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(string $variable, $default = null) { $domains = $this->getDomains(); [$domain, $var] = explode('.', $variable, 2); if (!in_array(ucfirst($domain), $domains)) { return $default; } $class = '\\FOF40\\Configuration\\Domain\\' . ucfirst($domain); /** @var \FOF40\Configuration\Domain\DomainInterface $o */ $o = new $class; return $o->get(self::$configurations[$this->container->componentName], $var, $default); } /** * Gets a list of the available configuration domain adapters * * @return array A list of the available domains */ protected function getDomains(): array { if (is_null($this->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); $this->domains[] = $domain; } $this->domains = array_unique($this->domains); } } return $this->domains; } /** * Parses the configuration of the specified component * * @return void */ protected function parseComponent(): void { 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(string $area, bool $userConfig = false): array { $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 = '\\FOF40\\Configuration\\Domain\\' . ucfirst($dom); if (class_exists($class, true)) { /** @var \FOF40\Configuration\Domain\DomainInterface $o */ $o = new $class; $o->parseDomain($xml, $ret); } } // Finally, return the result return $ret; } } PK gi"]�a�! ! Configuration/Domain/Views.phpnu &1i� <?php /** * @package FOF * @copyright Copyright (c)2010-2022 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace FOF40\Configuration\Domain; use SimpleXMLElement; defined('_JEXEC') || die; /** * Configuration parser for the view-specific settings * * @since 2.1 */ class Views implements DomainInterface { /** * Parse the XML data, adding them to the $ret array * * @param SimpleXMLElement $xml The XML data of the component's configuration area * @param array &$ret The parsed data, in the form of a hash array * * @return void */ public function parseDomain(SimpleXMLElement $xml, array &$ret): void { // Initialise $ret['views'] = []; // Parse view configuration $viewData = $xml->xpath('view'); // Sanity check if (empty($viewData)) { return; } foreach ($viewData as $aView) { $key = (string) $aView['name']; // Parse ACL options $ret['views'][$key]['acl'] = []; $aclData = $aView->xpath('acl/task'); foreach ($aclData as $acl) { $k = (string) $acl['name']; $ret['views'][$key]['acl'][$k] = (string) $acl; } // Parse taskmap $ret['views'][$key]['taskmap'] = []; $taskmapData = $aView->xpath('taskmap/task'); foreach ($taskmapData as $map) { $k = (string) $map['name']; $ret['views'][$key]['taskmap'][$k] = (string) $map; } // Parse controller configuration $ret['views'][$key]['config'] = []; $optionData = $aView->xpath('config/option'); foreach ($optionData as $option) { $k = (string) $option['name']; $ret['views'][$key]['config'][$k] = (string) $option; } // Parse the toolbar $ret['views'][$key]['toolbar'] = []; $toolBars = $aView->xpath('toolbar'); foreach ($toolBars as $toolBar) { $taskName = isset($toolBar['task']) ? (string) $toolBar['task'] : '*'; // If a toolbar title is specified, create a title element. if (isset($toolBar['title'])) { $ret['views'][$key]['toolbar'][$taskName]['title'] = [ 'value' => (string) $toolBar['title'], ]; } // Parse the toolbar buttons data $toolbarData = $toolBar->xpath('button'); foreach ($toolbarData as $button) { $k = (string) $button['type']; $ret['views'][$key]['toolbar'][$taskName][$k] = current($button->attributes()); $ret['views'][$key]['toolbar'][$taskName][$k]['value'] = (string) $button; } } } } /** * Return a configuration variable * * @param string &$configuration Configuration variables (hashed array) * @param string $var The variable we want to fetch * @param mixed $default Default value * * @return mixed The variable's value */ public function get(array &$configuration, string $var, $default = null) { $parts = explode('.', $var); $view = $parts[0]; $method = 'get' . ucfirst($parts[1]); if (!method_exists($this, $method)) { return $default; } array_shift($parts); array_shift($parts); return $this->$method($view, $configuration, $parts, $default); } /** * Internal function to return the task map for a view * * @param string $view The view for which we will be fetching a task map * @param array &$configuration The configuration parameters hash array * @param array $params Extra options (not used) * @param array $default ßDefault task map; empty array if not provided * * @return array The task map as a hash array in the format task => method */ protected function getTaskmap(string $view, array &$configuration, array $params = [], ?array $default = []): ?array { $taskmap = []; if (isset($configuration['views']['*']) && isset($configuration['views']['*']['taskmap'])) { $taskmap = $configuration['views']['*']['taskmap']; } if (isset($configuration['views'][$view]) && isset($configuration['views'][$view]['taskmap'])) { $taskmap = array_merge($taskmap, $configuration['views'][$view]['taskmap']); } if (empty($taskmap)) { return $default; } return $taskmap; } /** * Internal method to return the ACL mapping (privilege required to access * a specific task) for the given view's tasks * * @param string $view The view for which we will be fetching a task map * @param array &$configuration The configuration parameters hash array * @param array $params Extra options; key 0 defines the task we want to fetch * @param string $default Default ACL option; empty (no ACL check) if not defined * * @return string|array The privilege required to access this view */ protected function getAcl(string $view, array &$configuration, array $params = [], ?string $default = '') { $aclmap = []; if (isset($configuration['views']['*']) && isset($configuration['views']['*']['acl'])) { $aclmap = $configuration['views']['*']['acl']; } if (isset($configuration['views'][$view]) && isset($configuration['views'][$view]['acl'])) { $aclmap = array_merge($aclmap, $configuration['views'][$view]['acl']); } $acl = $default; if (empty($params) || empty($params[0])) { return $aclmap; } if (isset($aclmap['*'])) { $acl = $aclmap['*']; } if (isset($aclmap[$params[0]])) { $acl = $aclmap[$params[0]]; } return $acl; } /** * Internal method to return the a configuration option for the view. These * are equivalent to $config array options passed to the Controller * * @param string $view The view for which we will be fetching a task map * @param array & $configuration The configuration parameters hash array * @param array $params Extra options; key 0 defines the option variable we want to fetch * @param string|array|null $default Default option; null if not defined * * @return string|array|null The setting for the requested option */ protected function getConfig(string $view, array &$configuration, array $params = [], $default = null) { $ret = $default; $config = []; if (isset($configuration['views']['*']['config'])) { $config = $configuration['views']['*']['config']; } if (isset($configuration['views'][$view]['config'])) { $config = array_merge($config, $configuration['views'][$view]['config']); } if (empty($params) || empty($params[0])) { return $config; } if (isset($config[$params[0]])) { $ret = $config[$params[0]]; } return $ret; } /** * Internal method to return the toolbar infos. * * @param string $view The view for which we will be fetching buttons * @param array & $configuration The configuration parameters hash array * @param array $params Extra options * @param array|null $default Default option * * @return array|null The toolbar data for this view */ protected function getToolbar(string $view, array &$configuration, array $params = [], ?array $default = []): ?array { $toolbar = []; if (isset($configuration['views']['*']) && isset($configuration['views']['*']['toolbar']) && isset($configuration['views']['*']['toolbar']['*'])) { $toolbar = $configuration['views']['*']['toolbar']['*']; } if (isset($configuration['views']['*']) && isset($configuration['views']['*']['toolbar']) && isset($configuration['views']['*']['toolbar'][$params[0]])) { $toolbar = array_merge($toolbar, $configuration['views']['*']['toolbar'][$params[0]]); } if (isset($configuration['views'][$view]) && isset($configuration['views'][$view]['toolbar']) && isset($configuration['views'][$view]['toolbar']['*'])) { $toolbar = array_merge($toolbar, $configuration['views'][$view]['toolbar']['*']); } if (isset($configuration['views'][$view]) && isset($configuration['views'][$view]['toolbar']) && isset($configuration['views'][$view]['toolbar'][$params[0]])) { $toolbar = array_merge($toolbar, $configuration['views'][$view]['toolbar'][$params[0]]); } if (empty($toolbar)) { return $default; } return $toolbar; } } PK gi"]\6;�� � # Configuration/Domain/Dispatcher.phpnu &1i� <?php /** * @package FOF * @copyright Copyright (c)2010-2022 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace FOF40\Configuration\Domain; use SimpleXMLElement; defined('_JEXEC') || die; /** * Configuration parser for the dispatcher-specific settings * * @since 2.1 */ class Dispatcher implements DomainInterface { /** * Parse the XML data, adding them to the $ret array * * @param SimpleXMLElement $xml The XML data of the component's configuration area * @param array &$ret The parsed data, in the form of a hash array * * @return void */ public function parseDomain(SimpleXMLElement $xml, array &$ret): void { // Initialise $ret['dispatcher'] = []; // Parse the dispatcher configuration $dispatcherData = $xml->dispatcher; // Sanity check if (empty($dispatcherData)) { return; } $options = $xml->xpath('dispatcher/option'); foreach ($options as $option) { $key = (string) $option['name']; $ret['dispatcher'][$key] = (string) $option; } } /** * Return a configuration variable * * @param string &$configuration Configuration variables (hashed array) * @param string $var The variable we want to fetch * @param mixed $default Default value * * @return mixed The variable's value */ public function get(array &$configuration, string $var, $default = null) { if ($var == '*') { return $configuration['dispatcher']; } if (isset($configuration['dispatcher'][$var])) { return $configuration['dispatcher'][$var]; } else { return $default; } } } PK gi"]��� � ( Configuration/Domain/DomainInterface.phpnu &1i� <?php /** * @package FOF * @copyright Copyright (c)2010-2022 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ namespace FOF40\Configuration\Domain; use SimpleXMLElement; defined('_JEXEC') || die; /** * The Interface of a FOF configuration domain class. The methods are used to parse and * provision sensible information to consumers. The Configuration class acts as an * adapter to the domain classes. * * @since 2.1 */ interface DomainInterface { /** * Parse the XML data, adding them to the $ret array * * @param SimpleXMLElement $xml The XML data of the component's configuration area * @param array &$ret The parsed data, in the form of a hash array * * @return void */ public function parseDomain(SimpleXMLElement $xml, array &$ret): void; /** * Return a configuration variable * * @param array &$configuration Configuration variables (hashed array) * @param string $var The variable we want to fetch * @param mixed $default Default value * * @return mixed The variable's value */ public function get(array &$configuration, string $var, $default = null); } PK gi"]!�&� � '