<?php
/**
 * -------------------------------------------------------------------------
 *
 * The main module for receiving requests.
 *
 * The source code and accompanying modules of this application are written
 * simply and clearly for webmasters. Although this is just an example, it
 * can be used as a complete web application.
 *
 * -------------------------------------------------------------------------
 *
 * How did this file run?
 *
 *     ├─> .htaccess
 *     └─> index.php
 *           ├─> tiny.news.feed/Config.php
 *           ├─> mimimi.core/Routines.php
 *           │               │
 *           │               ├─<─ routine mimimiInclude()
 *           │               ├─<─ routine mimimiServer()
 *           │               └─<─ routine mimimiStop()
 *           │
 *           ├─> [MAKE THE $app GLOBAL VARIABLE]
 *           │
 *           ├─> tiny.news.feed/Constants.php
 *           │                  │
 *           │                  ├─<─ constant TINYFEED_ERROR_NO_ROUTER
 *           │                  ├─<─ constant TINYFEED_ERROR_ILLEGAL_METHOD
 *           │                  ├─<─ constant TINYFEED_ON_DEMO_NOW
 *           │                  └─<─ constant TINYFEED_ADMIN_IPS
 *           │
 *           │                                      ┌─<─ class mimimi.core/Module.php
 *           │                                      │                        └─> __construct()
 *           │               ┌─<─ class mimimi.core/NodeModule.php
 *           │               │                           └─> __construct()
 *           └─> tiny.news.feed/Application.php
 *                              │    └─> run()
 *                              │         │
 *                              │         └─> [LAUNCH THE ROUTER MODULE]
 *                              │
 *                              ├─<─ method getLatest()
 *                              ├─<─ method getViewers()
 *                              ├─<─ method getSitemap()
 *                              ├─<─ method getList()
 *                              ├─<─ method getPage()
 *                              └─<─ method amIAdmin()
 *
 * The down-right arrows show the order in which app files are loaded and
 * their methods that are called when processing a request to the site.
 * The left-down arrows show the classes from which the corresponding
 * application file is derived. The left-up arrows show some of the public
 * routines or some of the public methods that the corresponding file
 * exposes to other application modules.
 *
 * -------------------------------------------------------------------------
 *
 * @package    MimimiFramework
 * @subpackage Examples / Tiny News Feed site
 * @license    GPL-2.0
 *             https://opensource.org/license/gpl-2-0/
 * @copyright  2022 MiMiMi Community
 *             https://mimimi.software/
 *
 * -------------------------------------------------------------------------
 */

                                                        // -----------------
mimimiInclude(                                          // load a file              ( see file mimimi.core/Routines.php    -> mimimiInclude )
    'Constants.php', FALSE                              // . . with these constants ( see file tiny.news.feed/Constants.php )
);                                                      //
                                                        // -----------------
mimimiInclude(                                          // load a file              ( see file mimimi.core/Routines.php    -> mimimiInclude )
    'Application.php'                                   // . . with this base class ( see file mimimi.core/Application.php -> MimimiApplication )
);                                                      //
                                                        // -----------------
class MyMimimiApplication extends MimimiApplication {   // define required "My..." class for the main module

    /**
     * ---------------------------------------------------------------------
     *
     * Renders the requested page.
     *
     * ---------------------------------------------------------------------
     *
     * The application's job of rendering any web page or document always
     * starts with this method. It stops unsupported request types by
     * responding with the 501 Error HTTP status and corresponding text
     * on the screen. And for supported request types like HEAD, GET, POST,
     * this method checks for the presence the of ROUTER module and launches
     * it.
     *
     * ---------------------------------------------------------------------
     *
     * @public
     * @param   mixed  $params  (optional) Some parameters from the calling process.
     * @return  void
     *
     * ---------------------------------------------------------------------
     */

