<?php
    /**
     * Admin Class
     *
     * @package Wojo Framework
     * @author wojoscripts.com
     * @copyright 2023
     * @version 5.50: Admin.php, v1.00 8/4/2023 11:18 AM Gewa Exp $
     *
     */
    if (!defined('_WOJO')) {
        die('Direct access to this location is not allowed.');
    }
    
    class Admin
    {
        
        const gTable = 'gateways';
        
        /**
         * index
         *
         * @return void
         */
        public function index(): void
        {
            $tpl = App::View(BASEPATH . 'view/');
            $tpl->dir = 'admin/';
            $tpl->title = Language::$word->META_M_DASH;
            $tpl->caption = Language::$word->META_M_DASH;
            $tpl->subtitle = Language::$word->DASH_INFO;
            
            $sql = '
                SELECT COUNT(*) AS total,
                  COUNT(CASE WHEN type = ? THEN 1  END) AS users,
                  COUNT(CASE WHEN type = ? AND active = ? THEN 1  END) AS active,
                  COUNT(CASE WHEN type = ? AND active = ? THEN 1  END) AS pending,
                  COUNT(CASE WHEN type = ? AND membership_id >= 1 THEN 1  END) AS memberships
                  FROM `' . User::mTable . '`
                ';
            
            $tpl->data = Database::Go()->rawQuery($sql, array('member', 'member', 'y', 'member', 't', 'member'))->first()->run();
            $tpl->memberships = Stats::MembershipsExpireMonth();
            
            $tpl->template = 'admin/index';
        }
        
        /**
         * account
         *
         * @return void
         */
        public function account(): void
        {
            $tpl = App::View(BASEPATH . 'view/');
            $tpl->dir = 'admin/';
            $tpl->title = Language::$word->META_ACCOUNT;
            
            $tpl->data = Database::Go()->select(User::mTable)->where('id', App::Auth()->uid, '=')->first()->run();
            $tpl->custom_fields = Content::renderCustomFields(App::Auth()->uid, 'profile');
            
            $tpl->template = 'admin/account';
        }
        
        /**
         * password
         *
         * @return void
         */
        public function password(): void
        {
            $tpl = App::View(BASEPATH . 'view/');
            $tpl->dir = 'admin/';
            $tpl->title = Language::$word->USR_PASSUPDATE;
            $tpl->crumbs = ['admin', array(0 => Language::$word->META_ACCOUNT, 1 => 'account'), Language::$word->META_PASSWORD];
            
            $tpl->template = 'admin/account';
        }
        
        /**
         * UpdateAccount
         *
         * @return void
         */
        public function updateAccount(): void
        {
            $validate = Validator::run($_POST);
            $validate
                ->set('fname', Language::$word->FNAME)->required()->string()->min_len(2)->max_len(60)
                ->set('lname', Language::$word->LNAME)->required()->string()->min_len(2)->max_len(60)
                ->set('email', Language::$word->EMAIL)->required()->email();
            
            $safe = $validate->safe();
            
            $thumb = File::upload('avatar', 512000, 'png,jpg,jpeg');
            
            Content::verifyCustomFields('profile');
            
            if (count(Message::$msgs) === 0) {
                $data = array(
                    'email' => $safe->email,
                    'lname' => $safe->lname,
                    'fname' => $safe->fname
                );
                
                if (array_key_exists('avatar', $_FILES)) {
                    $thumbPath = UPLOADS . '/avatars/';
                    if (Auth::$udata->avatar != '') {
                        File::deleteFile(UPLOADS . '/avatars/' . Auth::$udata->avatar);
                    }
                    $result = File::process($thumb, $thumbPath, 'AVT_');
                    App::Auth()->avatar = Session::set('avatar', $result['fname']);
                    $data['avatar'] = $result['fname'];
                }
                
                Database::Go()->update(User::mTable, $data)->where('id', App::Auth()->uid, '=')->run();
                if (Database::Go()->affected()) {
                    App::Auth()->fname = Session::set('fname', $data['fname']);
                    App::Auth()->lname = Session::set('lname', $data['lname']);
                    App::Auth()->email = Session::set('email', $data['email']);
                }
                
                // Start Custom Fields
                $fl_array = Utility::array_key_exists_wildcard($_POST, 'custom_*', 'key-value');
                if ($fl_array) {
                    foreach ($fl_array as $key => $val) {
                        $cfdata['field_value'] = Validator::sanitize($val);
                        Database::Go()->update(Content::cfdTable, $cfdata)->where('id', App::Auth()->uid, '=')->where('field_name', str_replace('custom_', '', $key), '=')->run();
                    }
                }
                
                $message = str_replace('[NAME]', '', Language::$word->USR_UPDATED_A);
                Message::msgReply(true, 'success', $message);
            } else {
                Message::msgSingleStatus();
            }
        }
        
        /**
         * updateAdminPassword
         *
         * @return void
         */
        public function updateAdminPassword(): void
        {
            
            $validate = Validator::run($_POST);
            $validate->set('password', Language::$word->NEWPASS)->required()->string()->min_len(6)->max_len(20);
            $validate->set('password2', Language::$word->CONPASS)->required()->string()->equals($_POST['password'])->min_len(6)->max_len(20);
            
            $safe = $validate->safe();
            
            if (count(Message::$msgs) === 0) {
                $data['hash'] = Auth::doHash($safe->password);
                
                Database::Go()->update(User::mTable, $data)->where('id', App::Auth()->uid, '=')->run();
                Message::msgReply(Database::Go()->affected(), 'success', Language::$word->USR_PASSUPDATE_OK);
            } else {
                Message::msgSingleStatus();
            }
        }
        
        /**
         * mailerIndex
         *
         * @return void
         */
        public function mailerIndex(): void
        {
            $tpl = App::View(BASEPATH . 'view/');
            $tpl->dir = 'admin/';
            $tpl->title = Language::$word->META_M_NEWSLETTER;
            $tpl->caption = Language::$word->META_M_NEWSLETTER;
            $tpl->subtitle = Language::$word->NL_INFO;
            
            $type = Validator::get('email') ? 'singleMail' : 'newsletter';
            $tpl->data = Database::Go()->select(Content::eTable)->where('typeid', $type, '=')->first()->run();
            
            $tpl->template = 'admin/mailer';
        }
        
        /**
         * processMailer
         *
         * @return void
         * @throws \PHPMailer\PHPMailer\Exception
         */
        public function processMailer(): void
        {
            
            $validate = Validator::run($_POST);
            $validate
                ->set('subject', Language::$word->NL_SUBJECT)->required()->string()
                ->set('recipient', Language::$word->NL_RCPT)->required()->string()
                ->set('body', Language::$word->NL_BODY)->text('advanced');
            
            $safe = $validate->safe();
            $upl = Upload::instance(20971520, 'zip,jpg,pdf,doc,docx');
            
            if (count(Message::$msgs) === 0) {
                $to = $safe->recipient;
                $subject = $safe->subject;
                $body = $safe->body;
                $numSent = 0;
                $userRow = null;
                $row = null;
                $failedRecipients = array();
                $core = App::Core();
                
                $mailer = Mailer::sendMail();
                $mailer->Subject = $subject;
                $mailer->SMTPKeepAlive = true;
                $mailer->setFrom($core->site_email, $core->company);
                $mailer->isHTML();
                
                if (array_key_exists('attachment', $_FILES)) {
                    $upl->process('attachment', UPLOADS . '/attachments/', 'ATT_');
                    $attachment = '<a href="' . UPLOADURL . '/attachments/' . $upl->fileInfo['fname'] . '">' . Language::$word->NL_ATTACH . '</a>';
                } else {
                    $attachment = '';
                }
                
                switch ($to) {
                    case 'all':
                        $userRow = Database::Go()->select(User::mTable, array('email', 'CONCAT(fname," ",lname) as name'))->where('active', 'y', '=')->where('type', 'member', '=')->run();
                        break;
                    
                    case 'newsletter':
                        $userRow = Database::Go()->select(User::mTable, array('email', 'CONCAT(fname," ",lname) as name'))->where('newsletter', 1, '=')->where('type', 'member', '=')->run();
                        break;
                    
                    case 'paid':
                        $userRow = Database::Go()->select(User::mTable, array('email', 'CONCAT(fname," ",lname) as name'))->where('membership_id', 0, '>')->where('type', 'member', '=')->run();
                        break;
                    
                    default:
                        $row = Database::Go()->rawQuery("SELECT email, CONCAT(fname,' ',lname) as name FROM `" . User::mTable . "` WHERE email LIKE '%" . $to . "%'")->first()->run();
                        break;
                    
                }
                
                switch ($to) {
                    case 'all':
                    case 'newsletter':
                    case 'paid':
                        if ($userRow) {
                            foreach ($userRow as $row) {
                                $mailer->Body = str_replace(array(
                                    '[LOGO]',
                                    '[NAME]',
                                    '[DATE]',
                                    '[SITE_NAME]',
                                    '[COMPANY]',
                                    '[ATTACHMENT]',
                                    '[FB]',
                                    '[TW]',
                                    '[CEMAIL]',
                                    '[SITEURL]'
                                ), array(
                                    $core->plogo,
                                    $row->name,
                                    date('Y'),
                                    $core->site_name,
                                    $core->company,
                                    $attachment,
                                    $core->social->facebook,
                                    $core->social->twitter,
                                    $core->site_email,
                                    SITEURL
                                ), $body);
                                
                                $mailer->addAddress($row->email, $row->name);
                                
                                try {
                                    $mailer->send();
                                    $numSent++;
                                } catch (Exception) {
                                    $failedRecipients[] = htmlspecialchars($row->email);
                                    $mailer->getSMTPInstance()->reset();
                                }
                                $mailer->clearAddresses();
                                $mailer->clearAttachments();
                                
                            }
                            unset($row);
                        }
                        break;
                    
                    default:
                        if ($row) {
                            $newbody = str_replace(array(
                                '[COMPANY]',
                                '[SITE_NAME]',
                                '[ATTACHMENT]',
                                '[LOGO]',
                                '[NAME]',
                                '[URL]',
                                '[FB]',
                                '[TW]',
                                '[CEMAIL]',
                                '[DATE]'
                            ), array(
                                $core->company,
                                $core->site_name,
                                $attachment,
                                $core->plogo,
                                $row->name,
                                SITEURL,
                                $core->social->facebook,
                                $core->social->twitter,
                                $core->site_email,
                                date('Y')
                            ), $body);
                            
                            $mailer->addAddress($to, $row->name);
                            $mailer->Body = $newbody;
                            
                            $numSent++;
                            $mailer->send();
                        }
                        break;
                }
                if ($numSent) {
                    $json['type'] = 'success';
                    $json['title'] = Language::$word->SUCCESS;
                    $json['message'] = $numSent . ' ' . Language::$word->NL_SENT;
                } else {
                    $json['type'] = 'error';
                    $json['title'] = Language::$word->ERROR;
                    $res = '<ul>';
                    foreach ($failedRecipients as $failed) {
                        $res .= '<li>' . $failed . '</li>';
                    }
                    $res .= '</ul>';
                    $json['message'] = Language::$word->NL_ALERT . $res;
                    
                    unset($failed);
                }
                print json_encode($json);
                
            } else {
                Message::msgSingleStatus();
            }
        }
        
        /**
         * role
         *
         * @return void
         */
        public function role(): void
        {
            $tpl = App::View(BASEPATH . 'view/');
            $tpl->dir = 'admin/';
            $tpl->title = Language::$word->META_M_PERMISSIONS;
            $tpl->caption = Language::$word->META_M_PERMISSIONS;
            $tpl->subtitle = Language::$word->PS_INFO;
            
            $tpl->data = Database::Go()->select(User::rTable)->run();
            
            $tpl->template = 'admin/role';
        }
        
        /**
         * roleEdit
         *
         * @param int $id
         * @return void
         */
        public function roleEdit(int $id): void
        {
            $tpl = App::View(BASEPATH . 'view/');
            $tpl->dir = 'admin/';
            $tpl->title = Language::$word->META_PRIVILEGES;
            $tpl->caption = Language::$word->META_M_PRIVILEGE;
            $tpl->subtitle = null;
            $tpl->crumbs = ['admin', 'roles', Language::$word->META_PRIVILEGES];
            
            if (!$row = Database::Go()->select(User::rTable)->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->role = $row;
                $tpl->result = Utility::groupToLoop(App::User()->getPrivileges($id), 'type');
                
                $tpl->subtitle = str_replace('[ROLE]', '<span class="text-weight-500">' . $row->name . '</span>', Language::$word->PS_INFO1);
                $tpl->subtitle .= ($row->code != 'owner') ? '<span class="text-weight-500"><i>' . Language::$word->PS_INFO2 . '</i></span>' : null;
                
                $tpl->template = 'admin/role';
            }
        }
        
        /**
         * transactionIndex
         *
         * @return void
         */
        public function transactionIndex(): void
        {
            $tpl = App::View(BASEPATH . 'view/');
            $tpl->dir = 'admin/';
            $tpl->title = Language::$word->META_TRANS;
            $tpl->caption = Language::$word->TRX_PAY;
            $tpl->subtitle = null;
            
            $enddate = (Validator::get('enddate_submit') && $_GET['enddate_submit'] <> '') ? Validator::sanitize(Database::toDate($_GET['enddate_submit'], false)) : date('Y-m-d');
            $fromdate = Validator::get('fromdate_submit') ? Validator::sanitize(Database::toDate($_GET['fromdate_submit'], false)) : null;
            
            if (Validator::get('fromdate_submit') && $_GET['fromdate_submit'] <> '') {
                $counter = Database::Go()->count(Product::xTable, "WHERE `created` BETWEEN '" . trim($fromdate) . "' AND '" . trim($enddate) . " 23:59:59' AND status = 1")->run();
                $where = "WHERE p.created BETWEEN '" . trim($fromdate) . "' AND '" . trim($enddate) . " 23:59:59' AND p.status = 1";
                
            } else {
                $counter = Database::Go()->count(Product::xTable)->run();
                $where = null;
            }
            
            $pager = Paginator::instance();
            $pager->items_total = $counter;
            $pager->default_ipp = App::Core()->perpage;
            $pager->path = Url::url(Router::$path, '?');
            $pager->paginate();
            
            $sql = "
            SELECT p.*, m.title, CONCAT(u.fname,' ',u.lname) AS name
              FROM `" . Product::xTable . '` AS p
              LEFT JOIN ' . User::mTable . ' AS u ON p.user_id = u.id
              LEFT JOIN ' . Product::mTable . " AS m ON p.product_id = m.id
              $where
              ORDER BY created
              DESC " . $pager->limit;
            
            $row = Database::Go()->rawQuery($sql)->run();
            $tpl->data = $row ?? null;
            $tpl->pager = $pager;
            
            $tpl->template = 'admin/transaction';
        }
        
        /**
         * transactionNew
         *
         * @return void
         */
        public function transactionNew(): void
        {
            $tpl = App::View(BASEPATH . 'view/');
            $tpl->dir = 'admin/';
            $tpl->title = Language::$word->META_TRANS;
            $tpl->caption = Language::$word->TRX_NEW;
            $tpl->subtitle = null;
            
            $tpl->products = Database::Go()->select(Product::mTable, array('id', 'title'))->where('active', 1, '=')->orderBy('title', 'ASC')->run();
            $tpl->users = Database::Go()->select(User::mTable, array('id', "CONCAT(fname,' ',lname) as name"))->where('active', 'y', '=')->run();
            $tpl->gateways = Database::Go()->select(self::gTable, array('name', 'displayname'))->where('active', 1, '=')->run();
            
            $tpl->template = 'admin/transaction';
        }
        
        /**
         * processTransaction
         *
         * @return void
         * @throws \PHPMailer\PHPMailer\Exception
         */
        public function processTransaction(): void
        {
            $validate = Validator::run($_POST);
            $validate
                ->set('pp', Language::$word->GW_NAME)->required()->string()
                ->set('product_id', Language::$word->CF_SEC_P)->required()->integer()
                ->set('user_id', Language::$word->USER)->required()->integer()
                ->set('qty', Language::$word->QUANTITY)->required()->integer()
                ->set('memo', Language::$word->TRX_MEMO)->string(true, true);
            
            $safe = $validate->safe();
            
            if (count(Message::$msgs) === 0) {
                $items = array();
                $core = App::Core();
                
                $product = Database::Go()->select(Product::mTable)->where('id', $safe->product_id, '=')->first()->run();
                $user = Database::Go()->select(User::mTable)->where('id', $safe->user_id, '=')->first()->run();
                $txn_id = 'MAN_' . time();
                $price = ($product->is_sale) ? $product->sprice : $product->price;
                for ($k = 0; $k < $safe->qty; $k++) {
                    $key = Database::Go()->select(Product::cdTable, array('cdkey'))->where('product_id', $safe->product_id, '=')->one()->run();
                    $data = array(
                        'user_id' => $user->id,
                        'product_id' => $product->id,
                        'txn_id' => $txn_id,
                        'amount' => $price,
                        'total' => $price,
                        'cdkey' => ($key) ? : '',
                        'pp' => $safe->pp,
                        'file_date' => time(),
                        'currency' => $core->currency,
                        'memo' => $safe->memo,
                        'status' => 1,
                    );
                    
                    $items[$k]['title'] = $product->title;
                    $items[$k]['qty'] = 1;
                    $items[$k]['price'] = $price;
                    $items[$k]['cdkey'] = $data['cdkey'];
                    
                    Database::Go()->insert(Product::xTable, $data)->run();
                    if ($key) {
                        Database::Go()->delete(Product::cdTable)->where('cdkey', $data['cdkey'], '=')->run();
                    }
                }
                
                // invoice table
                $xdata = array(
                    'invoice_id' => substr(time(), 5),
                    'transaction_id' => $txn_id,
                    'user_id' => $user->id,
                    'items' => json_encode($items),
                    'subtotal' => Validator::sanitize($price * $safe->qty, 'float'),
                    'grand' => Validator::sanitize($price * $safe->qty, 'float'),
                    'currency' => App::Core()->currency,
                );
                Database::Go()->insert(Product::ivTable, $xdata)->run();
                
                Message::msgReply(Database::Go()->affected(), 'success', Language::$word->TRX_ADDED_OK);
                
                if (isset($_POST['notify'])) {
                    $tpl = Database::Go()->select(Content::eTable, array('body', 'subject'))->where('typeid', 'notifyUser', '=')->first()->run();
                    $mailer = Mailer::sendMail();
                    
                    $body = str_replace(array(
                        '[LOGO]',
                        '[CEMAIL]',
                        '[NAME]',
                        '[DATE]',
                        '[COMPANY]',
                        '[SITE_NAME]',
                        '[ITEMNAME]',
                        '[LINK]',
                        '[FB]',
                        '[TW]',
                        '[SITEURL]'
                    ), array(
                        $core->plogo,
                        $core->site_email,
                        $user->fname . ' ' . $user->lname,
                        date('Y'),
                        $core->company,
                        $core->site_name,
                        $product->title,
                        Url::url('/login'),
                        $core->social->facebook,
                        $core->social->twitter,
                        SITEURL
                    ), $tpl->body
                    );
                    
                    $mailer->setFrom($core->site_email, $core->company);
                    $mailer->addAddress($user->email, $user->fname . ' ' . $user->lname);
                    
                    $mailer->isHTML();
                    $mailer->Subject = $tpl->subject;
                    $mailer->Body = $body;
                    $mailer->send();
                }
            } else {
                Message::msgSingleStatus();
            }
        }
        
        /**
         * maintenanceIndex
         *
         * @return void
         */
        public function maintenanceIndex(): void
        {
            $tpl = App::View(BASEPATH . 'view/');
            $tpl->dir = 'admin/';
            $tpl->title = Language::$word->META_MAINTENANCE;
            $tpl->caption = Language::$word->META_M_MAINTENANCE;
            $tpl->subtitle = Language::$word->MT_INFO;
            
            $tpl->banned = Database::Go()->count(User::mTable)->where('active', 'b', '=')->where('type', 'member', '=')->run();
            
            $tpl->template = 'admin/maintenance';
        }
        
        /**
         * makeSiteMap
         *
         * @return string
         */
        public static function makeSiteMap(): string
        {
            
            $html = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n";
            $html .= "<urlset xmlns=\"https://www.sitemaps.org/schemas/sitemap/0.9\" xmlns:xsi=\"https://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"https://www.sitemaps.org/schemas/sitemap/0.9 https://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd\">\r\n";
            $html .= "<url>\r\n";
            $html .= '<loc>' . SITEURL . "/</loc>\r\n";
            $html .= '<lastmod>' . date('Y-m-d') . "</lastmod>\r\n";
            $html .= "</url>\r\n";
            
            //products
            $items = 'SELECT slug FROM `' . Product::mTable . '` WHERE active = ? ORDER BY created DESC;';
            $query = Database::Go()->rawQuery($items, array(1));
            
            foreach ($query->run() as $row) {
                $html .= "<url>\r\n";
                $html .= '<loc>' . Url::url('/product', $row->slug) . "</loc>\r\n";
                $html .= '<lastmod>' . date('Y-m-d') . "</lastmod>\r\n";
                $html .= "<changefreq>weekly</changefreq>\r\n";
                $html .= "</url>\r\n";
            }
            unset($row);
            
            //categories
            $cats = 'SELECT slug FROM `' . Content::cTable . '` WHERE active = ? ORDER BY parent_id;';
            $query = Database::Go()->rawQuery($cats, array(1));
            
            foreach ($query->run() as $row) {
                $html .= "<url>\r\n";
                $html .= '<loc>' . Url::url('/category', $row->slug) . "</loc>\r\n";
                $html .= '<lastmod>' . date('Y-m-d') . "</lastmod>\r\n";
                $html .= "<changefreq>weekly</changefreq>\r\n";
                $html .= "</url>\r\n";
            }
            unset($row);
            
            //pages
            $pages = 'SELECT slug FROM `' . Content::pTable . "` WHERE active = ? AND page_type <> 'home' ORDER BY created DESC;";
            $query = Database::Go()->rawQuery($pages, array(1));
            
            foreach ($query->run() as $row) {
                $html .= "<url>\r\n";
                $html .= '<loc>' . Url::url('/page', $row->slug) . "</loc>\r\n";
                $html .= '<lastmod>' . date('Y-m-d') . "</lastmod>\r\n";
                $html .= "<changefreq>weekly</changefreq>\r\n";
                $html .= "</url>\r\n";
            }
            unset($row);
            
            $html .= '</urlset>';
            
            return $html;
        }
        
        /**
         * writeSiteMap
         *
         * @return void
         */
        public static function writeSiteMap(): void
        {
            $filename = BASEPATH . 'sitemap.xml';
            $file = SITEURL . '/sitemap.xml';
            if (is_writable($filename)) {
                file_put_contents($filename, self::makeSiteMap());
                Message::msgReply($file, 'success', Message::formatSuccessMessage($file, Language::$word->MT_MAP_OK));
            } else {
                Message::msgReply($file, 'success', Message::formatSuccessMessage($file, Language::$word->MT_MAP_ERROR));
            }
        }
        
        /**
         * systemIndex
         *
         * @return void
         */
        public function systemIndex(): void
        {
            $tpl = App::View(BASEPATH . 'view/');
            $tpl->dir = 'admin/';
            $tpl->title = Language::$word->META_M_SYSTEM;
            $tpl->caption = Language::$word->META_M_SYSTEM;
            $tpl->subtitle = str_replace('[VER]', App::Core()->wojov, Language::$word->SYS_INFO);
            
            $_oSTH = Database::Go()->prepare('SHOW TABLES FROM ' . DB_DATABASE);
            $_oSTH->execute();
            $tpl->data = $_oSTH->fetchAll(PDO::FETCH_COLUMN);
            
            $tpl->template = 'admin/system';
        }
        
        /**
         * backupIndex
         *
         * @return void
         */
        public function backupIndex(): void
        {
            $tpl = App::View(BASEPATH . 'view/');
            $tpl->dir = 'admin/';
            $tpl->title = Language::$word->META_M_BACKUP;
            $tpl->caption = Language::$word->META_M_BACKUP;
            $tpl->subtitle = Language::$word->DBM_INFO;
            
            $tpl->dbdir = UPLOADS . '/backups/';
            $tpl->data = File::findFiles($tpl->dbdir, array('fileTypes' => array('sql'), 'returnType' => 'fileOnly'));
            
            $tpl->template = 'admin/backup';
        }
        
        /**
         * gatewayIndex
         *
         * @return void
         */
        public function gatewayIndex(): void
        {
            $tpl = App::View(BASEPATH . 'view/');
            $tpl->dir = 'admin/';
            $tpl->title = Language::$word->META_GATEWAYS;
            $tpl->caption = Language::$word->META_M_GATEWAY;
            $tpl->subtitle = Language::$word->GW_INFO;
            
            $tpl->data = Database::Go()->select(Core::gTable)->run();
            
            $tpl->template = 'admin/gateway';
        }
        
        /**
         * gatewayEdit
         *
         * @param int $id
         * @return void
         */
        public function gatewayEdit(int $id): void
        {
            $tpl = App::View(BASEPATH . 'view/');
            $tpl->dir = 'admin/';
            $tpl->title = Language::$word->GW_EDIT;
            $tpl->caption = Language::$word->META_M_GATEWAY;
            $tpl->crumbs = ['admin', 'gateways', 'edit'];
            
            if (!$row = Database::Go()->select(Core::gTable)->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/gateway';
            }
        }
        
        /**
         * processGateway
         *
         * @return void
         */
        public function processGateway(): void
        {
            $validate = Validator::run($_POST);
            $validate
                ->set('displayname', Language::$word->GW_NAME)->required()->string()->min_len(3)->max_len(60)
                ->set('extra', Language::$word->GW_NAME)->required()->string()
                ->set('extra2', Language::$word->GW_NAME)->string()
                ->set('extra3', Language::$word->GW_NAME)->string()
                ->set('live', Language::$word->GW_LIVE)->numeric()
                ->set('active', Language::$word->ACTIVE)->numeric();
            
            $safe = $validate->safe();
            
            if (count(Message::$msgs) === 0) {
                $data = array(
                    'displayname' => $safe->displayname,
                    'extra' => $safe->extra,
                    'extra2' => $safe->extra2,
                    'extra3' => $safe->extra3,
                    'live' => $safe->live,
                    'active' => $safe->active,
                );
                
                Database::Go()->update(Core::gTable, $data)->where('id', Filter::$id, '=')->run();
                Message::msgReply(Database::Go()->affected(), 'success', Message::formatSuccessMessage($data['displayname'], Language::$word->GW_UPDATE_OK));
            } else {
                Message::msgSingleStatus();
            }
        }
        
        /**
         * renameFile
         *
         * @return void
         */
        public function renameFile(): void
        {
            $validate = Validator::run($_POST);
            $validate->set('alias', Language::$word->FM_ALIAS)->required()->string()->min_len(3)->max_len(60);
            
            $safe = $validate->safe();
            
            if (count(Message::$msgs) === 0) {
                $data = array(
                    'alias' => $safe->alias
                );
                
                Database::Go()->update(Product::fTable, $data)->where('id', Filter::$id, '=')->run();
                $row = Database::Go()->select(Product::fTable)->where('id', Filter::$id, '=')->first()->run();
                
                $tpl = App::View(BASEPATH . 'view/admin/snippets/');
                $tpl->template = 'loadFile';
                $tpl->row = $row;
                
                if (Database::Go()->affected()) {
                    $json['type'] = 'success';
                    $json['title'] = Language::$word->SUCCESS;
                    $json['message'] = Message::formatSuccessMessage($data['alias'], Language::$word->FM_REN_OK);
                    $json['html'] = $tpl->render();
                } else {
                    $json['type'] = 'alert';
                    $json['title'] = Language::$word->ALERT;
                    $json['message'] = Language::$word->NOPROCCESS;
                }
                print json_encode($json);
            } else {
                Message::msgSingleStatus();
            }
        }
        
        /**
         * trashIndex
         *
         * @return void
         */
        public function trashIndex(): void
        {
            $tpl = App::View(BASEPATH . 'view/');
            $tpl->dir = 'admin/';
            $tpl->title = Language::$word->META_M_TRASH;
            $tpl->caption = Language::$word->META_M_TRASH;
            $tpl->subtitle = Language::$word->TRS_INFO;
            $data = Database::Go()->select(Core::txTable)->run();
            $tpl->data = Utility::groupToLoop($data, 'type');
            
            $tpl->template = 'admin/trash';
        }
    }