Файловый менеджер - Редактировать - /home/wuectly/www/03cbe/Utils.zip
Назад
PK zt!]v���- - helpers.phpnu &1i� <?php /** * @package FOF * @copyright Copyright (c)2010-2022 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU General Public License version 3, or later */ /** * This is a modified copy of Laravel 4's "helpers.php" * * Laravel 4 is distributed under the MIT license, see https://github.com/laravel/framework/blob/master/LICENSE.txt */ defined('_JEXEC') || die; if (!function_exists('array_add')) { /** * Add an element to an array if it doesn't exist. * * @param array $array * @param string $key * @param mixed $value * * @return array */ function array_add(array $array, string $key, $value): array { if (!isset($array[$key])) { $array[$key] = $value; } return $array; } } if (!function_exists('array_build')) { /** * Build a new array using a callback. * * @param array $array * @param \Closure $callback * * @return array */ function array_build(array $array, Closure $callback): array { $results = []; foreach ($array as $key => $value) { [$innerKey, $innerValue] = call_user_func($callback, $key, $value); $results[$innerKey] = $innerValue; } return $results; } } if (!function_exists('array_divide')) { /** * Divide an array into two arrays. One with keys and the other with values. * * @param array $array * * @return array */ function array_divide(array $array) { return [array_keys($array), array_values($array)]; } } if (!function_exists('array_dot')) { /** * Flatten a multi-dimensional associative array with dots. * * @param array $array * @param string $prepend * * @return array */ function array_dot(array $array, string $prepend = ''): array { $results = []; foreach ($array as $key => $value) { if (is_array($value)) { $results = array_merge($results, array_dot($value, $prepend . $key . '.')); } else { $results[$prepend . $key] = $value; } } return $results; } } if (!function_exists('array_except')) { /** * Get all of the given array except for a specified array of items. * * @param array $array * @param array $keys * * @return array */ function array_except(array $array, array $keys): array { return array_diff_key($array, array_flip((array) $keys)); } } if (!function_exists('array_fetch')) { /** * Fetch a flattened array of a nested array element. * * @param array $array * @param string $key * * @return array */ function array_fetch(array $array, string $key): array { foreach (explode('.', $key) as $segment) { $results = []; foreach ($array as $value) { $value = (array) $value; $results[] = $value[$segment]; } $array = array_values($results); } return array_values($results); } } if (!function_exists('array_first')) { /** * Return the first element in an array passing a given truth test. * * @param array $array * @param Closure $callback * @param mixed $default * * @return mixed */ function array_first(array $array, callable $callback, $default = null) { foreach ($array as $key => $value) { if (call_user_func($callback, $key, $value)) { return $value; } } return value($default); } } if (!function_exists('array_last')) { /** * Return the last element in an array passing a given truth test. * * @param array $array * @param Closure $callback * @param mixed $default * * @return mixed */ function array_last(array $array, callable $callback, $default = null) { return array_first(array_reverse($array), $callback, $default); } } if (!function_exists('array_flatten')) { /** * Flatten a multi-dimensional array into a single level. * * @param array $array * * @return array */ function array_flatten(array $array): array { $return = []; array_walk_recursive($array, function ($x) use (&$return) { $return[] = $x; }); return $return; } } if (!function_exists('array_forget')) { /** * Remove an array item from a given array using "dot" notation. * * @param array $array * @param string $key * * @return void */ function array_forget(array &$array, string $key): void { $keys = explode('.', $key); while (count($keys) > 1) { $key = array_shift($keys); if (!isset($array[$key]) || !is_array($array[$key])) { return; } $array =& $array[$key]; } unset($array[array_shift($keys)]); } } if (!function_exists('array_get')) { /** * Get an item from an array using "dot" notation. * * @param array $array * @param string $key * @param mixed $default * * @return mixed */ function array_get(array $array, string $key, $default = null) { if (is_null($key)) { return $array; } if (isset($array[$key])) { return $array[$key]; } foreach (explode('.', $key) as $segment) { if (!is_array($array) || !array_key_exists($segment, $array)) { return value($default); } $array = $array[$segment]; } return $array; } } if (!function_exists('array_only')) { /** * Get a subset of the items from the given array. * * @param array $array * @param array $keys * * @return array */ function array_only(array $array, array $keys): array { return array_intersect_key($array, array_flip((array) $keys)); } } if (!function_exists('array_pluck')) { /** * Pluck an array of values from an array. * * @param array $array * @param string $value * @param string $key * * @return array */ function array_pluck(array $array, string $value, ?string $key = null): array { $results = []; foreach ($array as $item) { $itemValue = is_object($item) ? $item->{$value} : $item[$value]; // If the key is "null", we will just append the value to the array and keep // looping. Otherwise we will key the array using the value of the key we // received from the developer. Then we'll return the final array form. if (is_null($key)) { $results[] = $itemValue; } else { $itemKey = is_object($item) ? $item->{$key} : $item[$key]; $results[$itemKey] = $itemValue; } } return $results; } } if (!function_exists('array_pull')) { /** * Get a value from the array, and remove it. * * @param array $array * @param string $key * * @return mixed */ function array_pull(array &$array, string $key) { $value = array_get($array, $key); array_forget($array, $key); return $value; } } if (!function_exists('array_set')) { /** * Set an array item to a given value using "dot" notation. * * If no key is given to the method, the entire array will be replaced. * * @param array $array * @param string $key * @param mixed $value * * @return array */ function array_set(array &$array, string $key, $value): array { if (is_null($key)) { return $array = $value; } $keys = explode('.', $key); while (count($keys) > 1) { $key = array_shift($keys); // If the key doesn't exist at this depth, we will just create an empty array // to hold the next value, allowing us to create the arrays to hold final // values at the correct depth. Then we'll keep digging into the array. if (!isset($array[$key]) || !is_array($array[$key])) { $array[$key] = []; } $array =& $array[$key]; } $array[array_shift($keys)] = $value; return $array; } } if (!function_exists('array_sort')) { /** * Sort the array using the given Closure. * * @param array $array * @param \Closure $callback * * @return array */ function array_sort(array $array, callable $callback): array { return FOF40\Utils\Collection::make($array)->sortBy($callback)->all(); } } if (!function_exists('array_where')) { /** * Filter the array using the given Closure. * * @param array $array * @param \Closure $callback * * @return array */ function array_where(array $array, callable $callback): array { $filtered = []; foreach ($array as $key => $value) { if (call_user_func($callback, $key, $value)) { $filtered[$key] = $value; } } return $filtered; } } if (!function_exists('ends_with')) { /** * Determine if a given string ends with a given substring. * * @param string $haystack * @param string|array $needles * * @return bool */ function ends_with(string $haystack, $needles): bool { foreach ((array) $needles as $needle) { if ((string) $needle === substr($haystack, -strlen($needle))) { return true; } } return false; } } if (!function_exists('last')) { /** * Get the last element from an array. * * @param array $array * * @return mixed */ function last(array $array) { return end($array); } } if (!function_exists('object_get')) { /** * Get an item from an object using "dot" notation. * * @param object $object * @param string $key * @param mixed $default * * @return mixed */ function object_get($object, string $key, $default = null) { if (is_null($key) || trim($key) == '') { return $object; } foreach (explode('.', $key) as $segment) { if (!is_object($object) || !isset($object->{$segment})) { return value($default); } $object = $object->{$segment}; } return $object; } } if (!function_exists('preg_replace_sub')) { /** * Replace a given pattern with each value in the array in sequentially. * * @param string $pattern * @param array $replacements * @param string $subject * * @return string */ function preg_replace_sub(string $pattern, array &$replacements, string $subject): string { return preg_replace_callback($pattern, function ($match) use (&$replacements) { return array_shift($replacements); }, $subject); } } if (!function_exists('starts_with')) { /** * Determine if a given string starts with a given substring. * * @param string $haystack * @param string|array $needles * * @return bool */ function starts_with(string $haystack, $needles): bool { foreach ((array) $needles as $needle) { if ($needle != '' && strpos($haystack, $needle) === 0) { return true; } } return false; } } if (!function_exists('value')) { /** * Return the default value of the given value. * * @param mixed $value * * @return mixed */ function value($value) { return $value instanceof Closure ? $value() : $value; } } if (!function_exists('with')) { /** * Return the given object. Useful for chaining. * * @param mixed $object * * @return mixed */ function with($object) { return $object; } } if (!function_exists('fofStringToBool')) { /** * Convert a string to a boolean. It understands the following human-readable boolean notations 0, 1, true, false, * yes, no, on, off, enabled, disabled. If the value is anything else it will delegate it to PHP's `(bool)` type * casting operator. * * @param string $string The string with the human-readable boolean value. * * @return boolean The converted string */ function fofStringToBool(string $string): bool { $string = trim((string) $string); $string = strtolower($string); if (in_array($string, ['1', 'true', 'yes', 'on', 'enabled'], true)) { return true; } if (in_array($string, ['0', 'false', 'no', 'off', 'disabled'], true)) { return false; } return (bool) $string; } } PK zt!]��J� � CliSessionHandler.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\Utils; defined('_JEXEC') || die; use FOF40\Encrypt\Randval; use JSessionHandlerInterface; use RuntimeException; /** * CLI session handler for Joomla 3.x */ class CliSessionHandler implements JSessionHandlerInterface { private $id; private $name = 'clisession'; public function __construct() { $this->makeId(); } /** * Starts the session. * * @return boolean True if started. * * @throws RuntimeException If something goes wrong starting the session. * @since 3.4.8 */ public function start() { return true; } /** * Checks if the session is started. * * @return boolean True if started, false otherwise. * * @since 3.4.8 */ public function isStarted() { return true; } /** * Returns the session ID * * @return string The session ID * * @since 3.4.8 */ public function getId() { return $this->id; } /** * Sets the session ID * * @param string $id The session ID * * @return void * * @since 3.4.8 */ public function setId($id) { $this->id = $id; } /** * Returns the session name * * @return mixed The session name. * * @since 3.4.8 */ public function getName() { return $this->name; } /** * Sets the session name * * @param string $name The name of the session * * @return void * * @since 3.4.8 */ public function setName($name) { $this->name = $name; } /** * Regenerates ID that represents this storage. * * Note regenerate+destroy should not clear the session data in memory only delete the session data from persistent * storage. * * @param boolean $destroy Destroy session when regenerating? * @param integer $lifetime Sets the cookie lifetime for the session cookie. A null value will leave the system * settings unchanged, * 0 sets the cookie to expire with browser session. Time is in seconds, and is not a * Unix timestamp. * * @return boolean True if session regenerated, false if error * * @since 3.4.8 */ public function regenerate($destroy = false, $lifetime = null) { $this->makeId(); return true; } /** * Force the session to be saved and closed. * * This method must invoke session_write_close() unless this interface is used for a storage object design for unit * or functional testing where a real PHP session would interfere with testing, in which case it should actually * persist the session data if required. * * @return void * * @throws RuntimeException If the session is saved without being started, or if the session is already closed. * @since 3.4.8 * @see session_write_close() */ public function save() { // No operation. This is a CLI session, we save nothing. } /** * Clear all session data in memory. * * @return void * * @since 3.4.8 */ public function clear() { $this->makeId(); } private function makeId() { $rand = new Randval(); $this->id = md5($rand->generate(32)); } }PK zt!]�T$?=: =: Collection.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\Utils; defined('_JEXEC') || die; use ArrayAccess; use ArrayIterator; use CachingIterator; use Closure; use Countable; use IteratorAggregate; use JsonSerializable; class Collection implements ArrayAccess, Countable, IteratorAggregate, JsonSerializable { /** * The items contained in the collection. * * @var array */ protected $items = []; /** * Create a new collection. * * @param array $items */ public function __construct(array $items = []) { $this->items = $items; } /** * Create a new collection instance if the value isn't one already. If given an array then the array is wrapped in * a Collection. Otherwise we return a Collection with only one item, whatever was passed in $items. If you pass * null you get an empty Collection. * * @param array|mixed $items * * @return static */ public static function make($items): Collection { if (is_null($items)) { return new static; } if ($items instanceof Collection) { return $items; } return new static(is_array($items) ? $items : [$items]); } /** * Get all of the items in the collection. * * @return array */ public function all(): array { return $this->items; } /** * Collapse the collection items into a single array. This assumes that the Collection is composed of arrays. We * are essentially merging all of these arrays and creating a new Collection out of them. * * If $this->items = [ ['a','b'], ['c','d'], ['e'] ] after collapse it becomes [ 'a','b','c','d','e' ] * * @return Collection */ public function collapse(): Collection { $results = []; foreach ($this->items as $values) { $results = array_merge($results, $values); } return new static($results); } /** * Diff the collection with the given items. * * @param Collection|array $items * * @return Collection */ public function diff($items): Collection { return new static(array_diff($this->items, $this->getIterableItemsAsArray($items))); } /** * Execute a callback over each item. * * @param Closure $callback * * @return Collection */ public function each(Closure $callback): Collection { array_map($callback, $this->items); return $this; } /** * Fetch a nested element of the collection. * * @param string $key * * @return Collection */ public function fetch(string $key): Collection { return new static(array_fetch($this->items, $key)); } /** * Run a filter over each of the items. * * @param Closure $callback * * @return Collection */ public function filter(Closure $callback): Collection { return new static(array_filter($this->items, $callback)); } /** * Get the first item from the collection. * * @param \Closure $callback * @param mixed $default * * @return mixed|null */ public function first(Closure $callback = null, $default = null) { if (is_null($callback)) { return count($this->items) > 0 ? reset($this->items) : null; } else { return array_first($this->items, $callback, $default); } } /** * Get a flattened array of the items in the collection. * * @return Collection */ public function flatten(): Collection { return new static(array_flatten($this->items)); } /** * Remove an item from the collection by key. * * @param mixed $key * * @return void */ public function forget(string $key): void { unset($this->items[$key]); } /** * Get an item from the collection by key. * * @param mixed $key * @param mixed $default * * @return mixed */ public function get(string $key, $default = null) { if (array_key_exists($key, $this->items)) { return $this->items[$key]; } return value($default); } /** * Group an associative array by a field or Closure value. * * @param callable|string $groupBy * * @return Collection */ public function groupBy($groupBy): Collection { $results = []; foreach ($this->items as $key => $value) { $key = is_callable($groupBy) ? $groupBy($value, $key) : array_get($value, $groupBy); $results[$key][] = $value; } return new static($results); } /** * Determine if an item exists in the collection by key. * * @param string $key * * @return bool */ public function has(string $key): bool { return array_key_exists($key, $this->items); } /** * Concatenate values of a given key as a string. * * @param string $value * @param string|null $glue * * @return string */ public function implode(string $value, ?string $glue = null): string { if (is_null($glue)) { return implode($this->lists($value)); } return implode($glue, $this->lists($value)); } /** * Intersect the collection with the given items. * * @param Collection|array $items * * @return Collection */ public function intersect($items): Collection { return new static(array_intersect($this->items, $this->getIterableItemsAsArray($items))); } /** * Determine if the collection is empty or not. * * @return bool */ public function isEmpty(): bool { return empty($this->items); } /** * Get the last item from the collection. * * @return mixed|null */ public function last() { return count($this->items) > 0 ? end($this->items) : null; } /** * Get an array with the values of a given key. * * @param string $value * @param string|null $key * * @return array */ public function lists(string $value, ?string $key = null) { return array_pluck($this->items, $value, $key); } /** * Run a map over each of the items. * * @param Closure $callback * * @return Collection */ public function map(Closure $callback): Collection { return new static(array_map($callback, $this->items, array_keys($this->items))); } /** * Merge the collection with the given items. * * @param Collection|array $items * * @return Collection */ public function merge($items): Collection { return new static(array_merge($this->items, $this->getIterableItemsAsArray($items))); } /** * Get and remove the last item from the collection. * * @return mixed|null */ public function pop() { return array_pop($this->items); } /** * Push an item onto the beginning of the collection. * * @param mixed $value * * @return void */ public function prepend($value): void { array_unshift($this->items, $value); } /** * Push an item onto the end of the collection. * * @param mixed $value * * @return void */ public function push($value): void { $this->items[] = $value; } /** * Put an item in the collection by key. * * @param string $key * @param mixed $value * * @return void */ public function put(string $key, $value): void { $this->items[$key] = $value; } /** * Reduce the collection to a single value. * * @param callable $callback * @param mixed $initial * * @return mixed */ public function reduce(callable $callback, $initial = null) { return array_reduce($this->items, $callback, $initial); } /** * Get one or more items randomly from the collection. * * @param int $amount * * @return mixed */ public function random(int $amount = 1) { $keys = array_rand($this->items, $amount); return is_array($keys) ? array_intersect_key($this->items, array_flip($keys)) : $this->items[$keys]; } /** * Reverse items order. * * @return Collection */ public function reverse(): Collection { return new static(array_reverse($this->items)); } /** * Get and remove the first item from the collection. * * @return mixed|null */ public function shift() { return array_shift($this->items); } /** * Slice the underlying collection array. * * @param int $offset * @param int|null $length * @param bool $preserveKeys * * @return Collection */ public function slice(int $offset, ?int $length = null, bool $preserveKeys = false): Collection { return new static(array_slice($this->items, $offset, $length, $preserveKeys)); } /** * Sort through each item with a callback. * * @param Closure $callback * * @return Collection */ public function sort(Closure $callback): Collection { uasort($this->items, $callback); return $this; } /** * Sort the collection using the given Closure. * * @param \Closure|string $callback * @param int $options * @param bool $descending * * @return Collection */ public function sortBy($callback, int $options = SORT_REGULAR, bool $descending = false): Collection { $results = []; if (is_string($callback)) { $callback = $this->valueRetriever($callback); } // First we will loop through the items and get the comparator from a callback // function which we were given. Then, we will sort the returned values and // and grab the corresponding values for the sorted keys from this array. foreach ($this->items as $key => $value) { $results[$key] = $callback($value); } $descending ? arsort($results, $options) : asort($results, $options); // Once we have sorted all of the keys in the array, we will loop through them // and grab the corresponding model so we can set the underlying items list // to the sorted version. Then we'll just return the collection instance. foreach (array_keys($results) as $key) { $results[$key] = $this->items[$key]; } $this->items = $results; return $this; } /** * Sort the collection in descending order using the given Closure. * * @param \Closure|string $callback * @param int $options * * @return Collection */ public function sortByDesc($callback, int $options = SORT_REGULAR): Collection { return $this->sortBy($callback, $options, true); } /** * Splice portion of the underlying collection array. * * @param int $offset * @param int $length * @param mixed $replacement * * @return Collection */ public function splice(int $offset, int $length = 0, $replacement = []): Collection { return new static(array_splice($this->items, $offset, $length, $replacement)); } /** * Get the sum of the given values. * * @param \Closure|string $callback * * @return mixed */ public function sum($callback) { if (is_string($callback)) { $callback = $this->valueRetriever($callback); } return $this->reduce(function ($result, $item) use ($callback) { return $result += $callback($item); }, 0); } /** * Take the first or last {$limit} items. * * @param int|null $limit * * @return Collection */ public function take(?int $limit = null): Collection { if ($limit < 0) { return $this->slice($limit, abs($limit)); } return $this->slice(0, $limit); } /** * Resets the Collection (removes all items) * * @return Collection */ public function reset(): Collection { $this->items = []; return $this; } /** * Transform each item in the collection using a callback. * * @param callable $callback * * @return Collection */ public function transform(callable $callback): Collection { $this->items = array_map($callback, $this->items); return $this; } /** * Return only unique items from the collection array. * * @return Collection */ public function unique(): Collection { return new static(array_unique($this->items)); } /** * Reset the keys on the underlying array. * * @return Collection */ public function values(): Collection { $this->items = array_values($this->items); return $this; } /** * Get the collection of items as a plain array. * * @return array */ public function toArray(): array { return array_map(function ($value) { return (is_object($value) && method_exists($value, 'toArray')) ? $value->toArray() : $value; }, $this->items); } /** * Convert the object into something JSON serializable. * * @return array */ #[\ReturnTypeWillChange] public function jsonSerialize(): array { return $this->toArray(); } /** * Get the collection of items as JSON. * * @param int $options * * @return string */ public function toJson(int $options = 0): string { return json_encode($this->toArray(), $options); } /** * Get an iterator for the items. * * @return ArrayIterator */ public function getIterator(): ArrayIterator { return new ArrayIterator($this->items); } /** * Get a CachingIterator instance. * * @param integer $flags Caching iterator flags * * @return \CachingIterator */ public function getCachingIterator(int $flags = CachingIterator::CALL_TOSTRING): CachingIterator { return new \CachingIterator($this->getIterator(), $flags); } /** * Count the number of items in the collection. * * @return int */ public function count(): int { return count($this->items); } /** * Determine if an item exists at an offset. * * @param mixed $key * * @return bool */ public function offsetExists($key): bool { return array_key_exists($key, $this->items); } /** * Get an item at a given offset. * * @param mixed $key * * @return mixed */ #[\ReturnTypeWillChange] public function offsetGet($key) { return $this->items[$key]; } /** * Set the item at a given offset. * * @param mixed $key * @param mixed $value * * @return void */ #[\ReturnTypeWillChange] public function offsetSet($key, $value) { if (is_null($key)) { $this->items[] = $value; } else { $this->items[$key] = $value; } } /** * Unset the item at a given offset. * * @param string $key * * @return void */ #[\ReturnTypeWillChange] public function offsetUnset($key) { unset($this->items[$key]); } /** * Convert the collection to its string representation. * * @return string */ public function __toString(): string { return $this->toJson(); } /** * Get a value retrieving callback. * * @param string $value * * @return \Closure */ protected function valueRetriever(string $value): callable { return function ($item) use ($value) { return is_object($item) ? $item->{$value} : array_get($item, $value); }; } /** * Results array of items from Collection. * * @param Collection|array $items * * @return array */ private function getIterableItemsAsArray($items): array { if ($items instanceof Collection) { $items = $items->all(); } elseif (is_object($items) && method_exists($items, 'toArray')) { $items = $items->toArray(); } return $items; } } PK zt!]T�a@3 @3 ArrayHelper.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\Utils; defined('_JEXEC') || die; /** * ArrayHelper is an array utility class for doing all sorts of odds and ends with arrays. * * Copied from Joomla Framework to avoid class name issues between Joomla! versions 3 and 4. sortObjects is not included * because it needs the UTF-8 package. If you need to use that then you should be using the Joomla! Framework's helper * anyway. */ final class ArrayHelper { /** * Private constructor to prevent instantiation of this class * * @since 1.0 */ private function __construct() { } /** * Function to convert array to integer values * * @param array $array The source array to convert * @param int|array|null $default A default value (int|array) to assign if $array is not an array * * @return int[] * * @since 1.0 */ public static function toInteger(array $array, $default = null): array { if (is_array($array)) { return array_map('intval', $array); } if ($default === null) { return []; } if (is_array($default)) { return static::toInteger($default, null); } return [(int) $default]; } /** * Utility function to map an array to a stdClass object. * * @param array $array The array to map. * @param string $class Name of the class to create * @param boolean $recursive Convert also any array inside the main array * * @return object * * @since 1.0 */ public static function toObject(array $array, string $class = 'stdClass', bool $recursive = true) { $obj = new $class; foreach ($array as $k => $v) { $obj->$k = ($recursive && is_array($v)) ? static::toObject($v, $class) : $v; } return $obj; } /** * Utility function to map an array to a string. * * @param array $array The array to map. * @param string $inner_glue The glue (optional, defaults to '=') between the key and the value. * @param string $outer_glue The glue (optional, defaults to ' ') between array elements. * @param boolean $keepOuterKey True if final key should be kept. * * @return string * * @since 1.0 */ public static function toString(array $array, string $inner_glue = '=', string $outer_glue = ' ', bool $keepOuterKey = false): string { $output = []; foreach ($array as $key => $item) { if (is_array($item)) { if ($keepOuterKey) { $output[] = $key; } // This is value is an array, go and do it again! $output[] = static::toString($item, $inner_glue, $outer_glue, $keepOuterKey); } else { $output[] = $key . $inner_glue . '"' . $item . '"'; } } return implode($outer_glue, $output); } /** * Utility function to map an object to an array * * @param object $p_obj The source object * @param boolean $recurse True to recurse through multi-level objects * @param string|null $regex An optional regular expression to match on field names * * @return array * * @since 1.0 */ public static function fromObject($p_obj, bool $recurse = true, ?string $regex = null): array { if (is_object($p_obj) || is_array($p_obj)) { return self::arrayFromObject($p_obj, $recurse, $regex); } return []; } /** * Extracts a column from an array of arrays or objects * * @param array $array The source array * @param string $valueCol The index of the column or name of object property to be used as value * It may also be NULL to return complete arrays or objects (this is * useful together with <var>$keyCol</var> to reindex the array). * @param string|null $keyCol The index of the column or name of object property to be used as key * * @return array Column of values from the source array * * @since 1.0 * @see http://php.net/manual/en/language.types.array.php * @see http://php.net/manual/en/function.array-column.php */ public static function getColumn(array $array, string $valueCol, ?string $keyCol = null): array { $result = []; foreach ($array as $item) { // Convert object to array $subject = is_object($item) ? static::fromObject($item) : $item; /* * We process arrays (and objects already converted to array) * Only if the value column (if required) exists in this item */ if (is_array($subject) && (!isset($valueCol) || isset($subject[$valueCol]))) { // Use whole $item if valueCol is null, else use the value column. $value = isset($valueCol) ? $subject[$valueCol] : $item; // Array keys can only be integer or string. Casting will occur as per the PHP Manual. if (isset($keyCol) && isset($subject[$keyCol]) && is_scalar($subject[$keyCol])) { $key = $subject[$keyCol]; $result[$key] = $value; } else { $result[] = $value; } } } return $result; } /** * Utility function to return a value from a named array or a specified default * * @param array|\ArrayAccess $array A named array or object that implements ArrayAccess * @param string $name The key to search for * @param mixed $default The default value to give if no key found * @param string $type Return type for the variable (INT, FLOAT, STRING, WORD, BOOLEAN, ARRAY) * * @return mixed * * @throws \InvalidArgumentException * @since 1.0 */ public static function getValue(array $array, string $name, $default = null, string $type = '') { if (!is_array($array) && !($array instanceof \ArrayAccess)) { throw new \InvalidArgumentException('The object must be an array or an object that implements ArrayAccess'); } $result = null; if (isset($array[$name])) { $result = $array[$name]; } // Handle the default case if (is_null($result)) { $result = $default; } // Handle the type constraint switch (strtoupper($type)) { case 'INT': case 'INTEGER': // Only use the first integer value @preg_match('/-?\d+/', $result, $matches); $result = @(int) $matches[0]; break; case 'FLOAT': case 'DOUBLE': // Only use the first floating point value @preg_match('/-?\d+(\.\d+)?/', $result, $matches); $result = @(float) $matches[0]; break; case 'BOOL': case 'BOOLEAN': $result = (bool) $result; break; case 'ARRAY': if (!is_array($result)) { $result = [$result]; } break; case 'STRING': $result = (string) $result; break; case 'WORD': $result = (string) preg_replace('#\W#', '', $result); break; case 'NONE': default: // No casting necessary break; } return $result; } /** * Takes an associative array of arrays and inverts the array keys to values using the array values as keys. * * Example: * $input = array( * 'New' => array('1000', '1500', '1750'), * 'Used' => array('3000', '4000', '5000', '6000') * ); * $output = ArrayHelper::invert($input); * * Output would be equal to: * $output = array( * '1000' => 'New', * '1500' => 'New', * '1750' => 'New', * '3000' => 'Used', * '4000' => 'Used', * '5000' => 'Used', * '6000' => 'Used' * ); * * @param array $array The source array. * * @return array * * @since 1.0 */ public static function invert(array $array): array { $return = []; foreach ($array as $base => $values) { if (!is_array($values)) { continue; } foreach ($values as $key) { // If the key isn't scalar then ignore it. if (is_scalar($key)) { $return[$key] = $base; } } } return $return; } /** * Method to determine if an array is an associative array. * * @param array $array An array to test. * * @return boolean * * @since 1.0 */ public static function isAssociative(array $array): bool { if (is_array($array)) { foreach (array_keys($array) as $k => $v) { if ($k !== $v) { return true; } } } return false; } /** * Pivots an array to create a reverse lookup of an array of scalars, arrays or objects. * * @param array $source The source array. * @param string|null $key Where the elements of the source array are objects or arrays, the key to pivot * on. * * @return array An array of arrays pivoted either on the value of the keys, or an individual key of an object or * array. * * @since 1.0 */ public static function pivot(array $source, ?string $key = null): array { $result = []; $counter = []; foreach ($source as $index => $value) { // Determine the name of the pivot key, and its value. if (is_array($value)) { // If the key does not exist, ignore it. if (!isset($value[$key])) { continue; } $resultKey = $value[$key]; $resultValue = $source[$index]; } elseif (is_object($value)) { // If the key does not exist, ignore it. if (!isset($value->$key)) { continue; } $resultKey = $value->$key; $resultValue = $source[$index]; } else { // Just a scalar value. $resultKey = $value; $resultValue = $index; } // The counter tracks how many times a key has been used. if (empty($counter[$resultKey])) { // The first time around we just assign the value to the key. $result[$resultKey] = $resultValue; $counter[$resultKey] = 1; } elseif ($counter[$resultKey] == 1) { // If there is a second time, we convert the value into an array. $result[$resultKey] = [ $result[$resultKey], $resultValue, ]; $counter[$resultKey]++; } else { // After the second time, no need to track any more. Just append to the existing array. $result[$resultKey][] = $resultValue; } } unset($counter); return $result; } /** * Multidimensional-array-safe unique test * * @param array $array The array to make unique. * * @return array * * @see http://php.net/manual/en/function.array-unique.php * @since 1.0 */ public static function arrayUnique(array $array): array { $array = array_map('serialize', $array); $array = array_unique($array); return array_map('unserialize', $array); } /** * An improved array_search that allows for partial matching of strings values in associative arrays. * * @param string $needle The text to search for within the array. * @param array $haystack Associative array to search in to find $needle. * @param boolean $caseSensitive True to search case sensitive, false otherwise. * * @return mixed Returns the matching array $key if found, otherwise false. * * @since 1.0 */ public static function arraySearch(string $needle, array $haystack, bool $caseSensitive = true) { foreach ($haystack as $key => $value) { $searchFunc = ($caseSensitive) ? 'strpos' : 'stripos'; if ($searchFunc($value, $needle) === 0) { return $key; } } return false; } /** * Method to recursively convert data to a one dimension array. * * @param array|object $array The array or object to convert. * @param string $separator The key separator. * @param string $prefix Last level key prefix. * * @return array * * @since 1.3.0 */ public static function flatten($array, string $separator = '.', string $prefix = ''): array { if ($array instanceof \Traversable) { $array = iterator_to_array($array); } elseif (is_object($array)) { $array = get_object_vars($array); } foreach ($array as $k => $v) { $key = $prefix ? ($prefix . $separator . $k) : $k; if (is_object($v) || is_array($v)) { $array = array_merge($array, static::flatten($v, $separator, $key)); } else { $array[$key] = $v; } } return $array; } /** * Utility function to map an object or array to an array * * @param mixed $item The source object or array * @param boolean $recurse True to recurse through multi-level objects * @param string $regex An optional regular expression to match on field names * * @return array * * @since 1.0 */ private static function arrayFromObject($item, bool $recurse, ?string $regex): array { if (is_object($item)) { $result = []; foreach (get_object_vars($item) as $k => $v) { if (!$regex || preg_match($regex, $k)) { $result[$k] = $recurse ? self::arrayFromObject($v, $recurse, $regex) : $v; } } return $result; } if (is_array($item)) { $result = []; foreach ($item as $k => $v) { $result[$k] = self::arrayFromObject($v, $recurse, $regex); } return $result; } return $item; } } PK zt!]� ^�� � ModelTypeHints.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\Utils; defined('_JEXEC') || die; use FOF40\Model\DataModel; /** * Generate phpDoc type hints for the magic properties and methods of your DataModels. * * Usage: * $typeHinter = new ModelTypeHints($instanceOfYourFOFDataModel); * var_dump($typeHinter->getHints()); * * This will dump the type hints you should add to the DocBlock of your DataModel class to allow IDEs such as phpStorm * to provide smart type hinting for magic property and method access. * * @package FOF40\Utils */ class ModelTypeHints { /** * The model for which to create type hints * * @var DataModel */ protected $model; /** * Name of the class. If empty will be inferred from the current object * * @var string */ protected $className; /** * Public constructor * * @param \FOF40\Model\DataModel $model The model to create hints for */ public function __construct(DataModel $model) { $this->model = $model; $this->className = get_class($model); } /** * Translates the database field type into a PHP base type * * @param string $type The type of the field * * @return string The PHP base type */ public static function getFieldType(string $type): string { // Remove parentheses, indicating field options / size (they don't matter in type detection) if (!empty($type)) { [$type,] = explode('(', $type); } $detectedType = null; switch (trim($type)) { case 'varchar': case 'text': case 'smalltext': case 'longtext': case 'char': case 'mediumtext': case 'character varying': case 'nvarchar': case 'nchar': $detectedType = 'string'; break; case 'date': case 'datetime': case 'time': case 'year': case 'timestamp': case 'timestamp without time zone': case 'timestamp with time zone': $detectedType = 'string'; break; case 'tinyint': case 'smallint': $detectedType = 'bool'; break; case 'float': case 'currency': case 'single': case 'double': $detectedType = 'float'; break; } // Sometimes we have character types followed by a space and some cruft. Let's handle them. if (is_null($detectedType) && !empty($type)) { [$type,] = explode(' ', $type); switch (trim($type)) { case 'varchar': case 'text': case 'smalltext': case 'longtext': case 'char': case 'mediumtext': case 'nvarchar': case 'nchar': $detectedType = 'string'; break; case 'date': case 'datetime': case 'time': case 'year': case 'timestamp': case 'enum': $detectedType = 'string'; break; case 'tinyint': case 'smallint': $detectedType = 'bool'; break; case 'float': case 'currency': case 'single': case 'double': $detectedType = 'float'; break; default: $detectedType = 'int'; break; } } // If all else fails assume it's an int and hope for the best if (empty($detectedType)) { $detectedType = 'int'; } return $detectedType; } /** * @param string $className */ public function setClassName(string $className): void { $this->className = $className; } /** * Return the raw hints array * * @return array * * @throws \FOF40\Model\DataModel\Relation\Exception\RelationNotFound */ public function getRawHints(): array { $model = $this->model; $hints = [ 'property' => [], 'method' => [], 'property-read' => [], ]; $hasFilters = $model->getBehavioursDispatcher()->hasObserverClass('FOF40\Model\DataModel\Behaviour\Filters'); $magicFields = [ 'enabled', 'ordering', 'created_on', 'created_by', 'modified_on', 'modified_by', 'locked_on', 'locked_by', ]; foreach ($model->getTableFields() as $fieldName => $fieldMeta) { $fieldType = static::getFieldType($fieldMeta->Type); if (!in_array($fieldName, $magicFields)) { $hints['property'][] = [$fieldType, '$' . $fieldName]; } if ($hasFilters) { $hints['method'][] = [ '$this', $fieldName . '()', $fieldName . '(' . $fieldType . ' $v)', ]; } } $relations = $model->getRelations()->getRelationNames(); $modelType = get_class($model); $modelTypeParts = explode('\\', $modelType); array_pop($modelTypeParts); $modelType = implode('\\', $modelTypeParts) . '\\'; if ($relations !== []) { foreach ($relations as $relationName) { $relationObject = $model->getRelations()->getRelation($relationName)->getForeignModel(); $relationType = get_class($relationObject); $relationType = str_replace($modelType, '', $relationType); $hints['property-read'][] = [ $relationType, '$' . $relationName, ]; } } return $hints; } /** * Returns the docblock with the magic field hints for the model class * * @return string */ public function getHints(): string { $modelName = $this->className; $text = "/**\n * Model $modelName\n *\n"; $hints = $this->getRawHints(); if (!empty($hints['property'])) { $text .= " * Fields:\n *\n"; $colWidth = 0; foreach ($hints['property'] as $hintLine) { $colWidth = max($colWidth, strlen($hintLine[0])); } $colWidth += 2; foreach ($hints['property'] as $hintLine) { $text .= " * @property " . str_pad($hintLine[0], $colWidth, ' ') . $hintLine[1] . "\n"; } $text .= " *\n"; } if (!empty($hints['method'])) { $text .= " * Filters:\n *\n"; $colWidth = 0; $col2Width = 0; foreach ($hints['method'] as $hintLine) { $colWidth = max($colWidth, strlen($hintLine[0])); $col2Width = max($col2Width, strlen($hintLine[1])); } $colWidth += 2; $col2Width += 2; foreach ($hints['method'] as $hintLine) { $text .= " * @method " . str_pad($hintLine[0], $colWidth, ' ') . str_pad($hintLine[1], $col2Width, ' ') . $hintLine[2] . "\n"; } $text .= " *\n"; } if (!empty($hints['property-read'])) { $text .= " * Relations:\n *\n"; $colWidth = 0; foreach ($hints['property-read'] as $hintLine) { $colWidth = max($colWidth, strlen($hintLine[0])); } $colWidth += 2; foreach ($hints['property-read'] as $hintLine) { $text .= " * @property " . str_pad($hintLine[0], $colWidth, ' ') . $hintLine[1] . "\n"; } $text .= " *\n"; } return $text . "**/\n"; } } PK zt!]�o<o o ViewManifestMigration.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\Utils; use FOF40\Container\Container; use Joomla\CMS\Filesystem\File; use Joomla\Filesystem\Folder; class ViewManifestMigration { /** * Migrates Joomla 4 view XML manifests into their Joomla 3 locations * * @param Container $container The FOF 4 container of the component we'll be migrating. * * @return void */ public static function migrateJoomla4MenuXMLFiles(Container $container): void { self::migrateJoomla4MenuXMLFiles_real($container->frontEndPath, $container->backEndPath); } /** * Migrates Joomla 4 view XML manifests into their Joomla 3 locations * * @param string $frontendPath Component's frontend path * @param string $backendPath Component's backend path * * @return void * @noinspection PhpUnused */ public static function migrateJoomla4MenuXMLFiles_real($frontendPath, $backendPath): void { // This only applies to Joomla 3 if (version_compare(JVERSION, '3.999.999', 'gt')) { return; } // Map modern to legacy locations $maps = [ $frontendPath . '/tmpl' => $frontendPath . '/views', $frontendPath . '/ViewTemplates' => $frontendPath . '/views', $backendPath . '/tmpl' => $backendPath . '/views', $backendPath . '/ViewTemplates' => $backendPath . '/views', ]; foreach ($maps as $source => $dest) { try { self::migrateViewXMLManifests($source, $dest); } catch (\UnexpectedValueException $e) { // This means the source folder doesn't exist. No problem! } } } /** * Removes the legacy `views` paths from the front- and backend of the component on Joomla 4 and later versions. * * @param Container $container * * @return void */ public static function removeJoomla3LegacyViews(Container $container): void { self::removeJoomla3LegacyViews_real($container->frontEndPath, $container->backEndPath); } /** * Removes the legacy `views` paths from the front- and backend of the component on Joomla 4 and later versions. * * @param string $frontendPath Component's frontend path * @param string $backendPath Component's backend path * * @return void * @noinspection PhpUnused */ public static function removeJoomla3LegacyViews_real($frontendPath, $backendPath): void { // This only applies to Joomla 4 if (version_compare(JVERSION, '3.999.999', 'le')) { return; } $legacyLocations = [ $frontendPath . '/views', $backendPath . '/views', ]; foreach ($legacyLocations as $path) { if (!is_dir($path)) { continue; } Folder::delete($path); } } /** * Migrates view manifest XML files from the source to the dest folder. * * @param string $source Source folder to scan, i.e. the `tmpl` or `ViewTemplates` folder. * @param string $dest Target folder to copy the files to, i.e. the legacy `views` folder. */ private static function migrateViewXMLManifests(string $source, string $dest): void { $di = new \DirectoryIterator($source); /** @var \DirectoryIterator $folderItem */ foreach ($di as $folderItem) { if ($folderItem->isDot() || !$folderItem->isDir()) { continue; } // Delete the metadata.xml and tmpl/*.xml files in the corresponding `views` subfolder $killLegacyFile = $dest . '/' . $folderItem->getFilename() . '/metadata.xml'; $killLegacyFolder = $dest . '/' . $folderItem->getFilename() . '/tmpl'; if (!@is_file($killLegacyFile)) { File::delete($killLegacyFile); } if (@file_exists($killLegacyFolder) && @is_dir($killLegacyFolder)) { $files = Folder::files($killLegacyFolder, '\.xml$', false, true); if (!empty($files)) { File::delete($files); } } $filesIterator = new \DirectoryIterator($folderItem->getPathname()); /** @var \DirectoryIterator $fileItem */ foreach ($filesIterator as $fileItem) { if ($fileItem->isDir()) { continue; } if ($fileItem->getExtension() != 'xml') { continue; } $destPath = $dest . '/' . $folderItem->getFilename() . (($fileItem->getFilename() == 'metadata.xml') ? '' : '/tmpl'); $destPathName = $destPath . '/' . $fileItem->getFilename(); Folder::create($destPath); File::copy($fileItem->getPathname(), $destPathName); } } } }PK zt!]` A� Buffer.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\Utils; defined('_JEXEC') || die; /** * Registers a fof:// stream wrapper */ class Buffer { /** * Buffer hash * * @var array */ public static $buffers = []; public static $canRegisterWrapper; /** * Stream position * * @var integer */ public $position = 0; /** * Buffer name * * @var string */ public $name; /** * Should I register the fof:// stream wrapper * * @return bool True if the stream wrapper can be registered */ public static function canRegisterWrapper(): bool { if (is_null(static::$canRegisterWrapper)) { static::$canRegisterWrapper = false; // Maybe the host has disabled registering stream wrappers altogether? if (!function_exists('stream_wrapper_register')) { return false; } // Check for Suhosin if (function_exists('extension_loaded')) { $hasSuhosin = extension_loaded('suhosin'); } else { $hasSuhosin = -1; // Can't detect } if ($hasSuhosin !== true) { $hasSuhosin = defined('SUHOSIN_PATCH') ? true : -1; } if (($hasSuhosin === -1) && function_exists('ini_get')) { $hasSuhosin = false; $maxIdLength = ini_get('suhosin.session.max_id_length'); if ($maxIdLength !== false) { $hasSuhosin = ini_get('suhosin.session.max_id_length') !== ''; } } // If we can't detect whether Suhosin is installed we won't proceed to prevent a White Screen of Death if ($hasSuhosin === -1) { return false; } // If Suhosin is installed but ini_get is not available we won't proceed to prevent a WSoD if ($hasSuhosin && !function_exists('ini_get')) { return false; } // If Suhosin is installed check if fof:// is whitelisted if ($hasSuhosin) { $whiteList = ini_get('suhosin.executor.include.whitelist'); // Nothing in the whitelist? I can't go on, sorry. if (empty($whiteList)) { return false; } $whiteList = explode(',', $whiteList); $whiteList = array_map(function ($x) { return trim($x); }, $whiteList); if (!in_array('fof://', $whiteList)) { return false; } } static::$canRegisterWrapper = true; } return static::$canRegisterWrapper; } /** * Function to open file or url * * @param string $path The URL that was passed * @param string $mode Mode used to open the file @see fopen * @param integer $options Flags used by the API, may be STREAM_USE_PATH and * STREAM_REPORT_ERRORS * @param string &$opened_path Full path of the resource. Used with STREAM_USE_PATH option * * @return boolean * * @see streamWrapper::stream_open */ public function stream_open(string $path, string $mode, ?int $options, ?string &$opened_path): bool { $url = parse_url($path); $this->name = $url['host'] . $url['path']; $this->position = 0; if (!isset(static::$buffers[$this->name])) { static::$buffers[$this->name] = null; } return true; } public function unlink(string $path): void { $url = parse_url($path); $name = $url['host']; if (isset(static::$buffers[$name])) { unset (static::$buffers[$name]); } } public function stream_stat(): array { return [ 'dev' => 0, 'ino' => 0, 'mode' => 0644, 'nlink' => 0, 'uid' => 0, 'gid' => 0, 'rdev' => 0, 'size' => strlen(static::$buffers[$this->name]), 'atime' => 0, 'mtime' => 0, 'ctime' => 0, 'blksize' => -1, 'blocks' => -1, ]; } /** * Read stream * * @param integer $count How many bytes of data from the current position should be returned. * * @return mixed The data from the stream up to the specified number of bytes (all data if * the total number of bytes in the stream is less than $count. Null if * the stream is empty. * * @see streamWrapper::stream_read * @since 11.1 */ public function stream_read(int $count): ?string { $ret = substr(static::$buffers[$this->name], $this->position, $count); $this->position += strlen($ret); return $ret; } /** * Write stream * * @param string $data The data to write to the stream. * * @return integer * * @see streamWrapper::stream_write * @since 11.1 */ public function stream_write(string $data): int { $left = substr(static::$buffers[$this->name], 0, $this->position); $right = substr(static::$buffers[$this->name], $this->position + strlen($data)); static::$buffers[$this->name] = $left . $data . $right; $this->position += strlen($data); return strlen($data); } /** * Function to get the current position of the stream * * @return integer * * @see streamWrapper::stream_tell * @since 11.1 */ public function stream_tell(): int { return $this->position; } /** * Function to test for end of file pointer * * @return boolean True if the pointer is at the end of the stream * * @see streamWrapper::stream_eof * @since 11.1 */ public function stream_eof(): bool { return $this->position >= strlen(static::$buffers[$this->name]); } /** * The read write position updates in response to $offset and $whence * * @param integer $offset The offset in bytes * @param integer $whence Position the offset is added to * Options are SEEK_SET, SEEK_CUR, and SEEK_END * * @return boolean True if updated * * @see streamWrapper::stream_seek * @since 11.1 */ public function stream_seek(int $offset, int $whence): bool { switch ($whence) { case SEEK_SET: if ($offset < strlen(static::$buffers[$this->name]) && $offset >= 0) { $this->position = $offset; return true; } else { return false; } break; case SEEK_CUR: if ($offset >= 0) { $this->position += $offset; return true; } else { return false; } break; case SEEK_END: if (strlen(static::$buffers[$this->name]) + $offset >= 0) { $this->position = strlen(static::$buffers[$this->name]) + $offset; return true; } else { return false; } break; default: return false; } } } if (Buffer::canRegisterWrapper()) { stream_wrapper_register('fof', 'FOF40\\Utils\\Buffer'); } PK zt!]�]T�m m MediaVersion.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\Utils; defined('_JEXEC') || die; use Exception; use FOF40\Container\Container; use JDatabaseDriver; use Joomla\CMS\Factory; use Joomla\Registry\Registry; /** * Class MediaVersion * * @since 3.5.3 */ class MediaVersion { /** * Cached the version and date of FOF-powered components * * @var array * @since 3.5.3 */ protected static $componentVersionCache = []; /** * @var string|mixed */ public $componentName; /** * The current component's container * * @var Container * @since 3.5.3 */ protected $container; /** * The configured media query version * * @var string|null; * @since 3.5.3 */ protected $mediaVersion; /** * MediaVersion constructor. * * @param Container $c The component container * * @since 3.5.3 */ public function __construct(Container $c) { $this->container = $c; } /** * Get a component's version and date * * @param string $component * @param JDatabaseDriver $db * * @return array * @since 3.5.3 */ protected static function getComponentVersionAndDate(string $component, JDatabaseDriver $db): array { if (array_key_exists($component, self::$componentVersionCache)) { return self::$componentVersionCache[$component]; } $version = '0.0.0'; $date = date('Y-m-d H:i:s'); try { $query = $db->getQuery(true) ->select([ $db->qn('manifest_cache'), ])->from($db->qn('#__extensions')) ->where($db->qn('type') . ' = ' . $db->q('component')) ->where($db->qn('name') . ' = ' . $db->q($component)); $db->setQuery($query); $json = $db->loadResult() ?? '{}'; $params = new Registry($json); $version = $params->get('version', $version); $date = $params->get('creationDate', $date); } catch (Exception $e) { } self::$componentVersionCache[$component] = [$version, $date]; return self::$componentVersionCache[$component]; } /** * Serialization helper * * This is for the benefit of legacy components which might use Joomla's JS/CSS inclusion directly passing * $container->mediaVersion as the version argument. In FOF 3.5.2 and lower that was always string or null, making * it a safe bet. In FOF 3.5.3 and later it's an object. It's not converted to a string until Joomla builds its * template header. However, Joomla's cache system will try to serialize all CSS and JS definitions, including their * parameters of which version is one. Therefore, for those legacy applications, Joomla would be trying to serialize * the MediaVersion object which would try to serialize the container. That would cause an immediate failure since * we protect the Container from being serialized. * * Our Template service knows about this and stringifies the MediaVersion before passing it to Joomla. Legacy apps * may not do that. Using the __sleep and __wakeup methods in this class we make sure that we are essentially * storing nothing but strings in the serialized representation and we reconstruct the container upon * unseralization. That said, it's a good idea to use the Template service instead of $container->mediaVersion * directly or, at the very least, use (string) $container->mediaVersion when using the Template service is not a * viable option. * * @return string[] */ public function __sleep(): array { $this->componentName = $this->container->componentName; return [ 'mediaVersion', 'componentName', ]; } /** * Unserialization helper * * @return void * @see __sleep */ public function __wakeup(): void { if (isset($this->componentName)) { $this->container = Container::getInstance($this->componentName); } } /** * Returns the media query version string * * @return string * @since 3.5.3 */ public function __toString(): string { if (empty($this->mediaVersion)) { $this->mediaVersion = $this->getDefaultMediaVersion(); } return $this->mediaVersion; } /** * Sets the media query version string * * @param string|null $mediaVersion * * @since 3.5.3 */ public function setMediaVersion(?string $mediaVersion): void { $this->mediaVersion = $mediaVersion; } /** * Returns the default media query version string if none is already defined * * @return string * @since 3.5.3 */ protected function getDefaultMediaVersion(): string { // Initialise [$version, $date] = self::getComponentVersionAndDate($this->container->componentName, $this->container->db); // Get the site's secret try { $app = Factory::getApplication(); if (method_exists($app, 'get')) { $secret = $app->get('secret'); } } catch (Exception $e) { } // Generate the version string return md5($version . $date . $secret); } }PK zt!]��cnQ Q FilesCheck.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\Utils; defined('_JEXEC') || die; use FOF40\Timer\Timer; use Joomla\CMS\Factory as JoomlaFactory; /** * A utility class to check that your extension's files are not missing and have not been tampered with. * * You need a file called fileslist.php in your component's administrator root directory with the following contents: * * $phpFileChecker = array( * 'version' => 'revCEE2DAB', * 'date' => '2014-10-16', * 'directories' => array( * 'administrator/components/com_foobar', * .... * ), * 'files' => array( * 'administrator/components/com_foobar/access.xml' => array('705', '09aa0351a316bf011ecc8c1145134761', * 'b95f00c7b49a07a60570dc674f2497c45c4e7152'), * .... * ) * ); * * All directory and file paths are relative to the site's root * * The directories array is a list of directories which must exist. The files array has the file paths as keys. The * value is a simple array containing the following elements in this order: file size in bytes, MD5 checksum, SHA1 * checksum. */ class FilesCheck { /** @var string The name of the component */ protected $option = ''; /** @var string Current component version */ protected $version; /** @var string Current component release date */ protected $date; /** @var array List of files to check as filepath => (filesize, md5, sha1) */ protected $fileList = []; /** @var array List of directories to check that exist */ protected $dirList = []; /** @var bool Is the reported component version different than the version of the #__extensions table? */ protected $wrongComponentVersion = false; /** @var bool Is the fileslist.php reporting a version different than the reported component version? */ protected $wrongFilesVersion = false; /** * Create and initialise the object * * @param string $componentName Component name, e.g. com_foobar * @param string $version The current component version, as reported by the component * @param string $date The current component release date, as reported by the component */ public function __construct(string $componentName, string $version, string $date) { // Initialise from parameters $this->option = $componentName; $this->version = $version; $this->date = $date; // Retrieve the date and version from the #__extensions table $db = JoomlaFactory::getDbo(); $query = $db->getQuery(true)->select('*')->from($db->qn('#__extensions')) ->where($db->qn('element') . ' = ' . $db->q($this->option)) ->where($db->qn('type') . ' = ' . $db->q('component')); $extension = $db->setQuery($query)->loadObject(); // Check the version and date against those from #__extensions. I hate heavily nested IFs as much as the next // guy, but what can you do... if (!is_null($extension)) { $manifestCache = $extension->manifest_cache; if (!empty($manifestCache)) { $manifestCache = json_decode($manifestCache, true); if (is_array($manifestCache) && isset($manifestCache['creationDate']) && isset($manifestCache['version'])) { // Make sure the fileslist.php version and date match the component's version if ($this->version != $manifestCache['version']) { $this->wrongComponentVersion = true; } if ($this->date != $manifestCache['creationDate']) { $this->wrongComponentVersion = true; } } } } // Try to load the fileslist.php file from the component's back-end root $filePath = JPATH_ADMINISTRATOR . '/components/' . $this->option . '/fileslist.php'; if (!file_exists($filePath)) { return; } $couldInclude = @include($filePath); // If we couldn't include the file with the array OR if it didn't define the array we have to quit. if (!$couldInclude || !isset($phpFileChecker)) { return; } // Make sure the fileslist.php version and date match the component's version if ($this->version != $phpFileChecker['version']) { $this->wrongFilesVersion = true; } if ($this->date != $phpFileChecker['date']) { $this->wrongFilesVersion = true; } // Initialise the files and directories lists $this->fileList = $phpFileChecker['files']; $this->dirList = $phpFileChecker['directories']; } /** * Is the reported component version different than the version of the #__extensions table? * * @return boolean */ public function isWrongComponentVersion(): bool { return $this->wrongComponentVersion; } /** * Is the fileslist.php reporting a version different than the reported component version? * * @return boolean */ public function isWrongFilesVersion(): bool { return $this->wrongFilesVersion; } /** * Performs a fast check of file and folders. If even one of the files/folders doesn't exist, or even one file has * the wrong file size it will return false. * * @return bool False when there are mismatched files and directories */ public function fastCheck(): bool { // Check that all directories exist foreach ($this->dirList as $directory) { $directory = JPATH_ROOT . '/' . $directory; if (!@is_dir($directory)) { return false; } } // Check that all files exist and have the right size foreach ($this->fileList as $filePath => $fileData) { $filePath = JPATH_ROOT . '/' . $filePath; if (!@file_exists($filePath)) { return false; } $fileSize = @filesize($filePath); if ($fileSize != $fileData[0]) { return false; } } return true; } /** * Performs a slow, thorough check of all files and folders (including MD5/SHA1 sum checks) * * @param int $idx The index from where to start * * @return array Progress report */ public function slowCheck(int $idx = 0): array { $ret = [ 'done' => false, 'files' => [], 'folders' => [], 'idx' => $idx, ]; $totalFiles = count($this->fileList); $totalFolders = count($this->dirList); $fileKeys = array_keys($this->fileList); $timer = new Timer(3.0, 75.0); while ($timer->getTimeLeft() && (($idx < $totalFiles) || ($idx < $totalFolders))) { if ($idx < $totalFolders) { $directory = JPATH_ROOT . '/' . $this->dirList[$idx]; if (!@is_dir($directory)) { $ret['folders'][] = $directory; } } if ($idx < $totalFiles) { $fileKey = $fileKeys[$idx]; $filePath = JPATH_ROOT . '/' . $fileKey; $fileData = $this->fileList[$fileKey]; if (!@file_exists($filePath)) { $ret['files'][] = $fileKey . ' (missing)'; } elseif (@filesize($filePath) != $fileData[0]) { $ret['files'][] = $fileKey . ' (size ' . @filesize($filePath) . ' ≠ ' . $fileData[0] . ')'; } elseif (function_exists('sha1_file')) { $fileSha1 = @sha1_file($filePath); if ($fileSha1 != $fileData[2]) { $ret['files'][] = $fileKey . ' (SHA1 ' . $fileSha1 . ' ≠ ' . $fileData[2] . ')'; } } elseif (function_exists('md5_file')) { $fileMd5 = @md5_file($filePath); if ($fileMd5 != $fileData[1]) { $ret['files'][] = $fileKey . ' (MD5 ' . $fileMd5 . ' ≠ ' . $fileData[1] . ')'; } } } $idx++; } if (($idx >= $totalFiles) && ($idx >= $totalFolders)) { $ret['done'] = true; } $ret['idx'] = $idx; return $ret; } } PK zt!]v���- - helpers.phpnu &1i� PK zt!]��J� � F- CliSessionHandler.phpnu &1i� PK zt!]�T$?=: =: R: Collection.phpnu &1i� PK zt!]T�a@3 @3 �t ArrayHelper.phpnu &1i� PK zt!]� ^�� � L� ModelTypeHints.phpnu &1i� PK zt!]�o<o o 3� ViewManifestMigration.phpnu &1i� PK zt!]` A� �� Buffer.phpnu &1i� PK zt!]�]T�m m 0� MediaVersion.phpnu &1i� PK zt!]��cnQ Q � FilesCheck.phpnu &1i� PK � l
| ver. 1.4 |
Github
|
.
| PHP 8.1.34 | Генерация страницы: 0 |
proxy
|
phpinfo
|
Настройка