    public function run ( $params = '' ) {              // -----------------
        $method = mimimiServer('REQUEST_METHOD');       // get related server parameter ( see file mimimi.core/Routines.php -> mimimiServer )
        switch ( $method ) {                            // what method was requested?
                                                        // -----------------
            case 'HEAD':                                //     if it's legal
            case 'GET':                                 //     . .
            case 'POST':                                //     . .
                $ok = $this                             //         check if this app has the ROUTER module
                      ->has                             //         . . via HAS module        ( see file mimimi.core/Has/Has.php -> __get )
                      ->router;                         //         . . check for this module ( see file tiny.news.feed/Router/Router.php )
                                                        // -----------------
                $ok                                     //         if it's true
                    ? $this                             //             launch it
                      ->router                          //             . . via ROUTER module ( see file tiny.news.feed/Router/Router.php -> run )
                      ->run()                           //             . . using this method
                                                        // -----------------
                    : mimimiStop(                       //         otherwise stop execution       ( see file mimimi.core/Routines.php     -> mimimiStop )
                          TINYFEED_ERROR_NO_ROUTER,     //             . . with this notification ( see file tiny.news.feed/Constants.php -> TINYFEED_ERROR_NO_ROUTER )
                          501                           //             . . with this HTML status code
                      );                                //             
                break;                                  //
                                                        // -----------------
            case 'PUT':                                 //     otherwise it's illegal
            case 'DELETE':                              //     . .
            case 'CONNECT':                             //     . .
            case 'OPTIONS':                             //     . .
            case 'TRACE':                               //     . .
            case 'PATCH':                               //     . .
            default:                                    //     . .
                mimimiStop(                             //         stop execution             ( see file mimimi.core/Routines.php     -> mimimiStop )
                    TINYFEED_ERROR_ILLEGAL_METHOD,      //         . . with this notification ( see file tiny.news.feed/Constants.php -> TINYFEED_ERROR_ILLEGAL_METHOD )
                    501                                 //         . . with this HTML status code
                );                                      //
        }                                               //
    }                                                   // -----------------

    /**
     * ---------------------------------------------------------------------
     *
     * Reads the latest publications.
     *
     * ---------------------------------------------------------------------
     *
     * You can use this method to read all or only certain database records
     * that should be shown as the latest publications. The optional input
     * parameter $filter is intended to read only certain types of records.
     *
     * Where has this method been used?
     *
     *     tiny.news.feed/Themes/default/home.tpl
     *     tiny.news.feed/Themes/default/404.tpl
     *
     * ---------------------------------------------------------------------
     *
     * @public
     * @param   int    $size    (optional) The capacity of the list for each viewer. Default size is 6 (that is 2 * 3 publications).
     * @param   array  $filter  (optional) The list containing only the names of specific viewers, or an empty list for reading the latest publications for all viewers.
     * @return  array           Name-indexed list of list of publications that were fetched from the database.
     *
     * ---------------------------------------------------------------------
     */

    public function getLatest ( $size = 6, $filter = [] ) {
                                                        // -----------------
        $result = [];                                   // there is no result
                                                        // -----------------
        $ok = $this                                     // check if viewers are installed in this app
              ->router                                  // . . via ROUTER module ( see file tiny.news.feed/Router/Router.php -> checkFor )
              ->checkFor();                             // . . using this method
        if ( $ok ) {                                    // if it's true
                                                        // -----------------
            if ( ! $filter ) {                          //     if filter is empty
                $filter = $this                         //         get viewer names
                          ->viewers                     //         . . via VIEWERS module ( see file tiny.news.feed/Viewers/Viewers.php -> getViewerNames )
                          ->getViewerNames();           //         . . using this method
            }                                           //
            if ( is_array($filter) ) {                  //     if filter is a list
                                                        // -----------------
                $okAdmin = $this->amIAdmin();           //         am I admin?
                                                        // -----------------
                $filter = $this                         //         drop irrelevant names
                          ->viewers                     //         . . via VIEWERS module ( see file tiny.news.feed/Viewers/Viewers.php -> filterNames )
                          ->filterNames(                //         . . using this method
                              $filter,                  //             . . based on this list
                              '*-page.tpl'              //             . . check for this template (where the symbol * is a viewer name)
                          );                            //
                                                        // -----------------
                foreach ( $filter as $viewer ) {        //         walk through the remaining names
                    $ok = $this                         //             check if this app has the required viewer installed
                          ->router                      //             . . via ROUTER module ( see file tiny.news.feed/Router/Router.php -> checkFor )
                          ->checkFor(                   //             . . using this method
                              $viewer                   //                 . . check for this viewer name
                          );                            //
                    if ( $ok ) {                        //             if it's true
                                                        // -----------------
                        $result[$viewer] = $this        //                 get the latest publications and add them to the result as an indexed element
                                           ->viewers    //                 . . via VIEWERS module   ( see file tiny.news.feed/Viewers/Viewers.php )
                                           ->$viewer    //                 . . using this submodule ( see file tiny.news.feed/Viewers/[$viewer]/[$viewer].php -> getItems )
                                           ->getRecent( //                 . . using this method
                                               $size,   //                     . . no more than so many items
                                               $okAdmin //                     . . if I'm admin, get items even if they are disabled
                                           );           //
                    }                                   //
                }                                       //
            }                                           //
        }                                               //
                                                        // -----------------
        return $result;                                 // return the list of publications
    }                                                   // -----------------

