<?php
/**
 * -------------------------------------------------------------------------
 * Miniature library of helper routines for system purposes.
 *
 * -------------------------------------------------------------------------
 *
 * Implemented constants below are:
 *     MIMIMI_CLASS_PREFIX
 *
 * Implemented routines below are:
 *     mimimiCheck
 *     mimimiCreate
 *     mimimiInclude
 *     mimimiDump
 *     mimimiModule
 *     mimimiInform
 *     mimimiCookie
 *     mimimiEnvironment
 *     mimimiFiles
 *     mimimiGet
 *     mimimiPost
 *     mimimiRequest
 *     mimimiServer
 *     mimimiSession
 *     mimimiStop
 *     mimimiSite
 *     mimimiRoot
 *     mimimiUri
 *     mimimiFolders
 *     mimimiRandomId
 *
 * -------------------------------------------------------------------------
 *
 * @package    MimimiFramework
 * @subpackage Core
 * @copyright  2022 MiMiMi Community
 *             https://mimimi.software/
 * @license    CC BY 4
 *             https://www.creativecommons.org/licenses/by/4.0
 * -------------------------------------------------------------------------
 */

    /* =========================================================
    |                                                          |
    |   Define some constants                                  |
    |                                                          |
    ========================================================= */

    define('MIMIMI_CLASS_PREFIX', 'Mimimi');

    /* =========================================================
    |                                                          |
    |   Define a global routine to check for the existence     |
    |   of main constants                                      |
    |                                                          |
    |   ----------------------------------------------------   |
    |                                                          |
    |   Input parameters:                                      |
    |       NONE                                               |
    |                                                          |
    |   ----------------------------------------------------   |
    |                                                          |
    |   Output parameters:                                     |
    |       NONE                                               |
    |                                                          |
    ========================================================= */

    function mimimiCheck () {
        $subject = 'Technical problem on [site]';

        /* -------------------------------------
        |                                      |
        |   Build a plan for testing           |
        |                                      |
        ------------------------------------- */

        $plan = array(
            'MIMIMI_CORE_VERSION'   => 'index.php',
            'MIMIMI_CORE_FOLDER'    => 'index.php',
            'MIMIMI_MODULES_FOLDER' => 'index.php',
            'MIMIMI_APP_FOLDER'     => 'index.php',
            'MIMIMI_INSTALL_FOLDER' => 'index.php',

            'MIMIMI_DATABASE_DRIVER'       => 'Config.php',
            'MIMIMI_DATABASE_HOST'         => 'Config.php',
            'MIMIMI_DATABASE_PORT'         => 'Config.php',
            'MIMIMI_DATABASE_USER'         => 'Config.php',
            'MIMIMI_DATABASE_PASSWORD'     => 'Config.php',
            'MIMIMI_DATABASE_NAME'         => 'Config.php',
            'MIMIMI_DATABASE_TABLE_PREFIX' => 'Config.php',
            'MIMIMI_DATABASE_CHARSET'      => 'Config.php',
            'MIMIMI_DATABASE_COLLATION'    => 'Config.php',

            'MIMIMI_EMAILS_FOR_WEBMASTER'       => 'Config.php',
            'MIMIMI_EMAILS_FOR_CONTENT_MASTER'  => 'Config.php',
            'MIMIMI_EMAILS_FOR_TRAFFIC_MASTER'  => 'Config.php',
            'MIMIMI_EMAILS_FOR_SECURITY_MASTER' => 'Config.php',

            'MIMIMI_CLASS_PREFIX' => 'Routines.php'
        );

        /* -------------------------------------
        |                                      |
        |   Try to test the constant by plan   |
        |                                      |
        ------------------------------------- */

        foreach ($plan as $name => $file) {
            if (!defined($name)) {

                /* -----------------------------
                |                              |
                |   Inform your masters        |
                |                              |
                ----------------------------- */

                $msg = 'ERROR: Required constant ' . $name . ' at the file ' . $file . ' not defined!';
                $constant = 'MIMIMI_EMAILS_FOR_WEBMASTER';
                if (defined($constant)) {
                    mimimiInform(
                        $subject,
                        $msg,
                        constant($constant)
                    );
                }

                /* -----------------------------
                |                              |
                |   Inform the user            |
                |                              |
                ----------------------------- */

                mimimiStop($msg);
            }
        }
    }

    /* =========================================================
    |                                                          |
    |   Define a global routine to load a named module as      |
    |   the same property of the parent module                 |
    |                                                          |
    |   ----------------------------------------------------   |
    |                                                          |
    |   Input parameters:                                      |
    |       $name    = STRING  = name of object property       |
    |       $owner   = OBJECT  = reference to the parent module|
    |       $testing = BOOLEAN = TRUE if it is a test          |
    |                                                          |
    |   ----------------------------------------------------   |
    |                                                          |
    |   Output parameters:                                     |
    |       BOOLEAN = if it is a test                          |
    |       NONE    = if it isn't a test                       |
    |                                                          |
    ========================================================= */

    function mimimiCreate ( $name, $owner = NULL, $testing = FALSE ) {
        $constant = 'MIMIMI_EMAILS_FOR_WEBMASTER';
        $subject = 'Technical problem on [site]';

        $path = dirname(__FILE__) . '/../';
        $extension = '.php';

        /* -------------------------------------
        |                                      |
        |   Compute a parent path              |
        |                                      |
        ------------------------------------- */

        $isOwner = !empty($owner);
        $ownerPath = $isOwner
                     ? preg_replace('~^[^/]*/+~u', '', $owner->getNodePath())
                     : '';

        /* -------------------------------------
        |                                      |
        |   Convert a module name to CamelCase |
        |                                      |
        ------------------------------------- */

        $module = preg_replace('/[\W_]+/u', ' ', $name);
        $module = preg_replace('/(^\s+|\s+$)/u', '', $module);
        $module = mb_convert_case($module, MB_CASE_TITLE, 'UTF-8');
        $module = preg_replace('/\s/u', '', $module);

        /* -------------------------------------
        |                                      |
        |   Build a plan for loading           |
        |                                      |
        ------------------------------------- */

        $plan = array(
            MIMIMI_INSTALL_FOLDER => 'My',
            MIMIMI_APP_FOLDER     => 'My',
            MIMIMI_MODULES_FOLDER => '',
            MIMIMI_CORE_FOLDER    => ''
        );

        /* -------------------------------------
        |                                      |
        |   Try to load the module by plan     |
        |                                      |
        ------------------------------------- */

        foreach ($plan as $folder => $class) {
            $folder .= $isOwner
                       ? ( $ownerPath . $module . '/' )
                       : '';
            $file = $path . $folder . $module . $extension;
            if (file_exists($file)) {

                /* -----------------------------
                |                              |
                |   Try to test (if this mode) |
                |                              |
                ----------------------------- */

                $class .= MIMIMI_CLASS_PREFIX . preg_replace('~/~u', '', $ownerPath) . $module;
                if ($testing) {
                    if (class_exists($class)) return TRUE;
                    $file = @ file_get_contents($file);
                    return is_string($file) &&
                           preg_match('/[\s;]class\s+' . $class . '[\s\{]/ui', ' ' . $file);
                }

                /* -----------------------------
                |                              |
                |   Try to create its object   |
                |                              |
                ----------------------------- */

                try {
                    require_once($file);
                } catch (Exception $e) { }
                if (class_exists($class)) {
                    if ($isOwner) {
                        $owner->$name = new $class($owner);
                        return $owner->$name;
                    }
                    return new $class();
                }

                /* -----------------------------
                |                              |
                |   Else infrom your masters   |
                |                              |
                ----------------------------- */

                $msg = 'ERROR: The "' . $folder . $module . $extension . '" file does not have the required class ' . $class . '!';
                if (defined($constant)) {
                    mimimiInform(
                        $subject,
                        $msg,
                        constant($constant)
                    );
                }

                /* -----------------------------
                |                              |
                |   Show that error to user    |
                |                              |
                ----------------------------- */

                mimimiStop($msg);
            }
        }

        /* -------------------------------------
        |                                      |
        |   No more actions in test mode       |
        |                                      |
        ------------------------------------- */

        if ($testing) {
            return FALSE;
        }

        /* -------------------------------------
        |                                      |
        |   Otherwise inform your masters      |
        |                                      |
        ------------------------------------- */

        $msg = 'ERROR: The "' . $folder . $module . $extension . '" file not found!';
        if (defined($constant)) {
            mimimiInform(
                $subject,
                $msg,
                constant($constant)
            );
        }

        /* -------------------------------------
        |                                      |
        |   Show that error to user            |
        |                                      |
        ------------------------------------- */

        mimimiStop($msg);
    }

    /**
     * ---------------------------------------------------------------------
     * Global routine to load a required PHP file.
     *
     * Please note that these varaibles will be available in the loaded
     * file: $params, $folder, $filename, $file.
     *
     * @public
     * @param   string  $filename  Relative path and name, for example, Hello/Hello.php.
     * @param   bool    $fromCore  True  if look in the CORE folder,
     *                             False if look in the APP folder,
     *                             Null  if look in both folders.
     * @param   bool    $once      True  if only on first call,
     *                             False if load on every call.
     * @param   mixed   $params    Some parameters from the calling file.
     * @return  void
     * ---------------------------------------------------------------------
     */

    if ( ! function_exists('mimimiInclude') ) {
        function mimimiInclude ( $filename, $fromCore = TRUE, $once = TRUE, $params = FALSE ) {
            $path = dirname(__FILE__) . '/../';

            /* ---------------------------------
            |                                  |
            |   Build a plan for loading       |
            |                                  |
            --------------------------------- */

            $plan = array(
                MIMIMI_INSTALL_FOLDER => $fromCore !== TRUE,
                MIMIMI_APP_FOLDER     => $fromCore !== TRUE,
                MIMIMI_MODULES_FOLDER => $fromCore !== FALSE,
                MIMIMI_CORE_FOLDER    => $fromCore !== FALSE
            );

            /* ---------------------------------
            |                                  |
            |   Loop through plan's items      |
            |                                  |
            --------------------------------- */

            foreach ($plan as $folder => $enabled) {
                if ($enabled) {
                    $file = $path . $folder . $filename;
                    if (file_exists($file)) {

                        /* ---------------------
                        |                      |
                        |   Prepare input vars |
                        |                      |
                        --------------------- */

                        unset($path);
                        unset($enabled);
                        unset($fromCore);
                        unset($plan);
                        global $app;

                        /* -------------------------
                        |                          |
                        |   Try to load the file   |
                        |                          |
                        ------------------------- */

                        if ($once) {
                            unset($once);
                            try {
                                include_once($file);
                            } catch (Exception $e) { }
                        } else {
                            unset($once);
                            try {
                                include($file);
                            } catch (Exception $e) { }
                        }
                        break;
                    }
                }
            }
        }
    }

    /* =========================================================
    |                                                          |
    |   Define a global routine to output a required THEME'S   |
    |   TEXTUAL file                                           |
    |                                                          |
    |   ----------------------------------------------------   |
    |                                                          |
    |   Input parameters:                                      |
    |       $filename = STRING   = relative path and name,     |
    |                              for example, css/style.css  |
    |       $fromCore = BOOLEAN  = TRUE  if look in CORE folder|
    |                            = FALSE if look in APP folder |
    |                            = NULL if look in both folders|
    |       $toDisplay = BOOLEAN = TRUE if echo it to browser  |
    |                              FALSE if returns as result  |
    |                                                          |
    |   ----------------------------------------------------   |
    |                                                          |
    |   Output parameters:                                     |
    |       STRING = empty string if $toDisplay is TRUE,       |
    |                file content if $toDisplay is FALSE       |
    |                                                          |
    ========================================================= */

    if ( ! function_exists('mimimiDump') ) {
        function mimimiDump ( $filename, $fromCore = FALSE, $toDisplay = TRUE ) {
            $path = dirname(__FILE__) . '/../';
            $theme = 'Themes/' .
                     (
                         $fromCore
                         ? MIMIMI_CORE_THEME
                         : MIMIMI_APP_THEME
                     ) .
                     '/';

            /* ---------------------------------
            |                                  |
            |   Build a plan for dumping       |
            |                                  |
            --------------------------------- */

            $plan = array(
                MIMIMI_INSTALL_FOLDER => $fromCore !== TRUE,
                MIMIMI_APP_FOLDER     => $fromCore !== TRUE,
                MIMIMI_MODULES_FOLDER => $fromCore !== FALSE,
                MIMIMI_CORE_FOLDER    => $fromCore !== FALSE
            );

            /* ---------------------------------
            |                                  |
            |   Loop through plan's items      |
            |                                  |
            --------------------------------- */

            $result = '';
            foreach ($plan as $folder => $enabled) {
                if ($enabled) {
                    $file = $path . $folder . $theme . $filename;
                    if (file_exists($file)) {

                        /* -------------------------
                        |                          |
                        |   Try to dump the file   |
                        |                          |
                        ------------------------- */

                        if ($toDisplay) {
                            readfile($file);
                        } else {
                            $result = file_get_contents($file);
                        }
                        break;
                    }
                }
            }
            return $result;
        }
    }

    /**
     * ---------------------------------------------------------------------
     * Global routine to load a required THEME'S TEMPLATE file.
     *
     * Note: This routine should be considered as syntactic sugar to be used
     *       only in the theme files of the framework's modified version.
     *
     * @public
     * @param   string|array  $filename  STRING Relative path and name, for example, blocks/header.php.
     *                                   ARRAY  The first item is a relative path and name, other items are the input parameters.
     * @param   bool          $fromCore  True if look in the CORE folder,
     *                                   False if look in the APP folder.
     * @return  void
     * ---------------------------------------------------------------------
     */

    if ( ! function_exists('mimimiModule') ) {
        function mimimiModule ( $filename, $fromCore = FALSE ) {
            $params = FALSE;
            if ( is_array($filename) ) {
                $params = $filename;
                $filename = array_shift($params);
                if ( is_array($params) ) {
                    if ( count($params) == 1 ) {
                        $params = reset($params);
                    }
                }
            }
            if ( is_string($filename) ) {
                $theme = 'Themes/' .
                         (
                             $fromCore
                             ? MIMIMI_CORE_THEME
                             : MIMIMI_APP_THEME
                         ) .
                         '/';
                mimimiInclude(
                    $theme . $filename,
                    $fromCore == TRUE,
                    FALSE,
                    $params
                );
            }
        }
    }

    /**
     * ---------------------------------------------------------------------
     * Global routine to inform your masters by email.
     *
     * @public
     * @param   string  $subject  Title of the letter.
     * @param   string  $message  Your message to the master.
     * @param   string  $to       Comma-separated list of emails.
     * @param   array   $details  Optional details.
     * @return  void
     * ---------------------------------------------------------------------
     */

    if ( ! function_exists('mimimiInform') ) {
        function mimimiInform ( $subject, $message, $to, $details = array() ) {
        }
    }

    /* =========================================================
    |                                                          |
    |   Define a global routine to retrieve a named COOKIE's   |
    |   parameter                                              |
    |                                                          |
    |   ----------------------------------------------------   |
    |                                                          |
    |   Input parameters:                                      |
    |       $param = STRING = name of the parameter            |
    |       $def   = MIXED  = a default value                  |
    |                                                          |
    |   ----------------------------------------------------   |
    |                                                          |
    |   Output parameters:                                     |
    |       MIXED = retrieved parameter                        |
    |                                                          |
    ========================================================= */

    if ( ! function_exists('mimimiCookie') ) {
        function mimimiCookie ( $param, $def = NULL ) {
            return isset($_COOKIE[$param])
                   ? $_COOKIE[$param]
                   : $def;
        }
    }

    /* =========================================================
    |                                                          |
    |   Define a global routine to retrieve a named ENV's      |
    |   parameter                                              |
    |                                                          |
    |   ----------------------------------------------------   |
    |                                                          |
    |   Input parameters:                                      |
    |       $param = STRING = name of the parameter            |
    |       $def   = MIXED  = a default value                  |
    |                                                          |
    |   ----------------------------------------------------   |
    |                                                          |
    |   Output parameters:                                     |
    |       MIXED = retrieved parameter                        |
    |                                                          |
    ========================================================= */

    if ( ! function_exists('mimimiEnvironment') ) {
        function mimimiEnvironment ( $param, $def = '' ) {
            return isset($_ENV[$param])
                   ? $_ENV[$param]
                   : $def;
        }
    }

    /* =========================================================
    |                                                          |
    |   Define a global routine to retrieve a named FILES's    |
    |   parameter                                              |
    |                                                          |
    |   ----------------------------------------------------   |
    |                                                          |
    |   Input parameters:                                      |
    |       $param = STRING = name of the parameter            |
    |       $def   = MIXED  = a default value                  |
    |                                                          |
    |   ----------------------------------------------------   |
    |                                                          |
    |   Output parameters:                                     |
    |       MIXED = retrieved parameter                        |
    |                                                          |
    ========================================================= */

    if ( ! function_exists('mimimiFiles') ) {
        function mimimiFiles ( $param, $def = NULL ) {
            return isset($_FILES[$param])
                   ? $_FILES[$param]
                   : $def;
        }
    }

    /* =========================================================
    |                                                          |
    |   Define a global routine to retrieve a named GET's      |
    |   parameter                                              |
    |                                                          |
    |   ----------------------------------------------------   |
    |                                                          |
    |   Input parameters:                                      |
    |       $param = STRING = name of the parameter            |
    |       $def   = MIXED  = a default value                  |
    |                                                          |
    |   ----------------------------------------------------   |
    |                                                          |
    |   Output parameters:                                     |
    |       MIXED = retrieved parameter                        |
    |                                                          |
    ========================================================= */

    if ( ! function_exists('mimimiGet') ) {
        function mimimiGet ( $param, $def = '' ) {
            return isset($_GET[$param])
                   ? $_GET[$param]
                   : $def;
        }
    }

    /* =========================================================
    |                                                          |
    |   Define a global routine to retrieve a named POST's     |
    |   parameter                                              |
    |                                                          |
    |   ----------------------------------------------------   |
    |                                                          |
    |   Input parameters:                                      |
    |       $param = STRING = name of the parameter            |
    |       $def   = MIXED  = a default value                  |
    |                                                          |
    |   ----------------------------------------------------   |
    |                                                          |
    |   Output parameters:                                     |
    |       MIXED = retrieved parameter                        |
    |                                                          |
    ========================================================= */

    if ( ! function_exists('mimimiPost') ) {
        function mimimiPost ( $param, $def = '' ) {
            return isset($_POST[$param])
                   ? $_POST[$param]
                   : $def;
        }
    }

    /* =========================================================
    |                                                          |
    |   Define a global routine to retrieve a named REQUEST's  |
    |   parameter                                              |
    |                                                          |
    |   ----------------------------------------------------   |
    |                                                          |
    |   Input parameters:                                      |
    |       $param = STRING = name of the parameter            |
    |       $def   = MIXED  = a default value                  |
    |                                                          |
    |   ----------------------------------------------------   |
    |                                                          |
    |   Output parameters:                                     |
    |       MIXED = retrieved parameter                        |
    |                                                          |
    ========================================================= */

    if ( ! function_exists('mimimiRequest') ) {
        function mimimiRequest ( $param, $def = '' ) {
            return isset($_REQUEST[$param])
                   ? $_REQUEST[$param]
                   : $def;
        }
    }

    /* =========================================================
    |                                                          |
    |   Define a global routine to retrieve a named SERVER's   |
    |   parameter                                              |
    |                                                          |
    |   ----------------------------------------------------   |
    |                                                          |
    |   Input parameters:                                      |
    |       $param = STRING = name of the parameter            |
    |       $def   = MIXED  = a default value                  |
    |                                                          |
    |   ----------------------------------------------------   |
    |                                                          |
    |   Output parameters:                                     |
    |       MIXED = retrieved parameter                        |
    |                                                          |
    ========================================================= */

    if ( ! function_exists('mimimiServer') ) {
        function mimimiServer ( $param, $def = '' ) {
            return isset($_SERVER[$param])
                   ? $_SERVER[$param]
                   : $def;
        }
    }

    /* =========================================================
    |                                                          |
    |   Define a global routine to retrieve a named SESSION's  |
    |   parameter                                              |
    |                                                          |
    |   ----------------------------------------------------   |
    |                                                          |
    |   Input parameters:                                      |
    |       $param = STRING = name of the parameter            |
    |       $def   = MIXED  = a default value                  |
    |                                                          |
    |   ----------------------------------------------------   |
    |                                                          |
    |   Output parameters:                                     |
    |       MIXED = retrieved parameter                        |
    |                                                          |
    ========================================================= */

    if ( ! function_exists('mimimiSession') ) {
        function mimimiSession ( $param, $def = NULL ) {
            return isset($_SESSION[$param])
                   ? $_SESSION[$param]
                   : $def;
        }
    }

    /* =========================================================
    |                                                          |
    |   Define a global routine to stop execution and send     |
    |   a message to the user's browser with such HTTP status  |
    |   code                                                   |
    |                                                          |
    |   ----------------------------------------------------   |
    |                                                          |
    |   Input parameters:                                      |
    |       $message = STRING     = your message to the user   |
    |                  ARRAY OF URI (for status code 300)      |
    |                  URI          (for 301, 302, 307, 308)   |
    |                  RULES        (for 401, 407)             |
    |                  INTEGER      (for 429)                  |
    |       $code    = INTEGER = HTTP status code              |
    |                                                          |
    |   ----------------------------------------------------   |
    |                                                          |
    |   Output parameters:                                     |
    |       NONE                                               |
    |                                                          |
    ========================================================= */

    if ( ! function_exists('mimimiStop') ) {
        function mimimiStop ( $message, $code = 404 ) {
            $scheme = mimimiServer(
                'SERVER_PROTOCOL',
                'HTTP/1.1'
            );
            switch ($code) {

                /* -----------------------------
                |                              |
                |   If a success code          |
                |                              |
                ----------------------------- */

                case 200:
                    @ header($scheme . ' 200 OK', TRUE, $code);
                    break;

                /* -----------------------------
                |                              |
                |   If a redirect code         |
                |                              |
                ----------------------------- */

                case 300:
                    @ header($scheme . ' 300 Multiple Choices', TRUE, $code);
                    if (is_array($message)) {
                        foreach ($message as $uri) {
                            @ header('Location: ' . $uri);
                        }
                    } else {
                        @ header('Location: ' . $message);
                    }
                    exit;
                case 301:
                    @ header($scheme . ' 301 Moved Permanently', TRUE, $code);
                    @ header('Location: ' . $message);
                    exit;
                case 302:
                    @ header($scheme . ' 302 Found', TRUE, $code);
                    @ header('Location: ' . $message);
                    exit;
                case 307:
                    @ header($scheme . ' 307 Temporary Redirect', TRUE, $code);
                    @ header('Location: ' . $message);
                    exit;
                case 308:
                    @ header($scheme . ' 308 Permanent Redirect', TRUE, $code);
                    @ header('Location: ' . $message);
                    exit;

                /* -----------------------------
                |                              |
                |   If a content error code    |
                |                              |
                ----------------------------- */

                case 400:
                    @ header($scheme . ' 400 Bad Request', TRUE, $code);
                    break;
                case 401:
                    @ header($scheme . ' 401 Unauthorized', TRUE, $code);
                    @ header('WWW-Authenticate: ' . $message);
                    exit;
                case 403:
                    @ header($scheme . ' 403 Forbidden', TRUE, $code);
                    break;
                case 404:
                    @ header($scheme . ' 404 Not Found', TRUE, $code);
                    break;
                case 405:
                    @ header($scheme . ' 405 Method Not Allowed', TRUE, $code);
                    break;
                case 406:
                    @ header($scheme . ' 406 Not Acceptable', TRUE, $code);
                    break;
                case 407:
                    @ header($scheme . ' 407 Proxy Authentication Required', TRUE, $code);
                    @ header('Proxy-Authenticate: ' . $message);
                    exit;
                case 408:
                    @ header($scheme . ' 408 Request Timeout', TRUE, $code);
                    break;
                case 409:
                    @ header($scheme . ' 409 Conflict', TRUE, $code);
                    break;
                case 410:
                    @ header($scheme . ' 410 Gone', TRUE, $code);
                    break;
                case 429:
                    @ header($scheme . ' 429 Too Many Requests', TRUE, $code);
                    @ header('Retry-After: ' . $message);
                    exit;
                case 451:
                    @ header($scheme . ' 451 Unavailable For Legal Reasons', TRUE, $code);
                    break;

                /* -----------------------------
                |                              |
                |   If a server error code     |
                |                              |
                ----------------------------- */

                case 500:
                    @ header($scheme . ' 500 Internal Server Error', TRUE, $code);
                    break;
                case 501:
                    @ header($scheme . ' 501 Not Implemented', TRUE, $code);
                    break;
                case 503:
                    @ header($scheme . ' 503 Service Unavailable', TRUE, $code);
                    break;
            }

            /* ---------------------------------
            |                                  |
            |   And show message to user       |
            |                                  |
            --------------------------------- */

            echo $message;
            exit;
        }
    }

    /* =========================================================
    |                                                          |
    |   Define a global routine to display or retrieve the     |
    |   website domain's absolute URI                          |
    |                                                          |
    |   ----------------------------------------------------   |
    |                                                          |
    |   Input parameters:                                      |
    |       $toDisplay = BOOLEAN = TRUE if echo it to browser  |
    |                              FALSE if returns as result  |
    |                                                          |
    |   ----------------------------------------------------   |
    |                                                          |
    |   Output parameters:                                     |
    |       STRING = retrieved URI (with trailing slash)       |
    |                                                          |
    ========================================================= */

    if ( ! function_exists('mimimiSite') ) {
        function mimimiSite ( $toDisplay = TRUE ) {
            $domain = mimimiServer('HTTP_HOST');
            $scheme = mimimiServer('HTTPS')
                      ? 'https'
                      : mimimiServer('REQUEST_SCHEME');
            if ($scheme != '') {
                $scheme .= ':';
            }
            $value = $scheme . '//' . $domain . '/';
            if ($toDisplay) {
                echo $value;
            } else {
                return $value;
            }
        }
    }

    /* =========================================================
    |                                                          |
    |   Define a global routine to display or retrieve the     |
    |   relative path's offset to the Core's folder            |
    |                                                          |
    |   ----------------------------------------------------   |
    |                                                          |
    |   Input parameters:                                      |
    |       $toDisplay = BOOLEAN = TRUE if echo it to browser  |
    |                              FALSE if returns as result  |
    |                                                          |
    |   ----------------------------------------------------   |
    |                                                          |
    |   Output parameters:                                     |
    |       STRING = retrieved path (without leading slash)    |
    |                                                          |
    ========================================================= */

    if ( ! function_exists('mimimiRoot') ) {
        function mimimiRoot ( $toDisplay = TRUE ) {
            $value = mimimiServer('SCRIPT_NAME');
                $value = preg_replace('/[\s.]*[\/\\\\]+/u', '/', $value);
                $value = preg_replace('/\/+[^\/]+\.php$/ui', '/', $value);
                $value = preg_replace('/^\/+\s*/u', '', $value);
            if ($toDisplay) {
                echo $value;
            } else {
                return $value;
            }
        }
    }

    /* =========================================================
    |                                                          |
    |   Define a global routine to display or retrieve the     |
    |   page's relative URI                                    |
    |                                                          |
    |   ----------------------------------------------------   |
    |                                                          |
    |   Input parameters:                                      |
    |       $toDisplay = BOOLEAN = TRUE if echo it to browser  |
    |                              FALSE if returns as result  |
    |                                                          |
    |   ----------------------------------------------------   |
    |                                                          |
    |   Output parameters:                                     |
    |       STRING = retrieved URI (without GET-parameters     |
    |                and leading or trailing slash)            |
    |                                                          |
    ========================================================= */

    if ( ! function_exists('mimimiUri') ) {
        function mimimiUri ( $toDisplay = TRUE ) {
            $encoding = 'UTF-8';
            $value = mimimiServer('REQUEST_URI');
                $value = preg_replace('/^([^\#?]*)[\#?].*$/u', '$1', $value);
                $value = preg_replace('/([\s.]*[\/\\\\])+/u', '/', $value);
                $value = preg_replace('/^(\/\s*)+/u', '', $value);
            $root = mimimiRoot(FALSE);
                $size = mb_strlen($root, $encoding);
                $test = mb_substr($value, 0, $size, $encoding);
                $test = mb_strtolower($test, $encoding) == mb_strtolower($root, $encoding);
                if ($test) {
                    $value = mb_substr($value, $size, 1000000, $encoding);
                }
                $value = preg_replace('/(\/[\s.]*)+$/u', '', $value);
            if ($toDisplay) {
                echo $value;
            } else {
                return $value;
            }
        }
    }

    /* =========================================================
    |                                                          |
    |   Define a global routine to retrieve a list of folders  |
    |   (or files) in specific directory                       |
    |                                                          |
    |   ----------------------------------------------------   |
    |                                                          |
    |   Input parameters:                                      |
    |       $dir       = STRING  = relative path to the        |
    |                              directory                   |
    |       $except    = ARRAY   = list of ignored folders (or |
    |                              files)                      |
    |       $filesOnly = BOOLEAN = TRUE if retrieve files,     |
    |                              FALSE if retrieve folders   |
    |                                                          |
    |   ----------------------------------------------------   |
    |                                                          |
    |   Output parameters:                                     |
    |       ARRAY = list of folders                            |
    |                                                          |
    ========================================================= */

    if ( ! function_exists('mimimiFolders') ) {
        function mimimiFolders ( $dir, $except = array(), $filesOnly = FALSE ) {
            $result = array();
            $dir = preg_replace('/[\/\\\\]+/u', '/', $dir);
            $dir = preg_replace('/[.\s]*\/+\s*/u', '/', $dir);
            $dir = preg_replace('/\/+/u', '/', $dir);
            $dir = preg_replace('/[.\s\/]+$/u', '', $dir);
            $dir = preg_replace('/^[\/]+/u', '', $dir . '/');
            $path = dirname(__FILE__) . '/../' . $dir;
            $handle = @ opendir($path);
            if ($handle !== FALSE) {
                if (!is_array($except)) {
                    $except = array();
                }
                foreach ($except as & $dir) {
                    $dir = is_string($dir)
                           ? preg_replace('/[.\s\/\\\\]+$/u', '', $dir)
                           : '';
                }
                while (($file = readdir($handle)) !== FALSE) {
                    if (trim($file, '.') != '') {
                        if ($filesOnly) {
                            if (is_file($path . $file)) {
                                if (!in_array($file, $except)) {
                                    $result[] = $file;
                                }
                            }
                        } else {
                            if (is_dir($path . $file)) {
                                if (!in_array($file, $except)) {
                                    $result[] = $file;
                                }
                            }
                        }
                    }
                }
                closedir($handle);
                sort($result, SORT_STRING | SORT_FLAG_CASE);
            }
            return $result;
        }
    }

    /**
     * ---------------------------------------------------------------------
     * Global routine to generate random identifier.
     *
     * @public
     * @param   integer  $len    Required length of ID string.
     * @param   bool     $alpha  True if alpha-numeric identifier,
     *                           False if numeric only.
     * @return  string           An identifier.
     * ---------------------------------------------------------------------
     */

    if ( ! function_exists('mimimiRandomId') ) {
        function mimimiRandomId ( $len, $alpha = true ) {
            $id = false;
            $func = 'openssl_random_pseudo_bytes';
            if ($alpha && function_exists($func)) {
                $id = $func($len);
            }
            if ($id !== false) {
                $id = bin2hex($id);
                $id = substr($id, 0, $len);
                $id = strtolower($id);
            } else {
                $id = '';
                while ($len > 0) {
                    $id .= mt_rand(0, 9);
                    $len--;
                }
            }
            return $id;
        }
    }
