<?php
    /**
     * Content Class
     *
     * @package Wojo Framework
     * @author wojoscripts.com
     * @copyright 2023
     * @version 5.50: Content.php, v1.00 7/24/2023 3:49 PM Gewa Exp $
     *
     */
    if (!defined('_WOJO')) {
        die('Direct access to this location is not allowed.');
    }
    
    class Content
    {
        
        const mTable = 'menus';
        const pTable = 'pages';
        const cTable = 'categories';
        const crTable = 'categories_related';
        const cnTable = 'countries';
        const dcTable = 'coupons';
        const fTable = 'faq';
        const eTable = 'email_templates';
        const cfTable = 'custom_fields';
        const cfdTable = 'custom_fields_data';
        const nTable = 'news';
        const wTable = 'wishlist';
        const xTable = 'cart';
        
        public static array $segments = array();
        
        /**
         * menuIndex
         *
         * @return void
         */
        public function menuIndex(): void
        {
            $tpl = App::View(BASEPATH . 'view/');
            $tpl->dir = 'admin/';
            $tpl->title = Language::$word->META_M_MENUS;
            $tpl->caption = Language::$word->META_M_MENUS;
            $tpl->subtitle = Language::$word->MU_INFO;
            
            $tpl->contenttype = self::getContentType();
            $tpl->tree = Database::Go()->select(self::mTable)->orderBy('sorting', 'ASC')->run();
            $tpl->sortlist = $this->getSortMenuList($tpl->tree);
            $tpl->template = 'admin/menu';
        }
        
        /**
         * menuEdit
         *
         * @param int $id
         * @return void
         */
        public function menuEdit(int $id): void
        {
            $tpl = App::View(BASEPATH . 'view/');
            $tpl->dir = 'admin/';
            $tpl->title = Language::$word->MU_EDIT;
            $tpl->caption = Language::$word->MU_EDIT;
            $tpl->crumbs = ['admin', 'menus', 'edit'];
            
            if (!$row = Database::Go()->select(self::mTable)->where('id', $id, '=')->first()->run()) {
                if (DEBUG) {
                    $tpl->error = 'Invalid ID ' . ($id) . ' detected [' . __CLASS__ . ', ln.:' . __line__ . ']';
                } else {
                    $tpl->error = Language::$word->META_ERROR;
                }
                $tpl->template = 'admin/error';
            } else {
                $tpl->data = $row;
                $tpl->tree = Database::Go()->select(self::mTable)->orderBy('sorting', 'ASC')->run();
                $tpl->pagelist = Database::Go()->select(self::pTable, array('id', 'title'))->orderBy('title', 'ASC')->run();
                $tpl->sortlist = $this->getSortMenuList($tpl->tree);
                $tpl->contenttype = self::getContentType();
                
                $tpl->template = 'admin/menu';
            }
        }
        
        /**
         * processMenu
         *
         * @return void
         */
        public function processMenu(): void
        {
            $validate = Validator::run($_POST);
            $validate
                ->set('name', Language::$word->NAME)->required()->string()->min_len(3)->max_len(100)
                ->set('active', Language::$word->PUBLISHED)->required()->numeric()
                ->set('content_type', Language::$word->MU_TYPE)->required()->string();
            
            $safe = $validate->safe();
            
            if ($safe->content_type == 'page' and !array_key_exists('page_id', $_POST)) {
                Message::$msgs['page_id'] = Language::$word->MU_PAGE;
            }
            
            if (count(Message::$msgs) === 0) {
                $data = array(
                    'name' => $safe->name,
                    'content_type' => $safe->content_type,
                    'link' => (isset($_POST['web'])) ? Validator::sanitize($_POST['web']) : 'NULL',
                    'target' => (isset($_POST['target'])) ? Validator::sanitize($_POST['target'], 'db') : 'NULL',
                    'page_id' => (isset($_POST['page_id'])) ? Validator::sanitize($_POST['page_id'], 'int') : 0,
                    'active' => $safe->active,
                );
                
                $last_id = 0;
                $message = null;
                (Filter::$id) ? Database::Go()->update(self::mTable, $data)->where('id', Filter::$id, '=')->run() : $last_id = Database::Go()->insert(self::mTable, $data)->run();
                if (Filter::$id) {
                    $message = Message::formatSuccessMessage($data['name'], Language::$word->MU_UPDATE_OK);
                    Message::msgReply(Database::Go()->affected(), 'success', $message);
                } else {
                    if ($last_id) {
                        $message = Message::formatSuccessMessage($data['name'], Language::$word->MU_ADDED_OK);
                        $json['type'] = 'success';
                        $json['title'] = Language::$word->SUCCESS;
                        $json['message'] = $message;
                        $json['redirect'] = Url::url('/admin/menus');
                    } else {
                        $json['type'] = 'alert';
                        $json['title'] = Language::$word->ALERT;
                        $json['message'] = Language::$word->NOPROCCESS;
                    }
                    print json_encode($json);
                }
                Logger::writeLog($message);
            } else {
                Message::msgSingleStatus();
            }
        }
        
        /**
         * pageIndex
         *
         * @return void
         */
        public function pageIndex(): void
        {
            $tpl = App::View(BASEPATH . 'view/');
            $tpl->dir = 'admin/';
            $tpl->title = Language::$word->META_M_PAGES;
            $tpl->caption = Language::$word->META_M_PAGES;
            $tpl->subtitle = Language::$word->PAG_INFO;
            
            $tpl->data = Database::Go()->select(self::pTable)->orderBy('page_type', 'ASC')->run();
            $tpl->template = 'admin/page';
        }
        
        /**
         * pageNew
         *
         * @return void
         */
        public function pageNew(): void
        {
            $tpl = App::View(BASEPATH . 'view/');
            $tpl->dir = 'admin/';
            $tpl->title = Language::$word->PAG_NEW;
            $tpl->caption = Language::$word->PAG_NEW;
            $tpl->subtitle = null;
            
            $tpl->template = 'admin/page';
        }
        
        /**
         * pageEdit
         *
         * @param int $id
         * @return void
         */
        public function pageEdit(int $id): void
        {
            $tpl = App::View(BASEPATH . 'view/');
            $tpl->dir = 'admin/';
            $tpl->title = Language::$word->PAG_EDIT;
            $tpl->caption = Language::$word->PAG_EDIT;
            $tpl->crumbs = ['admin', 'pages', 'edit'];
            
            if (!$row = Database::Go()->select(self::pTable)->where('id', $id, '=')->first()->run()) {
                if (DEBUG) {
                    $tpl->error = 'Invalid ID ' . ($id) . ' detected [' . __CLASS__ . ', ln.:' . __line__ . ']';
                } else {
                    $tpl->error = Language::$word->META_ERROR;
                }
                $tpl->template = 'admin/error';
            } else {
                $tpl->data = $row;
                
                $tpl->template = 'admin/page';
            }
        }
        
        /**
         * processPage
         *
         * @return void
         */
        public function processPage(): void
        {
            
            $validate = Validator::run($_POST);
            $validate
                ->set('title', Language::$word->NAME)->required()->string()->min_len(3)->max_len(100)
                ->set('slug', Language::$word->PAG_SLUG)->string()
                ->set('body', Language::$word->DESCRIPTION)->text('advanced')
                ->set('keywords', Language::$word->METAKEYS)->string(true, true)
                ->set('description', Language::$word->METADESC)->string(true, true)
                ->set('active', Language::$word->PUBLISHED)->required()->numeric();
            
            $safe = $validate->safe();
            
            if (count(Message::$msgs) === 0) {
                $data = array(
                    'title' => $safe->title,
                    'slug' => strlen($safe->slug) === 0 ? Url::doSeo($safe->title) : Url::doSeo($safe->slug),
                    'body' => Url::in_url($safe->body),
                    'keywords' => $safe->keywords,
                    'description' => $safe->description,
                    'active' => $safe->active,
                );
                
                (Filter::$id) ? Database::Go()->update(self::pTable, $data)->where('id', Filter::$id, '=')->run() : Database::Go()->insert(self::pTable, $data)->run();
                
                if (Filter::$id) {
                    $pages = Database::Go()->select('pages', array('page_type'))->where('page_type', 'contact', '=')->orWhere('page_type', 'privacy', '=')->orWhere('page_type', 'home', '=')->run();
                    $result = Utility::groupToLoop($pages, 'page_type');
                    Database::Go()->update(Core::sTable, array('page_slugs' => json_encode($result)))->where('id', 1, '=')->run();
                }
                
                $message = Filter::$id ?
                    Message::formatSuccessMessage($data['title'], Language::$word->PAG_UPDATE_OK) :
                    Message::formatSuccessMessage($data['title'], Language::$word->PAG_ADDED_OK);
                Message::msgReply(Database::Go()->affected(), 'success', $message);
                Logger::writeLog($message);
            } else {
                Message::msgSingleStatus();
            }
        }
        
        /**
         * categoryIndex
         *
         * @return void
         */
        public function categoryIndex(): void
        {
            $tpl = App::View(BASEPATH . 'view/');
            $tpl->dir = 'admin/';
            $tpl->title = Language::$word->META_M_CATEGORIES;
            $tpl->caption = Language::$word->META_M_CATEGORIES;
            $tpl->subtitle = Language::$word->CT_INFO;
            
            $tpl->tree = $this->categoryTree();
            $tpl->droplist = self::getCategoryDropList($tpl->tree, 0, 0, '&#166;&nbsp;&nbsp;&nbsp;&nbsp;');
            $tpl->sortlist = $this->getSortCategoryList($tpl->tree);
            
            $tpl->template = 'admin/category';
        }
        
        /**
         * categoryEdit
         *
         * @param int $id
         * @return void
         */
        public function categoryEdit(int $id): void
        {
            $tpl = App::View(BASEPATH . 'view/');
            $tpl->dir = 'admin/';
            $tpl->title = Language::$word->CT_EDIT;
            $tpl->caption = Language::$word->CT_EDIT;
            $tpl->crumbs = ['admin', 'categories', 'edit'];
            
            if (!$row = Database::Go()->select(self::cTable)->where('id', $id, '=')->first()->run()) {
                if (DEBUG) {
                    $tpl->error = 'Invalid ID ' . ($id) . ' detected [' . __CLASS__ . ', ln.:' . __line__ . ']';
                } else {
                    $tpl->error = Language::$word->META_ERROR;
                }
                $tpl->template = 'admin/error';
            } else {
                $tpl->data = $row;
                $tpl->tree = $this->categoryTree();
                $tpl->droplist = self::getCategoryDropList($tpl->tree, 0, 0, '&#166;&nbsp;&nbsp;&nbsp;&nbsp;', $row->parent_id);
                $tpl->sortlist = $this->getSortCategoryList($tpl->tree);
                
                $tpl->template = 'admin/category';
            }
        }
        
        /**
         * processCategory
         *
         * @return void
         */
        public function processCategory(): void
        {
            $validate = Validator::run($_POST);
            $validate
                ->set('name', Language::$word->NAME)->required()->string()->min_len(2)->max_len(60)
                ->set('slug', Language::$word->PAG_SLUG)->string()
                ->set('body', Language::$word->DESCRIPTION)->string(true, true)
                ->set('keywords', Language::$word->METAKEYS)->string(true, true)
                ->set('description', Language::$word->METADESC)->string(true, true)
                ->set('parent_id', Language::$word->CT_PARENT)->required()->numeric()
                ->set('active', Language::$word->PUBLISHED)->required()->numeric();
            
            $safe = $validate->safe();
            
            if (count(Message::$msgs) === 0) {
                $data = array(
                    'name' => $safe->name,
                    'slug' => strlen($safe->slug) === 0 ? Url::doSeo($safe->name) : Url::doSeo($safe->slug),
                    'parent_id' => $safe->parent_id,
                    'body' => $safe->body,
                    'keywords' => $safe->keywords,
                    'description' => $safe->description,
                    'active' => $safe->active,
                );
                
                $last_id = 0;
                (Filter::$id) ? Database::Go()->update(self::cTable, $data)->where('id', Filter::$id, '=')->run() : $last_id = Database::Go()->insert(self::cTable, $data)->run();
                
                if (Filter::$id) {
                    $message = Message::formatSuccessMessage($data['name'], Language::$word->CT_UPDATE_OK);
                    Message::msgReply(Database::Go()->affected(), 'success', $message);
                } else {
                    if ($last_id) {
                        $message = Message::formatSuccessMessage($data['name'], Language::$word->CT_ADDED_OK);
                        $json['type'] = 'success';
                        $json['title'] = Language::$word->SUCCESS;
                        $json['message'] = $message;
                        $json['redirect'] = Url::url('/admin/categories');
                    } else {
                        $json['type'] = 'alert';
                        $json['title'] = Language::$word->ALERT;
                        $json['message'] = Language::$word->NOPROCCESS;
                    }
                    print json_encode($json);
                }
            } else {
                Message::msgSingleStatus();
            }
        }
        
        /**
         * couponIndex
         *
         * @return void
         */
        public function couponIndex(): void
        {
            $tpl = App::View(BASEPATH . 'view/');
            $tpl->dir = 'admin/';
            $tpl->title = Language::$word->META_M_COUPONS;
            $tpl->caption = Language::$word->META_M_COUPONS;
            $tpl->subtitle = Language::$word->DC_INFO;
            
            $tpl->data = Database::Go()->select(self::dcTable)->run();
            
            $tpl->template = 'admin/coupon';
        }
        
        /**
         * couponNew
         *
         * @return void
         */
        public function couponNew(): void
        {
            $tpl = App::View(BASEPATH . 'view/');
            $tpl->dir = 'admin/';
            $tpl->title = Language::$word->DC_NEW;
            $tpl->caption = Language::$word->DC_NEW;
            
            $tpl->template = 'admin/coupon';
        }
        
        /**
         * couponEdit
         *
         * @param int $id
         * @return void
         */
        public function couponEdit(int $id): void
        {
            $tpl = App::View(BASEPATH . 'view/');
            $tpl->dir = 'admin/';
            $tpl->title = Language::$word->DC_EDIT;
            $tpl->caption = Language::$word->DC_EDIT;
            $tpl->crumbs = ['admin', 'coupons', 'edit'];
            
            if (!$row = Database::Go()->select(self::dcTable)->where('id', $id, '=')->first()->run()) {
                if (DEBUG) {
                    $tpl->error = 'Invalid ID ' . ($id) . ' detected [' . __CLASS__ . ', ln.:' . __line__ . ']';
                } else {
                    $tpl->error = Language::$word->META_ERROR;
                }
                $tpl->template = 'admin/error';
            } else {
                $tpl->data = $row;
                
                $tpl->template = 'admin/coupon';
            }
        }
        
        /**
         * processCoupon
         *
         * @return void
         */
        public function processCoupon(): void
        {
            $validate = Validator::run($_POST);
            $validate
                ->set('title', Language::$word->NAME)->required()->string()->min_len(2)->max_len(40)
                ->set('code', Language::$word->DC_CODE)->required()->string()
                ->set('discount', Language::$word->DC_DISC)->required()->numeric()->min_numeric(1)->max_numeric(99)
                ->set('type', Language::$word->DC_TYPE)->required()->string()
                ->set('minval', Language::$word->DC_MIN)->required()->float()
                ->set('validuntil_submit', Language::$word->DC_VALID)->required()->date()
                ->set('active', Language::$word->PUBLISHED)->required()->numeric();
            
            $safe = $validate->safe();
            
            if (count(Message::$msgs) === 0) {
                $data = array(
                    'title' => $safe->title,
                    'code' => $safe->code,
                    'discount' => $safe->discount,
                    'type' => $safe->type,
                    'validuntil' => Database::toDate($safe->validuntil_submit),
                    'minval' => $safe->minval,
                    'active' => $safe->active,
                );
                
                (Filter::$id) ? Database::Go()->update(self::dcTable, $data)->where('id', Filter::$id, '=')->run() : Database::Go()->insert(self::dcTable, $data)->run();
                
                $message = Filter::$id ?
                    Message::formatSuccessMessage($data['title'], Language::$word->DC_UPDATE_OK) :
                    Message::formatSuccessMessage($data['title'], Language::$word->DC_ADDED_OK);
                Message::msgReply(Database::Go()->affected(), 'success', $message);
                Logger::writeLog($message);
            } else {
                Message::msgSingleStatus();
            }
        }
        
        /**
         * countryIndex
         *
         * @return void
         */
        public function countryIndex(): void
        {
            $tpl = App::View(BASEPATH . 'view/');
            $tpl->dir = 'admin/';
            $tpl->title = Language::$word->META_M_COUNTRIES;
            $tpl->caption = Language::$word->META_M_COUNTRIES;
            $tpl->subtitle = Language::$word->CNT_INFO;
            
            $tpl->data = Database::Go()->select(self::cnTable)->orderBy('sorting', 'DESC')->run();
            $tpl->template = 'admin/country';
        }
        
        /**
         * countryEdit
         *
         * @param int $id
         * @return void
         */
        public function countryEdit(int $id): void
        {
            $tpl = App::View(BASEPATH . 'view/');
            $tpl->dir = 'admin/';
            $tpl->title = Language::$word->CNT_EDIT;
            $tpl->caption = Language::$word->CNT_EDIT;
            $tpl->crumbs = ['admin', 'countries', 'edit'];
            
            if (!$row = Database::Go()->select(self::cnTable)->where('id', $id, '=')->first()->run()) {
                if (DEBUG) {
                    $tpl->error = 'Invalid ID ' . ($id) . ' detected [' . __CLASS__ . ', ln.:' . __line__ . ']';
                } else {
                    $tpl->error = Language::$word->META_ERROR;
                }
                $tpl->template = 'admin/error';
            } else {
                $tpl->data = $row;
                $tpl->template = 'admin/country';
            }
        }
        
        /**
         * processCountry
         *
         * @return void
         */
        public function processCountry(): void
        {
            $validate = Validator::run($_POST);
            $validate
                ->set('name', Language::$word->NAME)->required()->string()->min_len(2)->max_len(60)
                ->set('abbr', Language::$word->CNT_ABBR)->required()->string()->uppercase()->exact_len(2)
                ->set('active', Language::$word->STATUS)->required()->numeric()
                ->set('home', Language::$word->DEFAULT)->required()->numeric()
                ->set('sorting', Language::$word->SORTING)->numeric()
                ->set('vat', Language::$word->TRX_TAX)->required()->float()
                ->set('id', 'ID')->required()->numeric();
            
            $safe = $validate->safe();
            
            if (count(Message::$msgs) === 0) {
                $data = array(
                    'name' => $safe->name,
                    'abbr' => $safe->abbr,
                    'sorting' => $safe->sorting,
                    'home' => $safe->home,
                    'active' => $safe->active,
                    'vat' => $safe->vat,
                );
                
                if ($data['home'] == 1) {
                    Database::Go()->rawQuery('UPDATE `' . Content::cnTable . '` SET `home`= ?;', array(0))->run();
                }
                
                Database::Go()->update(Content::cnTable, $data)->where('id', Filter::$id, '=')->run();
                Message::msgReply(Database::Go()->affected(), 'success', Message::formatSuccessMessage($data['name'], Language::$word->CNT_UPDATE_OK));
                Logger::writeLog(Message::formatSuccessMessage($data['name'], Language::$word->CNT_UPDATE_OK));
            } else {
                Message::msgSingleStatus();
            }
        }
        
        /**
         * templateIndex
         *
         * @return void
         */
        public function templateIndex(): void
        {
            $tpl = App::View(BASEPATH . 'view/');
            $tpl->dir = 'admin/';
            $tpl->title = Language::$word->META_M_TEMPLATES;
            $tpl->caption = Language::$word->META_M_TEMPLATES;
            $tpl->subtitle = Language::$word->ET_INFO;
            
            $tpl->data = Database::Go()->select(self::eTable)->orderBy('name', 'ASC')->run();
            $tpl->template = 'admin/template';
        }
        
        /**
         * templateEdit
         *
         * @param int $id
         * @return void
         */
        public function templateEdit(int $id): void
        {
            $tpl = App::View(BASEPATH . 'view/');
            $tpl->dir = 'admin/';
            $tpl->title = Language::$word->ET_EDIT;
            $tpl->caption = Language::$word->ET_EDIT;
            $tpl->crumbs = ['admin', 'templates', 'edit'];
            
            if (!$row = Database::Go()->select(self::eTable)->where('id', $id, '=')->first()->run()) {
                if (DEBUG) {
                    $tpl->error = 'Invalid ID ' . ($id) . ' detected [' . __CLASS__ . ', ln.:' . __line__ . ']';
                } else {
                    $tpl->error = Language::$word->META_ERROR;
                }
                $tpl->template = 'admin/error';
            } else {
                $tpl->data = $row;
                
                $tpl->template = 'admin/template';
            }
        }
        
        /**
         * processTemplate
         *
         * @return void
         */
        public function processTemplate(): void
        {
            $validate = Validator::run($_POST);
            $validate
                ->set('name', Language::$word->ET_NAME)->required()->string()->min_len(2)->max_len(60)
                ->set('subject', Language::$word->ET_SUBJECT)->required()->string()->min_len(2)->max_len(100)
                ->set('help', Language::$word->DESCRIPTION)->required()->string()
                ->set('body', Language::$word->DC_TYPE)->required()->text('advanced');
            
            $safe = $validate->safe();
            
            if (count(Message::$msgs) === 0) {
                $data = array(
                    'name' => $safe->name,
                    'subject' => $safe->subject,
                    'help' => $safe->help,
                    'body' => str_replace(array(SITEURL, App::Core()->plogo), array('[SITEURL]', '[LOGO]'), $safe->body)
                );
                
                Database::Go()->update(self::eTable, $data)->where('id', Filter::$id, '=')->run();
                
                Message::msgReply(Database::Go()->affected(), 'success', Message::formatSuccessMessage($data['name'], Language::$word->ET_UPDATE_OK));
                Logger::writeLog(Message::formatSuccessMessage($data['name'], Language::$word->ET_UPDATE_OK));
            } else {
                Message::msgSingleStatus();
            }
        }
        
        /**
         * fieldIndex
         *
         * @return void
         */
        public function fieldIndex(): void
        {
            $tpl = App::View(BASEPATH . 'view/');
            $tpl->dir = 'admin/';
            $tpl->title = Language::$word->META_FIELDS;
            $tpl->caption = Language::$word->META_FIELDS;
            $tpl->subtitle = Language::$word->DC_INFO;
            
            $tpl->data = Database::Go()->select(self::cfTable)->orderBy('sorting', 'ASC')->run();
            
            $tpl->template = 'admin/field';
        }
        
        /**
         * fieldNew
         *
         * @return void
         */
        public function fieldNew(): void
        {
            $tpl = App::View(BASEPATH . 'view/');
            $tpl->dir = 'admin/';
            $tpl->title = Language::$word->CF_NEW;
            $tpl->caption = Language::$word->CF_NEW;
            
            $tpl->template = 'admin/field';
        }
        
        /**
         * fieldEdit
         *
         * @param int $id
         * @return void
         */
        public function fieldEdit(int $id): void
        {
            $tpl = App::View(BASEPATH . 'view/');
            $tpl->dir = 'admin/';
            $tpl->title = Language::$word->CF_EDIT;
            $tpl->caption = Language::$word->CF_EDIT;
            $tpl->crumbs = ['admin', 'fields', 'edit'];
            
            if (!$row = Database::Go()->select(self::cfTable)->where('id', $id, '=')->first()->run()) {
                if (DEBUG) {
                    $tpl->error = 'Invalid ID ' . ($id) . ' detected [' . __CLASS__ . ', ln.:' . __line__ . ']';
                } else {
                    $tpl->error = Language::$word->META_ERROR;
                }
                $tpl->template = 'admin/error';
            } else {
                $tpl->data = $row;
                
                $tpl->template = 'admin/field';
            }
        }
        
        /**
         * processField
         *
         * @return void
         */
        public function processField(): void
        {
            $validate = Validator::run($_POST);
            $validate
                ->set('title', Language::$word->NAME)->required()->string()->min_len(2)->max_len(60)
                ->set('required', Language::$word->CF_REQUIRED)->required()->numeric()
                ->set('tooltip', Language::$word->CF_TIP)->string()
                ->set('section', Language::$word->CF_SECTION)->required()->string()
                ->set('active', Language::$word->PUBLISHED)->required()->numeric();
            
            $safe = $validate->safe();
            
            if (count(Message::$msgs) === 0) {
                $data = array(
                    'title' => $safe->title,
                    'tooltip' => $safe->tooltip,
                    'required' => $safe->required,
                    'section' => $safe->section,
                    'active' => $safe->active,
                );
                
                if (!Filter::$id) {
                    $data['name'] = Utility::randomString(6);
                }
                $last_id = 0;
                $dataArray = array();
                (Filter::$id) ? Database::Go()->update(self::cfTable, $data)->where('id', Filter::$id, '=')->run() : $last_id = Database::Go()->insert(self::cfTable, $data)->run();
                
                if (!Filter::$id) {
                    switch ($safe->section) {
                        case 'product':
                            $products = Database::Go()->select(Product::mTable)->run();
                            foreach ($products as $row) {
                                $dataArray[] = array(
                                    'product_id' => $row->id,
                                    'field_id' => $last_id,
                                    'section' => $safe->section,
                                    'field_name' => $data['name'],
                                );
                            }
                            break;
                        
                        default:
                            $users = Database::Go()->select(User::mTable)->run();
                            foreach ($users as $row) {
                                $dataArray[] = array(
                                    'user_id' => $row->id,
                                    'field_id' => $last_id,
                                    'section' => $safe->section,
                                    'field_name' => $data['name'],
                                );
                            }
                            break;
                    }
                    
                    Database::Go()->batch(self::cfdTable, $dataArray)->run();
                }
                
                $message = Filter::$id ?
                    Message::formatSuccessMessage($data['title'], Language::$word->CF_UPDATE_OK) :
                    Message::formatSuccessMessage($data['title'], Language::$word->CF_ADDED_OK);
                
                Message::msgReply(Database::Go()->affected(), 'success', $message);
                Logger::writeLog($message);
            } else {
                Message::msgSingleStatus();
            }
        }
        
        /**
         * newsIndex
         *
         * @return void
         */
        public function newsIndex(): void
        {
            $tpl = App::View(BASEPATH . 'view/');
            $tpl->dir = 'admin/';
            $tpl->title = Language::$word->META_M_NEWS;
            $tpl->caption = Language::$word->META_M_NEWS;
            $tpl->subtitle = Language::$word->NW_INFO;
            
            $tpl->data = Database::Go()->select(self::nTable)->orderBy('created', 'DESC')->run();
            
            $tpl->template = 'admin/news';
        }
        
        /**
         * newsNew
         *
         * @return void
         */
        public function newsNew(): void
        {
            $tpl = App::View(BASEPATH . 'view/');
            $tpl->dir = 'admin/';
            $tpl->title = Language::$word->NW_NEW;
            $tpl->caption = Language::$word->NW_NEW;
            
            $tpl->template = 'admin/news';
        }
        
        /**
         * newsEdit
         *
         * @param int $id
         * @return void
         */
        public function newsEdit(int $id): void
        {
            $tpl = App::View(BASEPATH . 'view/');
            $tpl->dir = 'admin/';
            $tpl->title = Language::$word->CF_EDIT;
            $tpl->caption = Language::$word->CF_EDIT;
            $tpl->crumbs = ['admin', 'news', 'edit'];
            
            if (!$row = Database::Go()->select(self::nTable)->where('id', $id, '=')->first()->run()) {
                if (DEBUG) {
                    $tpl->error = 'Invalid ID ' . ($id) . ' detected [' . __CLASS__ . ', ln.:' . __line__ . ']';
                } else {
                    $tpl->error = Language::$word->META_ERROR;
                }
                $tpl->template = 'admin/error';
            } else {
                $tpl->data = $row;
                
                $tpl->template = 'admin/news';
            }
        }
        
        /**
         * processNews
         *
         * @return void
         */
        public function processNews(): void
        {
            $validate = Validator::run($_POST);
            $validate
                ->set('title', Language::$word->NAME)->required()->string()->min_len(2)->max_len(60)
                ->set('active', Language::$word->PUBLISHED)->required()->numeric()
                ->set('body', Language::$word->DESCRIPTION)->text('advanced');
            
            $safe = $validate->safe();
            
            if (count(Message::$msgs) === 0) {
                $data = array(
                    'title' => $safe->title,
                    'body' => str_replace(array(SITEURL), array('[SITEURL]'), $safe->body),
                    'author' => App::Auth()->name,
                    'active' => $safe->active
                );
                
                (Filter::$id) ? Database::Go()->update(self::nTable, $data)->where('id', Filter::$id, '=')->run() : Database::Go()->insert(self::nTable, $data)->run();
                
                $message = Filter::$id ?
                    Message::formatSuccessMessage($data['title'], Language::$word->NW_UPDATE_OK) :
                    Message::formatSuccessMessage($data['title'], Language::$word->NW_ADDED_OK);
                
                Message::msgReply(Database::Go()->affected(), 'success', $message);
                Logger::writeLog($message);
            } else {
                Message::msgSingleStatus();
            }
        }
        
        /**
         * faqIndex
         *
         * @return void
         */
        public function faqIndex(): void
        {
            $tpl = App::View(BASEPATH . 'view/');
            $tpl->dir = 'admin/';
            $tpl->title = Language::$word->META_FAQ;
            $tpl->caption = Language::$word->META_M_FAQ;
            $tpl->subtitle = Language::$word->FAQ_INFO;
            
            $tpl->data = Database::Go()->select(self::fTable)->orderBy('sorting', 'ASC')->run();
            
            $tpl->template = 'admin/faq';
        }
        
        /**
         * faqNew
         *
         * @return void
         */
        public function faqNew(): void
        {
            $tpl = App::View(BASEPATH . 'view/');
            $tpl->dir = 'admin/';
            $tpl->title = Language::$word->FAQ_NEW;
            $tpl->caption = Language::$word->FAQ_NEW;
            
            $tpl->template = 'admin/faq';
        }
        
        /**
         * faqEdit
         *
         * @param int $id
         * @return void
         */
        public function faqEdit(int $id): void
        {
            $tpl = App::View(BASEPATH . 'view/');
            $tpl->dir = 'admin/';
            $tpl->title = Language::$word->FAQ_EDIT;
            $tpl->caption = Language::$word->FAQ_EDIT;
            $tpl->crumbs = ['admin', 'faq', 'edit'];
            
            if (!$row = Database::Go()->select(self::fTable)->where('id', $id, '=')->first()->run()) {
                if (DEBUG) {
                    $tpl->error = 'Invalid ID ' . ($id) . ' detected [' . __CLASS__ . ', ln.:' . __line__ . ']';
                } else {
                    $tpl->error = Language::$word->META_ERROR;
                }
                $tpl->template = 'admin/error';
            } else {
                $tpl->data = $row;
                
                $tpl->template = 'admin/faq';
            }
        }
        
        /**
         * processFaq
         *
         * @return void
         */
        public function processFaq(): void
        {
            $validate = Validator::run($_POST);
            $validate
                ->set('question', Language::$word->FAQ_QUESTION)->required()->string()->min_len(3)->max_len(100)
                ->set('answer', Language::$word->FAQ_ANSWER)->required()->string(true, true);
            
            $safe = $validate->safe();
            
            if (count(Message::$msgs) === 0) {
                $data = array(
                    'question' => $safe->question,
                    'answer' => $safe->answer
                );
                
                (Filter::$id) ? Database::Go()->update(self::fTable, $data)->where('id', Filter::$id, '=')->run() : Database::Go()->insert(self::fTable, $data)->run();
                
                $message = Filter::$id ?
                    Message::formatSuccessMessage($data['question'], Language::$word->FAQ_UPDATE_OK) :
                    Message::formatSuccessMessage($data['question'], Language::$word->FAQ_ADDED_OK);
                
                Message::msgReply(Database::Go()->affected(), 'success', $message);
                Logger::writeLog($message);
            } else {
                Message::msgSingleStatus();
            }
        }
        
        /**
         * getCategoryDropList
         *
         * @param array $array
         * @param int $parent_id
         * @param int $level
         * @param string $spacer
         * @param int $selected
         * @return string
         */
        public static function getCategoryDropList(array $array, int $parent_id, int $level = 0, string $spacer = '__', int $selected = 0): string
        {
            $html = '';
            if ($array) {
                foreach ($array as $key => $row) {
                    $sel = ($row['id'] == $selected) ? " selected=\"selected\"" : '';
                    
                    if ($parent_id == $row['parent_id']) {
                        $html .= "<option value=\"" . $row['id'] . "\"" . $sel . '>';
                        
                        $html .= str_repeat($spacer, $level);
                        
                        $html .= $row['name'] . "</option>\n";
                        $level++;
                        $html .= self::getCategoryDropList($array, $key, $level, $spacer, $selected);
                        $level--;
                    }
                }
                unset($row);
            }
            return $html;
        }
        
        /**
         * getSortCategoryList
         *
         * @param array $array
         * @param int $parent_id
         * @return string
         */
        public static function getSortCategoryList(array $array, int $parent_id = 0): string
        {
            $submenu = false;
            $icon = '<i class="icon negative trash"></i>';
            $html = '';
            foreach ($array as $key => $row) {
                if ($row['parent_id'] == $parent_id) {
                    if ($submenu === false) {
                        $submenu = true;
                        $html .= "<ul class=\"wojo nestable list\">\n";
                    }
                    $html .= '
                         <li class="item" data-id="' . $row['id'] . '">'
                        . '<div class="content"><div class="handle"><i class="icon grip horizontal"></i></div><div class="text">
                         <a href="' . Url::url('/admin/categories/edit', $row['id']) . '">' . $row['name'] . '</a></div>'
                        . '<div class="actions"><a class="data" data-set=\'{"option":[{"trash": "trashCategory","title": "' . Validator::sanitize($row['name'], 'chars') . '","id":' . $row['id'] . '}],"action":"trash","parent":"li", "redirect":"' . Url::url('/admin/categories') . '"}\'>' . $icon . '</a>
                         </div></div>';
                    $html .= self::getSortCategoryList($array, $key);
                    $html .= "</li>\n";
                }
            }
            unset($row);
            
            if ($submenu === true) {
                $html .= "</ul>\n";
            }
            
            return $html;
        }
        
        /**
         * getSortMenuList
         *
         * @param array|null $array
         * @return string
         */
        public function getSortMenuList(array|null $array): string
        {
            $icon = '<i class="icon negative trash"></i>';
            $html = "<ul class=\"wojo nestable list\">\n";
            
            foreach ($array as $row) {
                $html .= '<li class="item" data-id="' . $row->id . '">';
                $html .= '<div class="content"><div class="handle"><i class="icon grip horizontal"></i></div>';
                $html .= '<div class="text"><a href="' . Url::url('/admin/menus/edit', $row->id) . '/">' . $row->name . '</a></div>';
                $html .= '<div class="actions">';
                $html .= '<a class="data" data-set=\'{"option":[{"trash": "trashMenu","title": "' . Validator::sanitize($row->name, 'chars') . '","id":' . $row->id . '}],"action":"trash","parent":"li", "redirect":"' . Url::url('/admin/menus') . '"}\'>' . $icon . '</a></div>';
                $html .= '</div>';
                $html .= "</li>\n";
            }
            unset($row);
            
            $html .= "</ul>\n";
            
            return $html;
        }
        
        /**
         * categoryTree
         *
         * @return array
         */
        public function categoryTree(): array
        {
            
            $data = Database::Go()->select(self::cTable, array('id', 'parent_id', ' name', ' slug'))->orderBy('parent_id', 'ASC')->orderBy('sorting', 'ASC')->run();
            
            $cats = array();
            $result = array();
            
            foreach ($data as $row) {
                $cats['id'] = $row->id;
                $cats['name'] = $row->name;
                $cats['slug'] = $row->slug;
                $cats['parent_id'] = $row->parent_id;
                $result[$row->id] = $cats;
            }
            return $result;
        }
        
        /**
         * getCatCheckList
         *
         * @param array $array
         * @param int $parent_id
         * @param int $level
         * @param string $spacer
         * @param bool $selected
         * @return string
         */
        public static function getCatCheckList(array $array, int $parent_id, int $level = 0, string $spacer = '--', bool $selected = false): string
        {
            
            $html = '';
            if ($array) {
                if ($selected) {
                    $arr = explode(',', $selected);
                }
                foreach ($array as $key => $row) {
                    $active = ($selected and in_array($row['id'], $arr)) ? " checked=\"checked\"" : '';
                    
                    if ($parent_id == $row['parent_id']) {
                        $html .= "<div class=\"item\"><div class=\"wojo small checkbox fitted inline\"> <input id=\"ckb_" . $row['id'] . "\" type=\"checkbox\" name=\"categories[]\" value=\"" . $row['id'] . "\"" . $active . '>';
                        $html .= "<label for=\"ckb_" . $row['id'] . "\">";
                        $html .= str_repeat($spacer, $level);
                        
                        $html .= $row['name'] . "</label></div></div>\n";
                        $level++;
                        $html .= self::getCatCheckList($array, $key, $level, $spacer, $selected);
                        $level--;
                    }
                }
                unset($row);
            }
            return $html;
        }
        
        /**
         * renderCustomFields
         *
         * @param int $id
         * @param string $section
         * @return string
         */
        public static function renderCustomFields(int $id, string $section): string
        {
            $item = match ($section) {
                'product' => 'cfd.product_id = ? ',
                default => 'cfd.user_id = ? ',
            };
            
            if ($id) {
                $sql = '
                SELECT cf.*, cfd.field_value
                  FROM `' . self::cfTable . '` AS cf
                  LEFT JOIN `' . self::cfdTable . "` AS cfd ON cfd.field_id = cf.id
                  WHERE $item
                  AND cf.section = ?
                  ORDER BY cf.sorting
                ";
                $data = Database::Go()->rawQuery($sql, array($id, $section))->run();
            } else {
                $data = Database::Go()->select(self::cfTable)->where('section', $section, '=')->orderBy('sorting', 'ASC')->run();
            }
            
            $html = '';
            if ($data) {
                foreach ($data as $row) {
                    $tooltip = $row->tooltip ? ' <span data-tooltip="' . $row->tooltip . '"><i class="icon question circle"></i></span>' : '';
                    $required = $row->required ? ' <i class="icon asterisk"></i>' : '';
                    $html .= '<div class="wojo fields align-middle">';
                    $html .= '<div class="field four wide labeled">';
                    $html .= '<label>' . $row->title . $required . $tooltip . '</label>';
                    $html .= '</div>';
                    $html .= '<div class="six wide field">';
                    $html .= '<input name="custom_' . $row->name . '" type="text" placeholder="' . $row->title . '" value="' . ($id ? $row->field_value : '') . '">';
                    $html .= '</div>';
                    $html .= '</div>';
                }
            }
            return $html;
        }
        
        /**
         * renderCustomFieldsFront
         *
         * @param int $id
         * @param string $section
         * @return string
         */
        public static function renderCustomFieldsFront(int $id, string $section): string
        {
            $item = match ($section) {
                'product' => 'cfd.product_id = ? ',
                default => 'cfd.user_id = ? ',
            };
            
            if ($id) {
                $sql = '
                SELECT cf.*, cfd.field_value
                  FROM `' . self::cfTable . '` as cf
                  LEFT JOIN `' . self::cfdTable . "` as cfd ON cfd.field_id = cf.id
                  WHERE $item
                  AND cf.section = ?
                  ORDER BY cf.sorting
                ";
                
                $result = Database::Go()->rawQuery($sql, array($id, $section))->run();
            } else {
                $result = Database::Go()->select(self::cfTable)->where('section', $section, '=')->orderBy('sorting', 'ASC')->run();
            }
            
            return Utility::getSnippets(THEMEBASE . '/snippets/customFields.tpl.php', ['data' => $result, 'id' => $id, 'section' => $section]);
        }
        
        /**
         * verifyCustomFields
         *
         * @param string $section
         * @return void
         */
        public static function verifyCustomFields(string $section): void
        {
            if ($data = Database::Go()->select(self::cfTable)->where('active', 1, '=')->where('section', $section, '=')->where('required', 1, '=')->run()) {
                foreach ($data as $row) {
                    Validator::checkPost('custom_' . $row->name, Language::$word->FIELD_R0 . ' "' . $row->title . '" ' . Language::$word->FIELD_R100);
                }
            }
        }
        
        /**
         * getCountryList
         *
         * @return mixed
         */
        public function getCountryList(): mixed
        {
            return Database::Go()->select(self::cnTable)->orderBy('sorting', 'DESC')->run();
        }
        
        /**
         * getMenus
         *
         * @return int|mixed
         */
        public static function getMenus(): mixed
        {
            
            $sql = '
            SELECT m.id, m.name, m.content_type, m.link, m.target, p.slug, p.page_type
              FROM `' . self::mTable . '` AS m
              LEFT JOIN `' . self::pTable . '` AS p ON p.id = m.page_id
              WHERE m.active = ?
              ORDER BY m.sorting
            ';
            
            $row = Database::Go()->rawQuery($sql, array(1))->run();
            
            return ($row) ? : 0;
        }
        
        /**
         * renderCategories
         *
         * @param array|null $array
         * @param int $parent_id
         * @param string $menuid
         * @param string $class
         * @return string
         */
        public function renderCategories(array|null $array, int $parent_id = 0, string $menuid = 'main-menu', string $class = 'top-menu'): string
        {
            $html = '';
            if (is_array($array) && count($array) > 0) {
                $submenu = false;
                $attr = (!$parent_id) ? ' class="' . $class . '" id="' . $menuid . '"' : ' class="menu-submenu"';
                $attr2 = (!$parent_id) ? ' class="nav-item"' : ' class="nav-submenu-item"';
                
                foreach ($array as $key => $row) {
                    if ($row['parent_id'] == $parent_id) {
                        if ($submenu === false) {
                            $submenu = true;
                            $html .= '<ul' . $attr . ">\n";
                        }
                        
                        $url = Url::url('/category', $row['slug'] . '/');
                        $active = (in_array($row['slug'], self::$segments) ? 'active' : 'normal');
                        $name = ($parent_id == 0) ? '<strong>' . $row['name'] . '</strong>' : $row['name'];
                        $link = '<a href="' . $url . '" class="' . $active . '">' . $name . '</a>';
                        
                        $html .= '<li' . $attr2 . '>';
                        $html .= $link;
                        $html .= $this->renderCategories($array, $key);
                        $html .= "</li>\n";
                    }
                }
                unset($row);
                
                if ($submenu === true) {
                    $html .= "</ul>\n";
                }
            }
            return $html;
        }
        
        /**
         * categoryRender
         *
         * @param string $slug
         * @return void
         */
        public function categoryRender(string $slug): void
        {
            $core = App::Core();
            $tpl = App::View(BASEPATH . 'view/');
            $tpl->dir = 'front/themes/' . $core->theme . '/';
            $tpl->title = str_replace('[COMPANY]', $core->company, Language::$word->META_WELCOME);
            $tpl->crumbs = [array(0 => Language::$word->HOME, 1 => ''), Language::$word->META_DASH, Language::$word->META_M_ACCNT];
            $tpl->keywords = '';
            $tpl->description = '';
            $tpl->data = null;
            
            if (!$row = Database::Go()->select(self::cTable)->where('slug', $slug, '=')->first()->run()) {
                if (DEBUG) {
                    $tpl->error = 'Invalid slug ' . ($slug) . ' detected [' . __CLASS__ . ', ln.:' . __line__ . ']';
                    $tpl->template = 'front/themes/' . $core->theme . '/error';
                } else {
                    $tpl->error = Language::$word->META_ERROR;
                    $tpl->title = Language::$word->META_ERROR;
                    $tpl->template = 'front/themes/' . $core->theme . '/404';
                }
            } else {
                if (isset($_GET['order']) and count(explode('|', $_GET['order'])) == 2) {
                    list($sort, $order) = explode('|', $_GET['order']);
                    $sort = Validator::sanitize($sort, 'string', 16);
                    $order = Validator::sanitize($order, 'string', 5);
                    if (in_array($sort, array(
                        'title',
                        'price',
                        'memberships',
                        'likes'
                    ))) {
                        $ord = ($order == 'DESC') ? ' DESC' : ' ASC';
                        $sorting = $sort . $ord;
                    } else {
                        $sorting = ' created DESC';
                    }
                } else {
                    $sorting = ' created DESC';
                }
                
                $pSql = '
                SELECT COUNT(p.id) as items
                  FROM `' . Product::mTable . '` as p
                  INNER JOIN `' . self::crTable . '` as rc ON p.id = rc.product_id
                  WHERE rc.category_id = ' . $row->id . '
                  AND p.active = 1
                  LIMIT 1';
                
                $total = Database::Go()->rawQuery($pSql)->first()->run();
                
                $pager = Paginator::instance();
                $pager->items_total = (($total->items < 2) ? 0 : ($total->items - 2));
                $pager->default_ipp = $core->cperpage;
                $pager->path = Url::url(Router::$path, '?');
                $pager->paginate();
                
                $sql = "
                SELECT p.id, p.created, p.price, p.sprice, p.is_sale, p.title, p.slug, p.thumb, p.audio, p.token, p.likes, p.body, p.type, p.token, p.affiliate, p.membership_id, c.slug as cslug, c.name,
                       GROUP_CONCAT(m.title SEPARATOR ', ') as memberships,
                       (SELECT COUNT(product_id) FROM `" . Comment::mTable . '`
                       WHERE `' . Comment::mTable . '`.product_id = p.id) as comments
                       FROM `' . Product::mTable . '` as p
                       LEFT JOIN `' . self::cTable . '` as c ON c.id = p.category_id
                       INNER JOIN `' . self::crTable . '` as rc ON p.id = rc.product_id
                       LEFT JOIN `' . Membership::mTable . "` as m ON FIND_IN_SET(m.id, p.membership_id)
                  WHERE rc.category_id = ?
                  AND p.active = ?
                  AND c.active = ?
                  GROUP BY p.id
                  ORDER BY $sorting " . $pager->limit;
                
                $tpl->data = Database::Go()->rawQuery($sql, array($row->id, 1, 1))->run();
                $tpl->special = ($tpl->data) ? array_slice($tpl->data, 0, 2) : null;
                $tpl->featured = ($tpl->data) ? array_slice($tpl->data, 2) : null;
                
                $tpl->pager = $pager;
                $tpl->row = $row;
                $tpl->title = Url::formatMeta($row->name);
                $tpl->keywords = $row->keywords;
                $tpl->description = $row->description;
                $tpl->crumbs = [array(0 => Language::$word->HOME, 1 => ''), $row->name];
                
                $tpl->template = 'front/themes/' . $core->theme . '/category';
            }
        }
        
        /**
         * applyCoupon
         *
         * @return void
         */
        public function applyCoupon(): void
        {
            $validate = Validator::run($_POST);
            
            $validate->set('coupon', Language::$word->DC_CODE)->required()->string();
            $safe = $validate->safe();
            
            if (count(Message::$msgs) === 0) {
                $sql = 'SELECT * FROM `' . self::dcTable . '` WHERE validuntil >= CURDATE() AND code = ? AND active = ?';
                if ($row = Database::Go()->rawQuery($sql, array($safe->coupon, 1))->first()->run()) {
                    
                    $totals = Product::getCartTotal();
                    $tax = self::calculateTax();
                    
                    if (Validator::compareNumbers($row->minval, $totals->subtotal, '>')) {
                        $json['type'] = 'error';
                        $json['title'] = Language::$word->ERROR;
                        $json['message'] = str_replace('[TOTAL]', Utility::formatMoney($row->minval), Language::$word->DC_CODE_MIN);
                        print json_encode($json);
                        exit;
                    } else {
                        $cart_content = Database::Go()->select(Product::cxTable)->where('user_id', App::Auth()->sesid, '=')->where('membership_id', 1, '<')->run();
                        Session::set('tmp_cart', $cart_content);
                        $cart = Session::get('tmp_cart');
                        
                        $data = array();
                        foreach ($cart as $rows) {
                            if ($rows->coupon < 1) {
                                $coupon = self::calculateCoupon($row->type, $row->discount, $rows->originalprice, $totals->subtotal);
                                
                                $total = number_format($rows->originalprice - $coupon, 2);
                                $t_tax = Validator::sanitize(($rows->originalprice - $coupon) * $tax, 'float');
                                $data[] = array(
                                    'id' => $rows->id,
                                    'user_id' => $rows->user_id,
                                    'product_id' => $rows->product_id,
                                    'tax' => $tax,
                                    'totaltax' => $t_tax,
                                    'coupon' => Validator::sanitize($coupon, 'float'),
                                    'originalprice' => $rows->originalprice,
                                    'total' => $total,
                                    'totalprice' => Validator::sanitize($total + $t_tax, 'float')
                                );
                                
                                
                                Database::Go()->delete(Product::cxTable)->where('user_id', App::Auth()->sesid, '=')->where('membership_id', 1, '<')->run();
                                Database::Go()->batch(Product::cxTable, $data)->run();
                            }
                        }
                        
                        Session::remove('tmp_cart');
                        $totals = Product::getCartTotal();
                        
                        $json['type'] = 'success';
                        $json['title'] = Language::$word->SUCCESS;
                        $json['message'] = str_replace('[AMOUNT]', Utility::formatMoney($totals->discount), Language::$word->DC_CODE_OK);
                        $json['coupon'] = '<div class="icon-text"><i class="icon dash positive alt"></i> ' . Utility::formatNumber($totals->discount) . '</div>';
                        $json['tax'] = '<div class="icon-text"><i class="icon plus negative alt"></i>' . Utility::formatNumber($totals->tax) . '</div>';
                        $json['subtotal'] = Utility::formatNumber($totals->subtotal);
                        $json['total'] = Utility::formatMoney($totals->grand);
                        print json_encode($json);
                    }
                } else {
                    $json['type'] = 'error';
                    $json['title'] = Language::$word->ERROR;
                    $json['message'] = Language::$word->DC_INVALID;
                    print json_encode($json);
                }
            } else {
                Message::msgSingleStatus();
            }
        }
        
        /**
         * calculateCoupon
         *
         * @param string $type
         * @param float $amount
         * @param float $price
         * @param float $subtotal
         * @return string
         */
        public static function calculateCoupon(string $type, float $amount, float $price, float $subtotal): string
        {
            return ($type == 'p') ? number_format($price / 100 * $amount, 2) : number_format($amount / ($subtotal) * $price, 2);
        }
        
        /**
         * calculateTax
         *
         * @return float|int
         */
        public static function calculateTax(): float|int
        {
            $core = App::Core();
            
            return ($core->enable_tax and $core->tax_rate > 0) ? $core->tax_rate / 100 : 0;
        }
        
        /**
         * pageType
         *
         * @param string $type
         * @return string
         */
        public static function pageType(string $type): string
        {
            return match ($type) {
                'home' => "<i class=\"icon primary house disabled\"></i>",
                'membership' => "<i class=\"icon primary lock disabled\"></i>",
                'faq' => "<i class=\"icon primary question circle disabled\"></i>",
                'contact' => "<i class=\"icon primary envelope disabled\"></i>",
                'policy' => "<i class=\"icon primary shield disabled\"></i>",
                default => "<i class=\"icon file disabled\"></i>",
            };
        }
        
        /**
         * pageTypeList
         *
         * @return array
         */
        public static function pageTypeList(): array
        {
            return array(
                'normal' => Language::$word->PAG_NORMAL,
                'faq' => Language::$word->PAG_FAQ,
                'contact' => Language::$word->PAG_CONTACT,
                'home' => Language::$word->PAG_HOME
            );
        }
        
        /**
         * getContentType
         *
         * @return array
         */
        public static function getContentType(): array
        {
            return array(
                'page' => Language::$word->MU_PAGE,
                'web' => Language::$word->EXT_LINK
            );
        }
    }