PHPackages                             gzhegow/lib - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. gzhegow/lib

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

gzhegow/lib
===========

1.0.0-rc.1764171242+20251126(5mo ago)0881↓75%7MITPHPPHP ^7.3|^8.0

Since Oct 31Pushed 5mo ago1 watchersCompare

[ Source](https://github.com/gzhegow1991/lib)[ Packagist](https://packagist.org/packages/gzhegow/lib)[ RSS](/packages/gzhegow-lib/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (7)DependenciesVersions (8)Used By (7)

Lib
===

[](#lib)

Библиотека вспомогательных функций для использования в проектах и остальных пакетах

Установить
----------

[](#установить)

```
composer require gzhegow/lib

```

Запустить тесты
---------------

[](#запустить-тесты)

```
php test.php

```

Примеры и тесты
---------------

[](#примеры-и-тесты)

```
= 70400, '
"[ FormatModule ]"

"1MB"
1048576 | TRUE

"col1;col2\n
val1;val2\n
"

"col1;col2\n
"

"[ CATCH ] The `json` should be not null"
NULL

"[ CATCH ] The `jsonc` should be not null"
NULL

[ "hello" => "world" ]
[ "hello" => "world" ]

[ "hello" => "world" ]
[ "hello" => "world" ]

"[ CATCH ] Unable to `json_decode` due to invalid JSON"
"[ CATCH ] Unable to `json_decode` due to invalid JSON"
[ 1, 3 ]
[ "hello" => "world", "foo" => "bar" ]

"[ CATCH ] The value `NULL` cannot be encoded to JSON when `allowsNull` is set to FALSE"
NULL
"NULL"

"[ CATCH ] The value `NAN` or values of type `resource` cannot be encoded to JSON"
"NAN"

"\"\u043f\u0440\u0438\u0432\u0435\u0442\""
"\"привет\""

{ object(countable(3) iterable stringable) # SimpleXMLElement }
{ object # DOMDocument }
{ object # DOMDocument }
FALSE | NULL
###
[
  [
    "[ ERROR ] expected \'>\' at line 4",
    "  Reminder",
    "{ object # LibXMLError }"
  ]
]
###
');
$test->expectStdoutIf(PHP_VERSION_ID < 70400, '
"[ FormatModule ]"

"1MB"
1048576 | TRUE

"col1;col2\n
val1;val2\n
"

"col1;col2\n
"

"[ CATCH ] The `json` should be not null"
NULL

"[ CATCH ] The `jsonc` should be not null"
NULL

[ "hello" => "world" ]
[ "hello" => "world" ]

[ "hello" => "world" ]
[ "hello" => "world" ]

"[ CATCH ] Unable to `json_decode` due to invalid JSON"
"[ CATCH ] Unable to `json_decode` due to invalid JSON"
[ 1, 3 ]
[ "hello" => "world", "foo" => "bar" ]

"[ CATCH ] The value `NULL` cannot be encoded to JSON when `allowsNull` is set to FALSE"
NULL
"NULL"

"[ CATCH ] The value `NAN` or values of type `resource` cannot be encoded to JSON"
"NAN"

"\"\u043f\u0440\u0438\u0432\u0435\u0442\""
"\"привет\""

{ object(iterable stringable) # SimpleXMLElement }
{ object # DOMDocument }
{ object # DOMDocument }
FALSE | NULL
###
[
  [
    "[ ERROR ] expected \'>\' at line 4",
    "  Reminder",
    "{ object # LibXMLError }"
  ]
]
###
');
$test->run();

// >>> TEST
// > тесты FsModule
$fn = function () use ($ffn) {
    $ffn->print('[ FsModule ]');
    echo "\n";

    $theFs = \Gzhegow\Lib\Lib::fs();
    $f = $theFs->fileSafe();

    $file = $ffn->root() . '/var/1/1/1/1.txt';
    $realpath = $f->file_put_contents($file, '123', FILE_APPEND, [], [ 0775, true ]);
    $relpath = $theFs->path_relative($realpath, $ffn->root());
    $ffn->print($relpath);

    $file = $ffn->root() . '/var/1/1/1.txt';
    $realpath = $f->file_put_contents($file, '123', FILE_APPEND, [], [ 0775, true ]);
    $relpath = $theFs->path_relative($realpath, $ffn->root());
    $ffn->print($relpath);

    $file = $ffn->root() . '/var/1/1.txt';
    $realpath = $f->file_put_contents($file, '123', FILE_APPEND, [], [ 0775, true ]);
    $relpath = $theFs->path_relative($realpath, $ffn->root());
    $ffn->print($relpath);

    echo "\n";

    $file = $ffn->root() . '/var/1/1/1/1.txt';
    $content = $f->file_get_contents($file);
    $ffn->print($content);

    echo "\n";

    $dir = $ffn->root() . '/var/1';
    foreach ( \Gzhegow\Lib\Lib::fs()->dir_walk_it($dir) as $spl ) {
        $spl->isDir()
            ? $f->rmdir($spl->getRealPath())
            : $f->unlink($spl->getRealPath());
    }
    $f->rmdir($ffn->root() . '/var/1');
};
$test = $ffn->test($fn);
$test->expectStdout('
"[ FsModule ]"

"var\1\1\1\1.txt"
"var\1\1\1.txt"
"var\1\1.txt"

"123"
');
$test->run();

// >>> TEST
// > тесты HttpModule
$fn = function () use ($ffn) {
    $ffn->print('[ HttpModule ]');
    echo "\n";

    $theHttpCookies = \Gzhegow\Lib\Lib::httpCookies();
    $theHttpCookies->set('hello', 'value', 3600, '/', null);
    $ffn->print($theHttpCookies);

    echo "\n";

    $theHttpSession = \Gzhegow\Lib\Lib::httpSession();
    // \Gzhegow\Lib\Lib::http()->disableSession();

    $theHttpSession->set('hello', 'world');
    $ffn->print($theHttpSession, $_SESSION ?? []);

    $theHttpSession->unset('hello');
    $ffn->print($theHttpSession, $_SESSION ?? []);

    echo "\n";

    $res = \Gzhegow\Lib\Lib::http()->http_accept_match(
        'text/html',
        [ 'text/html', 'application/signed-exchange' ],
    );
    $ffn->print_array_multiline($res, 3);

    $res = \Gzhegow\Lib\Lib::http()->http_accept_match(
        'text/html',
        [ 'text/html' ],
        [ 'application/signed-exchange' ]
    );
    $ffn->print_array_multiline($res, 3);

    $res = \Gzhegow\Lib\Lib::http()->http_accept_match(
        'application/signed-exchange;v=b3;q=0.7',
        [ 'text/html' ],
        [ 'application/signed-exchange' ]
    );
    $ffn->print_array_multiline($res, 3);

    $res = \Gzhegow\Lib\Lib::http()->http_accept_match(
        'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
        [ 'text/html' ],
        [ 'application/signed-exchange' ]
    );
    $ffn->print_array_multiline($res, 3);

    $res = \Gzhegow\Lib\Lib::http()->http_accept_match(
        'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
        [ 'text/html', 'application/signed-exchange' ]
    );
    $ffn->print_array_multiline($res, 3);
};
$test = $ffn->test($fn);
$test->expectStdout('
"[ HttpModule ]"

{ object # Gzhegow\Lib\Modules\Http\Cookies\DefaultCookies }

{ object # Gzhegow\Lib\Modules\Http\Session\SessionSafe\SessionSafeProxy } | [ "hello" => "world" ]
{ object # Gzhegow\Lib\Modules\Http\Session\SessionSafe\SessionSafeProxy } | []

###
[]
###
###
[
  "text/html" => [
    "1",
    []
  ]
]
###
###
[
  "application/signed-exchange" => [
    "0.7",
    [
      "v" => "b3",
      "q" => "0.7"
    ]
  ]
]
###
###
[
  "text/html" => [
    "1",
    []
  ],
  "application/signed-exchange" => [
    "0.7",
    [
      "v" => "b3",
      "q" => "0.7"
    ]
  ]
]
###
###
[
  "text/html" => [
    "1",
    []
  ],
  "application/signed-exchange" => [
    "0.7",
    [
      "v" => "b3",
      "q" => "0.7"
    ]
  ]
]
###
');
$test->run();

// >>> TEST
// > тесты ItertoolsModule
$fn = function () use ($ffn) {
    $ffn->print('[ ItertoolsModule ]');
    echo "\n";

    $it = \Gzhegow\Lib\Lib::itertools()->range_it(0, 10);
    $result = iterator_to_array($it);
    $ffn->print($result);

    echo PHP_EOL;

    $it = \Gzhegow\Lib\Lib::itertools()->range_it(0, 10);
    $it = \Gzhegow\Lib\Lib::itertools()->reversed_it($it);
    $result = iterator_to_array($it);
    $ffn->print($result);

    echo PHP_EOL;

    $it = \Gzhegow\Lib\Lib::itertools()->product_it([ 'A', 'B', 'C', 'D' ], [ 'x', 'y' ]);
    $result = iterator_to_array($it);
    $result = array_map('implode', $result);
    $ffn->print_array($result);

    echo PHP_EOL;

    $it = \Gzhegow\Lib\Lib::itertools()->product_repeat_it(3, [ '0', '1' ]);
    $result = iterator_to_array($it);
    $result = array_map('implode', $result);
    $ffn->print_array($result);

    echo PHP_EOL;

    $it = \Gzhegow\Lib\Lib::itertools()->combinations_unique_it([ 'A', 'B', 'C', 'D' ], 2);
    $result = iterator_to_array($it);
    $result = array_map('implode', $result);
    $ffn->print_array($result);

    $it = \Gzhegow\Lib\Lib::itertools()->combinations_unique_it([ '0', '1', '2', '3' ], 3);
    $result = iterator_to_array($it);
    $result = array_map('implode', $result);
    $ffn->print_array($result);

    echo PHP_EOL;

    $it = \Gzhegow\Lib\Lib::itertools()->combinations_all_it([ 'A', 'B', 'C' ], 2);
    $result = iterator_to_array($it);
    $result = array_map('implode', $result);
    $ffn->print_array($result);

    echo PHP_EOL;

    $it = \Gzhegow\Lib\Lib::itertools()->permutations_it([ 'A', 'B', 'C', 'D' ], 2);
    $result = iterator_to_array($it);
    $result = array_map('implode', $result);
    $ffn->print_array($result);

    $it = \Gzhegow\Lib\Lib::itertools()->permutations_it([ '0', '1', '2' ]);
    $result = iterator_to_array($it);
    $result = array_map('implode', $result);
    $ffn->print_array($result);
};
$test = $ffn->test($fn);
$test->expectStdout('
"[ ItertoolsModule ]"

[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]

[ 10 => 10, 9 => 9, 8 => 8, 7 => 7, 6 => 6, 5 => 5, 4 => 4, 3 => 3, 2 => 2, 1 => 1, 0 => 0 ]

[ "Ax", "Ay", "Bx", "By", "Cx", "Cy", "Dx", "Dy" ]

[ "000", "001", "010", "011", "100", "101", "110", "111" ]

[ "AB", "AC", "AD", "BC", "BD", "CD" ]
[ "012", "013", "023", "123" ]

[ "AA", "AB", "AC", "BB", "BC", "CC" ]

[ "AB", "AC", "AD", "BA", "BC", "BD", "CA", "CB", "CD", "DA", "DB", "DC" ]
[ "012", "021", "102", "120", "201", "210" ]
');
$test->run();

// >>> TEST
// > тесты NetModule
$fn = function () use ($ffn) {
    $ffn->print('[ NetModule ]');
    echo "\n";

    $ipV4List = [
        '192.168.1.10',
        '192.168.2.10',
        '10.0.0.1',
        '10.0.1.1',
    ];
    $subnetV4List = [
        '192.168.1.10/32',
        '192.168.1.10/24',
        '192.168.1.10/16',
        '10.0.0.1/32',
        '10.0.0.1/24',
        '10.0.0.1/16',
    ];

    foreach ( $ipV4List as $ip ) {
        \Gzhegow\Lib\Lib::net()->type_address_ip_v4($ip)->isOk([ &$addressIpV4 ]);

        foreach ( $subnetV4List as $subnet ) {
            \Gzhegow\Lib\Lib::net()->type_subnet_v4($subnet)->isOk([ &$subnetV4 ]);

            $status1 = \Gzhegow\Lib\Lib::net()->is_ip_in_subnet($addressIpV4, $subnetV4);
            $status2 = \Gzhegow\Lib\Lib::net()->is_ip_in_subnet_v4($addressIpV4, $subnetV4);

            $ffn->print($ip, $subnet, $status1, $status1 === $status2);
        }

        echo "\n";
    }

    $ipV6List = [
        '2001:db8::',
        '2001:db8::1',
        '2001:db8:0:1::1',
        'fe80::1',
        '::1',
    ];
    $subnetV6List = [
        '2001:db8::/128',
        '2001:db8::/64',
        'fe80::/10',
        '::1/128',
        '::/0',
    ];

    foreach ( $ipV6List as $ip ) {
        \Gzhegow\Lib\Lib::net()->type_address_ip_v6($ip)->isOk([ &$addressIpV6 ]);

        foreach ( $subnetV6List as $subnet ) {
            \Gzhegow\Lib\Lib::net()->type_subnet_v6($subnet)->isOk([ &$subnetV6 ]);

            $status1 = \Gzhegow\Lib\Lib::net()->is_ip_in_subnet($addressIpV6, $subnetV6);
            $status2 = \Gzhegow\Lib\Lib::net()->is_ip_in_subnet_v6($addressIpV6, $subnetV6);

            $ffn->print($ip, $subnet, $status1, $status1 === $status2);
        }

        echo "\n";
    }
};
$test = $ffn->test($fn);
$test->expectStdout('
"[ NetModule ]"

"192.168.1.10" | "192.168.1.10/32" | TRUE | TRUE
"192.168.1.10" | "192.168.1.10/24" | TRUE | TRUE
"192.168.1.10" | "192.168.1.10/16" | TRUE | TRUE
"192.168.1.10" | "10.0.0.1/32" | FALSE | TRUE
"192.168.1.10" | "10.0.0.1/24" | FALSE | TRUE
"192.168.1.10" | "10.0.0.1/16" | FALSE | TRUE

"192.168.2.10" | "192.168.1.10/32" | FALSE | TRUE
"192.168.2.10" | "192.168.1.10/24" | FALSE | TRUE
"192.168.2.10" | "192.168.1.10/16" | TRUE | TRUE
"192.168.2.10" | "10.0.0.1/32" | FALSE | TRUE
"192.168.2.10" | "10.0.0.1/24" | FALSE | TRUE
"192.168.2.10" | "10.0.0.1/16" | FALSE | TRUE

"10.0.0.1" | "192.168.1.10/32" | FALSE | TRUE
"10.0.0.1" | "192.168.1.10/24" | FALSE | TRUE
"10.0.0.1" | "192.168.1.10/16" | FALSE | TRUE
"10.0.0.1" | "10.0.0.1/32" | TRUE | TRUE
"10.0.0.1" | "10.0.0.1/24" | TRUE | TRUE
"10.0.0.1" | "10.0.0.1/16" | TRUE | TRUE

"10.0.1.1" | "192.168.1.10/32" | FALSE | TRUE
"10.0.1.1" | "192.168.1.10/24" | FALSE | TRUE
"10.0.1.1" | "192.168.1.10/16" | FALSE | TRUE
"10.0.1.1" | "10.0.0.1/32" | FALSE | TRUE
"10.0.1.1" | "10.0.0.1/24" | FALSE | TRUE
"10.0.1.1" | "10.0.0.1/16" | TRUE | TRUE

"2001:db8::" | "2001:db8::/128" | TRUE | TRUE
"2001:db8::" | "2001:db8::/64" | TRUE | TRUE
"2001:db8::" | "fe80::/10" | FALSE | TRUE
"2001:db8::" | "::1/128" | FALSE | TRUE
"2001:db8::" | "::/0" | TRUE | TRUE

"2001:db8::1" | "2001:db8::/128" | FALSE | TRUE
"2001:db8::1" | "2001:db8::/64" | TRUE | TRUE
"2001:db8::1" | "fe80::/10" | FALSE | TRUE
"2001:db8::1" | "::1/128" | FALSE | TRUE
"2001:db8::1" | "::/0" | TRUE | TRUE

"2001:db8:0:1::1" | "2001:db8::/128" | FALSE | TRUE
"2001:db8:0:1::1" | "2001:db8::/64" | FALSE | TRUE
"2001:db8:0:1::1" | "fe80::/10" | FALSE | TRUE
"2001:db8:0:1::1" | "::1/128" | FALSE | TRUE
"2001:db8:0:1::1" | "::/0" | TRUE | TRUE

"fe80::1" | "2001:db8::/128" | FALSE | TRUE
"fe80::1" | "2001:db8::/64" | FALSE | TRUE
"fe80::1" | "fe80::/10" | TRUE | TRUE
"fe80::1" | "::1/128" | FALSE | TRUE
"fe80::1" | "::/0" | TRUE | TRUE

"::1" | "2001:db8::/128" | FALSE | TRUE
"::1" | "2001:db8::/64" | FALSE | TRUE
"::1" | "fe80::/10" | FALSE | TRUE
"::1" | "::1/128" | TRUE | TRUE
"::1" | "::/0" | TRUE | TRUE
');
$test->run();

// >>> TEST
// > тесты NumModule
$fn = function () use ($ffn) {
    $ffn->print('[ NumModule ]');
    echo "\n";

    $values = [];
    $values[] = [
        -2.4,
        -2.04,
        -2.004,
        -1.4,
        -1.04,
        -1.004,
        -0.4,
        -0.04,
        -0.004,
        0,
        0.004,
        0.04,
        0.4,
        1.004,
        1.04,
        1.4,
        2.004,
        2.04,
        2.4,
    ];
    $values[] = [
        -2.5,
        -2.05,
        -2.005,
        -1.5,
        -1.05,
        -1.005,
        -0.5,
        -0.05,
        -0.005,
        0,
        0.005,
        0.05,
        0.5,
        1.005,
        1.05,
        1.5,
        2.005,
        2.05,
        2.5,
    ];
    $values[] = [
        -2.6,
        -2.06,
        -2.006,
        -1.6,
        -1.06,
        -1.006,
        -0.6,
        -0.06,
        -0.006,
        0,
        0.006,
        0.06,
        0.6,
        1.006,
        1.06,
        1.6,
        2.006,
        2.06,
        2.6,
    ];

    $precisions = [ 0, 2 ];

    $modes = [];
    $modes['ROUNDING'] = [
        'R_AWAY_FROM_ZERO'  => _NUM_ROUND_AWAY_FROM_ZERO,
        'R_TOWARD_ZERO'     => _NUM_ROUND_TOWARD_ZERO,
        'R_TO_POSITIVE_INF' => _NUM_ROUND_TO_POSITIVE_INF,
        'R_TO_NEGATIVE_INF' => _NUM_ROUND_TO_NEGATIVE_INF,
        'R_EVEN'            => _NUM_ROUND_EVEN,
        'R_ODD'             => _NUM_ROUND_ODD,
    ];

    // $dumpPath = $ffn->root() . '/var/dump/num_mathround_2.txt';
    // if (is_file($dumpPath)) unlink($dumpPath);

    foreach ( $values as $array ) {
        $table = [];
        foreach ( $array as $v ) {
            foreach ( $precisions as $precision ) {
                foreach ( $modes['ROUNDING'] as $n => $f ) {
                    $vString = \Gzhegow\Lib\Lib::debug()->dump_value($v);

                    $nString = ".{$precision}|{$n}";

                    $res = \Gzhegow\Lib\Lib::num()->mathround(
                        $v, $precision,
                        $f, $f
                    );

                    $resString = \Gzhegow\Lib\Lib::debug()->dump_value($res);

                    $table[$nString][$vString] = $resString;
                }
            }
        }

        // $content = \Gzhegow\Lib\Lib::debug()->print_table($table, 1);
        // file_put_contents($dumpPath, $content . "\n" . "\n", FILE_APPEND);

        // dump(\Gzhegow\Lib\Lib::debug()->print_table($table, 1));
        echo md5(serialize($table)) . "\n";
    }

    // $dumpPath = $ffn->root() . '/var/dump/num_moneyround_2.txt';
    // if (is_file($dumpPath)) unlink($dumpPath);

    foreach ( $values as $array ) {
        $table = [];
        foreach ( $array as $v ) {
            foreach ( $precisions as $precision ) {
                foreach ( $modes['ROUNDING'] as $n => $f ) {
                    $vString = \Gzhegow\Lib\Lib::debug()->dump_value($v);

                    $nString = ".{$precision}|{$n}";

                    $res = \Gzhegow\Lib\Lib::num()->moneyround(
                        $v, $precision,
                        $f, $f
                    );

                    $resString = \Gzhegow\Lib\Lib::debug()->dump_value($res);

                    $table[$nString][$vString] = $resString;
                }
            }
        }

        // $content = \Gzhegow\Lib\Lib::debug()->print_table($table, 1);
        // file_put_contents($dumpPath, $content . "\n" . "\n", FILE_APPEND);

        // dump(\Gzhegow\Lib\Lib::debug()->print_table($table, 1));
        echo md5(serialize($table)) . "\n";
    }
};
$test = $ffn->test($fn);
$test->expectStdout('
"[ NumModule ]"

99dc2eb40c3227446051e89753ba0934
badc8db5c75f326de20847505c20138d
e75e199fd051315fc60b543f9791aaba
004baa64cef208c138d4ca4bc8e01dd9
eab6474281b856dd3aa86a12d87641a4
16baaadc1d5f2445bfb4279c4a72630c
');
$test->run();

// >>> TEST
// > тесты PhpModule
$fn = function () use ($ffn) {
    $ffn->print('[ PhpModule ]');
    echo "\n";

    class PhpModuleDummy
    {
        public           $publicProperty;
        protected        $protectedProperty;
        private          $privateProperty;
        public static    $publicStaticProperty;
        protected static $protectedStaticProperty;
        private static   $privateStaticProperty;
    }

    class PhpModuleDummy1
    {
        public function publicMethod()
        {
            echo __METHOD__ . "\n";
        }

        protected function protectedMethod()
        {
            echo __METHOD__ . "\n";
        }

        private function privateMethod()
        {
            echo __METHOD__ . "\n";
        }

        public static function publicStaticMethod()
        {
            echo __METHOD__ . "\n";
        }

        protected static function protectedStaticMethod()
        {
            echo __METHOD__ . "\n";
        }

        private static function privateStaticMethod()
        {
            echo __METHOD__ . "\n";
        }
    }

    class PhpModuleDummy2
    {
        public function __call($name, $args)
        {
            echo __METHOD__ . "\n";
        }
    }

    class PhpModuleDummy3
    {
        public static function __callStatic($name, $args)
        {
            echo __METHOD__ . "\n";
        }
    }

    class PhpModuleDummy4
    {
        public function __invoke()
        {
            echo __METHOD__ . "\n";
        }
    }

    function PhpModule_dummy_function()
    {
        echo __FUNCTION__ . "\n";
    }

    $sources = [
        $classDummy = \PhpModuleDummy::class,
        $objectDummy = new \PhpModuleDummy(),
    ];
    $sourceProperties = [
        'publicProperty',
        'protectedProperty',
        'privateProperty',
        'publicStaticProperty',
        'protectedStaticProperty',
        'privateStaticProperty',
        'publicDynamicProperty',
    ];
    $sourceFlags = [
        // public, static
        [ null, null ],
        [ null, false ],
        [ null, true ],
        [ false, null ],
        [ true, null ],
        [ false, false ],
        [ true, true ],
        [ false, true ],
        [ true, false ],
    ];

    $before = error_reporting(0);
    try {
        $objectDummy->publicDynamicProperty = null;
    }
    catch ( \Throwable $e ) {
    }
    error_reporting($before);

    $table = [];
    foreach ( $sources as $src ) {
        foreach ( $sourceProperties as $sourceProperty ) {
            foreach ( $sourceFlags as [$isPublic, $isStatic] ) {
                $status = \Gzhegow\Lib\Lib::php()->property_exists(
                    $src,
                    $sourceProperty,
                    $isPublic,
                    $isStatic
                );

                $tableColPublic = null
                    ?? (($isPublic === true) ? 'PUBLIC' : null)
                    ?? (($isPublic === null) ? '?PUBLIC' : null)
                    ?? (($isPublic === false) ? '!PUBLIC' : null);

                $tableColStatic = null
                    ?? (($isStatic === true) ? 'STATIC' : null)
                    ?? (($isStatic === null) ? '?STATIC' : null)
                    ?? (($isStatic === false) ? '!STATIC' : null);

                $tableRow = $ffn->values(' / ', $src, $sourceProperty);
                $tableCol = $ffn->values(' / ', $tableColPublic, $tableColStatic);

                $table[$tableRow][$tableCol] = $ffn->value($status);
            }
        }
    }
    // dd(\Gzhegow\Lib\Lib::debug()->print_table($table, 1));
    echo md5(serialize($table)) . "\n";
    unset($table);

    echo "\n";

    $sources = [
        $classDummy = \PhpModuleDummy1::class,
        $objectDummy = new \PhpModuleDummy1(),
    ];
    $sourceMethods = [
        'publicMethod',
        'protectedMethod',
        'privateMethod',
        'publicStaticMethod',
        'protectedStaticMethod',
        'privateStaticMethod',
    ];
    $sourceFlags = [
        // public, static
        [ null, null ],
        [ true, null ],
        [ null, true ],
        [ true, true ],
        [ false, null ],
        [ null, false ],
        [ false, false ],
        [ true, false ],
        [ false, true ],
    ];

    $table = [];
    foreach ( $sources as $src ) {
        foreach ( $sourceMethods as $sourceMethod ) {
            foreach ( $sourceFlags as [$isPublic, $isStatic] ) {
                $status = \Gzhegow\Lib\Lib::php()->method_exists(
                    $src,
                    $sourceMethod,
                    $isPublic,
                    $isStatic
                );

                $tableColPublic = null
                    ?? (($isPublic === true) ? 'PUBLIC' : null)
                    ?? (($isPublic === null) ? '?PUBLIC' : null)
                    ?? (($isPublic === false) ? '!PUBLIC' : null);

                $tableColStatic = null
                    ?? (($isStatic === true) ? 'STATIC' : null)
                    ?? (($isStatic === null) ? '?STATIC' : null)
                    ?? (($isStatic === false) ? '!STATIC' : null);

                $tableRow = $ffn->values(' / ', $src, $sourceMethod);
                $tableCol = $ffn->values(' / ', $tableColPublic, $tableColStatic);

                $table[$tableRow][$tableCol] = $ffn->value($status);
            }
        }
    }
    // dd(\Gzhegow\Lib\Lib::debug()->print_table($table, 1));
    echo md5(serialize($table)) . "\n";
    unset($table);

    echo "\n";

    $sources = [
        $functionInternal = 'strlen',
        $functionUser = 'PhpModule_dummy_function',
        $closure = function () { },
        $classInternal = \stdClass::class,
        $objectInternal = new \stdClass(),
        $classDummy1 = \PhpModuleDummy1::class,
        $classDummy2 = \PhpModuleDummy2::class,
        $classDummy3 = \PhpModuleDummy3::class,
        $classDummy4 = \PhpModuleDummy4::class,
        $objectDummy1 = new PhpModuleDummy1(),
        $objectDummy2 = new PhpModuleDummy2(),
        $objectDummy3 = new PhpModuleDummy3(),
        $objectDummy4 = new PhpModuleDummy4(),
    ];

    $table1 = [];
    $table2 = [];
    $table3 = [];
    $table4 = [];
    foreach ( $sources as $src ) {
        $tableRow = $ffn->value($src);

        $status = \Gzhegow\Lib\Lib::php()->type_method_string($src)->isOk([ &$result ]);
        $table1[$tableRow]['method_string'] = $ffn->value($result);

        $status = \Gzhegow\Lib\Lib::php()->type_method_array($src)->isOk([ &$result ]);
        $table1[$tableRow]['method_array'] = $ffn->value($result);

        $status = \Gzhegow\Lib\Lib::php()->type_callable($src, null)->isOk([ &$result ]);
        $table2[$tableRow]['callable'] = $ffn->value($result);
        $table3[$tableRow]['callable'] = $ffn->value($result);
        $table4[$tableRow]['callable'] = $ffn->value($result);

        $status = \Gzhegow\Lib\Lib::php()->type_callable_object($src, null)->isOk([ &$result ]);
        $table2[$tableRow]['callable_object'] = $ffn->value($result);

        $status = \Gzhegow\Lib\Lib::php()->type_callable_object_closure($src, null)->isOk([ &$result ]);
        $table2[$tableRow]['callable_object_closure'] = $ffn->value($result);

        $status = \Gzhegow\Lib\Lib::php()->type_callable_object_invokable($src, null)->isOk([ &$result ]);
        $table2[$tableRow]['callable_object_invokable'] = $ffn->value($result);

        $status = \Gzhegow\Lib\Lib::php()->type_callable_array($src, null)->isOk([ &$result ]);
        $table3[$tableRow]['callable_array'] = $ffn->value($result);

        $status = \Gzhegow\Lib\Lib::php()->type_callable_array_method($src, null)->isOk([ &$result ]);
        $table3[$tableRow]['callable_array_method'] = $ffn->value($result);

        $status = \Gzhegow\Lib\Lib::php()->type_callable_array_method_static($src, null)->isOk([ &$result ]);
        $table3[$tableRow]['callable_array_method_static'] = $ffn->value($result);

        $status = \Gzhegow\Lib\Lib::php()->type_callable_array_method_non_static($src, null)->isOk([ &$result ]);
        $table3[$tableRow]['callable_array_method_non_static'] = $ffn->value($result);

        $status = \Gzhegow\Lib\Lib::php()->type_callable_string($src, null)->isOk([ &$result ]);
        $table4[$tableRow]['callable_string'] = $ffn->value($result);

        $status = \Gzhegow\Lib\Lib::php()->type_callable_string_function($src)->isOk([ &$result ]);
        $table4[$tableRow]['callable_string_function'] = $ffn->value($result);

        $status = \Gzhegow\Lib\Lib::php()->type_callable_string_function_internal($src)->isOk([ &$result ]);
        $table4[$tableRow]['callable_string_function_internal'] = $ffn->value($result);

        $status = \Gzhegow\Lib\Lib::php()->type_callable_string_function_non_internal($src)->isOk([ &$result ]);
        $table4[$tableRow]['callable_string_function_non_internal'] = $ffn->value($result);

        $status = \Gzhegow\Lib\Lib::php()->type_callable_string_method_static($src, null)->isOk([ &$result ]);
        $table4[$tableRow]['callable_string_method_static'] = $ffn->value($result);
    }
    // dd(\Gzhegow\Lib\Lib::debug()->print_table($table1, 1));
    // dd(\Gzhegow\Lib\Lib::debug()->print_table($table2, 1));
    // dd(\Gzhegow\Lib\Lib::debug()->print_table($table3, 1));
    // dd(\Gzhegow\Lib\Lib::debug()->print_table($table4, 1));
    echo md5(serialize($table1)) . "\n";
    echo md5(serialize($table2)) . "\n";
    echo md5(serialize($table3)) . "\n";
    echo md5(serialize($table4)) . "\n";
    unset($table1);
    unset($table2);
    unset($table3);
    unset($table4);

    echo "\n";

    $sources = [];
    $sourceClasses = [
        \PhpModuleDummy1::class,
        \PhpModuleDummy2::class,
        \PhpModuleDummy3::class,
        \PhpModuleDummy4::class,
    ];

    foreach ( $sourceClasses as $sourceClass ) {
        $sourceObject = new $sourceClass();

        $sources[0][$sourceClass] = [
            $sourceClass, // class
            $sourceObject, // object
        ];
        $sources[1][$sourceClass] = [
            $sourceClass . '::publicMethod', // 'class::publicMethod'
            $sourceClass . '::protectedMethod', // 'class::protectedMethod'
            $sourceClass . '::privateMethod', // 'class::privateMethod'
            //
            $sourceClass . '::publicStaticMethod', // 'class::publicStaticMethod'
            $sourceClass . '::protectedStaticMethod', // 'class::protectedStaticMethod'
            $sourceClass . '::privateStaticMethod', // 'class::privateStaticMethod'
            //
            $sourceClass . '::__call', // 'class::__call'
            $sourceClass . '::__callStatic', // 'class::__callStatic'
            $sourceClass . '::__invoke', // 'class::__invoke'
        ];
        $sources[2][$sourceClass] = [
            [ $sourceClass, 'publicMethod' ], // '[ class, publicMethod ]'
            [ $sourceClass, 'protectedMethod' ], // '[ class, protectedMethod ]'
            [ $sourceClass, 'privateMethod' ], // '[ class, privateMethod ]'
            //
            [ $sourceClass, 'publicStaticMethod' ], // '[ class, publicStaticMethod ]'
            [ $sourceClass, 'protectedStaticMethod' ], // '[ class, protectedStaticMethod ]'
            [ $sourceClass, 'privateStaticMethod' ], // '[ class, privateStaticMethod ]'
            //
            [ $sourceClass, '__call' ], // '[ class, __call ]'
            [ $sourceClass, '__callStatic' ], // '[ class, __callStatic ]'
            [ $sourceClass, '__invoke' ], // '[ class, __invoke ]'
        ];
        $sources[3][$sourceClass] = [
            [ $sourceObject, 'publicMethod' ], // '[ object, publicMethod ]'
            [ $sourceObject, 'protectedMethod' ], // '[ object, protectedMethod ]'
            [ $sourceObject, 'privateMethod' ], // '[ object, privateMethod ]'
            //
            [ $sourceObject, 'publicStaticMethod' ], // '[ object, publicStaticMethod ]'
            [ $sourceObject, 'protectedStaticMethod' ], // '[ object, protectedStaticMethod ]'
            [ $sourceObject, 'privateStaticMethod' ], // '[ object, privateStaticMethod ]'
            //
            [ $sourceObject, '__call' ], // '[ object, __call ]'
            [ $sourceObject, '__callStatic' ], // '[ object, __callStatic ]'
            [ $sourceObject, '__invoke' ], // '[ object, __invoke ]'
        ];
    }

    $table = [];
    foreach ( $sources as $a ) {
        foreach ( $a as $aa ) {
            foreach ( $aa as $src ) {
                $tableRow = $ffn->value($src);

                $status = \Gzhegow\Lib\Lib::php()->type_method_array($src)->isOk([ &$result ]);
                $table[$tableRow]['method_array'] = $ffn->value($result);

                $status = \Gzhegow\Lib\Lib::php()->type_method_string($src)->isOk([ &$result ]);
                $table[$tableRow]['method_string'] = $ffn->value($result);
            }
        }
    }
    // dd(\Gzhegow\Lib\Lib::debug()->print_table($table, 1));
    echo md5(serialize($table)) . "\n";
    unset($table);

    echo "\n";

    $table1 = [];
    $table2 = [];
    $table3 = [];
    foreach ( $sources as $a ) {
        foreach ( $a as $sourceClass => $aa ) {
            foreach ( $aa as $src ) {
                $tableRow = $ffn->value($src);

                $sourceScopes = [
                    'scope: global' => null,
                    'scope: local'  => $sourceClass,
                ];

                foreach ( $sourceScopes as $scopeKey => $scope ) {
                    $tableCol = $ffn->values(' / ', 'callable', $scopeKey);
                    $status = \Gzhegow\Lib\Lib::php()->type_callable($src, $scope)->isOk([ &$result ]);
                    $table1[$tableRow][$tableCol] = $ffn->value($status);
                    $table2[$tableRow][$tableCol] = $ffn->value($status);
                    $table3[$tableRow][$tableCol] = $ffn->value($status);

                    $tableCol = $ffn->values(' / ', 'callable_object', $scopeKey);
                    $status = \Gzhegow\Lib\Lib::php()->type_callable_object($src, $scope)->isOk([ &$result ]);
                    $table1[$tableRow][$tableCol] = $ffn->value($result);

                    $tableCol = $ffn->values(' / ', 'callable_object_closure', $scopeKey);
                    $status = \Gzhegow\Lib\Lib::php()->type_callable_object_closure($src, $scope)->isOk([ &$result ]);
                    $table1[$tableRow][$tableCol] = $ffn->value($result);

                    $tableCol = $ffn->values(' / ', 'callable_object_invokable', $scopeKey);
                    $status = \Gzhegow\Lib\Lib::php()->type_callable_object_invokable($src, $scope)->isOk([ &$result ]);
                    $table1[$tableRow][$tableCol] = $ffn->value($result);

                    $tableCol = $ffn->values(' / ', 'callable_array', $scopeKey);
                    $status = \Gzhegow\Lib\Lib::php()->type_callable_array($src, $scope)->isOk([ &$result ]);
                    $table2[$tableRow][$tableCol] = $ffn->value($result);

                    $tableCol = $ffn->values(' / ', 'callable_array_method', $scopeKey);
                    $status = \Gzhegow\Lib\Lib::php()->type_callable_array_method($src, $scope)->isOk([ &$result ]);
                    $table2[$tableRow][$tableCol] = $ffn->value($result);

                    $tableCol = $ffn->values(' / ', 'callable_array_method_static', $scopeKey);
                    $status = \Gzhegow\Lib\Lib::php()->type_callable_array_method_static($src, $scope)->isOk([ &$result ]);
                    $table2[$tableRow][$tableCol] = $ffn->value($result);

                    $tableCol = $ffn->values(' / ', 'callable_array_method_non_static', $scopeKey);
                    $status = \Gzhegow\Lib\Lib::php()->type_callable_array_method_non_static($src, $scope)->isOk([ &$result ]);
                    $table2[$tableRow][$tableCol] = $ffn->value($result);

                    $tableCol = $ffn->values(' / ', 'callable_string', $scopeKey);
                    $status = \Gzhegow\Lib\Lib::php()->type_callable_string($src, $scope)->isOk([ &$result ]);
                    $table3[$tableRow][$tableCol] = $ffn->value($result);

                    $tableCol = $ffn->values(' / ', 'callable_string_function', $scopeKey);
                    $status = \Gzhegow\Lib\Lib::php()->type_callable_string_function($src)->isOk([ &$result ]);
                    $table3[$tableRow][$tableCol] = $ffn->value($result);

                    $tableCol = $ffn->values(' / ', 'callable_string_function_internal', $scopeKey);
                    $status = \Gzhegow\Lib\Lib::php()->type_callable_string_function_internal($src)->isOk([ &$result ]);
                    $table3[$tableRow][$tableCol] = $ffn->value($result);

                    $tableCol = $ffn->values(' / ', 'callable_string_function_non_internal', $scopeKey);
                    $status = \Gzhegow\Lib\Lib::php()->type_callable_string_function_non_internal($src)->isOk([ &$result ]);
                    $table3[$tableRow][$tableCol] = $ffn->value($result);

                    $tableCol = $ffn->values(' / ', 'callable_string_method_static', $scopeKey);
                    $status = \Gzhegow\Lib\Lib::php()->type_callable_string_method_static($src, $scope)->isOk([ &$result ]);
                    $table3[$tableRow][$tableCol] = $ffn->value($result);
                }
            }
        }
    }
    // dd(\Gzhegow\Lib\Lib::debug()->print_table($table1, 1));
    // dd(\Gzhegow\Lib\Lib::debug()->print_table($table2, 1));
    // dd(\Gzhegow\Lib\Lib::debug()->print_table($table3, 1));
    echo md5(serialize($table1)) . "\n";
    echo md5(serialize($table2)) . "\n";
    echo md5(serialize($table3)) . "\n";
    unset($table1);
    unset($table2);
    unset($table3);
};
$test = $ffn->test($fn);
$test->expectStdout('
"[ PhpModule ]"

2f37ec97bf4a8f3de2842a958e72f8ac

3c5b07dea71adcdf1bba77a417215792

bcdbd4da5c1d80d67e8800a4bab352e4
f492869c99c9d5b081a3e6b62c2b0aab
ea13e84bea1e4178af4dfc6b33594718
ee32e6bfadc76c6ffc6ca7383f2ef63e

06ef24bf80b3dbe188d41dabcacb2027

d91da25286bd7e000367a9758699e0ca
cb145079faba3ab6cf451fe9116389ba
3c3e6efcd8ead6feb5fde9b2d9edc105
');
$test->run();

// >>> TEST
// > тесты PregModule
$fn = function () use ($ffn) {
    $ffn->print('[ PregModule ]');
    echo "\n";

    $regex = \Gzhegow\Lib\Lib::preg()->preg_quote_ord("Hello, \x00!");
    $ffn->print($regex);
    echo "\n";

    $regex = \Gzhegow\Lib\Lib::preg()->preg_escape('/', '', [ '.*' ], '');
    $ffn->print($regex);

    $regex = \Gzhegow\Lib\Lib::preg()->preg_escape_ord(null, '/', '', [ '.*' ], '');
    $ffn->print($regex);
};
$test = $ffn->test($fn);
$test->expectStdout('
"[ PregModule ]"

"\x{48}\x{65}\x{6C}\x{6C}\x{6F}\x{2C}\x{20}\x{0}\x{21}"

"/\.*\/"
"/\x{3C}\x{68}\x{74}\x{6D}\x{6C}\x{3E}.*\x{3C}\x{2F}\x{68}\x{74}\x{6D}\x{6C}\x{3E}/"
');
$test->run();

// >>> TEST
// > тесты RandomModule
$fn = function () use ($ffn) {
    $ffn->print('[ RandomModule ]');
    echo "\n";

    $uuid = \Gzhegow\Lib\Lib::random()->uuid();
    $status = \Gzhegow\Lib\Lib::random()->type_uuid($uuid)->isOk([ &$result ]);
    $ffn->print(strlen($uuid), $status);

    echo "\n";

    $rand = \Gzhegow\Lib\Lib::random()->random_bytes(16);
    $ffn->print($len = strlen($rand), $len === 16);

    $rand = \Gzhegow\Lib\Lib::random()->random_hex(16);
    $ffn->print($len = strlen($rand), $len === 32);

    $rand = \Gzhegow\Lib\Lib::random()->random_int(1, 100);
    $ffn->print(1 print(mb_strlen($rand) === 16);

    echo "\n";

    $rand = \Gzhegow\Lib\Lib::random()->random_base64_urlsafe(16);
    $status = \Gzhegow\Lib\Lib::type()
        ->base(
            rtrim($rand, '='),
            \Gzhegow\Lib\Modules\CryptModule::ALPHABET_BASE_64_RFC4648_URLSAFE
        )
        ->isOk()
    ;
    $ffn->print($status);

    $rand = \Gzhegow\Lib\Lib::random()->random_base64(16);
    $status = \Gzhegow\Lib\Lib::type()
        ->base(
            rtrim($rand, '='),
            \Gzhegow\Lib\Modules\CryptModule::ALPHABET_BASE_64_RFC4648
        )
        ->isOk()
    ;
    $ffn->print($status);

    $rand = \Gzhegow\Lib\Lib::random()->random_base62(16);
    $status = \Gzhegow\Lib\Lib::type()
        ->base(
            $rand,
            \Gzhegow\Lib\Modules\CryptModule::ALPHABET_BASE_62
        )
        ->isOk()
    ;
    $ffn->print($status);

    $rand = \Gzhegow\Lib\Lib::random()->random_base58(16);
    $status = \Gzhegow\Lib\Lib::type()
        ->base(
            $rand,
            \Gzhegow\Lib\Modules\CryptModule::ALPHABET_BASE_58
        )
        ->isOk()
    ;
    $ffn->print($status);

    $rand = \Gzhegow\Lib\Lib::random()->random_base36(16);
    $status = \Gzhegow\Lib\Lib::type()
        ->base(
            $rand,
            \Gzhegow\Lib\Modules\CryptModule::ALPHABET_BASE_36
        )
        ->isOk()
    ;
    $ffn->print($status);
};
$test = $ffn->test($fn);
$test->expectStdout('
"[ RandomModule ]"

36 | TRUE

16 | TRUE
32 | TRUE
TRUE | TRUE
TRUE

TRUE
TRUE
TRUE
TRUE
TRUE
');
$test->run();

// >>> TEST
// > тесты SocialModule
$fn = function () use ($ffn) {
    $ffn->print('[ SocialModule ]');
    echo "\n";

    $status = \Gzhegow\Lib\Lib::social()->type_email('example@gmail.com')->isOk([ &$email ]);
    $ffn->print($status, $email);
    $status = \Gzhegow\Lib\Lib::social()->type_email('example@привет.рф')->isOk([ &$email ]);
    $ffn->print($status, $email);
    $status = \Gzhegow\Lib\Lib::social()->type_email('example@привет.рф', $filters = [ 'filter_unicode' ])->isOk([ &$email ]);
    $ffn->print($status, $email);
    try {
        $status = \Gzhegow\Lib\Lib::social()->type_email('example@привет.рф', $filters = [ 'rfc' ])->isOk([ &$email ]);
    }
    catch ( \Gzhegow\Lib\Exception\Runtime\ComposerException $e ) {
        $ffn->print('[ CATCH ] ' . $e->getMessage());
    }
    echo "\n";

    $status = \Gzhegow\Lib\Lib::social()->type_email_non_fake('example@gmail.com')->isOk([ &$email ]);
    $ffn->print($status, $email);
    $status = \Gzhegow\Lib\Lib::social()->type_email_non_fake('example@привет.рф')->isOk([ &$email ]);
    $ffn->print($status, $email);
    $status = \Gzhegow\Lib\Lib::social()->type_email_non_fake('example@привет.рф', $filters = [ 'filter_unicode' ])->isOk([ &$email ]);
    $ffn->print($status, $email);
    try {
        $status = \Gzhegow\Lib\Lib::social()->type_email_non_fake('example@привет.рф', $filters = [ 'rfc' ])->isOk([ &$email ]);
    }
    catch ( \Gzhegow\Lib\Exception\Runtime\ComposerException $e ) {
        $ffn->print('[ CATCH ] ' . $e->getMessage());
    }
    echo "\n";

    $status = \Gzhegow\Lib\Lib::social()->type_email_fake('no-reply@gmail.com')->isOk([ &$email ]);
    $ffn->print($status, $email);
    $status = \Gzhegow\Lib\Lib::social()->type_email_fake('email@example.com')->isOk([ &$email ]);
    $ffn->print($status, $email);
    echo "\n";

    $phones = [
        // > номера BY
        '+375 (29) 676-48-68',
        '+375296764868',
        '375296764868',

        // > номера RU
        '+7 (862) 220-40-16',
        '+78622204016',
        '78622204016',

        // > номера, начинающиеся на 89
        '89123456789',
        '89234567890',
        '89345678901',
        '89456789012',
        '89567890123',

        // > номера, начинающиеся на 9 и имеющие 10 цифр:
        '9123456789',
        '9234567890',
        '9345678901',
        '9456789012',
        '9567890123',

        // > номера мобильных операторов:
        '9012345678', // (МегаФон)
        '9023456789', // (Билайн)
        '9034567890', // (МТС)
        '9045678901', // (Теле2)
        '9056789012', // (МегаФон)
    ];

    $fakePhones = [
        // Фейковые номера для тестирования при разработке
        '+375990000000',
        '+79990000000',
        '+19700101000000',
    ];

    foreach ( $phones as $phone ) {
        $status = \Gzhegow\Lib\Lib::social()->type_phone($phone)->isOk([ &$result ]);
        $ffn->print($phone, $status, $result);

        $status = \Gzhegow\Lib\Lib::social()->type_phone_non_fake($phone)->isOk([ &$result ]);
        $ffn->print($phone, $status, $result);

        try {
            $status = \Gzhegow\Lib\Lib::social()->type_phone_real($phone, '')->isOk([ &$result ]);
        }
        catch ( \Gzhegow\Lib\Exception\Runtime\ComposerException $e ) {
            $ffn->print('[ CATCH ] ' . $e->getMessage());
        }

        $status = \Gzhegow\Lib\Lib::social()->type_tel($phone)->isOk([ &$result ]);
        $ffn->print($phone, $status, $result);

        $status = \Gzhegow\Lib\Lib::social()->type_tel_non_fake($phone)->isOk([ &$result ]);
        $ffn->print($phone, $status, $result);

        try {
            $status = \Gzhegow\Lib\Lib::social()->type_tel_real($phone, '')->isOk([ &$result ]);
        }
        catch ( \Gzhegow\Lib\Exception\Runtime\ComposerException $e ) {
            $ffn->print('[ CATCH ] ' . $e->getMessage());
        }

        echo "\n";
    }

    $phoneManager = \Gzhegow\Lib\Lib::social()->clonePhoneManager();
    $phoneManager->usePhoneFakeDatelike(true);

    foreach ( $fakePhones as $phone ) {
        $result = $phoneManager->parsePhone($phone);
        $ffn->print($phone, $result);

        $result = $phoneManager->parsePhoneFake($phone);
        $ffn->print($phone, $result);

        $result = $phoneManager->parseTel($phone);
        $ffn->print($phone, $result);

        $result = $phoneManager->parseTelFake($phone);
        $ffn->print($phone, $result);

        echo "\n";
    }

    // $phone = $phones[0];
    //
    // $phoneManager = \Gzhegow\Lib\Lib::social()->phoneManager();
    //
    // $phoneNumberWithoutDetection = $phoneManager->parsePhoneNumber($phone);
    // $phoneNumberWithDetection = $phoneManager->parsePhoneNumber($phone, '');
    //
    // $formatE164 = $phoneManager->formatE164($phone);
    // $formatNational = $phoneManager->formatNational($phone);
    // $formatInternational = $phoneManager->formatInternational($phone);
    // $formatRFC3966 = $phoneManager->formatRFC3966($phone);
    // $formatShort = $phoneManager->formatShort($phone);
    // $formatLong = $phoneManager->formatLong($phone);
    // $getLocationNameForPhone = $phoneManager->getLocationNameForPhone($phone);
    // $getOperatorNameForPhone = $phoneManager->getOperatorNameForPhone($phone);
    // $getTimezonesForPhone = $phoneManager->getTimezonesForPhone($phone);
    //
    // var_dump([
    //     $formatE164,
    //     $formatNational,
    //     $formatInternational,
    //     $formatRFC3966,
    //     $formatShort,
    //     $formatLong,
    //     $getLocationNameForPhone,
    //     $getOperatorNameForPhone,
    //     $getTimezonesForPhone,
    // ]);
};
$test = $ffn->test($fn);
$test->expectStdout('
"[ SocialModule ]"

TRUE | "example@gmail.com"
FALSE | NULL
TRUE | "example@привет.рф"
"[ CATCH ] Please, run following commands: [ composer require egulias/email-validator ]"

TRUE | "example@gmail.com"
FALSE | NULL
TRUE | "example@привет.рф"
"[ CATCH ] Please, run following commands: [ composer require egulias/email-validator ]"

TRUE | "no-reply@gmail.com"
TRUE | "email@example.com"

"+375 (29) 676-48-68" | TRUE | "+375 (29) 676-48-68"
"+375 (29) 676-48-68" | TRUE | "+375 (29) 676-48-68"
"[ CATCH ] Please, run following commands: [ composer require giggsey/libphonenumber-for-php ]"
"+375 (29) 676-48-68" | TRUE | "+375296764868"
"+375 (29) 676-48-68" | TRUE | "+375296764868"
"[ CATCH ] Please, run following commands: [ composer require giggsey/libphonenumber-for-php ]"

"+375296764868" | TRUE | "+375296764868"
"+375296764868" | TRUE | "+375296764868"
"[ CATCH ] Please, run following commands: [ composer require giggsey/libphonenumber-for-php ]"
"+375296764868" | TRUE | "+375296764868"
"+375296764868" | TRUE | "+375296764868"
"[ CATCH ] Please, run following commands: [ composer require giggsey/libphonenumber-for-php ]"

"375296764868" | TRUE | "375296764868"
"375296764868" | TRUE | "375296764868"
"[ CATCH ] Please, run following commands: [ composer require giggsey/libphonenumber-for-php ]"
"375296764868" | TRUE | "375296764868"
"375296764868" | TRUE | "375296764868"
"[ CATCH ] Please, run following commands: [ composer require giggsey/libphonenumber-for-php ]"

"+7 (862) 220-40-16" | TRUE | "+7 (862) 220-40-16"
"+7 (862) 220-40-16" | TRUE | "+7 (862) 220-40-16"
"[ CATCH ] Please, run following commands: [ composer require giggsey/libphonenumber-for-php ]"
"+7 (862) 220-40-16" | TRUE | "+78622204016"
"+7 (862) 220-40-16" | TRUE | "+78622204016"
"[ CATCH ] Please, run following commands: [ composer require giggsey/libphonenumber-for-php ]"

"+78622204016" | TRUE | "+78622204016"
"+78622204016" | TRUE | "+78622204016"
"[ CATCH ] Please, run following commands: [ composer require giggsey/libphonenumber-for-php ]"
"+78622204016" | TRUE | "+78622204016"
"+78622204016" | TRUE | "+78622204016"
"[ CATCH ] Please, run following commands: [ composer require giggsey/libphonenumber-for-php ]"

"78622204016" | TRUE | "78622204016"
"78622204016" | TRUE | "78622204016"
"[ CATCH ] Please, run following commands: [ composer require giggsey/libphonenumber-for-php ]"
"78622204016" | TRUE | "78622204016"
"78622204016" | TRUE | "78622204016"
"[ CATCH ] Please, run following commands: [ composer require giggsey/libphonenumber-for-php ]"

"89123456789" | TRUE | "89123456789"
"89123456789" | TRUE | "89123456789"
"[ CATCH ] Please, run following commands: [ composer require giggsey/libphonenumber-for-php ]"
"89123456789" | TRUE | "89123456789"
"89123456789" | TRUE | "89123456789"
"[ CATCH ] Please, run following commands: [ composer require giggsey/libphonenumber-for-php ]"

"89234567890" | TRUE | "89234567890"
"89234567890" | TRUE | "89234567890"
"[ CATCH ] Please, run following commands: [ composer require giggsey/libphonenumber-for-php ]"
"89234567890" | TRUE | "89234567890"
"89234567890" | TRUE | "89234567890"
"[ CATCH ] Please, run following commands: [ composer require giggsey/libphonenumber-for-php ]"

"89345678901" | TRUE | "89345678901"
"89345678901" | TRUE | "89345678901"
"[ CATCH ] Please, run following commands: [ composer require giggsey/libphonenumber-for-php ]"
"89345678901" | TRUE | "89345678901"
"89345678901" | TRUE | "89345678901"
"[ CATCH ] Please, run following commands: [ composer require giggsey/libphonenumber-for-php ]"

"89456789012" | TRUE | "89456789012"
"89456789012" | TRUE | "89456789012"
"[ CATCH ] Please, run following commands: [ composer require giggsey/libphonenumber-for-php ]"
"89456789012" | TRUE | "89456789012"
"89456789012" | TRUE | "89456789012"
"[ CATCH ] Please, run following commands: [ composer require giggsey/libphonenumber-for-php ]"

"89567890123" | TRUE | "89567890123"
"89567890123" | TRUE | "89567890123"
"[ CATCH ] Please, run following commands: [ composer require giggsey/libphonenumber-for-php ]"
"89567890123" | TRUE | "89567890123"
"89567890123" | TRUE | "89567890123"
"[ CATCH ] Please, run following commands: [ composer require giggsey/libphonenumber-for-php ]"

"9123456789" | TRUE | "9123456789"
"9123456789" | TRUE | "9123456789"
"[ CATCH ] Please, run following commands: [ composer require giggsey/libphonenumber-for-php ]"
"9123456789" | TRUE | "9123456789"
"9123456789" | TRUE | "9123456789"
"[ CATCH ] Please, run following commands: [ composer require giggsey/libphonenumber-for-php ]"

"9234567890" | TRUE | "9234567890"
"9234567890" | TRUE | "9234567890"
"[ CATCH ] Please, run following commands: [ composer require giggsey/libphonenumber-for-php ]"
"9234567890" | TRUE | "9234567890"
"9234567890" | TRUE | "9234567890"
"[ CATCH ] Please, run following commands: [ composer require giggsey/libphonenumber-for-php ]"

"9345678901" | TRUE | "9345678901"
"9345678901" | TRUE | "9345678901"
"[ CATCH ] Please, run following commands: [ composer require giggsey/libphonenumber-for-php ]"
"9345678901" | TRUE | "9345678901"
"9345678901" | TRUE | "9345678901"
"[ CATCH ] Please, run following commands: [ composer require giggsey/libphonenumber-for-php ]"

"9456789012" | TRUE | "9456789012"
"9456789012" | TRUE | "9456789012"
"[ CATCH ] Please, run following commands: [ composer require giggsey/libphonenumber-for-php ]"
"9456789012" | TRUE | "9456789012"
"9456789012" | TRUE | "9456789012"
"[ CATCH ] Please, run following commands: [ composer require giggsey/libphonenumber-for-php ]"

"9567890123" | TRUE | "9567890123"
"9567890123" | TRUE | "9567890123"
"[ CATCH ] Please, run following commands: [ composer require giggsey/libphonenumber-for-php ]"
"9567890123" | TRUE | "9567890123"
"9567890123" | TRUE | "9567890123"
"[ CATCH ] Please, run following commands: [ composer require giggsey/libphonenumber-for-php ]"

"9012345678" | TRUE | "9012345678"
"9012345678" | TRUE | "9012345678"
"[ CATCH ] Please, run following commands: [ composer require giggsey/libphonenumber-for-php ]"
"9012345678" | TRUE | "9012345678"
"9012345678" | TRUE | "9012345678"
"[ CATCH ] Please, run following commands: [ composer require giggsey/libphonenumber-for-php ]"

"9023456789" | TRUE | "9023456789"
"9023456789" | TRUE | "9023456789"
"[ CATCH ] Please, run following commands: [ composer require giggsey/libphonenumber-for-php ]"
"9023456789" | TRUE | "9023456789"
"9023456789" | TRUE | "9023456789"
"[ CATCH ] Please, run following commands: [ composer require giggsey/libphonenumber-for-php ]"

"9034567890" | TRUE | "9034567890"
"9034567890" | TRUE | "9034567890"
"[ CATCH ] Please, run following commands: [ composer require giggsey/libphonenumber-for-php ]"
"9034567890" | TRUE | "9034567890"
"9034567890" | TRUE | "9034567890"
"[ CATCH ] Please, run following commands: [ composer require giggsey/libphonenumber-for-php ]"

"9045678901" | TRUE | "9045678901"
"9045678901" | TRUE | "9045678901"
"[ CATCH ] Please, run following commands: [ composer require giggsey/libphonenumber-for-php ]"
"9045678901" | TRUE | "9045678901"
"9045678901" | TRUE | "9045678901"
"[ CATCH ] Please, run following commands: [ composer require giggsey/libphonenumber-for-php ]"

"9056789012" | TRUE | "9056789012"
"9056789012" | TRUE | "9056789012"
"[ CATCH ] Please, run following commands: [ composer require giggsey/libphonenumber-for-php ]"
"9056789012" | TRUE | "9056789012"
"9056789012" | TRUE | "9056789012"
"[ CATCH ] Please, run following commands: [ composer require giggsey/libphonenumber-for-php ]"

"+375990000000" | "+375990000000"
"+375990000000" | "+375990000000"
"+375990000000" | "+375990000000"
"+375990000000" | "+375990000000"

"+79990000000" | "+79990000000"
"+79990000000" | "+79990000000"
"+79990000000" | "+79990000000"
"+79990000000" | "+79990000000"

"+19700101000000" | "+19700101000000"
"+19700101000000" | "+19700101000000"
"+19700101000000" | "+19700101000000"
"+19700101000000" | "+19700101000000"
');
$test->run();

// >>> TEST
// > тесты StrModule
$fn = function () use ($ffn) {
    $ffn->print('[ StrModule ]');
    echo "\n";

    $ffn->print(\Gzhegow\Lib\Lib::str()->lines("hello\nworld"));
    $ffn->print(\Gzhegow\Lib\Lib::str()->eol("hello\nworld"));
    $ffn->print(\Gzhegow\Lib\Lib::str()->lines('hello' . "\n" . 'world'));
    $ffn->print(\Gzhegow\Lib\Lib::str()->eol('hello' . "\n" . 'world'));
    echo "\n";

    $ffn->print(\Gzhegow\Lib\Lib::str()->strlen('Привет'));
    $ffn->print(\Gzhegow\Lib\Lib::str()->strlen('Hello'));
    $ffn->print(\Gzhegow\Lib\Lib::str()->strsize('Привет'));
    $ffn->print(\Gzhegow\Lib\Lib::str()->strsize('Hello'));
    echo "\n";

    $ffn->print(\Gzhegow\Lib\Lib::str()->lower('ПРИВЕТ'));
    $ffn->print(\Gzhegow\Lib\Lib::str()->upper('привет'));
    $ffn->print(\Gzhegow\Lib\Lib::str()->lcfirst('ПРИВЕТ'));
    $ffn->print(\Gzhegow\Lib\Lib::str()->ucfirst('привет'));
    $ffn->print(\Gzhegow\Lib\Lib::str()->lcwords('ПРИВЕТ МИР'));
    $ffn->print(\Gzhegow\Lib\Lib::str()->ucwords('привет мир'));
    echo "\n";

    $status = \Gzhegow\Lib\Lib::str()->str_starts('привет', 'ПРИ', true, [ &$substr ]);
    $ffn->print($status, $substr);
    $status = \Gzhegow\Lib\Lib::str()->str_ends('приВЕТ', 'вет', true, [ &$substr ]);
    $ffn->print($status, $substr);
    echo "\n";

    $ffn->print(\Gzhegow\Lib\Lib::str()->lcrop('азаза_привет_азаза', 'аза'));
    $ffn->print(\Gzhegow\Lib\Lib::str()->rcrop('азаза_привет_азаза', 'аза'));
    $ffn->print(\Gzhegow\Lib\Lib::str()->crop('азаза_привет_азаза', 'аза'));
    $ffn->print(\Gzhegow\Lib\Lib::str()->unlcrop('"привет"', '"'));
    $ffn->print(\Gzhegow\Lib\Lib::str()->unrcrop('"привет"', '"'));
    $ffn->print(\Gzhegow\Lib\Lib::str()->uncrop('"привет"', '"'));
    echo "\n";

    $ffn->print(\Gzhegow\Lib\Lib::str()->str_replace_limit('за', '_', 'а-зазаза-зазаза', 3));
    $ffn->print(\Gzhegow\Lib\Lib::str()->str_ireplace_limit('зА', '_', 'а-заЗАза-заЗАза', 3));
    echo "\n";

    $ffn->print(\Gzhegow\Lib\Lib::str()->camel('-hello-world-foo-bar'));
    $ffn->print(\Gzhegow\Lib\Lib::str()->camel('-helloWorldFooBar'));
    $ffn->print(\Gzhegow\Lib\Lib::str()->camel('-HelloWorldFooBar'));

    $ffn->print(\Gzhegow\Lib\Lib::str()->pascal('-hello-world-foo-bar'));
    $ffn->print(\Gzhegow\Lib\Lib::str()->pascal('-helloWorldFooBar'));
    $ffn->print(\Gzhegow\Lib\Lib::str()->pascal('-HelloWorldFooBar'));

    $ffn->print(\Gzhegow\Lib\Lib::str()->space('_Hello_WORLD_Foo_BAR'));
    $ffn->print(\Gzhegow\Lib\Lib::str()->snake('-Hello-WORLD-Foo-BAR'));
    $ffn->print(\Gzhegow\Lib\Lib::str()->kebab(' Hello WORLD Foo BAR'));

    $ffn->print(\Gzhegow\Lib\Lib::str()->space_lower('_Hello_WORLD_Foo_BAR'));
    $ffn->print(\Gzhegow\Lib\Lib::str()->snake_lower('-Hello-WORLD-Foo-BAR'));
    $ffn->print(\Gzhegow\Lib\Lib::str()->kebab_lower(' Hello WORLD Foo BAR'));

    $ffn->print(\Gzhegow\Lib\Lib::str()->space_upper('_Hello_WORLD_Foo_BAR'));
    $ffn->print(\Gzhegow\Lib\Lib::str()->snake_upper('-Hello-WORLD-Foo-BAR'));
    $ffn->print(\Gzhegow\Lib\Lib::str()->kebab_upper(' Hello WORLD Foo BAR'));
    echo "\n";

    $ffn->print(\Gzhegow\Lib\Lib::str()->prefix('primary'));
    $ffn->print(\Gzhegow\Lib\Lib::str()->prefix('unique'));
    $ffn->print(\Gzhegow\Lib\Lib::str()->prefix('index'));
    $ffn->print(\Gzhegow\Lib\Lib::str()->prefix('fulltext'));
    $ffn->print(\Gzhegow\Lib\Lib::str()->prefix('fullText'));
    $ffn->print(\Gzhegow\Lib\Lib::str()->prefix('spatialIndex'));
    echo "\n";

    $ffn->print(\Gzhegow\Lib\Lib::str()->translit_ru2ascii('привет мир'));
    $ffn->print(\Gzhegow\Lib\Lib::str()->translit_ru2ascii('+привет +мир +100 abc', '-', '+'));
    echo "\n";

    $ffn->print(\Gzhegow\Lib\Lib::str()->interpolator()->interpolate('привет {{username}}', [ 'username' => 'мир' ]));
    echo "\n";

    $ffn->print(\Gzhegow\Lib\Lib::str()->slugger()->translit(' привет мир '));
    $ffn->print(\Gzhegow\Lib\Lib::str()->slugger()->translit(' привет мир ', null, [ 'и' ]));
    $ffn->print(\Gzhegow\Lib\Lib::str()->slugger()->slug('привет мир'));
    $ffn->print(\Gzhegow\Lib\Lib::str()->slugger()->slug('привет мир', ':', [ 'и' ]));
    echo "\n";

    $ffn->print(\Gzhegow\Lib\Lib::str()->inflector()->singularize('users'));
    $ffn->print(\Gzhegow\Lib\Lib::str()->inflector()->pluralize('user'));
    echo "\n";

    $array = [
        'users.name'   => false,
        'users..name'  => false,
        'users...name' => false,
        //
        'users.1.id'   => 1,
        'users.1.name' => 'name1',
        'users.2.id'   => 2,
        'users.2.name' => 'name2',
        'users.3.id'   => 3,
        'users.3.name' => 'name3',
    ];
    $keys = array_keys($array);
    $ffn->print_array_multiline(\Gzhegow\Lib\Lib::str()->str_match('users.*.name', $keys));
    $ffn->print_array_multiline(\Gzhegow\Lib\Lib::str()->str_match('users.*.name', $keys, '*'));
    $ffn->print_array_multiline(\Gzhegow\Lib\Lib::str()->str_match('users.*.name', $keys, '*', '.'));
    echo "\n";

    $array = [
        "users\x00name"         => false,
        "users\x00\x00name"     => false,
        "users\x00\x00\x00name" => false,
        //
        "users\x001\x00id"      => 1,
        "users\x001\x00name"    => 'name1',
        "users\x002\x00id"      => 2,
        "users\x002\x00name"    => 'name2',
        "users\x003\x00id"      => 3,
        "users\x003\x00name"    => 'name3',
    ];
    $keys = array_keys($array);
    $ffn->print_array_multiline(\Gzhegow\Lib\Lib::str()->str_match("users\x00*\x00name", $keys));
    $ffn->print_array_multiline($a = \Gzhegow\Lib\Lib::str()->str_match("users\x00*\x00name", $keys, '*'));
    $ffn->print_array_multiline(\Gzhegow\Lib\Lib::str()->str_match("users\x00*\x00name", $keys, '*', "\x00"));
    echo "\n";
};
$test = $ffn->test($fn);
$test->expectStdout('
"[ StrModule ]"

[ "hello", "world" ]
"hello\n
world"
[ "hello", "world" ]
"hello\n
world"

6
5
12
5

"привет"
"ПРИВЕТ"
"пРИВЕТ"
"Привет"
"пРИВЕТ мИР"
"Привет Мир"

TRUE | "вет"
TRUE | "при"

"за_привет_азаза"
"азаза_привет_аз"
"за_привет_аз"
"\"привет\""
"\"привет\""
"\"привет\""

"а-___-зазаза"
"а-___-заЗАза"

"helloWorldFooBar"
"helloWorldFooBar"
"helloWorldFooBar"
"HelloWorldFooBar"
"HelloWorldFooBar"
"HelloWorldFooBar"
" Hello WORLD Foo BAR"
"_Hello_WORLD_Foo_BAR"
"-Hello-WORLD-Foo-BAR"
" hello world foo bar"
"_hello_world_foo_bar"
"-hello-world-foo-bar"
" HELLO WORLD FOO BAR"
"_HELLO_WORLD_FOO_BAR"
"-HELLO-WORLD-FOO-BAR"

"pri"
"unq"
"ind"
"ful"
"ful"
"spa"

"npuBeT Mup"
"+npuBeT +Mup +100 ---"

"привет мир"

" privet mir "
" prиvet mиr "
"privet-mir"
"prиvet:mиr"

[ "user" ]
[ "users" ]

###
[]
###
###
[
  "users...name",
  "users.1.name",
  "users.2.name",
  "users.3.name"
]
###
###
[
  "users.1.name",
  "users.2.name",
  "users.3.name"
]
###

###
[]
###
###
[
  "b`users\x00\x00\x00name`",
  "b`users\x001\x00name`",
  "b`users\x002\x00name`",
  "b`users\x003\x00name`"
]
###
###
[
  "b`users\x001\x00name`",
  "b`users\x002\x00name`",
  "b`users\x003\x00name`"
]
###
');
$test->run();

// >>> TEST
// > тесты UrlModule
$fn = function () use ($ffn) {
    $ffn->print('[ UrlModule ]');
    echo "\n";

    $serverHttpHost = $_SERVER['HTTP_HOST'] ?? null;
    $serverRequestUri = $_SERVER['REQUEST_URI'] ?? null;
    $serverQueryString = $_SERVER['QUERY_STRING'] ?? null;

    $hasServerHttpHost = (null === $serverHttpHost);
    $hasServerRequestUri = (null === $serverRequestUri);
    $hasServerQueryString = (null === $serverQueryString);

    $_SERVER['HTTP_HOST'] = 'test.local:80';
    $_SERVER['REQUEST_URI'] = '/';
    $_SERVER['QUERY_STRING'] = '';

    $status = \Gzhegow\Lib\Lib::url()->type_url($src = 'https://google.com/hello/world')->isOk([ &$result ]);
    $ffn->print($src, $status, $result);

    $status = \Gzhegow\Lib\Lib::url()->type_url($src = ':hello/world')->isOk([ &$result ]);
    $ffn->print($src, $status, $result);

    $status = \Gzhegow\Lib\Lib::url()->type_url($src = '/')->isOk([ &$result ]);
    $ffn->print($src, $status, $result);

    echo "\n";

    $status = \Gzhegow\Lib\Lib::url()->type_uri($src = 'https://google.com/hello/world')->isOk([ &$result ]);
    $ffn->print($src, $status, $result);

    $status = \Gzhegow\Lib\Lib::url()->type_uri($src = ':hello/world')->isOk([ &$result ]);
    $ffn->print($src, $status, $result);

    $status = \Gzhegow\Lib\Lib::url()->type_uri($src = '/')->isOk([ &$result ]);
    $ffn->print($src, $status, $result);

    echo "\n";

    $status = \Gzhegow\Lib\Lib::url()->type_host($src = 'https://google.com/hello/world')->isOk([ &$result ]);
    $ffn->print($src, $status, $result);

    $status = \Gzhegow\Lib\Lib::url()->type_host($src = ':hello/world')->isOk([ &$result ]);
    $ffn->print($src, $status, $result);

    $status = \Gzhegow\Lib\Lib::url()->type_host($src = '/')->isOk([ &$result ]);
    $ffn->print($src, $status, $result);

    echo "\n";

    $status = \Gzhegow\Lib\Lib::url()->type_domain($src = 'https://google.com/hello/world')->isOk([ &$result ]);
    $ffn->print($src, $status, $result);

    $status = \Gzhegow\Lib\Lib::url()->type_domain($src = ':hello/world')->isOk([ &$result ]);
    $ffn->print($src, $status, $result);

    $status = \Gzhegow\Lib\Lib::url()->type_domain($src = '/')->isOk([ &$result ]);
    $ffn->print($src, $status, $result);

    echo "\n";

    $status = \Gzhegow\Lib\Lib::url()->type_link($src = 'https://google.com/hello/world')->isOk([ &$result ]);
    $ffn->print($src, $status, $result);

    $status = \Gzhegow\Lib\Lib::url()->type_link($src = ':hello/world')->isOk([ &$result ]);
    $ffn->print($src, $status, $result);

    $status = \Gzhegow\Lib\Lib::url()->type_link($src = '/')->isOk([ &$result ]);
    $ffn->print($src, $status, $result);

    echo "\n";

    $status = \Gzhegow\Lib\Lib::url()->type_url($src = 'https://привет.рф/hello/текст')->isOk([ &$result ]);
    $ffn->print($src, $status, $result);

    $status = \Gzhegow\Lib\Lib::url()->type_uri($src = 'https://привет.рф/hello/текст')->isOk([ &$result ]);
    $ffn->print($src, $status, $result);

    $status = \Gzhegow\Lib\Lib::url()->type_host($src = 'https://привет.рф/hello/текст')->isOk([ &$result ]);
    $ffn->print($src, $status, $result);

    $status = \Gzhegow\Lib\Lib::url()->type_link($src = 'https://привет.рф/hello/текст')->isOk([ &$result ]);
    $ffn->print($src, $status, $result);

    echo "\n";

    $src = 'https://привет.рф/hello/текст';

    $status = \Gzhegow\Lib\Lib::url()->type_url($src, null, null, 1, 1)->isOk([ &$result ]);
    $ffn->print($src, $status, $result);

    $status = \Gzhegow\Lib\Lib::url()->type_uri($src, null, null, 1)->isOk([ &$result ]);
    $ffn->print($src, $status, $result);

    $status = \Gzhegow\Lib\Lib::url()->type_host($src, 1)->isOk([ &$result ]);
    $ffn->print($src, $status, $result);

    $status = \Gzhegow\Lib\Lib::url()->type_link($src, null, null, 1)->isOk([ &$result ]);
    $ffn->print($src, $status, $result);

    echo "\n";

    $src = 'https://привет.рф/hello/текст';

    $status = \Gzhegow\Lib\Lib::url()->type_url($src, null, null, 2, 2)->isOk([ &$result ]);
    $ffn->print($src, $status, $result);

    $status = \Gzhegow\Lib\Lib::url()->type_uri($src, null, null, 2, 2)->isOk([ &$result ]);
    $ffn->print($src, $status, $result);

    $status = \Gzhegow\Lib\Lib::url()->type_host($src, 2)->isOk([ &$result ]);
    $ffn->print($src, $status, $result);

    $status = \Gzhegow\Lib\Lib::url()->type_link($src, null, null, 2)->isOk([ &$result ]);
    $ffn->print($src, $status, $result);

    $_SERVER['HTTP_HOST'] = $serverHttpHost;
    $_SERVER['REQUEST_URI'] = $serverRequestUri;
    $_SERVER['QUERY_STRING'] = $serverQueryString;

    if ( ! $hasServerHttpHost ) unset($_SERVER['HTTP_HOST']);
    if ( ! $hasServerRequestUri ) unset($_SERVER['REQUEST_URI']);
    if ( ! $hasServerQueryString ) unset($_SERVER['QUERY_STRING']);
};
$test = $ffn->test($fn);
$test->expectStdout('
"[ UrlModule ]"

"https://google.com/hello/world" | TRUE | "https://google.com/hello/world"
":hello/world" | FALSE | NULL
"/" | FALSE | NULL

"https://google.com/hello/world" | TRUE | "https://google.com/hello/world"
":hello/world" | TRUE | ":hello/world"
"/" | TRUE | "/"

"https://google.com/hello/world" | TRUE | "https://google.com/"
":hello/world" | FALSE | NULL
"/" | FALSE | NULL

"https://google.com/hello/world" | TRUE | "google.com"
":hello/world" | FALSE | NULL
"/" | FALSE | NULL

"https://google.com/hello/world" | TRUE | "/hello/world"
":hello/world" | TRUE | ":hello/world"
"/" | TRUE | "/"

"https://привет.рф/hello/текст" | TRUE | "https://привет.рф/hello/текст"
"https://привет.рф/hello/текст" | TRUE | "https://привет.рф/hello/текст"
"https://привет.рф/hello/текст" | TRUE | "https://привет.рф/"
"https://привет.рф/hello/текст" | TRUE | "/hello/текст"

"https://привет.рф/hello/текст" | FALSE | NULL
"https://привет.рф/hello/текст" | FALSE | NULL
"https://привет.рф/hello/текст" | FALSE | NULL
"https://привет.рф/hello/текст" | FALSE | NULL

"https://привет.рф/hello/текст" | TRUE | "https://xn--b1agh1afp.xn--p1ai/hello/%D1%82%D0%B5%D0%BA%D1%81%D1%82"
"https://привет.рф/hello/текст" | TRUE | "https://xn--b1agh1afp.xn--p1ai/hello/%D1%82%D0%B5%D0%BA%D1%81%D1%82"
"https://привет.рф/hello/текст" | TRUE | "https://xn--b1agh1afp.xn--p1ai/"
"https://привет.рф/hello/текст" | TRUE | "/hello/%D1%82%D0%B5%D0%BA%D1%81%D1%82"
');
$test->run();
```

###  Health Score

34

—

LowBetter than 77% of packages

Maintenance70

Regular maintenance activity

Popularity15

Limited adoption so far

Community15

Small or concentrated contributor base

Maturity31

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~4 days

Total

7

Last Release

173d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/9737632058a51458f24049d30c2bb81485e10db0d16dad010f2d9248295dba95?d=identicon)[gzhegow](/maintainers/gzhegow)

---

Top Contributors

[![gzhegow1991](https://avatars.githubusercontent.com/u/26746829?v=4)](https://github.com/gzhegow1991 "gzhegow1991 (445 commits)")

### Embed Badge

![Health badge](/badges/gzhegow-lib/health.svg)

```
[![Health](https://phpackages.com/badges/gzhegow-lib/health.svg)](https://phpackages.com/packages/gzhegow-lib)
```

###  Alternatives

[denismitr/translit

Russian-English Yandex transliteration package primarily for making slugs

147.1k2](/packages/denismitr-translit)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
