<?php
/**
 * -------------------------------------------------------------------------
 *
 * The database module for selecting vendor entries.
 *
 * -------------------------------------------------------------------------
 *
 * This module is always called using getByUrl(), or getVendors(), or
 * getProducts() methods implemented below. The initiator of that call is
 * run() method of the main module of your application.
 *
 * -------------------------------------------------------------------------
 *
 * @package    MimimiFramework
 * @subpackage Examples / Shopping UI with Vue.js
 * @license    GPL-2.0
 *             https://opensource.org/license/gpl-2-0/
 * @copyright  2022 MiMiMi Community
 *             https://mimimi.software/
 *
 * -------------------------------------------------------------------------
 */

    mimimiInclude ( 'NodeWithTable.php' );
    class MyMimimiVendors extends MimimiNodeModuleWithTable {

        /**
         * -----------------------------------------------------------------
         *
         * Specify a name of the database table to store vendors.
         *
         * -----------------------------------------------------------------
         *
         * @access public
         * @var    string
         *
         * -----------------------------------------------------------------
         */

        public $table = 'vendors';

        /**
         * -----------------------------------------------------------------
         *
         * Define a database table structure.
         *
         * -----------------------------------------------------------------
         *
         * @access protected
         * @var    array
         *
         * -----------------------------------------------------------------
         */

        protected $tableFields = [
                      '`id`     BIGINT(20)    NOT NULL  AUTO_INCREMENT   COMMENT "vendor system identifier"',
                      '`lang`   VARCHAR(25)   NOT NULL  DEFAULT "en-US"  COMMENT "language attribute for page HTML tag"',
                      '`url`    VARCHAR(255)  NOT NULL                   COMMENT "page URL relative to the site URL"',
                      '`brand`  VARCHAR(60)   NOT NULL                   COMMENT "vendor name"',
                      '`meta`   VARCHAR(512)  NOT NULL                   COMMENT "text for meta description tag"',
                      '`logo`   VARCHAR(255)  NOT NULL                   COMMENT "logo URL relative to the site URL"'
                  ];

        /**
         * -----------------------------------------------------------------
         *
         * Define a list of table keys to speed up the database operations
         * related to vendors.
         *
         * -----------------------------------------------------------------
         *
         * @access protected
         * @var    array
         *
         * -----------------------------------------------------------------
         */

        protected $tableKeys = [
                      'PRIMARY KEY ( `id`    )',
                      'UNIQUE KEY  ( `url`   )',
                      'KEY         ( `brand` )'
                  ];

        /**
         * -----------------------------------------------------------------
         *
         * Retrieves a vendor entry by its URL.
         *
         * -----------------------------------------------------------------
         *
         * Please note that "t1" below is an alias for the primary database
         * table "vendors". Note also that the filter used below will
         * actually result in the following MySQL query:
         *
         *     SELECT t1.*
         *     FROM   vendors AS t1
         *     WHERE  t1.url =  $url AND
         *            t1.id  != $exceptId
         *     LIMIT  1
         *
         * -----------------------------------------------------------------
         *
         * @public
         * @param   string      $url       The relative URL for the vendor you are looking for.
         * @param   int         $exceptId  (optional) Ignore the entry if it has an identifier.
         * @return  array|bool             ARRAY on success. It contains an entry obtained from a database table.
         *                                 FALSE on failure. This means no entries were found.
         *
         * -----------------------------------------------------------------
         */

        public function getByUrl ( $url, $exceptId = 0 ) {
            $filter = [
                'select' => [ 't1.*'    => TRUE ],
                /* where */   't1.url'  => $url,
                              '! t1.id' => $exceptId
            ];
            return $this->select ( $filter );
        }

        /**
         * -----------------------------------------------------------------
         *
         * Retrieves all vendor entries.
         *
         * -----------------------------------------------------------------
         *
         * These entries are sorted by their brand name. Mote that "t1"
         * below is an alias for the primary database table "vendors". Note
         * also that the filter used below will actually result in the
         * following MySQL query:
         *
         *     SELECT    t1.*,
         *               COUNT(t2.id) AS count
         *     FROM      vendors          AS t1
         *     LEFT JOIN vendors_products AS t2
         *                                   ON t2.vendor_id = t1.id
         *     GROUP BY  t1.id    ASC
         *     ORDER BY  t1.brand ASC
         *     LIMIT     1000000000
         *
         * -----------------------------------------------------------------
         *
         * @public
         * @return  array|bool  ARRAY on success. Each element is an array, like a row obtained from a database table.
         *                      FALSE on failure. This means no entries were found.
         *
         * -----------------------------------------------------------------
         */

        public function getVendors ( ) {
            $filter = [
                'select'  => [ 't1.*'             => TRUE    ,
                               'COUNT(`t2`.`id`)' => 'count' ],
                'join'    => [ $this->products->table => [ 't2.vendor_id' => 't1.id' ] ],
                'groupby' => [ 't1.id'    => 'asc' ],
                'orderby' => [ 't1.brand' => 'asc' ]
            ];
            return $this->select ( $filter, 0, 1000000000 );
        }

        /**
         * -----------------------------------------------------------------
         *
         * Retrieves a product entry by its identifier.
         *
         * -----------------------------------------------------------------
         *
         * Please note that "t1" below is an alias for the primary database
         * table "vendors" and "t2" is an alias for the secondary table
         * "vendors_products". Note also that the filter used below will
         * actually result in the following MySQL query:
         *
         *     SELECT    t2.*,
         *               t1.brand
         *     FROM      vendors          AS t1
         *     LEFT JOIN vendors_products AS t2
         *                                   ON t2.vendor_id = t1.id
         *     WHERE     t2.id = $id
         *     LIMIT     1
         *
         * -----------------------------------------------------------------
         *
         * @public
         * @param   int         $id  The identifier of the product you are looking for.
         * @return  array|bool       ARRAY on success. It contains an entry obtained from a database table.
         *                           FALSE on failure. This means no entries were found.
         *
         * -----------------------------------------------------------------
         */

        public function getProduct ( $id ) {
            $filter = [
                'select'  => [ 't2.*'     => TRUE ,
                               't1.brand' => TRUE ],
                'join'    => [ $this->products->table => [ 't2.vendor_id' => 't1.id' ] ],
                /* where */    't2.id'    => $id
            ];
            return $this->select ( $filter );
        }

        /**
         * -----------------------------------------------------------------
         *
         * Retrieves all product entries by a vendor URL.
         *
         * -----------------------------------------------------------------
         *
         * Please note that "t1" below is an alias for the primary database
         * table "vendors" and "t2" is an alias for the secondary table
         * "vendors_products". Note also that the filter used below will
         * actually result in the following MySQL query:
         *
         *     SELECT    t2.*,
         *               t1.brand
         *     FROM      vendors          AS t1
         *     LEFT JOIN vendors_products AS t2
         *                                   ON t2.vendor_id = t1.id
         *     WHERE     t1.url = $url
         *     ORDER BY  t2.name ASC
         *     LIMIT     1000000000
         *
         * -----------------------------------------------------------------
         *
         * @public
         * @param   string      $url  The relative URL for the vendor you are looking for.
         * @return  array|bool        ARRAY on success. Each element is an array, like a row obtained from a database table.
         *                            FALSE on failure. This means no entries were found.
         *
         * -----------------------------------------------------------------
         */

        public function getProducts ( $url ) {
            $filter = [
                'select'  => [ 't2.*'     => TRUE ,
                               't1.brand' => TRUE ],
                'join'    => [ $this->products->table => [ 't2.vendor_id' => 't1.id' ] ],
                /* where */    't1.url'   => $url                           ,
                'orderby' => [ 't2.name'  => 'asc' ]
            ];
            return $this->select ( $filter, 0, 1000000000 );
        }

        /**
         * -----------------------------------------------------------------
         *
         * Removes all product entries by a vendor URL.
         *
         * -----------------------------------------------------------------
         *
         * Please note that "t1" below is an alias for the secondary
         * database table "vendors_products" and "t2" is an alias for the
         * primary table "vendors". Note also that the $query variable
         * assembled below will actually result in the following MySQL
         * query:
         *
         *     DELETE    t1
         *     FROM      vendors_products AS t1
         *     LEFT JOIN vendors          AS t2
         *                                   ON t2.id = t1.vendor_id
         *     WHERE     t2.url = $url
         *
         * -----------------------------------------------------------------
         *
         * @public
         * @param   string    $url  The relative URL of the vendor whose products you are removing.
         * @return  int|bool        INTEGER on success. This means the number of entries removed.
         *                          FALSE on failure.
         *
         * -----------------------------------------------------------------
         */

        public function removeProducts ( $url ) {
            $query = 'DELETE    `t1` ' .
                     'FROM      `__' . $this->products->table . '` AS `t1` ' .
                     'LEFT JOIN `__' . $this->table           . '` AS `t2` ' .
                                                                      'ON `t2`.`id` = `t1`.`vendor_id` ' .
                     'WHERE     `t2`.`url` = ?';
            $object = $this->app->db->query ( $query, [ $url ] );
            return $object
                   ? $object->rowCount ( )
                   : FALSE;
        }

        /**
         * -----------------------------------------------------------------
         *
         * Specify demo rows that will be used as default vendor entries
         * if the database does not have a table named "vendors". In this
         * case, all demo rows will be automatically added to the newly
         * created primary table.
         *
         * -----------------------------------------------------------------
         *
         * @access protected
         * @var    array
         *
         * -----------------------------------------------------------------
         */

        protected $demoRows = [
            [
                'id'    => 1,
                'lang'  => 'en-US',
                'url'   => 'nike',
                'brand' => 'Nike Shoes',
                'meta'  => 'Here\'s an example showing what the Shopping UI looks like when filled with Nike products.',
                'logo'  => 'media/demo-posts/vue.js.cart/logo-nike.png'
            ], [
                'id'    => 2,
                'lang'  => 'en-US',
                'url'   => 'emptiness',
                'brand' => 'The Emptiness Wear',
                'meta'  => 'Here\'s an example showing what a vendor\'s page looks like when there are no products listed.',
                'logo'  => 'media/demo-posts/vue.js.cart/logo-emptiness.png'
            ]
        ];

        /**
         * -----------------------------------------------------------------
         *
         * Installs the demo table entries.
         *
         * -----------------------------------------------------------------
         *
         * The need to overwrite this method is due to the presence in your
         * web app of a node module with a primary and secondary table.
         *
         * -----------------------------------------------------------------
         *
         * @public
         * @param   mixed  $params  Some parameters if you need.
         * @return  bool            TRUE  if at least one new entry has been added.
         *                          FALSE if the table has not changed.
         *
         * -----------------------------------------------------------------
         */

        public function install ( $params = NULL ) {
            $this->products->install (         );
            return parent::install   ( $params );
        }

        /**
         * -----------------------------------------------------------------
         *
         * Reset namespace simulator.
         *
         * -----------------------------------------------------------------
         */

        protected $myNodeFile = __FILE__;
    };
