classes/yf_graphics.class.php

Summary

Maintainability
F
5 days
Test Coverage
<?php

/**
 * Core content-related methods stored here.
 *
 * @author        YFix Team <yfix.dev@gmail.com>
 * @version        1.0
 */
class yf_graphics
{
    /** @var bool Add pages names to the title */
    public $ADD_TITLE_PAGES = true;
    /** @var bool Show auto-parsed (and tried to translate) task name */
    public $SHOW_AUTO_TASK_NAME = false;
    /** @var string Sub-modules dir */
    public $SUB_MODULES_PATH = 'classes/graphics/';
    /** @var string Path to icons */
    public $ICONS_PATH = 'uploads/icons/';
    /** @var string Default HTML Title tag contents */
    public $META_TITLE = '';
    /** @var string Default HTML Meta tag 'keywords' */
    public $META_KEYWORDS = '';
    /** @var string Default HTML Meta tag 'description' */
    public $META_DESCRIPTION = '';
    /** @var bool Enable quick menu */
    public $QUICK_MENU_ENABLED = true;
    /** @var bool Menu hide links to disabled modules */
    public $MENU_HIDE_INACTIVE_MODULES = false;
    /** @var bool */
    public $NOT_FOUND_RAISE_WARNING = true;
    /** @var bool */
    public $HEADER_POWERED_BY = false;
    /** @var bool */
    public $JS_CONSOLE_ALLOW = true;
    /** @var string Required for the compatibility with old main class */
    public $MEDIA_PATH = '';

    /**
     * Catch missing method call.
     * @param mixed $name
     * @param mixed $args
     */
    public function __call($name, $args)
    {
        return main()->extend_call($this, $name, $args);
    }

    /**
     * Framework constructor.
     */
    public function _init()
    {
        // Default user group
        if (empty($_SESSION['user_group'])) {
            $_SESSION['user_group'] = 1;
        }
        // Try to assign class properties from global settings
        $add_title_pages = conf('add_title_pages');
        if (isset($add_title_pages)) {
            $this->ADD_TITLE_PAGES = $add_title_pages;
        }
        // Force hide inactive menu items inside admin section
        if (MAIN_TYPE_ADMIN) {
            $this->MENU_HIDE_INACTIVE_MODULES = true;
        }
        $this->MEDIA_PATH = WEB_PATH;
        if (defined('MEDIA_PATH')) {
            $this->MEDIA_PATH = MEDIA_PATH;
        }
    }

    /**
     * Show site title.
     */
    public function show_site_title()
    {
        if (defined('SITE_ADVERT_NAME')) {
            $title = SITE_ADVERT_NAME;
        }
        if (conf('SITE_ADVERT_NAME')) {
            $title = conf('SITE_ADVERT_NAME');
        }
        if (defined('SITE_TITLE')) {
            $title = SITE_TITLE;
        }
        if ( ! empty($this->META_TITLE)) {
            $title = $this->META_TITLE;
        }
        // For compatibility with old versions
        $website_name = conf('website_name');
        if (strlen($website_name)) {
            $title = $website_name;
        }
        // Add pages names to the title
        if ($this->ADD_TITLE_PAGES) {
            if (strlen($_GET['object']) && $_GET['object'] != 'static_pages') {
                $title .= ' :: ' . _ucfirst(t($_GET['object']));
                $title = _ucfirst(t($_GET['object'])) . ' : ' . $title;
            }
        }
        // Override by hook method
        // TODO: maybe need to check permissions at first
        $obj = module_safe($_GET['object']);
        if (is_object($obj)) {
            $hook_names = ['_hook_title', '_site_title'];
            foreach ($hook_names as $method_name) {
                if (method_exists($obj, $method_name)) {
                    $title = $obj->$method_name($title);
                    break;
                }
            }
        }
        // Force by global var
        $conf_title = conf('site_title');
        if ($conf_title) {
            $title = $conf_title;
        }
        $title = preg_replace('~\s+~ims', ' ', $title);
        return _prepare_html($title);
    }

