primo commit
This commit is contained in:
69
libraries/fof30/Cli/Traits/CGIModeAware.php
Normal file
69
libraries/fof30/Cli/Traits/CGIModeAware.php
Normal file
@ -0,0 +1,69 @@
|
||||
<?php
|
||||
/**
|
||||
* @package FOF
|
||||
* @copyright Copyright (c)2010-2021 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @license GNU General Public License version 2, or later
|
||||
*/
|
||||
|
||||
namespace FOF30\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 FOF30\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;
|
||||
}
|
||||
|
||||
}
|
||||
196
libraries/fof30/Cli/Traits/CustomOptionsAware.php
Normal file
196
libraries/fof30/Cli/Traits/CustomOptionsAware.php
Normal file
@ -0,0 +1,196 @@
|
||||
<?php
|
||||
/**
|
||||
* @package FOF
|
||||
* @copyright Copyright (c)2010-2021 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @license GNU General Public License version 2, or later
|
||||
*/
|
||||
|
||||
namespace FOF30\Cli\Traits;
|
||||
|
||||
defined('_JEXEC') || die;
|
||||
|
||||
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 FOF30\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 InputFilter
|
||||
*/
|
||||
protected $filter = null;
|
||||
|
||||
/**
|
||||
* Initializes the custom CLI options parsing
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function initialiseCustomOptions()
|
||||
{
|
||||
// Create a new InputFilter
|
||||
$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, '='))
|
||||
{
|
||||
[$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);
|
||||
}
|
||||
|
||||
}
|
||||
55
libraries/fof30/Cli/Traits/JoomlaConfigAware.php
Normal file
55
libraries/fof30/Cli/Traits/JoomlaConfigAware.php
Normal file
@ -0,0 +1,55 @@
|
||||
<?php
|
||||
/**
|
||||
* @package FOF
|
||||
* @copyright Copyright (c)2010-2021 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @license GNU General Public License version 2, or later
|
||||
*/
|
||||
|
||||
namespace FOF30\Cli\Traits;
|
||||
|
||||
defined('_JEXEC') || die;
|
||||
|
||||
/**
|
||||
* Allows the CLI application to use the Joomla Global Configuration parameters as its own configuration.
|
||||
*
|
||||
* @package FOF30\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();
|
||||
}
|
||||
|
||||
}
|
||||
73
libraries/fof30/Cli/Traits/MemStatsAware.php
Normal file
73
libraries/fof30/Cli/Traits/MemStatsAware.php
Normal file
@ -0,0 +1,73 @@
|
||||
<?php
|
||||
/**
|
||||
* @package FOF
|
||||
* @copyright Copyright (c)2010-2021 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @license GNU General Public License version 2, or later
|
||||
*/
|
||||
|
||||
namespace FOF30\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 FOF30\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 / 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)";
|
||||
}
|
||||
}
|
||||
}
|
||||
64
libraries/fof30/Cli/Traits/MessageAware.php
Normal file
64
libraries/fof30/Cli/Traits/MessageAware.php
Normal file
@ -0,0 +1,64 @@
|
||||
<?php
|
||||
/**
|
||||
* @package FOF
|
||||
* @copyright Copyright (c)2010-2021 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @license GNU General Public License version 2, or later
|
||||
*/
|
||||
|
||||
namespace FOF30\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 FOF30\Cli\Traits
|
||||
*/
|
||||
trait MessageAware
|
||||
{
|
||||
/** @var array Queue holding all messages */
|
||||
protected $messageQueue = [];
|
||||
|
||||
/**
|
||||
* @param $msg
|
||||
* @param $type
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
||||
100
libraries/fof30/Cli/Traits/TimeAgoAware.php
Normal file
100
libraries/fof30/Cli/Traits/TimeAgoAware.php
Normal file
@ -0,0 +1,100 @@
|
||||
<?php
|
||||
/**
|
||||
* @package FOF
|
||||
* @copyright Copyright (c)2010-2021 Nicholas K. Dionysopoulos / Akeeba Ltd
|
||||
* @license GNU General Public License version 2, or later
|
||||
*/
|
||||
|
||||
namespace FOF30\Cli\Traits;
|
||||
|
||||
defined('_JEXEC') || die;
|
||||
|
||||
/**
|
||||
* Allows the developer to show the relative time difference between two timestamps.
|
||||
*
|
||||
* @package FOF30\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).';
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user