<?php
    /**
     * Blog Class
     *
     * @package Wojo Framework
     * @author wojoscripts.com
     * @copyright 2023
     * @version 5.50: Blog.php, v1.00 11/16/2023 2:25 PM Gewa Exp $
     *
     */
    if (!defined('_WOJO')) {
        die('Direct access to this location is not allowed.');
    }
    
    class Blog
    {
        const mTable = 'blog';
        const cTable = 'blog_categories';
        
        const BLOGDATA = '/blog/data/';
        const BLOGFILES = '/blog/datafiles/';
        const FILES = 'zip,pdf,rar,mp3';
        const MAXIMG = 5242880;
        const MAXFILE = 52428800;
        
        public int $thumb_w;
        public int $thumb_h;
        public int $fperpage;
        
        /**
         *
         */
        public function __construct()
        {
            $this->config();
        }
        
        /**
         * adminIndex
         *
         * @return void
         */
        public function adminIndex(): void
        {
            $tpl = App::View(BASEPATH . 'view/');
            $tpl->dir = 'admin/';
            $tpl->title = Language::$word->_MOD_AM_TITLE;
            $tpl->caption = Language::$word->_MOD_AM_TITLE;
            $tpl->subtitle = null;
            
            $find = isset($_POST['find']) ? Validator::sanitize($_POST['find'], 'default', 30) : null;
            
            if (isset($_GET['letter']) and $find) {
                $letter = Validator::sanitize($_GET['letter'], 'string', 2);
                $counter = Database::Go()->count(self::mTable, "WHERE `title` LIKE '%" . trim($find) . "%' AND `title` REGEXP '^" . $letter . "'")->run();
                $where = "WHERE `title` LIKE '%" . trim($find) . "%' AND d.title REGEXP '^" . $letter . "'";
                
            } elseif (isset($_POST['find'])) {
                $counter = Database::Go()->count(self::mTable, "WHERE `title` LIKE '%" . trim($find) . "%'")->run();
                $where = "WHERE d.title LIKE '%" . trim($find) . "%'";
            } elseif (isset($_GET['letter'])) {
                $letter = Validator::sanitize($_GET['letter'], 'string', 2);
                $where = "WHERE d.title REGEXP '^" . $letter . "'";
                $counter = Database::Go()->count(self::mTable, "WHERE `title` REGEXP '^" . $letter . "' LIMIT 1")->run();
            } else {
                $counter = Database::Go()->count(self::mTable)->run();
                $where = null;
            }
            
            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', 4);
                if (in_array($sort, array(
                    'title',
                    'hits',
                    'active',
                    'category_id'
                ))) {
                    $ord = ($order == 'DESC') ? ' DESC' : ' ASC';
                    $sorting = $sort . $ord;
                } else {
                    $sorting = ' created DESC';
                }
            } else {
                $sorting = ' created DESC';
            }
            
            $pager = Paginator::instance();
            $pager->items_total = $counter;
            $pager->default_ipp = App::Core()->perpage;
            $pager->path = Url::url(Router::$path, '?');
            $pager->paginate();
            
            $sql = '
            SELECT d.id, d.category_id, d.hits, d.active, d.created, d.title, d.thumb, c.name
              FROM `' . self::mTable . '` as d
              LEFT JOIN `' . self::cTable . "` as c ON c.id = d.category_id
              $where
              GROUP BY d.id
              ORDER BY $sorting " . $pager->limit;
            
            $tpl->data = Database::Go()->rawQuery($sql)->run();
            $tpl->pager = $pager;
            
            $tpl->template = 'admin/blog/view/index';
        }
        
        /**
         * new
         *
         * @return void
         */
        public function new(): void
        {
            $tpl = App::View(BASEPATH . 'view/');
            $tpl->dir = 'admin/';
            $tpl->title = Language::$word->_MOD_AM_NEW;
            $tpl->caption = Language::$word->_MOD_AM_NEW;
            $tpl->crumbs = ['admin', 'blog', Language::$word->META_NEW];
            
            $tpl->tree = $this->categoryTree();
            $tpl->droplist = self::getCatCheckList($tpl->tree, 0, 0, '&#166;&nbsp;&nbsp;&nbsp;&nbsp;');
            Session::set('blogtoken', Utility::randNumbers(4));
            
            $tpl->template = 'admin/blog/view/index';
        }
        
        /**
         * edit
         *
         * @param int $id
         * @return void
         */
        public function edit(int $id): void
        {
            $tpl = App::View(BASEPATH . 'view/');
            $tpl->dir = 'admin/';
            $tpl->title = Language::$word->_MOD_AM_TITLE2;
            $tpl->caption = Language::$word->_MOD_AM_TITLE2;
            $tpl->crumbs = ['admin', 'blog', '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 = $this->categoryTree();
                $tpl->droplist = self::getCatCheckList($tpl->tree, 0, 0, '&#166;&nbsp;&nbsp;&nbsp;&nbsp;', $row->category_id);
                
                $tpl->template = 'admin/blog/view/index';
            }
        }
        
        /**
         * processItem
         *
         * @return void
         */
        public function processItem(): void
        {
            $validate = Validator::run($_POST);
            $validate
                ->set('title', Language::$word->NAME)->required()->string()->min_len(3)->max_len(100)
                ->set('slug', Language::$word->_MOD_AM_SLUG)->string()->min_len(3)->max_len(100)
                ->set('category_id', Language::$word->CATEGORIES)->required()->numeric()
                ->set('show_sharing', Language::$word->_MOD_AM_SHARE)->required()->numeric()
                ->set('show_created', Language::$word->_MOD_AM_CREATED)->required()->numeric()
                ->set('active', Language::$word->PUBLISHED)->required()->numeric();
            
            $validate
                ->set('body', Language::$word->PRD_BODY)->text('advanced')
                ->set('keywords', Language::$word->METAKEYS)->string(true, true)
                ->set('description', Language::$word->METADESC)->string(true, true);
            
            (Filter::$id) ? $this->_updateItem($validate) : $this->_addItem($validate);
        }
        
        /**
         * _addItem
         *
         * @param Validator $validate
         * @return void
         */
        private function _addItem(Validator $validate): void
        {
            $thumb = File::upload('thumb', self::MAXIMG, 'png,jpg,jpeg');
            $safe = $validate->safe();
            
            if (count(Message::$msgs) === 0) {
                $data = array(
                    'title' => $safe->title,
                    'slug' => empty($safe->slug) ? Url::doSeo($safe->title) : Url::doSeo($safe->slug),
                    'keywords' => $safe->keywords,
                    'description' => $safe->description,
                    'body' => Url::in_url($safe->body),
                    'category_id' => $safe->category_id,
                    'show_sharing' => $safe->show_sharing,
                    'show_created' => $safe->show_created,
                    'user_id' => App::Auth()->uid,
                    'active' => $safe->active,
                );
                
                $temp_id = Session::get('blogtoken');
                File::makeDirectory(FRONTBASE . self::BLOGDATA . $temp_id . '/thumbs');
                
                //process thumb
                if (array_key_exists('thumb', $_FILES)) {
                    $item_path = FRONTBASE . self::BLOGDATA . $temp_id . '/';
                    $tresult = File::process($thumb, $item_path, false);
                    try {
                        $img = new Image($item_path . $tresult['fname']);
                        $img->bestFit($this->thumb_w, $this->thumb_h)->save($item_path . 'thumbs/' . $tresult['fname']);
                    } catch (Exception $e) {
                        Debug::addMessage('errors', '<i>Error</i>', $e->getMessage(), 'session');
                    }
                    $data['thumb'] = $tresult['fname'];
                }
                
                $last_id = Database::Go()->insert(self::mTable, $data)->run();
                
                //rename temp folder
                File::copyDirectory(FRONTBASE . self::BLOGDATA . $temp_id . '/', FRONTBASE . self::BLOGDATA . $last_id . '/');
                File::deleteRecursive(FRONTBASE . self::BLOGDATA . $temp_id, true);
                
                if ($last_id) {
                    $message = Message::formatSuccessMessage($data['title'], Language::$word->_MOD_AM_ITM_ADDED_OK);
                    $json['type'] = 'success';
                    $json['title'] = Language::$word->SUCCESS;
                    $json['message'] = $message;
                    $json['redirect'] = Url::url('/admin', 'blog/');
                    Logger::writeLog($message);
                } else {
                    $json['type'] = 'alert';
                    $json['title'] = Language::$word->ALERT;
                    $json['message'] = Language::$word->NOPROCCESS;
                }
                print json_encode($json);
            } else {
                Message::msgSingleStatus();
            }
        }
        
        /**
         * _updateItem
         *
         * @param Validator $validate
         * @return void
         */
        private function _updateItem(Validator $validate): void
        {
            $thumb = File::upload('thumb', self::MAXIMG, 'png,jpg,jpeg');
            $safe = $validate->safe();
            
            if (count(Message::$msgs) === 0) {
                $data = array(
                    'title' => $safe->title,
                    'slug' => empty($safe->slug) ? Url::doSeo($safe->title) : Url::doSeo($safe->slug),
                    'keywords' => $safe->keywords,
                    'description' => $safe->description,
                    'body' => Url::in_url($safe->body),
                    'category_id' => $safe->category_id,
                    'show_sharing' => $safe->show_sharing,
                    'show_created' => $safe->show_created,
                    'user_id' => App::Auth()->uid,
                    'active' => $safe->active,
                );
                
                //process thumb
                if (array_key_exists('thumb', $_FILES)) {
                    $row = Database::Go()->select(self::mTable, array('thumb'))->where('id', Filter::$id, '=')->first()->run();
                    
                    $item_path = FRONTBASE . self::BLOGDATA . Filter::$id . '/';
                    $tresult = File::process($thumb, $item_path, false);
                    File::deleteFile($item_path . $row->thumb);
                    File::deleteFile($item_path . 'thumbs/' . $row->thumb);
                    try {
                        $img = new Image($item_path . $tresult['fname']);
                        $img->bestFit($this->thumb_w, $this->thumb_h)->save($item_path . 'thumbs/' . $tresult['fname']);
                    } catch (Exception $e) {
                        Debug::addMessage('errors', '<i>Error</i>', $e->getMessage(), 'session');
                    }
                    $data['thumb'] = $tresult['fname'];
                }
                
                Database::Go()->update(self::mTable, $data)->where('id', Filter::$id, '=')->run();
                $message = Message::formatSuccessMessage($data['title'], Language::$word->_MOD_AM_ITM_UPDATE_OK);
                Message::msgReply(Database::Go()->affected(), 'success', $message);
                
                Logger::writeLog($message);
            } else {
                Message::msgSingleStatus();
            }
        }
        
        /**
         * categoryNew
         *
         * @return void
         */
        public function categoryNew(): void
        {
            $tpl = App::View(BASEPATH . 'view/');
            $tpl->dir = 'admin/';
            $tpl->title = Language::$word->_MOD_AM_CATS;
            $tpl->caption = Language::$word->_MOD_AM_NEWCAT;
            
            $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/blog/view/index';
        }
        
        /**
         * categoryEdit
         *
         * @param int $id
         * @return void
         */
        public function categoryEdit(int $id): void
        {
            $tpl = App::View(BASEPATH . 'view/');
            $tpl->dir = 'admin/';
            $tpl->title = Language::$word->_MOD_AM_UPDATECAT;
            $tpl->caption = Language::$word->_MOD_AM_UPDATECAT;
            $tpl->crumbs = ['admin', 'blog', 'category'];
            
            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/blog/view/index';
            }
        }
        
        /**
         * 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->_MOD_AM_CSLUG)->string()
                ->set('keywords', Language::$word->METAKEYS)->string(true, true)
                ->set('description', Language::$word->METADESC)->string(true, true)
                ->set('parent_id', Language::$word->_MOD_AM_PARENT)->required()->numeric()
                ->set('perpage', Language::$word->_MOD_AM_IPC)->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,
                    'perpage' => $safe->perpage,
                    '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->_MOD_AM_CAT_UPDATE_OK);
                    Message::msgReply(Database::Go()->affected(), 'success', $message);
                } else {
                    if ($last_id) {
                        $message = Message::formatSuccessMessage($data['name'], Language::$word->_MOD_AM_CAT_ADDED_OK);
                        $json['type'] = 'success';
                        $json['title'] = Language::$word->SUCCESS;
                        $json['message'] = $message;
                        $json['redirect'] = Url::url('/admin/blog/categories');
                    } else {
                        $json['type'] = 'alert';
                        $json['title'] = Language::$word->ALERT;
                        $json['message'] = Language::$word->NOPROCCESS;
                    }
                    print json_encode($json);
                }
            } else {
                Message::msgSingleStatus();
            }
        }
        
        /**
         * settings
         *
         * @return void
         */
        public function settings(): void
        {
            
            $tpl = App::View(BASEPATH . 'view/');
            $tpl->dir = 'admin/';
            $tpl->title = Language::$word->_MOD_AM_CONF;
            $tpl->caption = Language::$word->_MOD_AM_CONF;
            $tpl->subtitle = null;
            
            $tpl->data = $this->config();
            
            $tpl->template = 'admin/blog/view/index';
        }
        
        /**
         * processConfig
         *
         * @return void
         */
        public function processConfig(): void
        {
            $validate = Validator::run($_POST);
            
            $validate
                ->set('fperpage', Language::$word->_MOD_AM_LATEST)->required()->numeric()
                ->set('thumb_w', Language::$word->_MOD_AM_THUMB_W)->required()->numeric()->min_len(3)->max_len(3)
                ->set('thumb_h', Language::$word->_MOD_AM_THUMB_H)->required()->numeric()->min_len(3)->max_len(3);
            
            $safe = $validate->safe();
            
            if (count(Message::$msgs) === 0) {
                $data = array(
                    'blog' => array(
                        'fperpage' => $safe->fperpage,
                        'thumb_w' => $safe->thumb_w,
                        'thumb_h' => $safe->thumb_h,
                    )
                );
                
                Message::msgReply(File::writeToFile(ADMINBASE . '/blog/config.json', json_encode($data, JSON_PRETTY_PRINT)), 'success', Language::$word->_MOD_AM_CUPDATED);
            } else {
                Message::msgSingleStatus();
            }
        }
        
        /**
         * frontIndex
         *
         * @return void
         */
        public function frontIndex(): void
        {
            
            $core = App::Core();
            $tpl = App::View(BASEPATH . 'view/');
            $tpl->dir = 'front/themes/' . $core->theme . '/';
            $tpl->title = Language::$word->_MOD_AM_LATEST_TITLE . ' - ' . $core->company;
            $tpl->crumbs = [array(0 => Language::$word->HOME, 1 => ''), strtolower(Language::$word->_MOD_AM_BLOG)];
            $tpl->keywords = null;
            $tpl->description = null;
            $tpl->core = $core;
            
            $pager = Paginator::instance();
            $pager->items_total = Database::Go()->count(self::mTable)->where('active', 1, '=')->run();
            $pager->default_ipp = $this->fperpage;
            $pager->path = Url::url(Router::$path, '?');
            $pager->paginate();
            
            $sql = '
            SELECT a.id, a.created, a.title, a.slug, a.body, a.thumb, c.slug as cslug, c.name as ctitle
              FROM `' . self::mTable . '` as a
              LEFT JOIN `' . self::cTable . '` as c ON c.id = a.category_id
              WHERE a.active = ?
              ORDER BY a.created
              DESC ' . $pager->limit;
            
            $tpl->rows = Database::Go()->rawQuery($sql, array(1))->run();
            $tpl->pager = $pager;
            
            $tpl->template = 'front/themes/' . $core->theme . '/blog';
        }
        
        /**
         * frontCategory
         *
         * @param string $slug
         * @return void
         */
        public function frontCategory(string $slug): void
        {
            
            $core = App::Core();
            $tpl = App::View(BASEPATH . 'view/');
            $tpl->dir = 'front/themes/' . $core->theme . '/';
            $tpl->title = $core->company;
            $tpl->core = $core;
            $tpl->keywords = null;
            $tpl->description = 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 {
                $counter = Database::Go()->count(self::mTable)->where('category_id', $row->id, '=')->where('active', 1, '=')->run();
                
                $pager = Paginator::instance();
                $pager->items_total = $counter;
                $pager->default_ipp = $row->perpage;
                $pager->path = Url::url(Router::$path, '?');
                $pager->paginate();
                
                $sql = '
                SELECT a.id, MAX(a.created) as created, a.title, a.slug, a.body, a.thumb, c.slug as cslug, c.name as ctitle
                  FROM `' . self::mTable . '` as a
                  LEFT JOIN `' . self::cTable . '` as c ON c.id = a.category_id
                  WHERE a.category_id = ?
                  AND a.active = ?
                  AND c.active = ?
                  GROUP BY a.id
                  ORDER BY created
                  DESC ' . $pager->limit;
                
                $tpl->row = $row;
                $tpl->data = Database::Go()->rawQuery($sql, array($row->id, 1, 1))->run();
                $tpl->pager = $pager;
                $tpl->conf = $this->config();
                
                $tpl->title = $row->name . ' - ' . Language::$word->_MOD_AM_BLOG . ' - ' . $core->company;
                $tpl->keywords = $row->keywords;
                $tpl->description = $row->description;
                $tpl->crumbs = [array(0 => Language::$word->HOME, 1 => ''), 'blog', $row->name];
                
                $tpl->template = 'front/themes/' . $core->theme . '/blog';
            }
        }
        
        /**
         * render
         *
         * @param string $slug
         * @return void
         */
        public function render(string $slug): void
        {
            $core = App::Core();
            $tpl = App::View(BASEPATH . 'view/');
            $tpl->dir = 'front/themes/' . $core->theme . '/';
            $tpl->title = $core->company;
            $tpl->keywords = null;
            $tpl->description = null;
            $tpl->core = $core;
            
            $sql = "
            SELECT a.*, a.slug, c.slug as catslug, c.name as catname, CONCAT(u.fname,' ',u.lname) as user, u.username
              FROM `" . self::mTable . '` AS a
              LEFT JOIN `' . User::mTable . '` AS u ON u.id = a.user_id
              LEFT JOIN `' . self::cTable . '` AS c ON c.id = a.category_id
              WHERE a.slug = ?
              AND a.active = ?
              GROUP BY a.id';
            
            if (!$row = Database::Go()->rawQuery($sql, array($slug, 1))->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 {
                $tpl->title = $row->title . ' - ' . Language::$word->_MOD_AM_BLOG . ' - ' . $core->company;
                $tpl->keywords = $row->keywords;
                $tpl->description = $row->description;
                $tpl->crumbs = [array(0 => Language::$word->HOME, 1 => ''), 'blog', $row->title];
                
                $tpl->row = $row;
                $this->doHits($row->id);
                $tpl->conf = $this->config();
                
                $tpl->template = 'front/themes/' . $core->theme . '/blog';
            }
        }
        
        /**
         * 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 = 'blogcats', string $class = 'vertical-menu'): string
        {
            $html = '';
            if (is_array($array) && count($array) > 0) {
                $submenu = false;
                $attr = (!$parent_id) ? ' class="' . $class . '" id="' . $menuid . '"' : ' class="menu-submenu"';
                
                foreach ($array as $key => $row) {
                    if ($row['parent_id'] == $parent_id) {
                        if ($submenu === false) {
                            $submenu = true;
                            
                            $html .= '<ul' . $attr . ">\n";
                        }
                        
                        $url = Url::url('/blog/category', $row['slug'] . Url::buildQuery());
                        
                        $active = (isset(Content::$segments[2]) and Content::$segments[2] == $row['slug']) ? ' active' : 'normal';
                        $link = '<a href="' . $url . '" class="' . $active . '" title="' . $row['name'] . '">' . $row['name'] . '</a>';
                        
                        $html .= '<li>';
                        $html .= $link;
                        $html .= $this->renderCategories($array, $key);
                        $html .= "</li>\n";
                    }
                }
                unset($row);
                
                if ($submenu === true) {
                    $html .= "</ul>\n";
                }
            }
            return $html;
        }
        
        /**
         * catList
         *
         * @return array
         */
        public function catList(): array
        {
            $sql = 'SELECT c.id, c.parent_id, c.name, c.slug FROM `' . self::cTable . '` as c GROUP BY c.id ORDER BY parent_id, sorting';
            
            $menu = array();
            $result = array();
            
            if ($data = Database::Go()->rawQuery($sql)->run()) {
                foreach ($data as $row) {
                    $menu['id'] = $row->id;
                    $menu['name'] = $row->name;
                    $menu['parent_id'] = $row->parent_id;
                    $menu['slug'] = $row->slug;
                    
                    $result[$row->id] = $menu;
                }
            }
            return $result;
        }
        
        /**
         * config
         *
         * @return $this|Blog|int
         */
        private function config(): int|Blog|static
        {
            $row = json_decode(File::loadFile(ADMINBASE . '/blog/config.json'));
            $this->thumb_w = $row->blog->thumb_w;
            $this->thumb_h = $row->blog->thumb_h;
            $this->fperpage = $row->blog->fperpage;
            
            return ($row) ? $this : 0;
        }
        
        /**
         * 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['parent_id'] = $row->parent_id;
                $result[$row->id] = $cats;
            }
            return $result;
        }
        
        /**
         * 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;
        }
        
        /**
         * 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 radio fitted inline\"> <input id=\"ckb_" . $row['id'] . "\" type=\"radio\" name=\"category_id\" 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;
        }
        
        /**
         * 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/blog/category', $row['id']) . '">' . $row['name'] . '</a></div>'
                        . '<div class="actions"><a class="data" data-set=\'{"option":[{"delete": "deleteCategory","title": "' . Validator::sanitize($row['name'], 'chars') . '","id":' . $row['id'] . '}],"action":"delete","parent":"li", "redirect":"' . Url::url('/admin/blog/categories') . '"}\'>' . $icon . '</a>
                         </div></div>';
                    $html .= self::getSortCategoryList($array, $key);
                    $html .= "</li>\n";
                }
            }
            unset($row);
            
            if ($submenu === true) {
                $html .= "</ul>\n";
            }
            
            return $html;
        }
        
        /**
         * doHits
         *
         * @param int $id
         * @return void
         */
        public function doHits(int $id): void
        {
            Database::Go()->rawQuery('
			  UPDATE `' . self::mTable . '`
			  SET `hits` = `hits` + 1
			  WHERE id = ' . $id . ';
		  ')->run();
        }
        
        /**
         * hasThumb
         *
         * @param string|null $thumb
         * @param int $id
         * @return string
         */
        public static function hasThumb(null|string $thumb, int $id): string
        {
            return ($thumb) ? FRONTVIEW . self::BLOGDATA . $id . '/thumbs/' . $thumb : UPLOADURL . '/blank.jpg';
        }
        
        /**
         * hasImage
         *
         * @param string|null $image
         * @param int $id
         * @return string
         */
        public static function hasImage(null|string $image, int $id): string
        {
            return ($image) ? FRONTVIEW . self::BLOGDATA . $id . '/thumbs/' . $image : UPLOADURL . '/blank.jpg';
        }
    }