    /**
     * Show metatags.
     * @param mixed $meta
     */
    public function show_metatags($meta = [])
    {
        if (empty($meta)) {
            $meta = $this->META_DEFAULT;
        }
        if ( ! is_array($meta)) {
            $meta = [];
        }
        $meta['charset'] = $meta['charset'] ?: (conf('charset') ?: 'utf-8');
        $meta['keywords'] = $meta['keywords'] ?: (conf('meta_keywords') ?: $this->META_KEYWORDS);
        $meta['description'] = $meta['description'] ?: (conf('meta_description') ?: $this->META_DESCRIPTION);
        // Override by hook method
        // TODO: maybe need to check permissions at first
        $obj = module_safe($_GET['object']);
        if (is_object($obj)) {
            $hook_names = ['_hook_meta_tags', '_hook_meta'];
            foreach ($hook_names as $method_name) {
                if (method_exists($obj, $method_name)) {
                    $meta = $obj->$method_name($meta);
                    break;
                }
            }
        }
        foreach ((array) $this->META_ADD as $k => $v) {
            if ( ! is_string($v) && is_callable($v)) {
                $meta = $v($meta);
            } elseif (isset($meta[$k])) {
                continue;
            } else {
                $meta[$k] = $v;
            }
        }
        // Quick fixes for common meta "og:" and "fb:"
        foreach ((array) $meta as $name => $value) {
            if (substr($name, 0, 3) === 'og_') {
                $meta['og:' . substr($name, 3)] = $value;
                unset($meta[$name]);
            } elseif (substr($name, 0, 3) === 'fb_') {
                $meta['og:' . substr($name, 3)] = $value;
                unset($meta[$name]);
            }
        }
        if (isset($meta['og:title']) && ! isset($meta['og:type'])) {
            $meta['og:type'] = 'website';
        }
        $robots_no_index = (main()->is_ajax() || MAIN_TYPE_ADMIN || conf('ROBOTS_NO_INDEX') || DEBUG_MODE || (defined('DEVELOP') && DEVELOP) || (defined('TEST_MODE') && TEST_MODE));
        if ($robots_no_index) {
            $meta['robots'] = 'noindex,nofollow,noarchive,nosnippet';
        }
        $out = [];
        foreach ((array) $meta as $name => $values) {
            $name = trim($name);
            if ( ! strlen($name) || ! $values) {
                continue;
            }
            $_name = _prepare_html($name);
            if ( ! is_array($values)) {
                $values = [$values];
            }
            foreach ((array) $values as $value) {
                $value = trim($value);
                if ( ! strlen($name) || ! strlen($value)) {
                    continue;
                }
                $value = str_replace(["\r\n\r\n\r\n", "\r\n\r\n", "\r\n", "\r", "\n"], ' ', $value);
                $value = _prepare_html($value);
                if ($name === 'canonical') {
                    $out[$name] = '<link rel="canonical" href="' . $value . '" />';
                } elseif ($name === 'charset') {
                    $out[$name] = '<meta http-equiv="Content-Type" content="text/html; charset=' . $value . '" />';
                } elseif (false !== strpos($name, ':')) {
                    $out[$name] = '<meta property="' . $_name . '" content="' . $value . '" />';
                } else {
                    $out[$name] = '<meta name="' . $_name . '" content="' . $value . '" />';
                }
            }
        }
        if (DEBUG_MODE) {
            debug('_DEBUG_META', $meta);
            debug('_DEBUG_META_OUT', $out);
        }
        return implode(PHP_EOL, $out);
    }

    /**
     * Show menu (alias for the '_show_menu').
     * @param mixed $params
     */
    public function show_menu($params)
    {
        return $this->_show_menu($params);
    }

    /**
     * Display main 'center' block contents.
     */
    public function show_center()
    {
        return _class('core_blocks')->show_center();
    }

    /**
     * Alias for the '_show_block'.
     * @param mixed $params
     */
    public function show_block($params = [])
    {
        return $this->_show_block($params);
    }