    /**
     * ---------------------------------------------------------------------
     *
     * Reads the names of installed viewers.
     *
     * ---------------------------------------------------------------------
     *
     * You can use this method to get viewer names that are relevant to
     * enumerate in a specific template of your website's theme. The optional
     * input parameter $pattern is intended to specify a specimen to search
     * for corresponding template file in the website theme, where the *
     * character is the name of the viewer under test. For example, if you
     * want to read viewer names that match sitemap functionality, you can
     * call the method like this:
     *
     *     $list = $this->app->getViewers( '*-sitemap.tpl' );
     *
     * With no input parameter, this method will read the entire list of
     * names of installed viewers.
     *
     * ---------------------------------------------------------------------
     *
     * @public
     * @param   string  $pattern  The pattern of template file to find irrelevant viewers.
     * @return  array             The list of relevant names fetched from the VIEWERS module.
     *
     * ---------------------------------------------------------------------
     */

    public function getViewers ( $pattern = '' ) {      // -----------------
        $result = [];                                   // there is no result
                                                        // -----------------
        $ok = $this                                     // check if viewers are installed in this app
              ->router                                  // . . via ROUTER module ( see file tiny.news.feed/Router/Router.php -> checkFor )
              ->checkFor();                             // . . using this method
        if ( $ok ) {                                    // if it's true
                                                        // -----------------
            $result = $this                             //     get viewer names
                      ->viewers                         //     . . via VIEWERS module ( see file tiny.news.feed/Viewers/Viewers.php -> getViewerNames )
                      ->getViewerNames();               //     . . using this method
            if ( $pattern ) {                           //     if a specimen is specified
                                                        // -----------------
                $result = $this                         //         drop irrelevant names
                          ->viewers                     //         . . via VIEWERS module ( see file tiny.news.feed/Viewers/Viewers.php -> filterNames )
                          ->filterNames(                //         . . using this method
                              $result,                  //             . . based on this list
                              $pattern                  //             . . check for this template (where the symbol * is a viewer name)
                          );                            //
            }                                           //
        }                                               //
                                                        // -----------------
        return $result;                                 // return the list of names
    }                                                   // -----------------

    /**
     * ---------------------------------------------------------------------
     *
     * Reads all URLs.
     *
     * ---------------------------------------------------------------------
     *
     * @public
     * @param   string      $viewer  The requested viewer. Its name is a page type written as the first segment of the page's URL.
     * @return  array|bool           ARRAY on success. It is a list of URLs fetched from the database.
     *                               FALSE on failure.
     *
     * ---------------------------------------------------------------------
     */

    public function getSitemap ( $viewer ) {            // -----------------
        $result = FALSE;                                // there is no result
                                                        // -----------------
        $ok = $this                                     // check if this app has the required viewer installed
              ->router                                  // . . via ROUTER module ( see file tiny.news.feed/Router/Router.php -> checkFor )
              ->checkFor(                               // . . using this method
                  $viewer                               //     . . check for this viewer name
              );                                        //
        if ( $ok ) {                                    // if it's true
                                                        // -----------------
            $result = $this                             //     get non-disabled URLs
                      ->viewers                         //     . . via VIEWERS module   ( see file tiny.news.feed/Viewers/Viewers.php )
                      ->$viewer                         //     . . using this submodule ( see file tiny.news.feed/Viewers/[$viewer]/[$viewer].php -> getSitemap )
                      ->getSitemap();                   //     . . using this method
        }                                               //
                                                        // -----------------
        return $result;                                 // return the list of URLs
    }                                                   // -----------------

    /**
     * ---------------------------------------------------------------------
     *
     * Reads publications listed on the current page.
     *
     * ---------------------------------------------------------------------
     *
     * @public
     * @param   string      $viewer  The requested viewer. Its name is a page type written as the first segment of the page's URL.
     * @param   int         $page    Page number being viewed.
     * @param   int         $size    (optional) The capacity of the page. Default size is 12 (that is 3 * 4 publications).
     * @return  array|bool           ARRAY on success. It is a list of publications fetched from the database.
     *                               FALSE on failure.
     *
     * ---------------------------------------------------------------------
     */

