gnomezgrave

qa-donut-layer.php

May 1st, 2016
187
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. <?php
  2.     if ( !defined( 'QA_VERSION' ) ) { // don't allow this page to be requested directly from browser
  3.         header( 'Location: ../../' );
  4.         exit;
  5.     }
  6.  
  7.     class qa_html_theme extends qa_html_theme_base
  8.     {
  9.  
  10.         /**
  11.          * Doctype function
  12.          */
  13.         function doctype()
  14.         {
  15.             if ( !property_exists( 'qa_html_theme_base', 'isRTL' ) ) {
  16.                 /*Fall back for the version 1.6.3*/
  17.                 $this->isRTL = isset( $this->content['direction'] ) && $this->content['direction'] === 'rtl';
  18.             }
  19.  
  20.             parent::doctype();
  21.         }
  22.  
  23.         function head()
  24.         {
  25.             $this->output(
  26.                     '<head>',
  27.                     '<meta http-equiv="content-type" content="' . $this->content['content_type'] . '"/>'
  28.             );
  29.  
  30.             $this->donut_default_meta();
  31.             $this->head_title();
  32.             $this->head_metas();
  33.             $this->head_css();
  34.             $this->donut_utility_for_old_ie();
  35.             $this->head_links();
  36.             $this->head_lines();
  37.             $this->head_script();
  38.             $this->head_custom();
  39.  
  40.             $this->output( '</head>' );
  41.         }
  42.  
  43.         /**
  44.          * prints the defult meta and view ports
  45.          *
  46.          * @return  null
  47.          */
  48.         function donut_default_meta()
  49.         {
  50.             $this->output_raw( '<meta charset="utf-8">' );
  51.             $this->output_raw( '<meta name="viewport" content="width=device-width, initial-scale=1">' );
  52.         }
  53.  
  54.         function head_css()
  55.         {
  56.             parent::head_css();
  57.  
  58.             $css_paths = array(
  59.                     'fonts'     => 'css/font-awesome.min.css?4.2.0',
  60.                     'bootstrap' => 'css/bootstrap.min.css?3.3.5',
  61.                     'donut'     => 'css/donut.css?' . DONUT_THEME_VERSION,
  62.             );
  63.  
  64.             if ( qa_opt( 'donut_activate_prod_mode' ) ) {
  65.                 $cdn_css_paths = array(
  66.                         'bootstrap' => Donut_Option_Keys::BS_CSS_CDN,
  67.                         'fonts'     => Donut_Option_Keys::FA_CDN,
  68.                 );
  69.  
  70.                 unset( $css_paths['bootstrap'] );
  71.                 unset( $css_paths['fonts'] );
  72.                 $this->donut_resources( $cdn_css_paths, 'css', true );
  73.  
  74.                 $css_paths['donut'] = 'css/donut.min.css?' . DONUT_THEME_VERSION;  //put the donut.min.css for the prod mode
  75.             }
  76.  
  77.             $this->donut_resources( $css_paths, 'css' );
  78.  
  79.             if( qa_opt('donut_use_local_font') ){
  80.                 $this->donut_resources( array( 'css/open-sans.css?' . DONUT_THEME_VERSION) );
  81.             } else {
  82.                 $this->donut_resources( array( 'https://fonts.googleapis.com/css?family=Open+Sans:400,700,700italic,400italic' ) , 'css' , true );
  83.             }
  84.         }
  85.  
  86.         /**
  87.          * prints the CSS and JS links
  88.          *
  89.          * @param  array   $paths    list of the resources
  90.          * @param  string  $type     type of the resource css or js
  91.          * @param  boolean $external weather it is relative to the theme or a external to the theme
  92.          *
  93.          * @return null
  94.          */
  95.         function donut_resources( $paths, $type = 'css', $external = false )
  96.         {
  97.             if ( count( $paths ) ) {
  98.                 foreach ( $paths as $key => $path ) {
  99.                     if ( $type === 'js' ) {
  100.                         $this->donut_js( $path, $external );
  101.                     } else if ( $type === 'css' ) {
  102.                         $this->donut_css( $path, $external );
  103.                     }
  104.                 }
  105.             }
  106.         }
  107.  
  108.         /**
  109.          * prints the js path
  110.          *
  111.          * @param  string  $path     path of the js file
  112.          * @param  boolean $external weather it is relative to the theme or a external to the theme
  113.          *
  114.          * @return null
  115.          */
  116.         function donut_js( $path, $external = false )
  117.         {
  118.             if ( $external ) {
  119.                 $full_path = $path;
  120.             } else {
  121.                 $full_path = donut_theme_url() . '/' . $path;
  122.             }
  123.  
  124.             if ( !empty( $path ) ) {
  125.                 $this->output( '<script src="' . $full_path . '" type="text/javascript"></script>' );
  126.             }
  127.         }
  128.  
  129.         /**
  130.          * prints the css path
  131.          *
  132.          * @param  string  $path     path of the css file
  133.          * @param  boolean $external weather it is relative to the theme or a external to the theme
  134.          *
  135.          * @return null
  136.          */
  137.         function donut_css( $path, $external = false )
  138.         {
  139.             if ( $external ) {
  140.                 $full_path = $path;
  141.             } else {
  142.                 $full_path = donut_theme_url() . '/' . $path;
  143.             }
  144.  
  145.             if ( !empty( $path ) ) {
  146.                 $this->output( '<link rel="stylesheet" type="text/css" href="' . $full_path . '"/>' );
  147.             }
  148.         }
  149.  
  150.         /**
  151.          * adds support for old IE browsers
  152.          *
  153.          */
  154.         function donut_utility_for_old_ie()
  155.         {
  156.             $this->output( '
  157.                     <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
  158.                        <!--[if lt IE 9]>
  159.                          <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
  160.                          <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
  161.                     <![endif]-->
  162.                 ' );
  163.         }
  164.  
  165.         function head_script() // change style of WYSIWYG editor to match theme better
  166.         {
  167.             parent::head_script();
  168.  
  169.             $js_paths = array(
  170.                     'bootstrap' => 'js/bootstrap.min.js?3.3.5',
  171.                     'donut'     => 'js/donut.js?' . DONUT_THEME_VERSION,
  172.             );
  173.  
  174.             if ( $this->template == 'admin' ) {
  175.                 $js_paths['admin'] = 'js/admin.js?' . DONUT_THEME_VERSION;
  176.             }
  177.  
  178.             if ( qa_opt( 'donut_activate_prod_mode' ) ) {
  179.                 $cdn_js_paths = array(
  180.                         'bootstrap' => Donut_Option_Keys::BS_JS_CDN,
  181.                 );
  182.                 unset( $js_paths['bootstrap'] );
  183.                 $this->donut_resources( $cdn_js_paths, 'js', true );
  184.             }
  185.  
  186.             $this->donut_resources( $js_paths, 'js' );
  187.  
  188.         }
  189.  
  190.         function body_content()
  191.         {
  192.             $sub_navigation = @$this->content['navigation']['sub'];
  193.  
  194.             if ( $this->template === 'admin' ) {
  195.                 unset( $this->content['navigation']['sub'] );
  196.             }
  197.  
  198.             $navigation = &$this->content['navigation'];
  199.  
  200.             if ( isset( $navigation['cat'] ) ) {
  201.                 donut_remove_brackets( $navigation['cat'] );
  202.             }
  203.  
  204.             $this->body_prefix();
  205.  
  206.             $this->output( '<div class="container">' );
  207.             $this->output( '<div class="top-divider"></div>' );
  208.             $this->output( '</div>' );
  209.  
  210.             $this->donut_site_header();
  211.  
  212.             $this->output( '<div class="container visible-xs">' );
  213.             $this->output( '<div class="top-search-bar">' );
  214.             $this->search();
  215.             $this->output( '</div>' );
  216.             $this->output( '</div>' );
  217.  
  218.             $this->output( '<main class="donut-masthead">' );
  219.  
  220.             $this->output( '<div class="container">' );
  221.             $this->notices();
  222.             $this->output( '</div>' );
  223.  
  224.             $this->output( '<div class="container">' );
  225.  
  226.             $extra_title_class = $this->donut_page_has_favorite() ? ' has-favorite' : '';
  227.  
  228.             $this->output( '<div class="page-title' . $extra_title_class . '">' );
  229.             $this->page_title_error();
  230.             $this->output( '</div>' );
  231.  
  232.             $this->donut_breadcrumb();
  233.             $this->output( '</div>' );
  234.  
  235.             $this->output( '</main>' );
  236.  
  237.             $this->output( '<div class="qa-body-wrapper container">', '' );
  238.  
  239.             $this->widgets( 'full', 'top' );
  240.             $this->header();
  241.             $this->widgets( 'full', 'high' );
  242.  
  243.             if ( count( $sub_navigation ) ) {
  244.                 // create the left side bar
  245.                 $this->left_side_bar( $sub_navigation );
  246.             }
  247.  
  248.             $this->main();
  249.  
  250.             if ( !$this->donut_do_hide_sidebar() ) {
  251.                 $this->sidepanel();
  252.             }
  253.  
  254.             $this->widgets( 'full', 'low' );
  255.             $this->footer();
  256.             $this->widgets( 'full', 'bottom' );
  257.  
  258.             $this->output( '</div> <!-- END body-wrapper -->' );
  259.  
  260.             $this->body_suffix();
  261.         }
  262.  
  263.         function page_title_error()
  264.         {
  265.             $favorite = @$this->content['favorite'];
  266.  
  267.             if ( isset( $favorite ) )
  268.                 $this->output( '<form ' . $favorite['form_tags'] . '>' );
  269.  
  270.             $this->feed_link();
  271.  
  272.             $this->output( '<h1>' );
  273.             $this->favorite();
  274.             $this->title();
  275.             $this->output( '</h1>' );
  276.  
  277.             if ( $this->template == 'not-found' && qa_opt( 'donut_show_custom_404_page' ) ) {
  278.                 $this->output( donut_include_template( 'page-not-found.php', false ) );
  279.             } else if ( isset( $this->content['error'] ) )
  280.                 $this->error( @$this->content['error'] );
  281.  
  282.             if ( isset( $favorite ) ) {
  283.                 $this->form_hidden_elements( @$favorite['form_hidden'] );
  284.                 $this->output( '</form>' );
  285.             }
  286.         }
  287.  
  288.         /**
  289.          * add RSS feed icon after the page title
  290.          *
  291.          * @return null
  292.          */
  293.         function feed_link()
  294.         {
  295.             if ( $this->donut_page_has_feed() ) {
  296.                 $feed = @$this->content['feed'];
  297.                 $this->output( '<a href="' . $feed['url'] . '" title="' . @$feed['label'] . '" class="qa-rss-feed"><i class="fa fa-rss qa-rss-icon" ></i></a>' );
  298.             }
  299.         }
  300.  
  301.         function header() // removes user navigation and search from header and replaces with custom header content. Also opens new <div>s
  302.         {
  303.             $this->output( '<div class="qa-header clearfix">' );
  304.             $this->header_clear();
  305.             $this->header_custom();
  306.             $this->output( '</div> <!-- END qa-header -->', '' );
  307.             $this->output( '<div class="qa-main-shadow clearfix">', '' );
  308.             $this->output( '<div class="qa-main-wrapper clearfix row">', '' );
  309.         }
  310.  
  311.         function header_custom() // allows modification of custom element shown inside header after logo
  312.         {
  313.             if ( isset( $this->content['body_header'] ) ) {
  314.                 $this->output( '<div class="header-banner">' );
  315.                 $this->output_raw( $this->content['body_header'] );
  316.                 $this->output( '</div>' );
  317.             }
  318.         }
  319.  
  320.         function left_side_bar( $sub_navigation )
  321.         {
  322.  
  323.             $this->output( '<div class="qa-left-side-bar" id="sidebar" role="navigation">', '' );
  324.             if ( count( $sub_navigation ) ) {
  325.  
  326.                 $this->output( '<div class="list-group">', '' );
  327.  
  328.                 foreach ( $sub_navigation as $key => $sub_navigation_item ) {
  329.                     $this->donut_nav_side_bar_item( $sub_navigation_item );
  330.                 }
  331.                 $this->output( '</div>', '' );
  332.                 if ( $this->template === 'admin' ) {
  333.                     unset( $this->content['navigation']['sub'] );
  334.                 }
  335.             }
  336.             $this->output( '</div>', '<!-- END of left-side-bar -->' );
  337.         }
  338.  
  339.         /**
  340.          * nav item for the sidebar
  341.          *
  342.          * @param  array $nav_item navigation item
  343.          *
  344.          * @return null
  345.          */
  346.         function donut_nav_side_bar_item( $nav_item )
  347.         {
  348.             $class = ( !!@$nav_item['selected'] ) ? ' active' : '';
  349.             $icon = ( !!@$nav_item['icon'] ) ? donut_get_fa_icon( @$nav_item['icon'] ) : '';
  350.             $this->output( '<a href="' . $nav_item['url'] . '" class="list-group-item ' . $class . '">' . $icon . $nav_item['label'] . '</a>' );
  351.         }
  352.  
  353.         function main()
  354.         {
  355.             $content = $this->content;
  356.             $width_class = ( $this->donut_do_hide_sidebar() && $this->template != 'admin' ) ? 'col-xs-12' : 'qa-main col-md-9 col-xs-12 pull-left';
  357.  
  358.             $this->output( '<div class="' . $width_class . ( @$this->content['hidden'] ? ' qa-main-hidden' : '' ) . '">' );
  359.  
  360.             if ( !empty( $this->content['navigation']['sub'] ) || $this->template == 'admin' ) {
  361.                 $this->donut_sidebar_toggle_nav_btn();
  362.             }
  363.  
  364.             $this->widgets( 'main', 'top' );
  365.  
  366.             if ( !empty( $this->content['navigation']['sub'] ) || $this->template == 'admin' ) {
  367.  
  368.                 $this->output( '<div class="hidden-xs subnav-row clearfix">' );
  369.                 $this->nav_main_sub();
  370.                 $this->output( '</div>' );
  371.  
  372.             }
  373.  
  374.             $this->widgets( 'main', 'high' );
  375.  
  376.             $this->main_parts( $content );
  377.  
  378.             $this->widgets( 'main', 'low' );
  379.  
  380.             $this->page_links();
  381.             $this->suggest_next();
  382.  
  383.             $this->widgets( 'main', 'bottom' );
  384.  
  385.             $this->output( '</div> <!-- END qa-main -->', '' );
  386.         }
  387.  
  388.         /**
  389.          * prints sidebar navigation
  390.          *
  391.          * @return  null
  392.          */
  393.         function donut_sidebar_toggle_nav_btn()
  394.         {
  395.             $this->output( '<div class="row">' );
  396.             $this->output( '<div class="pull-left col-xs-12 visible-xs side-toggle-button">' );
  397.             $this->output( '<button type="button" class="btn btn-primary btn-xs" data-toggle="offcanvas">' );
  398.             $this->output( '<i class="fa fa-chevron-right toggle-icon"></i>' );
  399.             $this->output( '</button>' );
  400.             $this->output( '</div>' );
  401.             $this->output( '</div>' );
  402.         }
  403.  
  404.         function sidepanel()
  405.         {
  406.             $this->output( '<div class="qa-sidepanel col-md-3 pull-right">' );
  407.             $this->output( '<div class="side-search-bar hidden-xs">' );
  408.             $this->search();
  409.             $this->output( '</div>' );
  410.             $this->widgets( 'side', 'top' );
  411.             $this->sidebar();
  412.             $this->widgets( 'side', 'high' );
  413.             $this->nav( 'cat', 1 );
  414.             $this->widgets( 'side', 'low' );
  415.             $this->output_raw( @$this->content['sidepanel'] );
  416.             $this->feed();
  417.             $this->widgets( 'side', 'bottom' );
  418.             $this->output( '</div>', '' );
  419.         }
  420.  
  421.         /**
  422.          * the feed icon with a link
  423.          *
  424.          * @return null
  425.          */
  426.         function feed()
  427.         {
  428.             $feed = @$this->content['feed'];
  429.  
  430.             if ( !empty( $feed ) ) {
  431.                 $icon = donut_get_fa_icon( 'rss' );
  432.                 $this->output( '<div class="qa-feed">' );
  433.                 $this->output( '<a href="' . $feed['url'] . '" class="qa-feed-link"> <span class="icon-wrapper"> <span class="qa-feed-icon">' . $icon . ' </span></span>' . @$feed['label'] . '</a>' );
  434.                 $this->output( '</div>' );
  435.             }
  436.         }
  437.  
  438.         /**
  439.          * prevent display of regular footer content (see body_suffix()) and replace with closing new <div>s
  440.          *
  441.          * @return  null
  442.          */
  443.         function footer()
  444.         {
  445.             $this->output( '</div> <!-- END main-wrapper -->' );
  446.             $this->output( '</div> <!-- END main-shadow -->' );
  447.         }
  448.  
  449.         function body_suffix() // to replace standard Q2A footer
  450.         {
  451.             if ( qa_opt( 'donut_show_site_stats_above_footer' ) ) {
  452.                 $this->donut_site_stats_bottom();
  453.             }
  454.  
  455.             $this->output( '<footer class="donut-footer">' );
  456.  
  457.             if ( qa_opt( 'donut_enable_back_to_top_btn' ) ) {
  458.                 $this->output( '<a class="donut-top"><span class="fa fa-chevron-up"></span></a>' );
  459.             }
  460.  
  461.             $this->output( '<div class="container">' );
  462.             parent::footer();
  463.             $this->output( '</div> <!--END Container-->' );
  464.             $this->output( '</footer> <!-- END footer -->', '' );
  465.         }
  466.  
  467.         function logged_in()
  468.         {
  469.             if ( qa_is_logged_in() ) // output user avatar to login bar
  470.                 $this->output(
  471.                         '<div class="qa-logged-in-avatar">',
  472.                         QA_FINAL_EXTERNAL_USERS
  473.                                 ? qa_get_external_avatar_html( qa_get_logged_in_userid(), 24, true )
  474.                                 : qa_get_user_avatar_html( qa_get_logged_in_flags(), qa_get_logged_in_email(), qa_get_logged_in_handle(),
  475.                                 qa_get_logged_in_user_field( 'avatarblobid' ), qa_get_logged_in_user_field( 'avatarwidth' ), qa_get_logged_in_user_field( 'avatarheight' ),
  476.                                 24, true ),
  477.                         '</div>'
  478.                 );
  479.  
  480.             parent::logged_in();
  481.  
  482.             if ( qa_is_logged_in() ) { // adds points count after logged in username
  483.                 $userpoints = qa_get_logged_in_points();
  484.  
  485.                 $pointshtml = ( $userpoints == 1 )
  486.                         ? qa_lang_html_sub( 'main/1_point', '1', '1' )
  487.                         : qa_lang_html_sub( 'main/x_points', qa_html( number_format( $userpoints ) ) );
  488.  
  489.                 $this->output(
  490.                         '<span class="qa-logged-in-points">',
  491.                         '(' . $pointshtml . ')',
  492.                         '</span>'
  493.                 );
  494.             }
  495.         }
  496.  
  497.         function body_header() // adds login bar, user navigation and search at top of page in place of custom header content
  498.         {
  499.             if ( !empty( $this->content['navigation']['main'] ) ) {
  500.                 $this->output( $this->donut_nav_bar( $this->content['navigation'] ) );
  501.                 unset( $this->content['navigation']['main'] );
  502.             }
  503.         }
  504.  
  505.         /**
  506.          * prints the complete navbar
  507.          *
  508.          * @param  $navigation
  509.          *
  510.          * @return text
  511.          */
  512.         function donut_nav_bar( $navigation )
  513.         {
  514.             ob_start();
  515.  
  516.             if ( qa_opt( 'donut_enable_top_bar' ) ) {
  517.                 donut_include_template( 'top-header.php' );
  518.             }
  519.  
  520.             ?>
  521.             <header id="nav-header">
  522.                 <nav id="nav" class="navbar navbar-static-top"
  523.                      role="navigation" <?php echo( qa_opt( 'donut_enable_sticky_header' ) ? 'data-spy="affix" data-offset-top="120"' : '' ) ?>>
  524.                     <div class="container">
  525.                         <div class="navbar-header">
  526.                             <button type="button" class="navbar-toggle collapsed" data-toggle="collapse"
  527.                                     data-target=".navbar-collapse">
  528.                                 <span class="sr-only">Toggle navigation</span>
  529.                                 <span class="glyphicon glyphicon-menu-hamburger"></span>
  530.                             </button>
  531.                         </div>
  532.                         <div class="col-sm-3 col-xs-8 logo-wrapper">
  533.                             <?php $this->logo(); ?>
  534.                         </div>
  535.                         <div class="donut-navigation col-sm-2 col-xs-3 pull-right">
  536.                             <?php $this->donut_user_drop_down(); ?>
  537.                         </div>
  538.                         <div class="col-sm-7 navbar-collapse collapse main-nav navbar-left">
  539.                             <ul class="nav navbar-nav inner-drop-nav">
  540.                                 <?php $this->donut_nav_bar_main_links( $navigation['main'] ); ?>
  541.                             </ul>
  542.                         </div>
  543.                     </div>
  544.                 </nav>
  545.             </header>
  546.             <?php
  547.             return ob_get_clean();
  548.         }
  549.  
  550.         /**
  551.          * prints the navbar search on the top
  552.          *
  553.          * @return null
  554.          */
  555.         function search()
  556.         {
  557.             $search = $this->content['search'];
  558.  
  559.             $this->output(
  560.                     '<form class="search-form" role="form" ' . $search['form_tags'] . '>',
  561.                     @$search['form_extra']
  562.             );
  563.  
  564.             $this->search_field( $search );
  565.             // $this->search_button($search);
  566.  
  567.             $this->output(
  568.                     '</form>'
  569.             );
  570.         }
  571.  
  572.         /**
  573.          * prints the search field
  574.          *
  575.          * @param  array $search
  576.          *
  577.          * @return null
  578.          */
  579.         function search_field( $search )
  580.         {
  581.             $this->output(
  582.                     '<div class="input-group">',
  583.                     '<input type="text" ' . $search['field_tags'] . ' value="' . @$search['value'] . '" class="qa-search-field form-control" placeholder="' . $search['button_label'] . '"/>' );
  584.             $this->search_button( $search );
  585.             $this->output( '</div>' );
  586.         }
  587.  
  588.         public function form_password( $field, $style )
  589.         {
  590.             $this->output( '<input ' . @$field['tags'] . ' type="password" value="' . @$field['value'] . '" class="qa-form-' . $style . '-text form-control"/>' );
  591.         }
  592.  
  593.         public function form_number( $field, $style )
  594.         {
  595.             $this->output( '<input ' . @$field['tags'] . ' type="text" value="' . @$field['value'] . '" class="qa-form-' . $style . '-number form-control"/>' );
  596.         }
  597.  
  598.  
  599.         public function form_text_single_row( $field, $style )
  600.         {
  601.             $this->output( '<input ' . @$field['tags'] . ' type="text" value="' . @$field['value'] . '" class="qa-form-' . $style . '-text form-control"/>' );
  602.         }
  603.  
  604.         public function form_text_multi_row( $field, $style )
  605.         {
  606.             $this->output( '<textarea ' . @$field['tags'] . ' rows="' . (int) $field['rows'] . '" cols="40" class="qa-form-' . $style . '-text  form-control">' . @$field['value'] . '</textarea>' );
  607.         }
  608.  
  609.         /**
  610.          * Output a <select> element. The $field array may contain the following keys:
  611.          *   options: (required) a key-value array containing all the options in the select.
  612.          *   tags: any attributes to be added to the select.
  613.          *   value: the selected value from the 'options' parameter.
  614.          *   match_by: whether to match the 'value' (default) or 'key' of each option to determine if it is to be selected.
  615.          */
  616.         public function form_select( $field, $style )
  617.         {
  618.             $this->output( '<select ' . ( isset( $field['tags'] ) ? $field['tags'] : '' ) . ' class="qa-form-' . $style . '-select form-control">' );
  619.  
  620.             // Only match by key if it is explicitly specified. Otherwise, for backwards compatibility, match by value
  621.             $matchbykey = isset( $field['match_by'] ) && $field['match_by'] === 'key';
  622.  
  623.             foreach ( $field['options'] as $key => $value ) {
  624.                 $selected = isset( $field['value'] ) && (
  625.                                 ( $matchbykey && $key === $field['value'] ) ||
  626.                                 ( !$matchbykey && $value === $field['value'] )
  627.                         );
  628.                 $this->output( '<option value="' . $key . '"' . ( $selected ? ' selected' : '' ) . '>' . $value . '</option>' );
  629.             }
  630.  
  631.             $this->output( '</select>' );
  632.         }
  633.  
  634.         public function form_select_radio( $field, $style )
  635.         {
  636.             $radios = 0;
  637.  
  638.             foreach ( $field['options'] as $tag => $value ) {
  639.                 if ( $radios++ )
  640.                     $this->output( '<br/>' );
  641.  
  642.                 $this->output( '<input ' . @$field['tags'] . ' type="radio" value="' . $tag . '"' . ( ( $value == @$field['value'] ) ? ' checked' : '' ) . ' class="qa-form-' . $style . '-radio"/> ' . $value );
  643.             }
  644.         }
  645.  
  646.         /**
  647.          * prints the aearch button
  648.          *
  649.          * @param  array $search
  650.          *
  651.          * @return null
  652.          */
  653.         function search_button( $search )
  654.         {
  655.             $this->output( '<span class="input-group-btn">' );
  656.             $this->output( '<button type="submit" value="" class="btn qa-search-button" ><span class="fa fa-search"></span></button>' );
  657.             $this->output( '</span>' );
  658.         }
  659.  
  660.         /**
  661.          * prints the drop down for the user
  662.          *
  663.          */
  664.         function donut_user_drop_down()
  665.         {
  666.             if ( qa_is_logged_in() ) {
  667.                 require_once DONUT_THEME_BASE_DIR . '/templates/user-loggedin-drop-down.php';
  668.             } else {
  669.                 require_once DONUT_THEME_BASE_DIR . '/templates/user-login-drop-down.php';
  670.             }
  671.         }
  672.  
  673.         /**
  674.          * grabs the sub-nav links for the navigation items
  675.          *
  676.          * @param  array $navigation navigation links
  677.          *
  678.          * @return null
  679.          */
  680.         function donut_nav_bar_main_links( $navigation )
  681.         {
  682.             if ( count( $navigation ) ) {
  683.                 foreach ( $navigation as $key => $nav_item ) {
  684.                     $this->donut_nav_bar_item( $nav_item );
  685.                 }
  686.             }
  687.         }
  688.  
  689.         /**
  690.          * Prints the drop down menu
  691.          *
  692.          * @param  array $nav_item      the navigation item
  693.          * @param  array $sub_nav_items sub-nav items to be displayed
  694.          *
  695.          * @return null
  696.          */
  697.         function donut_nav_bar_drop_down( $nav_item, $sub_nav_items )
  698.         {
  699.             $class = ( !!@$nav_item['selected'] ) ? 'active' : '';
  700.  
  701.             if ( !empty( $sub_nav_items ) && count( $sub_nav_items ) ) {
  702.                 $nav_item['class'] = "dropdown-split-left";
  703.                 $this->donut_nav_bar_item( $nav_item );
  704.                 $this->output( '<li class="dropdown dropdown-split-right hidden-xs ' . $class . '">' );
  705.                 $this->output( '<a href="#" class="dropdown-toggle transparent" data-toggle="dropdown"><i class="fa fa-caret-down"></i></a>' );
  706.                 $this->output( '<ul class="dropdown-menu" role="menu">' );
  707.                 foreach ( $sub_nav_items as $key => $sub_nav_item ) {
  708.                     $this->donut_nav_bar_item( $sub_nav_item );
  709.                 }
  710.                 $this->output( '</ul>' );
  711.                 $this->output( '</li>' );
  712.             } else {
  713.                 $this->donut_nav_bar_item( $nav_item );
  714.             }
  715.         }
  716.  
  717.         /**
  718.          * prints a single nav-bar item
  719.          *
  720.          * @param  array $nav_item navigation item
  721.          *
  722.          * @return null
  723.          */
  724.         function donut_nav_bar_item( $nav_item )
  725.         {
  726.             $class = ( !!@$nav_item['class'] ) ? $nav_item['class'] . ' ' : '';
  727.             $class .= ( !!@$nav_item['selected'] ) ? 'active' : '';
  728.  
  729.             if ( !empty( $class ) ) {
  730.                 $class = 'class="' . $class . '"';
  731.             }
  732.  
  733.             $icon = ( !!@$nav_item['icon'] ) ? donut_get_fa_icon( @$nav_item['icon'] ) : '';
  734.  
  735.             $this->output( '<li ' . $class . '><a href="' . $nav_item['url'] . '">' . $icon . $nav_item['label'] . '</a></li>' );
  736.         }
  737.  
  738.         function page_links_item( $page_link )
  739.         {
  740.             $active_class = ( @$page_link['type'] === 'this' ) ? ' active' : '';
  741.             $disabled_class = ( @$page_link['type'] === 'ellipsis' ) ? ' disabled' : '';
  742.             $this->output( '<li class="qa-page-links-item' . $active_class . $disabled_class . '">' );
  743.             $this->page_link_content( $page_link );
  744.             $this->output( '</li>' );
  745.         }
  746.  
  747.         function a_selection( $post )
  748.         {
  749.             $this->output( '<div class="qa-a-selection">' );
  750.  
  751.             if ( isset( $post['select_tags'] ) )
  752.                 $this->post_hover_button( $post, 'select_tags', '', 'qa-a-select' );
  753.             elseif ( isset( $post['unselect_tags'] ) )
  754.                 $this->post_hover_button( $post, 'unselect_tags', '', 'qa-a-unselect' );
  755.             elseif ( $post['selected'] )
  756.                 $this->output( '<div class="qa-a-selected"> <span class="fa fa-check"></span> </div>' );
  757.  
  758.             if ( isset( $post['select_text'] ) )
  759.                 $this->output( '<div class="qa-a-selected-text">' . @$post['select_text'] . '</div>' );
  760.  
  761.             $this->output( '</div>' );
  762.         }
  763.  
  764.         function post_hover_button( $post, $element, $value, $class )
  765.         {
  766.             if ( isset( $post[$element] ) ) {
  767.                 $icon = donut_get_voting_icon( $element );
  768.                 $this->output( '<button ' . $post[$element] . ' type="submit" value="' . $value . '" class="' . $class . '-button"/> ' . $icon . '</button>' );
  769.             }
  770.         }
  771.  
  772.         public function q_list_item( $q_item )
  773.         {
  774.             $this->output( '<div class="qa-q-list-item row' . rtrim( ' ' . @$q_item['classes'] ) . '" ' . @$q_item['tags'] . '>' );
  775.  
  776.             $this->q_item_stats( $q_item );
  777.             //$this->q_item_avatar( $q_item );
  778.             $this->q_item_main( $q_item );
  779.             $this->q_item_clear();
  780.  
  781.             $this->output( '</div> <!-- END qa-q-list-item -->', '' );
  782.         }
  783.  
  784.         function q_item_avatar( $q_item )
  785.         {
  786.             $avatar = donut_get_post_avatar( $q_item, 60 );
  787.             $this->output( '<div class="qa-q-item-avatar-warp">' );
  788.             $this->output( $avatar );
  789.             $this->output( '</div>' );
  790.         }
  791.  
  792.         /**
  793.          * add view count to question list
  794.          *
  795.          * @param  array $q_item
  796.          *
  797.          * @return null
  798.          */
  799.         function q_item_stats( $q_item )
  800.         {
  801.             $this->output( '<div class="qa-q-item-stats">' );
  802.  
  803.             $this->voting( $q_item );
  804.             $this->a_count( $q_item );
  805.  
  806.             $this->output( '</div>' );
  807.         }
  808.  
  809.         function post_meta( $post, $class, $prefix = null, $separator = '<br/>' )
  810.         {
  811.             $this->output( '<span class="' . $class . '-meta">' );
  812.  
  813.             if ( isset( $prefix ) )
  814.                 $this->output( $prefix );
  815.  
  816.             $order = explode( '^', @$post['meta_order'] );
  817.  
  818.             foreach ( $order as $element )
  819.                 switch ( $element ) {
  820.                     case 'what':
  821.                         $this->post_meta_what( $post, $class );
  822.                         break;
  823.  
  824.                     case 'when':
  825.                         $this->post_meta_when( $post, $class );
  826.                         break;
  827.  
  828.                     case 'where':
  829.                         $this->post_meta_where( $post, $class );
  830.                         break;
  831.  
  832.                     case 'who':
  833.                         $this->post_meta_who( $post, $class );
  834.                         break;
  835.                 }
  836.  
  837.             $this->post_meta_flags( $post, $class );
  838.  
  839.             if ( !empty( $post['what_2'] ) ) {
  840.                 $this->output( $separator );
  841.  
  842.                 foreach ( $order as $element )
  843.                     switch ( $element ) {
  844.                         case 'what':
  845.                             $this->output( '<span class="' . $class . '-what">' . $post['what_2'] . '</span>' );
  846.                             break;
  847.  
  848.                         case 'when':
  849.                             $this->output_split( @$post['when_2'], $class . '-when' );
  850.                             break;
  851.  
  852.                         case 'who':
  853.                             $this->output_split( @$post['who_2'], $class . '-who' );
  854.                             break;
  855.                     }
  856.             }
  857.             $this->donut_view_count( $post );
  858.             $this->output( '</span>' );
  859.         }
  860.  
  861.         /**
  862.          * prints the view count
  863.          *
  864.          * @param  array
  865.          *
  866.          * @return null
  867.          */
  868.         function donut_view_count( $post )
  869.         {
  870.             if ( !empty( $post['views'] ) ) {
  871.                 $this->output( '<span class="qa-q-item-view-count">' );
  872.                 $this->output( ' | <i class="fa fa-eye"></i>' );
  873.                 $this->output_split( @$post['views'], 'q-item-view' );
  874.                 $this->output( '</span>' );
  875.             }
  876.         }
  877.  
  878.         function view_count( $q_item ) // prevent display of view count in the usual place
  879.         {
  880.             if ( isset($q_item['content']) )
  881.                 parent::view_count( $q_item );
  882.         }
  883.  
  884.         function post_disabled_button( $post, $element, $value, $class )
  885.         {
  886.             if ( isset( $post[$element] ) ) {
  887.                 $icon = donut_get_voting_icon( $element );
  888.                 $this->output( '<button ' . $post[$element] . ' type="submit" value="' . $value . '" class="' . $class . '-disabled" disabled="disabled"/> ' . $icon . '</button>' );
  889.             }
  890.         }
  891.  
  892.         function form_button_data( $button, $key, $style )
  893.         {
  894.             $baseclass = 'qa-form-' . $style . '-button qa-form-' . $style . '-button-' . $key;
  895.  
  896.             $this->output( '<button' . rtrim( ' ' . @$button['tags'] ) . ' title="' . @$button['popup'] . '" type="submit"' .
  897.                     ( isset( $style ) ? ( ' class="' . $baseclass . '"' ) : '' ) . '>' . @$button['label'] . '</button>' );
  898.         }
  899.  
  900.         /**
  901.          * prints the favorite button
  902.          *
  903.          * @param  array $tags parameters
  904.          * @param  [type] $class class
  905.          *
  906.          * @return null
  907.          */
  908.         function favorite_button( $tags, $class )
  909.         {
  910.             if ( isset( $tags ) ) {
  911.                 $icon = donut_get_fa_icon( 'heart' );
  912.                 $this->output( '<button ' . $tags . ' type="submit" value="" class="' . $class . '-button"/> ' . $icon . '</button>' );
  913.             }
  914.         }
  915.  
  916.         /**
  917.          * Attribution link for the theme which adds the authors name
  918.          *
  919.          * @return null
  920.          */
  921.         function attribution()
  922.         {
  923.             if ( qa_opt( 'donut_show_social_links_at_footer' ) ) {
  924.                 $this->footer_social_links();
  925.             }
  926.  
  927.             $this->output( '<div class="footer-bottom">' );
  928.             $this->donut_attribution();
  929.             parent::attribution();
  930.  
  931.             if ( qa_opt( 'donut_show_copyright_at_footer' ) ) {
  932.                 $this->donut_copyright();
  933.             }
  934.  
  935.             $this->output( '</div>' );
  936.         }
  937.  
  938.         /**
  939.          * beautifies the default waiting template with a font aswome icon
  940.          *
  941.          * @return null
  942.          */
  943.         function waiting_template()
  944.         {
  945.             $this->output( '<span id="qa-waiting-template" class="qa-waiting fa fa-spinner fa-spin"></span>' );
  946.         }
  947.  
  948.         /**
  949.          * beautifies the default notice
  950.          *
  951.          * @param  array $notice notice parameters
  952.          *
  953.          * @return null
  954.          */
  955.         function notice( $notice )
  956.         {
  957.             $this->output( '<div class="qa-notice alert alert-info text-center alert-dismissible" role="alert" id="' . $notice['id'] . '">' );
  958.  
  959.             if ( isset( $notice['form_tags'] ) )
  960.                 $this->output( '<form ' . $notice['form_tags'] . '>' );
  961.  
  962.             $this->output( '<button ' . $notice['close_tags'] . ' type="submit" class="close" data-dismiss="alert"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>' );
  963.  
  964.             $this->output_raw( $notice['content'] );
  965.  
  966.  
  967.             if ( isset( $notice['form_tags'] ) ) {
  968.                 $this->form_hidden_elements( @$notice['form_hidden'] );
  969.                 $this->output( '</form>' );
  970.             }
  971.  
  972.             $this->output( '</div>' );
  973.         }
  974.  
  975.         public function error( $error )
  976.         {
  977.             if ( strlen( $error ) ) {
  978.                 $this->output(
  979.                         '<div class="donut-error alert alert-dismissible" role="alert">',
  980.                         $error,
  981.                         '<button class="close" data-dismiss="alert"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>',
  982.                         '</div>'
  983.                 );
  984.             }
  985.         }
  986.  
  987.         /**
  988.          * prints the favicon icon
  989.          *
  990.          * @return  null
  991.          */
  992.         function donut_favicon()
  993.         {
  994.             $this->output_raw( '<link rel="shortcut icon" href="favicon.ico">' );
  995.         }
  996.  
  997.         function ranking( $ranking )
  998.         {
  999.             $class = ( @$ranking['type'] == 'users' ) ? 'qa-top-users' : 'qa-top-tags';
  1000.             $item_count = min( $ranking['rows'], count( $ranking['items'] ) );
  1001.  
  1002.             if ( @$ranking['type'] == 'users' ) {
  1003.  
  1004.  
  1005.                 if ( count( $ranking['items'] ) ) {
  1006.                     $this->output( '<div class="page-users-list clearfix"><div class="row">' );
  1007.                     $columns = qa_opt( 'columns_users' );
  1008.                     $pagesize = qa_opt( 'page_size_users' );
  1009.                     $start = qa_get_start();
  1010.                     $users = qa_db_select_with_pending( qa_db_top_users_selectspec( $start, qa_opt_if_loaded( 'page_size_users' ) ) );
  1011.                     $users = array_slice( $users, 0, $pagesize );
  1012.                     $usershtml = qa_userids_handles_html( $users );
  1013.  
  1014.                     foreach ( $ranking['items'] as $user ) {
  1015.                         $this->output( '<div class="user-box col-sm-' . ceil( 12 / $columns ) . ' col-xs-12">' );
  1016.                         $user_raw = !empty( $user['raw'] ) ? $user['raw'] : $user;
  1017.                         $handle = @$user_raw['handle'];
  1018.                         $handle_html = @$usershtml[$user_raw['userid']];
  1019.  
  1020.                         if ( defined( 'QA_WORDPRESS_INTEGRATE_PATH' ) ) {
  1021.                             $level_html = $user['score'];
  1022.                             unset( $user['score'] );
  1023.                         } else {
  1024.                             if ( is_numeric( $user['score'] ) ) {
  1025.                                 $user_level = donut_get_user_level( $user_raw['userid'] );
  1026.                                 $level_html = qa_user_level_string( $user_level );
  1027.                             } else {
  1028.                                 $level_html = $user['score'];
  1029.                                 unset( $user['score'] );
  1030.                             }
  1031.                         }
  1032.  
  1033.                         if ( empty( $handle_html ) ) {
  1034.                             $handle_html = $user['label'];
  1035.                         }
  1036.  
  1037.                         $avatar = ( QA_FINAL_EXTERNAL_USERS
  1038.                                 ? qa_get_external_avatar_html( @$user_raw['userid'], qa_opt( 'avatar_users_size' ), true )
  1039.                                 : qa_get_user_avatar_html( @$user_raw['flags'], @$user_raw['email'], @$user_raw['handle'],
  1040.                                         @$user_raw['avatarblobid'], @$user_raw['avatarwidth'], @$user_raw['avatarheight'], 70, true )
  1041.                         );
  1042.  
  1043.                         if ( isset( $user['score'] ) ) {
  1044.                             $userpoints = $user['score'];
  1045.                             $pointshtml = ( $userpoints === 1 ) ? qa_lang_html_sub( 'main/1_point', '1', '1' )
  1046.                                     : qa_lang_html_sub( 'main/x_points', qa_html( $userpoints ) );
  1047.                             if ( !empty( $pointshtml ) ) {
  1048.                                 $pointshtml = '<p class="score">' . $pointshtml . '</p>';
  1049.                             }
  1050.                         }
  1051.  
  1052.                         $this->output( '
  1053.                                 <div class="user-box-inner">
  1054.                                     <div class="user-avatar">
  1055.                                         ' . $avatar . '
  1056.                                     </div>
  1057.                                     <div class="user-data">
  1058.                                         ' . $handle_html . '
  1059.                                         <div class="user-level">
  1060.                                             ' . $level_html . '
  1061.                                         </div>
  1062.                                         <div class="counts clearfix">
  1063.                                             ' . @$pointshtml . '
  1064.                                         </div>
  1065.                                 </div>' );
  1066.  
  1067.                         if ( qa_opt( 'badge_active' ) && function_exists( 'qa_get_badge_list' ) )
  1068.                             $this->output( '<div class="badge-list">' . donut_user_badge( $handle ) . '</div>' );
  1069.  
  1070.                         $this->output( '</div>' );
  1071.                         $this->output( '</div>' );
  1072.  
  1073.                     }
  1074.                     $this->output( '</div>' );
  1075.                     $this->output( '</div>' );
  1076.                 } else {
  1077.                     $title = isset( $this->content['ranking_users']['title'] ) ? $this->content['ranking_users']['title'] : @$this->content['title'];
  1078.                     $this->output( '
  1079.                                 <div class="no-items">
  1080.                                     <div class="alert alert-info"><span class="fa fa-warning"></span> ' . $title . '</div>
  1081.                                 </div>' );
  1082.                 }
  1083.  
  1084.  
  1085.             } elseif ( @$ranking['type'] == 'tags' ) {
  1086.  
  1087.                 if ( count( $ranking['items'] ) ) {
  1088.                     $this->output( '<div id="tags-list" class="row ' . $class . '">' );
  1089.  
  1090.                     $columns = qa_opt( 'columns_tags' );
  1091.  
  1092.                     for ( $column = 0 ; $column < $columns ; $column++ ) {
  1093.                         $this->set_context( 'ranking_column', $column );
  1094.                         $this->output( '<div class="col-md-' . ceil( 12 / $columns ) . ' col-xs-12" >' );
  1095.                         $this->output( '<ul class="donut-tags-list">' );
  1096.  
  1097.                         for ( $row = 0 ; $row < $item_count ; $row++ ) {
  1098.                             $this->set_context( 'ranking_row', $row );
  1099.                             $this->donut_tags_item( @$ranking['items'][$column * $item_count + $row], $class, $column > 0 );
  1100.                         }
  1101.  
  1102.                         $this->clear_context( 'ranking_column' );
  1103.  
  1104.                         $this->output( '</ul>' );
  1105.                         $this->output( '</div>' );
  1106.                     }
  1107.  
  1108.                     $this->clear_context( 'ranking_row' );
  1109.  
  1110.                     $this->output( '</div>' );
  1111.                 } else {
  1112.                     $this->output( '
  1113.                         <div class="no-items">
  1114.                         <div class="alert alert-info"><span class="fa fa-warning"></span> ' . $this->content['ranking_tags']['title'] . '</div>
  1115.                         </div>' );
  1116.                 }
  1117.  
  1118.             } else {
  1119.                 parent::ranking( $ranking );
  1120.             }
  1121.         }
  1122.  
  1123.         function donut_tags_item( $item, $class, $spacer )
  1124.         {
  1125.             $content = qa_db_read_one_value( qa_db_query_sub( "SELECT ^tagmetas.content FROM ^tagmetas WHERE ^tagmetas.tag =$ ", strip_tags( $item['label'] ) ), true );
  1126.  
  1127.             if ( isset( $item ) )
  1128.                 $this->output(
  1129.                         '<li class="tag-item">',
  1130.                         '<div class="tag-head clearfix">',
  1131.                         '<span> ' . $item['count'] . ' &#215;</span>',
  1132.                         '<div class="qa-tags-rank-tag-item">',
  1133.                         $item['label'],
  1134.                         '</div>',
  1135.                         '</div>'
  1136.                 );
  1137.             if ( !empty( $content ) ) {
  1138.                 $this->output( '<p class="desc">',
  1139.                         $this->truncate( $content, 150 ),
  1140.                         '</p>' );
  1141.             }
  1142.             $this->output( '</li>' );
  1143.         }
  1144.  
  1145.         function truncate( $string, $limit, $pad = "..." )
  1146.         {
  1147.             if ( strlen( $string ) <= $limit )
  1148.                 return $string;
  1149.             else {
  1150.                 $text = $string . ' ';
  1151.                 $text = substr( $text, 0, $limit );
  1152.                 $text = substr( $text, 0, strrpos( $text, ' ' ) );
  1153.  
  1154.                 return $text . $pad;
  1155.             }
  1156.         }
  1157.  
  1158.         private function donut_breadcrumb()
  1159.         {
  1160.             if ( class_exists( 'Ami_Breadcrumb' ) && qa_opt( 'donut_show_breadcrumbs' ) ) {
  1161.                 if ( !$this->is_home() && $this->template !== 'admin' ) {
  1162.                     $args = array(
  1163.                             'themeobject' => $this,
  1164.                             'content'     => $this->content,
  1165.                             'template'    => $this->template,
  1166.                             'request'     => qa_request(),
  1167.                     );
  1168.                     $breadcrumb = new Ami_Breadcrumb( $args );
  1169.                     $this->output( '<div class="donut-breadcrumb">' );
  1170.                     $breadcrumb->generate();
  1171.                     $this->output( '</div>' );
  1172.                 }
  1173.                 /*TODO: unset the breadcrumb if it exists*/
  1174.             }
  1175.         }
  1176.  
  1177.         public function message_content( $message )
  1178.         {
  1179.             if ( !empty( $message['content'] ) ) {
  1180.                 $this->output( '<div class="qa-message-content-wrapper">' );
  1181.                 $this->output( '<div class="qa-message-content">' );
  1182.                 $this->output_raw( $message['content'] );
  1183.                 $this->output( '</div>' );
  1184.                 $this->output( '</div>' );
  1185.             }
  1186.         }
  1187.  
  1188.         public function vote_clear()
  1189.         {
  1190.             $this->output(
  1191.                     '<div class="qa-vote-clear clearfix">',
  1192.                     '</div>'
  1193.             );
  1194.         }
  1195.  
  1196.         public function page_links_clear()
  1197.         {
  1198.             $this->output(
  1199.                     '<div class="qa-page-links-clear clearfix">',
  1200.                     '</div>'
  1201.             );
  1202.         }
  1203.  
  1204.         public function q_view_clear()
  1205.         {
  1206.             $this->output(
  1207.                     '<div class="qa-q-view-clear clearfix">',
  1208.                     '</div>'
  1209.             );
  1210.         }
  1211.  
  1212.         public function a_item_clear()
  1213.         {
  1214.             $this->output(
  1215.                     '<div class="qa-a-item-clear clearfix">',
  1216.                     '</div>'
  1217.             );
  1218.         }
  1219.  
  1220.         public function c_item_clear()
  1221.         {
  1222.             $this->output(
  1223.                     '<div class="qa-c-item-clear clearfix">',
  1224.                     '</div>'
  1225.             );
  1226.         }
  1227.  
  1228.         public function nav_clear( $navtype )
  1229.         {
  1230.             $this->output(
  1231.                     '<div class="qa-nav-' . $navtype . '-clear clearfix">',
  1232.                     '</div>'
  1233.             );
  1234.         }
  1235.  
  1236.         public function header_clear()
  1237.         {
  1238.             $this->output(
  1239.                     '<div class="qa-header-clear clearfix">',
  1240.                     '</div>'
  1241.             );
  1242.         }
  1243.  
  1244.         public function footer_clear()
  1245.         {
  1246.             $this->output(
  1247.                     '<div class="qa-footer-clear clearfix">',
  1248.                     '</div>'
  1249.             );
  1250.         }
  1251.  
  1252.         public function q_item_clear()
  1253.         {
  1254.             $this->output(
  1255.                     '<div class="qa-q-item-clear clearfix">',
  1256.                     '</div>'
  1257.             );
  1258.         }
  1259.  
  1260.         /**
  1261.          * @return array
  1262.          */
  1263.         private function donut_hide_sidebar_for_template()
  1264.         {
  1265.             return array(
  1266.                     'users',
  1267.                 /*'tags', 'categories' ,*/
  1268.                     'admin', 'user', 'account',
  1269.                     'favorites', 'user-wall', 'messages',
  1270.                     'user-activity', 'user-questions', 'user-answers' );
  1271.         }
  1272.  
  1273.         /**
  1274.          * @return bool
  1275.          */
  1276.         private function donut_do_hide_sidebar()
  1277.         {
  1278.             return in_array( $this->template, $this->donut_hide_sidebar_for_template() );
  1279.         }
  1280.  
  1281.         function donut_page_has_feed()
  1282.         {
  1283.             return !empty( $this->content['feed'] );
  1284.         }
  1285.  
  1286.         function donut_page_has_favorite()
  1287.         {
  1288.             return isset( $this->content['favorite'] );
  1289.         }
  1290.  
  1291.         /**
  1292.          * =================================================
  1293.          * Check if the current page is home page or not
  1294.          *
  1295.          * @return bool
  1296.          * =================================================
  1297.          */
  1298.         public function is_home()
  1299.         {
  1300.             return empty( $this->request );
  1301.         }
  1302.  
  1303.         public function donut_site_header()
  1304.         {
  1305.             if ( $this->is_home() && qa_opt( 'donut_show_home_page_banner' ) ) {
  1306.                 //check if user closed the header intentionally
  1307.                 $user_hidden = qa_opt( 'donut_banner_closable' ) ?
  1308.                         @$_COOKIE['donut_hide_site_header'] : 'no';
  1309.  
  1310.                 if ( $user_hidden !== 'yes' )
  1311.                     donut_include_template( 'site-header.php' );
  1312.             }
  1313.         }
  1314.  
  1315.         public function suggest_next()
  1316.         {
  1317.             $suggest = @$this->content['suggest_next'];
  1318.  
  1319.             if ( !empty( $suggest ) ) {
  1320.                 $this->output( '<div class="qa-suggest-next col-xs-12 text-center clearfix alert">' );
  1321.                 $this->output( $suggest );
  1322.                 $this->output( '</div>' );
  1323.             }
  1324.         }
  1325.  
  1326.         private function donut_site_stats_bottom()
  1327.         {
  1328.             donut_include_template( 'site-stats-bottom.php' );
  1329.         }
  1330.  
  1331.         /**
  1332.          * Attribution for Donut theme
  1333.          * Please do not remove this as you are using this for free .
  1334.          * I will appreciate if you keep this on your site
  1335.          */
  1336.         private function donut_attribution()
  1337.         {
  1338.             $this->output(
  1339.                     '<div class="qa-attribution">',
  1340.                     '<!--a href="https://github.com/amiyasahu/Donut">Donut Theme</a> <span class="fa fa-code"></span> with <span class="fa fa-heart"></span> by <a href="http://amiyasahu.com">Amiya Sahu</a-->',
  1341.                     '</div>'
  1342.             );
  1343.         }
  1344.  
  1345.         private function donut_copyright()
  1346.         {
  1347.             $this->output(
  1348.                     '<div class="donut-copyright">',
  1349.                     '<span class="fa fa-copyright"></span>',
  1350.                     qa_opt( 'donut_copyright_text' ),
  1351.                     '</div>'
  1352.             );
  1353.         }
  1354.  
  1355.         private function footer_social_links()
  1356.         {
  1357.             $this->output( '<div class="footer-social">' );
  1358.             $social_links = donut_generate_social_links();
  1359.             $this->output( '<ul>' );
  1360.             foreach ( $social_links as $key => $value ) {
  1361.                 $this->output( '<li>' );
  1362.                 $this->output( donut_get_social_link( $value, true ) );
  1363.                 $this->output( '</li>' );
  1364.             }
  1365.             $this->output( '</ul>' );
  1366.  
  1367.             $this->output( '</div>' );
  1368.         }
  1369.  
  1370.         public function widgets( $region, $place )
  1371.             /*
  1372.                 Output the widgets (as provided in $this->content['widgets']) for $region and $place
  1373.             */
  1374.         {
  1375.             if ( count( @$this->content['widgets'][$region][$place] ) ) {
  1376.                 $col = ( $region == 'full' ) ? ' col-xs-12' : '';
  1377.  
  1378.                 $this->output( '<div class="qa-widgets-' . $region . ' qa-widgets-' . $region . '-' . $place . $col . '">' );
  1379.  
  1380.                 foreach ( $this->content['widgets'][$region][$place] as $module ) {
  1381.                     $this->output( '<div class="qa-widget-' . $region . ' qa-widget-' . $region . '-' . $place . '">' );
  1382.                     $module->output_widget( $region, $place, $this, $this->template, $this->request, $this->content );
  1383.                     $this->output( '</div>' );
  1384.                 }
  1385.  
  1386.                 $this->output( '</div>', '' );
  1387.             }
  1388.         }
  1389.  
  1390.         public function post_tags( $post, $class )
  1391.         {
  1392.             if ( !empty( $post['q_tags'] ) ) {
  1393.                 $this->output( '<div class="' . $class . '-tags clearfix">' );
  1394.                 $this->post_tag_list( $post, $class );
  1395.                 $this->output( '</div>' );
  1396.             }
  1397.         }
  1398.  
  1399.         public function q_view_buttons( $q_view )
  1400.         {
  1401.             if ( qa_opt( 'donut_show_collapsible_btns' ) ) {
  1402.                 if ( !empty( $q_view['form'] ) ) {
  1403.                     $q_view_temp = $q_view;
  1404.                     $allowed_main_btns = array( 'answer', 'comment' );
  1405.                     $q_view_temp['form']['buttons'] = $this->donut_divide_array( $q_view['form']['buttons'], $allowed_main_btns );
  1406.                     $this->output( '<div class="qa-q-view-buttons clearfix">' );
  1407.                     $this->output( '<div class="default-buttons pull-left">' );
  1408.                     $this->form( $q_view['form'] );
  1409.                     $this->output( '</div>' );
  1410.                     $this->donut_generate_action_button( $q_view_temp );
  1411.                     $this->output( '</div>' );
  1412.                 }
  1413.             } else {
  1414.                 parent::q_view_buttons( $q_view );
  1415.             }
  1416.         }
  1417.  
  1418.         public function a_item_buttons( $a_item )
  1419.         {
  1420.             if ( qa_opt( 'donut_show_collapsible_btns' ) ) {
  1421.                 if ( !empty( $a_item['form'] ) ) {
  1422.                     $a_item_temp = $a_item;
  1423.                     $allowed_main_btns = array( 'comment' );
  1424.                     $a_item_temp['form']['buttons'] = $this->donut_divide_array( $a_item['form']['buttons'], $allowed_main_btns );
  1425.                     $this->output( '<div class="qa-a-item-buttons clearfix">' );
  1426.                     $this->output( '<div class="default-buttons pull-left">' );
  1427.                     $this->form( $a_item['form'] );
  1428.                     $this->output( '</div>' );
  1429.                     $this->donut_generate_action_button( $a_item_temp );
  1430.                     $this->output( '</div>' );
  1431.                 }
  1432.             } else {
  1433.                 parent::a_item_buttons( $a_item );
  1434.             }
  1435.         }
  1436.  
  1437.         public function c_item_buttons( $c_item )
  1438.         {
  1439.             if ( qa_opt( 'donut_show_collapsible_btns' ) ) {
  1440.                 if ( !empty( $c_item['form'] ) ) {
  1441.                     $this->output( '<div class="qa-c-item-buttons collapsed">' );
  1442.                     $this->donut_generate_action_button( $c_item );
  1443.                     $this->output( '</div>' );
  1444.                 }
  1445.             } else {
  1446.                 parent::c_item_buttons( $c_item );
  1447.             }
  1448.         }
  1449.  
  1450.         private function donut_generate_action_button( $action_view, $btn_style = 'vertical' )
  1451.         {
  1452.             $this->output( '<div class="action-buttons pull-right">' );
  1453.             $this->output( '<div class="btn-group">' );
  1454.             $this->output( '<button type="button" class="qa-form-light-button dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" title="More actions">' );
  1455.             $this->output( '<span class="glyphicon glyphicon-option-' . $btn_style . '"></span>' );
  1456.             $this->output( '</button>' );
  1457.             $this->donut_generate_action_dropdown( $action_view['form'] );
  1458.             $this->output( '</div>' );
  1459.             $this->output( '</div>' );
  1460.         }
  1461.  
  1462.         function donut_generate_action_dropdown( $form )
  1463.         {
  1464.             if ( !empty( $form['buttons'] ) ) {
  1465.                 $this->output( '<ul class="dropdown-menu action-buttons-dropdown">' );
  1466.                 foreach ( $form['buttons'] as $key => $btn ) {
  1467.                     $this->output( '<li>' );
  1468.                     $this->output( $this->form_button_data( $btn, $key, @$form['style'] ) );
  1469.                     $this->output( '</li>' );
  1470.                 }
  1471.                 $this->output( '</ul>' );
  1472.             }
  1473.         }
  1474.  
  1475.         function donut_divide_array( &$original, $allowed_keys )
  1476.         {
  1477.             if ( count( $original ) && count( $allowed_keys ) ) {
  1478.                 $copy = $original;
  1479.  
  1480.                 foreach ( $original as $key => $btn ) {
  1481.                     if ( !in_array( $key, $allowed_keys ) ) {
  1482.                         unset( $original[$key] );
  1483.                     }
  1484.                 }
  1485.  
  1486.                 foreach ( $copy as $key => $btn ) {
  1487.                     if ( in_array( $key, $allowed_keys ) ) {
  1488.                         unset( $copy[$key] );
  1489.                     }
  1490.                 }
  1491.  
  1492.                 return $copy;
  1493.             }
  1494.  
  1495.             return $original;
  1496.         }
  1497.  
  1498.     }
  1499. /*
  1500.     Omit PHP closing tag to help avoid accidental output
  1501. */
RAW Paste Data