    /**
     * Show custom block contents.
     * @param mixed $input
     */
    public function _show_block($input = [])
    {
        return _class('core_blocks')->_show_block($input);
    }

    /**
     * Action to on denied block.
     * @param mixed $block_name
     */
    public function _action_on_block_denied($block_name = '')
    {
        return _class('core_blocks')->_action_on_block_denied($block_name);
    }

    /**
     * Try to find id of the center block.
     */
    public function _get_center_block_id()
    {
        return _class('core_blocks')->_get_center_block_id();
    }

    /**
     * Load array of blocks rules.
     */
    public function _load_blocks_rules()
    {
        return _class('core_blocks')->_load_blocks_rules();
    }

    /**
     * Check rights for blocks.
     * @param mixed $block_id
     * @param mixed $OBJECT
     * @param mixed $ACTION
     */
    public function _check_block_rights($block_id = 0, $OBJECT = '', $ACTION = '')
    {
        return _class('core_blocks')->_check_block_rights($block_id, $OBJECT, $ACTION);
    }

    /**
     * Try to run center block module/method if allowed.
     */
    public function prefetch_center()
    {
        return _class('core_blocks')->prefetch_center();
    }

    /**
     * Main $_GET tasks handler.
     * @param mixed $allowed_check
     */
    public function tasks($allowed_check = false)
    {
        return _class('core_blocks')->tasks($allowed_check);
    }

    /**
     * Method that allows to change standard tasks mapping (if needed).
     */
    public function _route_request()
    {
        return _class('router')->_route_request();
    }

    /**
     * Welcome message method.
     */
    public function show_welcome()
    {
        // For authorized admins only
        if (MAIN_TYPE_ADMIN) {
            $login_time = $_SESSION['admin_login_time'];
            $admin_id = (int) main()->ADMIN_ID;
            $admin_group = (int) main()->ADMIN_GROUP;
            if ($admin_id && $admin_group) {
                $admin_info = db()->query_fetch('SELECT * FROM ' . db('admin') . ' WHERE id=' . $admin_id);
                $admin_groups = main()->get_data('admin_groups');

                $body .= tpl()->parse('system/admin_welcome', [
                    'id' => (int) $admin_id,
                    'name' => _prepare_html($admin_info['first_name'] . ' ' . $admin_info['last_name']),
                    'group' => _prepare_html(t($admin_groups[$admin_group])),
                    'time' => _format_date($login_time),
                    'edit_link' => './?object=admin_account',
                ]);
                if ($_SESSION['admin_prev_info']) {
                    $body .= '<li><a href="./?task=login&id=prev_info"><i class="icon icon-arrow-up fa fa-arrow-up"></i> ' . t('Login back') . '</a></li>';
                }
            }
            // For authorized users only
        } elseif (MAIN_TYPE_USER) {
            $login_time = $_SESSION['user_login_time'];
            $user_id = (int) main()->USER_ID;
            $user_group = (int) main()->USER_GROUP;
            if ($user_id && $user_group) {
                $user_info = user($user_id);
                $user_groups = main()->get_data('user_groups');

                $body .= tpl()->parse('system/user_welcome', [
                    'id' => (int) ($user_info['id']),
                    'name' => _prepare_html(_display_name($user_info)),
                    'group' => _prepare_html(t($user_groups[$user_group])),
                    'time' => _format_date($login_time),
                    'user_info' => $user_info,
                ]);
            }
        }
        return $body;
    }

    /**
     * Welcome message for the admin section.
     */
    public function show_welcome2()
    {
        if (MAIN_TYPE_ADMIN) {
            $body = t('You logged in as %user at %date', ['%date' => date('H:i:s', $_SESSION['admin_login_time']), '%user' => t('admin')]);
        }
        return $body;
    }

    /**
     * @deprecated
     * @param mixed $input
     */
    public function _show_se_keywords($input = '')
    {
        return false;
    }

    /**
     * @deprecated
     */
    public function _set_se_keywords()
    {
        return false;
    }