    public function getList ( $viewer, $page, $size = 12 ) {
                                                        // -----------------
        $result = FALSE;                                // there is no result
                                                        // -----------------
        $ok = $this                                     // check if this app has the required viewer installed
              ->router                                  // . . via ROUTER module ( see file tiny.news.feed/Router/Router.php -> checkFor )
              ->checkFor(                               // . . using this method
                  $viewer                               //     . . check for this viewer name
              );                                        //
        if ( $ok ) {                                    // if it's true
                                                        // -----------------
            $ok = $this->amIAdmin();                    //     am I admin?
                                                        // -----------------
            $result = $this                             //     get publications list
                      ->viewers                         //     . . via VIEWERS module   ( see file tiny.news.feed/Viewers/Viewers.php )
                      ->$viewer                         //     . . using this submodule ( see file tiny.news.feed/Viewers/[$viewer]/[$viewer].php -> getItems )
                      ->getItems(                       //     . . using this method
                          $page,                        //         . . located on this page
                          $size,                        //         . . expected list capacity
                          $ok                           //         . . if I'm admin, get items even if they are disabled
                      );                                //
        }                                               //
                                                        // -----------------
        return $result;                                 // return the list of publications
    }                                                   // -----------------

    /**
     * ---------------------------------------------------------------------
     *
     * Reads the page record by its URL.
     *
     * ---------------------------------------------------------------------
     *
     * Where has this method been used?
     *
     *     tiny.news.feed/Router/Router.php -> run
     *
     * ---------------------------------------------------------------------
     *
     * @public
     * @param   string      $viewer  The requested viewer. Its name is a page type written as the first segment of the page's URL.
     * @param   string      $url     The URL of the record to be found in the database.
     * @return  array|bool           ARRAY on success. It is a record fetched from the database.
     *                               FALSE on failure.
     *
     * ---------------------------------------------------------------------
     */

    public function getPage ( $viewer, $url ) {         // -----------------
        $result = FALSE;                                // there is no result
                                                        // -----------------
        $ok = $this                                     // check if this app has the required viewer installed
              ->router                                  // . . via ROUTER module ( see file tiny.news.feed/Router/Router.php -> checkFor )
              ->checkFor(                               // . . using this method
                  $viewer                               //     . . check for this viewer name
              );                                        //
        if ( $ok ) {                                    // if it's true
                                                        // -----------------
            $ok = $this->amIAdmin();                    //     am I admin?
                                                        // -----------------
            $result = $this                             //     get publication
                      ->viewers                         //     . . via VIEWERS module   ( see file tiny.news.feed/Viewers/Viewers.php )
                      ->$viewer                         //     . . using this submodule ( see file tiny.news.feed/Viewers/[$viewer]/[$viewer].php -> getItem )
                      ->getItem(                        //     . . using this method
                          $url,                         //         . . located on this URL
                          $ok                           //         . . if I'm admin, get it even if it's disabled
                      );                                //
        }                                               //
                                                        // -----------------
        return $result;                                 // return the publication
    }                                                   // -----------------

    /**
     * ---------------------------------------------------------------------
     *
     * Checks if the current user is an admin.
     *
     * ---------------------------------------------------------------------
     *
     * We are not yet using a database table with user records in this
     * application. However, we need page administration functions, and one
     * of them should check the current user's permissions. But since there
     * is no user table, we implement here the simplest administration
     * scheme, when there is only one website administrator, and his rights
     * are assigned according to the IP address.
     *
     * ---------------------------------------------------------------------
     *
     * @public
     * @return  bool  FALSE if the current user is not an admin.
     *
     * ---------------------------------------------------------------------
     */

    public function amIAdmin () {                       // -----------------
        if ( TINYFEED_ON_DEMO_NOW ) {                   // if we are now in demo mode ( see file tiny.news.feed/Constants.php -> TINYFEED_ON_DEMO_NOW )
            return TRUE;                                //     return the status "you are an admin"
        }                                               //
                                                        // -----------------
        $ip = mimimiServer('REMOTE_ADDR');              // get user IP     ( see file mimimi.core/Routines.php     -> mimimiServer )
        return in_array($ip, TINYFEED_ADMIN_IPS);       // return a status ( see file tiny.news.feed/Constants.php -> TINYFEED_ADMIN_IPS )
    }                                                   // -----------------
};