<?php
/**
 * -------------------------------------------------------------------------
 *
 * The basis for a system module that collects other modules.
 *
 * -------------------------------------------------------------------------
 *
 * Look at this diagram to understand how the module works:
 *
 *     │                                          ┌─<─ class mimimi.core/Module.php
 *     │                                          │                      │ └─> __construct()
 *     │                                          │                      │
 *     │                                          │                      ├─<─ property $owner
 *     │                                          │                      ├─<─ property $app
 *     │                                          │                      │
 *     │               ┌─<───── class mimimi.core/NodeModule.php         └─<─ method run()
 *     │               │                          │    └─> __construct()*
 *     └─> mimimi.core/Collection.php             │
 *                     │                          ├─<─ property $myNodeFile
 *                     ├─<─ method listModules()  │
 *                     └─<─ method checkFor()     ├─<─ method __get()
 *                                                └─<─ method getNodePath()
 *
 * The right arrows show the order in which app files are loaded and their
 * methods that are called when processing a request to this module. The
 * left arrows show the class from which the corresponding application file
 * is derived. They also show some public routines, some public methods, or
 * some constants that the corresponding file exposes to other application
 * modules. The method or property that has been overridden is marked with
 * an asterisk.
 *
 * -------------------------------------------------------------------------
 *
 * Implemented methods below are:
 *     listModules (          $method )  -->  to list submodules that have a specific method
 *     checkFor    ( $module, $method )  -->  to check whether a submodule exists
 *
 * -------------------------------------------------------------------------
 *
 * @package    MimimiFramework
 * @subpackage Core
 * @copyright  2022 MiMiMi Community
 *             https://mimimi.software/
 * @license    GPL-2.0
 *             https://opensource.org/license/gpl-2-0/
 *
 * -------------------------------------------------------------------------
 */

    mimimiInclude ( 'NodeModule.php' );

    class MimimiCollection extends MimimiNodeModule {

        /**
         * -----------------------------------------------------------------
         *
         * Lists child modules.
         *
         * -----------------------------------------------------------------
         *
         * @public
         * @param   string  $method  (optional) The name of the method if it needs to be found.
         * @return  array            A flat list whose index is the module name and whose value is the name of its folder.
         *                           The following example demonstrates 4 child modules
         *                           [
         *                               'hello_world'        => 'HelloWorld',
         *                               'and_lorem123_ipsum' => 'AndLorem123Ipsum',
         *                               'collection'         => 'Collection',
         *                               'version123'         => 'Version123'
         *                           ]
         *
         * ---------------------------------------------------------------------
         */

        public function listModules ( $method = '' ) {
            $list = [ ];
            $folders = mimimiFolders ( $this->getNodePath ( ) );
            foreach ( $folders as $folder ) {
                $name = preg_replace ( '~[\W_]+~u',        '_',     $folder );
                $name = preg_replace ( '~([^_])([A-Z])~u', '$1_$2', $name   );
                $name = strtolower   (                              $name   );
                if ( empty ( $list[ $name ] ) ) {
                    if ( $this->has->$name ) {
                        if ( $method ) {
                            if ( ! method_exists ( $this->$name, $method ) ) {
                                continue;
                            }
                        }
                        $list[ $name ] = $folder;
                    }
                }
            }
            return $list;
        }

        /**
         * -----------------------------------------------------------------
         *
         * Checks if the child module exists.
         *
         * -----------------------------------------------------------------
         *
         * @public
         * @param   string  $module  The name of the child module that will be tested.
         * @param   string  $method  (optional) The name of the method if it needs to be found.
         * @return  bool
         *
         * ---------------------------------------------------------------------
         */

        public function checkFor ( $module, $method = '' ) {
            return $this->has->$module
                   && ( $method == ''
                        || method_exists ( $this->$module, $method ) );
        }
    };