    /**
     * Show menu.
     * @param mixed $input
     */
    public function _show_menu($input = [])
    {
        return _class('core_menu')->_show_menu($input);
    }

    /**
     * Template for the custom class method for menu block (useful to inherit).
     * @param mixed $params
     */
    public function _custom_menu_items($params = [])
    {
        return _class('core_menu')->_custom_menu_items($params);
    }

    /**
     * Get menu items ordered array (recursively).
     * @param mixed $menu_id
     * @param mixed $skip_item_id
     * @param mixed $parent_id
     * @param mixed $level
     */
    public function _recursive_get_menu_items($menu_id = 0, $skip_item_id = 0, $parent_id = 0, $level = 0)
    {
        return _class('core_menu')->_recursive_get_menu_items($menu_id, $skip_item_id, $parent_id, $level);
    }

    /**
     * Prepare help for show.
     */
    public function show_help()
    {
        $module_name = $_GET['object'];
        $action_name = $_GET['action'];
        $replace = [
            'action' => $action_name,
        ];
        $STPL_NAME = $module_name . '/help';
        if (tpl()->_stpl_exists($STPL_NAME)) {
            $body = tpl()->parse($STPL_NAME, $replace);
        }
        return tpl()->parse('system/help_wrapper', ['body' => nl2br(trim($body))]);
    }

