MOON
Server: Apache
System: Linux server1.studioinfinity.com.br 2.6.32-954.3.5.lve1.4.90.el6.x86_64 #1 SMP Tue Feb 21 12:26:30 UTC 2023 x86_64
User: artinside (517)
PHP: 7.4.33
Disabled: exec,passthru,shell_exec,system
Upload Files
File: /home/artinside/sites.artinside.com.br/festival/vendor/aplus/helpers/src/ArraySimple.php
<?php declare(strict_types=1);
/*
 * This file is part of Aplus Framework Helpers Library.
 *
 * (c) Natan Felles <natanfelles@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Framework\Helpers;

use JetBrains\PhpStorm\Pure;

/**
 * Class ArraySimple.
 *
 * Contains methods to work with PHP arrays using "simple keys" (strings with
 * square brackets).
 *
 * Simple key format example: `parent[child1][child2]`.
 *
 * `user[country][state]` gets 'rs' in
 * `array('user' => ['country' => ['state' => 'rs']])`
 *
 * @see https://www.php.net/manual/en/language.types.array.php
 *
 * @package helpers
 */
class ArraySimple
{
    /**
     * @param string $simpleKey
     *
     * @return array<int,string>
     */
    protected static function extractKeys(string $simpleKey) : array
    {
        \preg_match_all('#\[(.*?)\]#', $simpleKey, $matches);
        return $matches[1];
    }

    /**
     * Reverts an associative array of simple keys to an native array.
     *
     * @param array<mixed> $arraySimple An array with simple keys
     *
     * @return array<string,mixed> An array with their corresponding values
     */
    public static function revert(array $arraySimple) : array
    {
        $array = [];
        foreach ($arraySimple as $simpleKey => $value) {
            $simpleKey = (string) $simpleKey;
            $parentKey = static::getParentKey($simpleKey);
            if ($parentKey === null) {
                $array[$simpleKey] = \is_array($value)
                    ? static::revert($value)
                    : $value;
                continue;
            }
            $parent = [];
            static::addChild(
                $parent,
                \array_merge([$parentKey], static::extractKeys($simpleKey)),
                $value
            );
            $array = \array_replace_recursive($array, $parent);
        }
        return $array;
    }

    /**
     * Converts an array to an associative array with simple keys.
     *
     * @param array<mixed> $array Array to be converted
     *
     * @return array<string,mixed> An associative array with the simple keys as
     * keys and their corresponding values
     */
    public static function convert(array $array) : array
    {
        $array = static::revert($array);
        $data = [];
        foreach (static::keys($array) as $key) {
            $data[$key] = static::value($key, $array);
        }
        return $data;
    }

    /**
     * Gets the value of an array item through a simple key.
     *
     * @param string $simpleKey A string in the simple key format
     * @param array<mixed> $array The array to search in
     *
     * @return mixed The item value or null if not found
     */
    public static function value(string $simpleKey, array $array) : mixed
    {
        $array = static::revert($array);
        $parentKey = static::getParentKey($simpleKey);
        if ($parentKey === null) {
            return $array[$simpleKey] ?? null;
        }
        $value = $array[$parentKey] ?? null;
        foreach (static::extractKeys($simpleKey) as $key) {
            if (!(\is_array($value) && \array_key_exists($key, $value))) {
                return null;
            }
            $value = $value[$key];
        }
        return $value;
    }

    /**
     * Gets the keys of an array in the simple keys format.
     *
     * @param array<mixed> $array The array to get the simple keys
     *
     * @return array<int,string> An indexed array containing the simple keys as
     * values
     */
    #[Pure]
    public static function keys(array $array) : array
    {
        return static::getKeys($array);
    }

    /**
     * @param array<mixed> $array
     * @param string $childKey
     *
     * @return array<int,string>
     */
    #[Pure]
    protected static function getKeys(array $array, string $childKey = '') : array
    {
        $allKeys = [];
        foreach ($array as $key => $value) {
            $key = (string) $key;
            if (\is_array($value)) {
                $allKeys = $childKey === ''
                    ? \array_merge($allKeys, static::getKeys($value, $key))
                    : \array_merge(
                        $allKeys,
                        static::getKeys($value, $childKey . static::getChildKey($key))
                    );
                continue;
            }
            $allKeys[] = $childKey === ''
                ? $key
                : $childKey . static::getChildKey($key);
        }
        return $allKeys;
    }

    /**
     * @param array<int,string> $parent
     * @param array<int,string> $childs
     * @param mixed $value
     */
    protected static function addChild(array &$parent, array $childs, mixed $value) : void
    {
        $key = \array_shift($childs);
        $key = (string) $key;
        $parent[$key] = [];
        if ($childs === []) {
            $parent[$key] = $value;
            return;
        }
        static::addChild($parent[$key], $childs, $value);
    }

    #[Pure]
    protected static function getParentKey(string $key) : ?string
    {
        $posOpen = \strpos($key, '[');
        $posClose = $posOpen ? \strpos($key, ']', $posOpen) : false;
        if ($posClose === false) {
            return null;
        }
        return \substr($key, 0, $posOpen); // @phpstan-ignore-line
    }

    #[Pure]
    protected static function getChildKey(string $key) : string
    {
        $parentKey = static::getParentKey($key);
        if ($parentKey === null) {
            return '[' . $key . ']';
        }
        $key = \explode('[', $key, 2);
        $key = '[' . $key[0] . '][' . $key[1];
        return $key;
    }

    /**
     * Get $_FILES in a re-organized way.
     *
     * NOTE: Do not use file input names as `name`, `type`, `tmp_name`, `error`,
     * `full_path` and `size` to avoid overwrite of arrays.
     *
     * @return array<string,mixed> An array ready to be used with
     * {@see ArraySimple::value()}
     */
    #[Pure]
    public static function files() : array
    {
        $files = [];
        foreach ($_FILES as $name => $values) {
            if (!isset($files[$name])) {
                $files[$name] = [];
            }
            if (!\is_array($values['error'])) {
                $files[$name] = $values;
                continue;
            }
            foreach ($values as $infoKey => $subArray) {
                $files[$name] = \array_replace_recursive(
                    $files[$name],
                    static::filesWalker($subArray, $infoKey)
                );
            }
        }
        return $files;
    }

    /**
     * @see https://stackoverflow.com/a/33261775/6027968
     *
     * @param array<mixed> $array
     * @param string $infoKey
     *
     * @return array<string,mixed>
     */
    #[Pure]
    protected static function filesWalker(array $array, string $infoKey) : array
    {
        $return = [];
        foreach ($array as $key => $value) {
            $key = (string) $key;
            if (\is_array($value)) {
                $return[$key] = static::filesWalker($value, $infoKey);
                continue;
            }
            $return[$key][$infoKey] = $value;
        }
        return $return;
    }
}