663 lines
18 KiB
PHP
663 lines
18 KiB
PHP
<?php
|
|
/*
|
|
CrazyToad for Question2Answer Package
|
|
Copyright (c) 2017 mose
|
|
based on
|
|
Copyright (C) 2014 Q2A Market <http://www.q2amarket.com>
|
|
|
|
File: qa-theme.php
|
|
Version: CrazyToad 1.0
|
|
Description: Q2A theme class
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
*/
|
|
|
|
/**
|
|
* Snow theme extends
|
|
*
|
|
* Extends the core theme class <code>qa_html_theme_base</code>
|
|
*
|
|
* @package qa_html_theme_base
|
|
* @subpackage qa_html_theme
|
|
* @category Theme
|
|
* @since Snow 1.0
|
|
* @version 1.4
|
|
* @author Q2A Market <http://www.q2amarket.com>
|
|
* @copyright (c) 2014, Q2A Market
|
|
* @license http://www.gnu.org/copyleft/gpl.html
|
|
*/
|
|
class qa_html_theme extends qa_html_theme_base
|
|
{
|
|
// use local font files instead of Google Fonts
|
|
private $localfonts = true;
|
|
|
|
// theme subdirectories
|
|
private $js_dir = 'js';
|
|
private $icon_url = 'images/icons';
|
|
|
|
private $fixed_topbar = false;
|
|
private $welcome_widget_class = 'wet-asphalt';
|
|
private $ask_search_box_class = 'turquoise';
|
|
// Size of the user avatar in the navigation bar
|
|
private $nav_bar_avatar_size = 52;
|
|
|
|
/**
|
|
* Adding aditional meta for responsive design
|
|
*
|
|
* @since Snow 1.4
|
|
*/
|
|
public function head_metas()
|
|
{
|
|
$this->output('<meta name="viewport" content="width=device-width, initial-scale=1"/>');
|
|
parent::head_metas();
|
|
}
|
|
|
|
/**
|
|
* Adding theme stylesheets
|
|
*
|
|
* @since Snow 1.4
|
|
*/
|
|
public function head_css()
|
|
{
|
|
// add RTL CSS file
|
|
if ($this->isRTL)
|
|
$this->content['css_src'][] = $this->rooturl . 'qa-styles-rtl.css?' . QA_VERSION;
|
|
|
|
// add Ubuntu font CSS file from Google Fonts
|
|
if ($this->localfonts)
|
|
$this->content['css_src'][] = $this->rooturl . 'fonts/ubuntu.css?' . QA_VERSION;
|
|
else
|
|
$this->content['css_src'][] = '//fonts.googleapis.com/css?family=Ubuntu:400,700,400italic,700italic';
|
|
|
|
parent::head_css();
|
|
|
|
// output some dynamic CSS inline
|
|
$this->head_inline_css();
|
|
}
|
|
|
|
/**
|
|
* Adding theme javascripts
|
|
*
|
|
* @since Snow 1.4
|
|
*/
|
|
public function head_script()
|
|
{
|
|
$jsUrl = $this->rooturl . $this->js_dir . '/snow-core.js?' . QA_VERSION;
|
|
$this->content['script'][] = '<script src="' . $jsUrl . '"></script>';
|
|
|
|
parent::head_script();
|
|
}
|
|
|
|
/**
|
|
* Adding point count for logged in user
|
|
*
|
|
* @since Snow 1.4
|
|
*/
|
|
public function logged_in()
|
|
{
|
|
parent::logged_in();
|
|
if (qa_is_logged_in()) {
|
|
$userpoints = qa_get_logged_in_points();
|
|
$pointshtml = $userpoints == 1
|
|
? qa_lang_html_sub('main/1_point', '1', '1')
|
|
: qa_html(number_format($userpoints))
|
|
;
|
|
$this->output('<div class="qam-logged-in-points">' . $pointshtml . '</div>');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Adding body class dynamically. Override needed to add class on admin/approve-users page
|
|
*
|
|
* @since Snow 1.4
|
|
*/
|
|
public function body_tags()
|
|
{
|
|
$class = 'qa-template-' . qa_html($this->template);
|
|
|
|
if (isset($this->content['categoryids'])) {
|
|
foreach ($this->content['categoryids'] as $categoryid)
|
|
$class .= ' qa-category-' . qa_html($categoryid);
|
|
}
|
|
|
|
// add class if admin/appovoe-users page
|
|
if ($this->template === 'admin' && qa_request_part(1) === 'approve')
|
|
$class .= ' qam-approve-users';
|
|
|
|
if ($this->fixed_topbar)
|
|
$class .= ' qam-body-fixed';
|
|
|
|
$this->output('class="' . $class . ' qa-body-js-off"');
|
|
}
|
|
|
|
/**
|
|
* Login form for user dropdown menu.
|
|
*
|
|
* @since Snow 1.4
|
|
*/
|
|
public function nav_user_search()
|
|
{
|
|
// outputs login form if user not logged in
|
|
$this->output('<div class="qam-account-items-wrapper">');
|
|
|
|
$this->qam_user_account();
|
|
|
|
$this->output('<div class="qam-account-items clearfix">');
|
|
|
|
if (!qa_is_logged_in()) {
|
|
if (isset($this->content['navigation']['user']['login']) && !QA_FINAL_EXTERNAL_USERS) {
|
|
$login = $this->content['navigation']['user']['login'];
|
|
$this->output(
|
|
'<form action="' . $login['url'] . '" method="post">',
|
|
'<input type="text" name="emailhandle" dir="auto" placeholder="' . trim(qa_lang_html(qa_opt('allow_login_email_only') ? 'users/email_label' : 'users/email_handle_label'), ':') . '"/>',
|
|
'<input type="password" name="password" dir="auto" placeholder="' . trim(qa_lang_html('users/password_label'), ':') . '"/>',
|
|
'<div><input type="checkbox" name="remember" id="qam-rememberme" value="1"/>',
|
|
'<label for="qam-rememberme">' . qa_lang_html('users/remember') . '</label></div>',
|
|
'<input type="hidden" name="code" value="' . qa_html(qa_get_form_security_code('login')) . '"/>',
|
|
'<input type="submit" value="' . $login['label'] . '" class="qa-form-tall-button qa-form-tall-button-login" name="dologin"/>',
|
|
'</form>'
|
|
);
|
|
|
|
// remove regular navigation link to log in page
|
|
unset($this->content['navigation']['user']['login']);
|
|
}
|
|
}
|
|
|
|
$this->nav('user');
|
|
$this->output('</div> <!-- END qam-account-items -->');
|
|
$this->output('</div> <!-- END qam-account-items-wrapper -->');
|
|
}
|
|
|
|
/**
|
|
* Modify markup for topbar.
|
|
*
|
|
* @since Snow 1.4
|
|
*/
|
|
public function nav_main_sub()
|
|
{
|
|
$this->output('<div class="qam-main-nav-wrapper clearfix">');
|
|
$this->output('<div class="sb-toggle-left qam-menu-toggle"><i class="icon-th-list"></i></div>');
|
|
$this->nav_user_search();
|
|
$this->logo();
|
|
$this->nav('main');
|
|
$this->output('</div> <!-- END qam-main-nav-wrapper -->');
|
|
$this->nav('sub');
|
|
}
|
|
|
|
/**
|
|
* Remove the '-' from the note for the category page (notes).
|
|
*
|
|
* @since Snow 1.4
|
|
* @param type $navlink
|
|
* @param type $class
|
|
*/
|
|
public function nav_link($navlink, $class)
|
|
{
|
|
if (isset($navlink['note']) && !empty($navlink['note'])) {
|
|
$search = array(' - <', '> - ');
|
|
$replace = array(' <', '> ');
|
|
$navlink['note'] = str_replace($search, $replace, $navlink['note']);
|
|
}
|
|
parent::nav_link($navlink, $class);
|
|
}
|
|
|
|
/**
|
|
* Rearranges the layout:
|
|
* - Swaps the <tt>main()</tt> and <tt>sidepanel()</tt> functions
|
|
* - Moves the header and footer functions outside qa-body-wrapper
|
|
* - Keeps top/high and low/bottom widgets separated
|
|
*
|
|
* @since Snow 1.4
|
|
*/
|
|
public function body_content()
|
|
{
|
|
$this->body_prefix();
|
|
$this->notices();
|
|
|
|
$this->widgets('full', 'top');
|
|
$this->header();
|
|
|
|
$this->output('<div class="qa-body-wrapper">', '');
|
|
$this->widgets('full', 'high');
|
|
|
|
$this->output('<div class="qa-main-wrapper">', '');
|
|
$this->main();
|
|
$this->sidepanel();
|
|
$this->output('</div> <!-- END main-wrapper -->');
|
|
|
|
$this->widgets('full', 'low');
|
|
$this->output('</div> <!-- END body-wrapper -->');
|
|
|
|
$this->footer();
|
|
|
|
$this->body_suffix();
|
|
}
|
|
|
|
/**
|
|
* Header in full width top bar
|
|
*
|
|
* @since Snow 1.4
|
|
*/
|
|
public function header()
|
|
{
|
|
$class = $this->fixed_topbar ? ' fixed' : '';
|
|
|
|
$this->output('<div id="qam-topbar" class="clearfix' . $class . '">');
|
|
|
|
$this->nav_main_sub();
|
|
$this->output('</div> <!-- END qam-topbar -->');
|
|
|
|
$this->output($this->ask_button());
|
|
$this->qam_search('the-top', 'the-top-search');
|
|
}
|
|
|
|
/**
|
|
* Footer in full width bottom bar
|
|
*
|
|
* @since Snow 1.4
|
|
*/
|
|
public function footer()
|
|
{
|
|
$this->output('<div class="qam-footer-box">');
|
|
|
|
$this->output('<div class="qam-footer-row">');
|
|
$this->widgets('full', 'bottom');
|
|
$this->output('</div> <!-- END qam-footer-row -->');
|
|
|
|
parent::footer();
|
|
$this->output('</div> <!-- END qam-footer-box -->');
|
|
}
|
|
|
|
/**
|
|
* Overridden to customize layout and styling
|
|
*
|
|
* @since Snow 1.4
|
|
*/
|
|
public function sidepanel()
|
|
{
|
|
// remove sidebar for user profile pages
|
|
if ($this->template == 'user')
|
|
return;
|
|
|
|
$this->output('<div id="qam-sidepanel-toggle"><i class="icon-left-open-big"></i></div>');
|
|
$this->output('<div class="qa-sidepanel" id="qam-sidepanel-mobile">');
|
|
$this->qam_search();
|
|
$this->widgets('side', 'top');
|
|
$this->sidebar();
|
|
$this->widgets('side', 'high');
|
|
$this->nav('cat', 1);
|
|
$this->widgets('side', 'low');
|
|
if (isset($this->content['sidepanel']))
|
|
$this->output_raw($this->content['sidepanel']);
|
|
$this->feed();
|
|
$this->widgets('side', 'bottom');
|
|
$this->output('</div> <!-- qa-sidepanel -->', '');
|
|
}
|
|
|
|
/**
|
|
* Allow alternate sidebar color.
|
|
*
|
|
* @since Snow 1.4
|
|
*/
|
|
public function sidebar()
|
|
{
|
|
if (isset($this->content['sidebar'])) {
|
|
$sidebar = $this->content['sidebar'];
|
|
if (!empty($sidebar)) {
|
|
$this->output('<div class="qa-sidebar ' . $this->welcome_widget_class . '">');
|
|
$this->output_raw($sidebar);
|
|
$this->output('</div> <!-- qa-sidebar -->', '');
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Add close icon
|
|
*
|
|
* @since Snow 1.4
|
|
* @param array $q_item
|
|
*/
|
|
public function q_item_title($q_item)
|
|
{
|
|
$closedText = qa_lang('main/closed');
|
|
$imgHtml = empty($q_item['closed'])
|
|
? ''
|
|
: '<img src="' . $this->rooturl . $this->icon_url . '/closed-q-list.png" class="qam-q-list-close-icon" alt="' . $closedText . '" title="' . $closedText . '"/>';
|
|
|
|
$this->output(
|
|
'<div class="qa-q-item-title">',
|
|
// add closed note in title
|
|
$imgHtml,
|
|
'<a href="' . $q_item['url'] . '">' . $q_item['title'] . '</a>',
|
|
'</div>'
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Add RSS feeds icon and closed icon for closed questions
|
|
*
|
|
* @since Snow 1.4
|
|
*/
|
|
public function title()
|
|
{
|
|
$q_view = isset($this->content['q_view']) ? $this->content['q_view'] : null;
|
|
|
|
// RSS feed link in title
|
|
if (isset($this->content['feed']['url'])) {
|
|
$feed = $this->content['feed'];
|
|
$label = isset($feed['label']) ? $feed['label'] : '';
|
|
$this->output('<a href="' . $feed['url'] . '" title="' . $label . '"><i class="icon-rss qam-title-rss"></i></a>');
|
|
}
|
|
|
|
// link title where appropriate
|
|
$url = isset($q_view['url']) ? $q_view['url'] : false;
|
|
|
|
// add closed image
|
|
$closedText = qa_lang('main/closed');
|
|
$imgHtml = empty($q_view['closed'])
|
|
? ''
|
|
: '<img src="' . $this->rooturl . $this->icon_url . '/closed-q-view.png" class="qam-q-view-close-icon" alt="' . $closedText . '" width="24" height="24" title="' . $closedText . '"/>';
|
|
|
|
if (isset($this->content['title'])) {
|
|
$this->output(
|
|
$imgHtml,
|
|
$url ? '<a href="' . $url . '">' : '',
|
|
$this->content['title'],
|
|
$url ? '</a>' : ''
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Add view counter to question list
|
|
*
|
|
* @since Snow 1.4
|
|
* @param array $q_item
|
|
*/
|
|
public function q_item_stats($q_item)
|
|
{
|
|
$this->output('<div class="qa-q-item-stats">');
|
|
|
|
$this->voting($q_item);
|
|
$this->a_count($q_item);
|
|
parent::view_count($q_item);
|
|
|
|
$this->output('</div>');
|
|
}
|
|
|
|
/**
|
|
* Prevent display view counter on usual place
|
|
*
|
|
* @since Snow 1.4
|
|
* @param type $q_item
|
|
*/
|
|
public function view_count($q_item) {}
|
|
|
|
/**
|
|
* Add view counter to question view
|
|
*
|
|
* @since Snow 1.4
|
|
* @param type $q_view
|
|
*/
|
|
public function q_view_stats($q_view)
|
|
{
|
|
$this->output('<div class="qa-q-view-stats">');
|
|
|
|
$this->voting($q_view);
|
|
$this->a_count($q_view);
|
|
parent::view_count($q_view);
|
|
|
|
$this->output('</div>');
|
|
}
|
|
|
|
/**
|
|
* Modify user whometa, move to top
|
|
*
|
|
* @since Snow 1.4
|
|
* @param type $q_view
|
|
*/
|
|
public function q_view_main($q_view)
|
|
{
|
|
$this->output('<div class="qa-q-view-main">');
|
|
|
|
if (isset($q_view['main_form_tags']))
|
|
$this->output('<form ' . $q_view['main_form_tags'] . '>'); // form for buttons on question
|
|
|
|
$this->post_avatar_meta($q_view, 'qa-q-view');
|
|
$this->q_view_content($q_view);
|
|
$this->q_view_extra($q_view);
|
|
$this->q_view_follows($q_view);
|
|
$this->q_view_closed($q_view);
|
|
$this->post_tags($q_view, 'qa-q-view');
|
|
|
|
$this->q_view_buttons($q_view);
|
|
$this->c_list(isset($q_view['c_list']) ? $q_view['c_list'] : null, 'qa-q-view');
|
|
|
|
if (isset($q_view['main_form_tags'])) {
|
|
if (isset($q_view['buttons_form_hidden']))
|
|
$this->form_hidden_elements($q_view['buttons_form_hidden']);
|
|
$this->output('</form>');
|
|
}
|
|
|
|
$this->c_form(isset($q_view['c_form']) ? $q_view['c_form'] : null);
|
|
|
|
$this->output('</div> <!-- END qa-q-view-main -->');
|
|
}
|
|
|
|
/**
|
|
* Move user whometa to top in answer
|
|
*
|
|
* @since Snow 1.4
|
|
* @param type $a_item
|
|
*/
|
|
public function a_item_main($a_item)
|
|
{
|
|
$this->output('<div class="qa-a-item-main">');
|
|
|
|
$this->post_avatar_meta($a_item, 'qa-a-item');
|
|
|
|
if (isset($a_item['main_form_tags']))
|
|
$this->output('<form ' . $a_item['main_form_tags'] . '>'); // form for buttons on answer
|
|
|
|
if ($a_item['hidden'])
|
|
$answerState = 'hidden';
|
|
elseif ($a_item['selected'])
|
|
$answerState = 'selected';
|
|
else
|
|
$answerState = null;
|
|
|
|
if (isset($answerState))
|
|
$this->output('<div class="qa-a-item-' . $answerState . '">');
|
|
|
|
$this->a_selection($a_item);
|
|
if (isset($a_item['error']))
|
|
$this->error($a_item['error']);
|
|
$this->a_item_content($a_item);
|
|
|
|
if (isset($answerState))
|
|
$this->output('</div>');
|
|
|
|
$this->a_item_buttons($a_item);
|
|
|
|
if (isset($a_item['c_list']))
|
|
$this->c_list($a_item['c_list'], 'qa-a-item');
|
|
|
|
if (isset($a_item['main_form_tags'])) {
|
|
if (isset($a_item['buttons_form_hidden']))
|
|
$this->form_hidden_elements($a_item['buttons_form_hidden']);
|
|
$this->output('</form>');
|
|
}
|
|
|
|
$this->c_form(isset($a_item['c_form']) ? $a_item['c_form'] : null);
|
|
|
|
$this->output('</div> <!-- END qa-a-item-main -->');
|
|
}
|
|
|
|
/**
|
|
* Move user whometa to top in comment
|
|
*
|
|
* @since Snow 1.4
|
|
* @param type $c_item
|
|
*/
|
|
public function c_item_main($c_item)
|
|
{
|
|
$this->post_avatar_meta($c_item, 'qa-c-item');
|
|
|
|
if (isset($c_item['error']))
|
|
$this->error($c_item['error']);
|
|
|
|
if (isset($c_item['expand_tags']))
|
|
$this->c_item_expand($c_item);
|
|
elseif (isset($c_item['url']))
|
|
$this->c_item_link($c_item);
|
|
else
|
|
$this->c_item_content($c_item);
|
|
|
|
$this->output('<div class="qa-c-item-footer">');
|
|
$this->c_item_buttons($c_item);
|
|
$this->output('</div>');
|
|
}
|
|
|
|
/**
|
|
* Q2A Market attribution.
|
|
* I'd really appreciate you displaying this link on your Q2A site. Thank you - Jatin
|
|
*
|
|
* @since Snow 1.4
|
|
*/
|
|
public function attribution()
|
|
{
|
|
// floated right
|
|
$this->output(
|
|
'<div class="qa-attribution">',
|
|
'CrazyToad on <a href="https://github.com/crazy-toads/q2a-theme-crazytoad">github</a>',
|
|
'</div>'
|
|
);
|
|
parent::attribution();
|
|
}
|
|
|
|
/**
|
|
* User account navigation item. This will return based on login information.
|
|
* If user is logged in, it will populate user avatar and account links.
|
|
* If user is guest, it will populate login form and registration link.
|
|
*
|
|
* @since Snow 1.4
|
|
*/
|
|
private function qam_user_account()
|
|
{
|
|
if (qa_is_logged_in()) {
|
|
// get logged-in user avatar
|
|
$handle = qa_get_logged_in_user_field('handle');
|
|
$toggleClass = 'qam-logged-in';
|
|
|
|
if (QA_FINAL_EXTERNAL_USERS)
|
|
$tobar_avatar = qa_get_external_avatar_html(qa_get_logged_in_user_field('userid'), $this->nav_bar_avatar_size, true);
|
|
else {
|
|
$tobar_avatar = qa_get_user_avatar_html(
|
|
qa_get_logged_in_user_field('flags'),
|
|
qa_get_logged_in_user_field('email'),
|
|
$handle,
|
|
qa_get_logged_in_user_field('avatarblobid'),
|
|
qa_get_logged_in_user_field('avatarwidth'),
|
|
qa_get_logged_in_user_field('avatarheight'),
|
|
$this->nav_bar_avatar_size,
|
|
false
|
|
);
|
|
}
|
|
|
|
$avatar = strip_tags($tobar_avatar, '<img>');
|
|
if (!empty($avatar))
|
|
$handle = '';
|
|
}
|
|
else {
|
|
// display login icon and label
|
|
$handle = $this->content['navigation']['user']['login']['label'];
|
|
$toggleClass = 'qam-logged-out';
|
|
$avatar = '<i class="icon-key qam-auth-key"></i>';
|
|
}
|
|
|
|
// finally output avatar with div tag
|
|
$handleBlock = empty($handle) ? '' : '<div class="qam-account-handle">' . qa_html($handle) . '</div>';
|
|
$this->output(
|
|
'<div id="qam-account-toggle" class="' . $toggleClass . '">',
|
|
$avatar,
|
|
$handleBlock,
|
|
'</div>'
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Add search-box wrapper with extra class for color scheme
|
|
*
|
|
* @since Snow 1.4
|
|
* @version 1.0
|
|
*/
|
|
private function qam_search($addon_class = null, $ids = null)
|
|
{
|
|
$id = isset($ids) ? ' id="' . $ids . '"' : '';
|
|
|
|
$this->output('<div class="qam-search ' . $this->ask_search_box_class . ' ' . $addon_class . '"' . $id . '>');
|
|
$this->search();
|
|
$this->output('</div>');
|
|
}
|
|
|
|
|
|
/**
|
|
* Dynamic <code>CSS</code> based on options and other interaction with Q2A.
|
|
*
|
|
* @since Snow 1.4
|
|
* @version 1.0
|
|
* @return string The CSS code
|
|
*/
|
|
private function head_inline_css()
|
|
{
|
|
$css = array('<style>');
|
|
|
|
if (!qa_is_logged_in())
|
|
$css[] = '.qa-nav-user { margin: 0 !important; }';
|
|
|
|
if (qa_request_part(1) !== qa_get_logged_in_handle()) {
|
|
$css[] = '@media (max-width: 979px) {';
|
|
$css[] = ' body.qa-template-user.fixed, body[class*="qa-template-user-"].fixed { padding-top: 118px !important; }';
|
|
$css[] = ' body.qa-template-users.fixed { padding-top: 95px !important; }';
|
|
$css[] = '}';
|
|
$css[] = '@media (min-width: 980px) {';
|
|
$css[] = ' body.qa-template-users.fixed { padding-top: 105px !important;}';
|
|
$css[] = '}';
|
|
}
|
|
|
|
$css[] = '</style>';
|
|
|
|
$this->output_array($css);
|
|
}
|
|
|
|
/**
|
|
* Custom ask button for medium and small screen
|
|
*
|
|
* @access private
|
|
* @since Snow 1.4
|
|
* @version 1.0
|
|
* @return string Ask button html markup
|
|
*/
|
|
private function ask_button()
|
|
{
|
|
return
|
|
'<div class="qam-ask-search-box">' .
|
|
'<div class="qam-ask-mobile">' .
|
|
'<a href="' . qa_path('ask', null, qa_path_to_root()) . '" class="' . $this->ask_search_box_class . '">' .
|
|
qa_lang_html('main/nav_ask') .
|
|
'</a>' .
|
|
'</div>' .
|
|
'<div class="qam-search-mobile ' . $this->ask_search_box_class . '" id="qam-search-mobile">' .
|
|
'</div>' .
|
|
'</div>';
|
|
}
|
|
|
|
}
|