    /**
     * Send main headers.
     * @param mixed $content_length
     */
    public function _send_main_headers($content_length = 0)
    {
        if (headers_sent($file, $line) || conf('no_headers')) {
            //            trigger_error('Headers were sent in '.$file.':'.$line, E_USER_WARNING);
            return false;
        }
        if ($this->HEADER_POWERED_BY) {
            header('X-Powered-By: YF');
        }
        header('Content-Type:text/html; charset=' . conf('charset'));
        header('Content-language: ' . conf('language'));
        if (tpl()->REWRITE_MODE && MAIN_TYPE_USER && ! main()->NO_CACHE_HEADERS) {
            // To emulate static pages need these headers (Tells that page is modified only one time per day)
            header('Last-Modified: ' . gmdate('D, d M Y 00:01:01') . ' GMT');
            header('Content-Length: ' . (int) $content_length);
        } else {
            header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); // Date in the past
            header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT'); // always modified
            header('Cache-Control: private, no-store, no-cache, must-revalidate, post-check=0, pre-check=0, max-age=0');
            header('Pragma: no-cache'); // HTTP/1.0
        }
        $robots_no_index = (main()->is_ajax() || MAIN_TYPE_ADMIN || conf('ROBOTS_NO_INDEX') || DEBUG_MODE || (defined('DEVELOP') && DEVELOP) || (defined('TEST_MODE') && TEST_MODE));
        if ($robots_no_index) {
            header('X-Robots-Tag: noindex,nofollow,noarchive,nosnippet');
        }
        // We need this to make nginx cache correctly working
        if ($uid = main()->USER_ID) {
            header('X-Logged-In: 1');
            header('X-Member-Id: ' . $uid);
        }
        // TODO: unify headers sending for 301, 302, 403, 404, also chech php_sapi_name() for strpos "cgi"
        // http://stackoverflow.com/questions/3258634/php-how-to-send-http-response-code
        //            http_response_code(404); // 5.4+
        //            header('X-PHP-Response-Code: 404', true, 404);
        //            header('Status: 404 Not Found');
        $this->_send_custom_http_headers();
    }


    public function _send_custom_http_headers()
    {
        // Override headers
        $conf_headers = conf('http_headers');
        if (is_array($conf_headers)) {
            foreach ($conf_headers as $name => $value) {
                $name = trim($name);
                if ( ! $name) {
                    continue;
                }
                $value = str_replace(PHP_EOL, ' ', trim($value));
                header($name . ': ' . $value, true);
            }
        }
    }

    /**
     * Display user geo location block.
     * @param mixed $params
     */
    public function _show_user_geo_block($params = [])
    {
        if ( ! main()->USE_GEO_IP) {
            return false;
        }
        $geo_data = main()->_USER_GEO_DATA;
        if (empty($geo_data)) {
            return false;
        }
        $replace = [
            'country_name' => _prepare_html($geo_data['country_name']),
            'country_code_lower' => strtolower($geo_data['country_code']),
            'region_code' => _prepare_html($geo_data['region_code']),
            'region_name' => _prepare_html(_region_name($geo_data['region_code'], $geo_data['country_code'])),
            'city_name' => _prepare_html($geo_data['city_name']),
            'change_link' => './?object=geo_content&action=change_location',
        ];
        return tpl()->parse('user_geo_block', $replace);
    }

    /**
     * Generate typos for the given text.
     * @param mixed $params
     */
    public function _generate_typos($params = [])
    {
        return _class('graphics_typos', $this->SUB_MODULES_PATH)->get_all_with_stpl($params['text'], $params);
    }

    /**
     * Get html code for external bookmarking (Yahoo, Digg, etc).
     * @param mixed $title
     * @param mixed $url
     * @param mixed $only_links
     */
    public function _show_bookmarks_button($title = '', $url = '', $only_links = 1)
    {
        return _class('graphics_bookmarks', $this->SUB_MODULES_PATH)->_show_bookmarks_button($title, $url, $only_links);
    }

    /**
     * Get html code for external bookmarking (Yahoo, Digg, etc).
     * @param mixed $feed_name
     * @param mixed $feed_link
     * @param mixed $only_links
     */
    public function _show_rss_button($feed_name = '', $feed_link = '', $only_links = 1)
    {
        return _class('graphics_bookmarks', $this->SUB_MODULES_PATH)->_show_rss_button($feed_name, $feed_link, $only_links);
    }

    /**
     * Display header content (hook).
     */
    public function _show_header()
    {
        if (conf('no_page_header')) {
            return false;
        }
        $page_header = '';
        $page_subheader = '';
        // Display hook contents
        // TODO: need to check permissions at first
        //        $obj = module($_GET['object']);
        if (method_exists($obj, '_show_header')) {
            $result = $obj->_show_header();
            if (is_array($result)) {
                $page_header = $result['header'];
                $page_subheader = $result['subheader'];
            } else {
                return (string) $result;
            }
        }
        // Show default header
        if ( ! isset($page_header)) {
            $page_header = _ucwords(str_replace('_', ' ', $_GET['object']));
        }
        if ( ! isset($page_subheader)) {
            if ($_GET['action'] != 'show') {
                $page_subheader = _ucwords(str_replace('_', ' ', $_GET['action']));
            }
        }
        $replace = [
            'header' => $page_header ? t($page_header) : '',
            'subheader' => $page_subheader ? t($page_subheader) : '',
        ];
        return tpl()->parse('system/page_header', $replace);
    }

    /**
     * Display quick menu items.
     */
    public function quick_menu()
    {
        if ( ! $this->QUICK_MENU_ENABLED
            || (MAIN_TYPE_USER && ( ! isset($_SESSION['user_id']) || ! $_SESSION['user_id']))
            || (MAIN_TYPE_ADMIN && ( ! isset($_SESSION['admin_id']) || ! $_SESSION['admin_id']))
        ) {
            return false;
        }
        if (MAIN_TYPE_ADMIN) {
            $data[-1] = [
                'name' => 'module settings',
                'url' => './?object=conf_editor&action=admin_modules&id=' . strtolower($_GET['object']),
            ];
        }
        $method_name = '_quick_menu';
        // TODO: need to check permissions at first
        //        $obj = module($_GET['object']);
        if (method_exists($obj, $method_name)) {
            $data2 = $obj->$method_name();
        }
        $data = (array) $data2 + (array) $data;
        if (empty($data)) {
            return false;
        }
        foreach ((array) $data as $_item) {
            if ( ! $_item['name']) {
                continue;
            }
            $replace2 = [
                'item_name' => _prepare_html(t($_item['name'])),
                'item_url' => $_item['url'],
            ];
            $items .= tpl()->parse('system/quick_menu_item', $replace2);
        }
        if ( ! $items) {
            return false;
        }
        $replace = [
            'items' => $items,
        ];
        return tpl()->parse('system/quick_menu_main', $replace);
    }

    /**
     * New unified method to display tooltips, all others should be deprecated. Examples:
     * tip('register.login')     tpl version: {tip('register.login')}
     * tip('Some inline help text')     tpl version: {tip('Some inline help text')}
     * tip('Some inline help text';'fa-eye')    tpl version: {tip('Some inline help text';'fa-eye')}
     * tip(array('raw' => '\'Some inline help text\';\'fa-eye\''))
     * tip(array('text' => 'Some inline help text', 'icon' => 'fa-eye'))
     * tip('Some inline help text', array('icon' => 'fa-eye')).
     * @param null|mixed $in
     * @param mixed $extra
     */
    public function tip($in = null, $extra = [])
    {
        if ( ! is_array($extra)) {
            $extra = [];
        }
        if (is_array($in) && isset($in['text'])) {
            $extra = (array) $extra + $in;
        } elseif (is_array($in) && isset($in['raw'])) {
            // Some inline help text
            // Some inline help text;fa-eye;my_tip_class'
            // Some inline help text; fa-eye; my_tip_class
            // 'Some inline help text'
            // 'Some inline help text';'fa-eye'
            // 'Some inline help text';'fa-eye';'my_tip_class'
            $raw = explode(';', str_replace(['\'', '"'], '', $in['raw']));
            $extra['text'] = trim($raw[0]);
            if ($raw[1] === 'return_text=1' || $raw[1] === 'text=1') {
                $return_text = true;
            }
            $extra['icon'] = trim($raw[1]);
            $extra['class'] = trim($raw[1]);
            if (isset($in['replace']) && $extra['text'] && substr($extra['text'], 0, 1) === '@') {
                $replace_var = substr($extra['text'], 1);
                if (isset($in['replace'][$replace_var])) {
                    $extra['text'] = $in['replace'][$replace_var];
                }
            }
        }
        $extra['text'] = trim($extra['text'] ?: (is_string($in) ? $in : ''));
        if ( ! strlen($extra['text'])) {
            return false;
        }
        $strip_tags = isset($extra['strip_tags']) ? $extra['strip_tags'] : $this->TIPS_STRIP_TAGS;
        if ( ! isset($this->_tips)) {
            $this->_tips = (array) main()->get_data('tips');
        }
        $tip = [];
        if (isset($this->_tips[$extra['text']])) {
            $lang = conf('language');
            // Exact match for current language
            if (isset($this->_tips[$extra['text']][$lang])) {
                $tip = $this->_tips[$extra['text']][$lang];
            } else {
                // Try to get first record and translate it
                $tip = current($this->_tips[$extra['text']]);
                if ($strip_tags) {
                    $tip['text'] = strip_tags($tip['text']); // Needed for correct translation
                }
                $tip['text'] = t($tip['text']);
            }
            if ( ! $tip['active']) {
                return false;
            }
            $extra['text'] = $tip['text'];
        }
        if ($strip_tags) {
            $extra['text'] = strip_tags($extra['text']);
        }
        if ( ! strlen($extra['text'])) {
            return false;
        }
        // Thinking that we have template variables or tags inside tip contents, try to replace them
        if (isset($in['replace']) && false !== strpos($extra['text'], '{')) {
            $extra['text'] = tpl()->parse_string($extra['text'], $in['replace'], 'html_tip_auto__' . crc32($extra['text']));
        }
        if ($return_text || $extra['return_text']) {
            return $extra['text'];
        }
        $extra['icon'] = $extra['icon'] ?: $tip['icon'];
        $extra['class_add'] = $extra['class_add'] ?: $tip['class_add'];
        return html()->tooltip($extra['text'], $extra);
    }
}