e107inc/e107

View on GitHub
e107_plugins/download/handlers/download_class.php

Summary

Maintainability
A
30 mins
Test Coverage
F
10%
<?php
/*
 * e107 website system
 *
 * Copyright (C) 2008-2013 e107 Inc (e107.org)
 * Released under the terms and conditions of the
 * GNU General Public License (http://www.gnu.org/licenses/gpl.txt)
 *
 */

if (!e107::isInstalled('download')) { exit(); }

class download
{
    
    private $qry = array();
    
    private $orderOptions = array('download_id','download_datestamp','download_filesize','download_name','download_author','download_requested');
    
    private $templateHeader;
    private $templateFooter;

    private $subCategories = array();
    private $categories = array();
    private $template = array();
    private $sc = null; // shortcode object.
    private $rows = array();
    
    function __construct()
    {
                
        require_once(e_PLUGIN."download/download_shortcodes.php");
        
        if(deftrue('BOOTSTRAP')) // v2.x 
        {
            $this->templateHeader = e107::getTemplate('download','download','header');
            $this->templateFooter = e107::getTemplate('download','download','footer');
        }
        else 
        {
            $this->templateHeader = '';
            $this->templateFooter = '';
        }

        $pref = e107::getPref();

    //    $catObj = new downloadCategory(varset($pref['download_subsub'],1),USERCLASS_LIST,null, varset($pref['download_incinfo'], false));
    //    $this->categories = $catObj->cat_tree;
        $this->loadCategories();


    }

    private function loadCategories()
    {
        $sql = e107::getDb();
        $data = $sql->retrieve("download_category", '*', 'ORDER BY download_category_order',true);

        foreach($data as $row)
        {

            $id = (int) $row['download_category_parent'];
            $sub= (int) $row['download_category_id'];

            $this->subCategories[$id][$sub] = $row;
            if(check_class($row['download_category_class']))
            {
                $this->categories[$sub] = $row;
            }

        }


        return $this;
    }

    private function getCategory($id)
    {
        return !empty($this->categories[$id]) ? $this->categories[$id] : false;

    }

    private function getParent($id)
    {
        $parent = $this->categories[$id]['download_category_parent'];
        return $this->getCategory($parent);
    }

    private function getChildren($parent)
    {
        return !empty($this->subCategories[$parent]) ? $this->subCategories[$parent] : false;
    }
    
    public function init()
    {

        $tp = e107::getParser();
        $pref = e107::getPref();
    
        $tmp = explode('.', e_QUERY);
        
        $order = str_replace("download_","", varset($pref['download_order'], 'id'));
                        
        // Set Defaults
        $this->qry['action']        = 'maincats';
        $this->qry['order']         = vartrue($order, 'datestamp');
        $this->qry['sort']            = vartrue($pref['download_sort'], 'desc');
        $this->qry['view']             = vartrue($pref['download_view'], 10);
        $this->qry['from']            = 0;
            
        // v2.x 
        if(!empty($_GET['action']))
        {
            $this->qry['action']     = (string) $_GET['action'];
            $this->qry['view']         = varset($_GET['view']) ? intval($_GET['view']) : $this->qry['view'];
            $this->qry['id']        = intval($_GET['id']);
            $this->qry['order']     = vartrue($_GET['order']) && in_array("download_".$_GET['order'],$this->orderOptions) ? $_GET['order'] : $this->qry['order'];
            $this->qry['sort']         = (varset($_GET['sort']) == 'asc') ? "asc" : 'desc';    
            $this->qry['from']        = varset($_GET['from'],0);

            if($this->qry['action'] == 'error')
            {
                $this->qry['error'] = intval($this->qry['id']);
            }
        }
        else // v1.x Legacy URL support. 
        {
            if (is_numeric($tmp[0]))    //legacy        // $tmp[0] at least must be valid
            {
                $parsed                 = preg_replace("#\W#", "", $tp->toDB($tmp[1]));
               $this->qry['action']     = varset($parsed,'list');
               $this->qry['id']         = intval($tmp[2]);
               $this->qry['view']         = intval($tmp[3]);
               $this->qry['order']         = preg_replace("#\W#", "", $tp->toDB($tmp[4]));
               $this->qry['sort']         = preg_replace("#\W#", "", $tp->toDB($tmp[5]));
               }
            elseif(!empty($tmp[1]))
               {
               $this->qry['action']     = preg_replace("#\W#", "", $tp->toDB($tmp[0]));
               $this->qry['id']         = intval($tmp[1]);
               $this->qry['error']        = intval(varset($tmp[2],0));
            }    
            
        }    
        
        // v1.x
        if(varset($_POST['view'])) 
        {
            $this->qry['view']         = varset($_POST['view']) ? intval($_POST['view']) : 10;
            $this->qry['order']     = varset($_POST['order']) && in_array("download_".$_POST['order'],$this->orderOptions) ? $_POST['order'] : 'datestamp';
            $this->qry['sort']         = (strtolower($_POST['sort']) == 'asc') ? "asc" : 'desc';    
        }    
        

    }  



    /**
     * Auto-detected loading of the appropriate headers/data.
     */
    public function load()
    {

        $pref = e107::getPref();

        switch($this->qry['action'])
        {
            case 'maincats':
                e107::canonical('download', 'index');
                e107::route('download/index');
            break;

            case "list":
                e107::route('download/category');
                $this->loadList();
                break;

            case "view":
                e107::route('download/item');
                $this->loadView();
                break;

            case "report":

                if(check_class($pref['download_reportbroken']))
                {
                    e107::route('download/report');
                    $this->loadReport();
                }
                break;
        /*
            case 'mirror':
            case 'error':

            break; */

        }


    }


    /**
     * Auto-detected Render of the appropriate download page. 
     */
    public function render()
    {
        
        $pref = e107::getPref();
        
        if($this->qry['action'] == 'maincats')
        {
            return $this->renderCategories();
        }
    
        if($this->qry['action'] == 'list')
        {
            return $this->renderList();
        }
        
        if($this->qry['action'] == 'view')
        {
            return $this->renderView();
        }
        
        if ($this->qry['action'] == "report" && check_class($pref['download_reportbroken']))
        {
            return $this->renderReport();        
        }
        
        if($this->qry['action'] == 'mirror')
        {
            return $this->renderMirror();    
        }
        
        if($this->qry['action'] == 'error')
        {
            return $this->renderError();    
        }    
        
    }






    /**
     * Render Download Categories. 
     * @todo Cache 
     */
    private function renderCategories()
    {
        $tp = e107::getParser();
        $ns = e107::getRender();
        $pref = e107::getPref();
        

    //    if ($cacheData = $e107cache->retrieve("download_cat".$maincatval,720)) // expires every 12 hours. //TODO make this an option
        {
       //      echo $cacheData;
        //    return;
        }


        
        if(deftrue('BOOTSTRAP')) // v2.x 
        {
            $template = e107::getTemplate('download','download','categories');
            
            $DOWNLOAD_CAT_TABLE_START     = varset($template['start']);
            $DOWNLOAD_CAT_PARENT_TABLE    = $template['parent'];
            $DOWNLOAD_CAT_CHILD_TABLE    = $template['child'];
            $DOWNLOAD_CAT_SUBSUB_TABLE    = $template['subchild'];
            $DOWNLOAD_CAT_TABLE_END        = varset($template['end']);
                
//            $DL_VIEW_NEXTPREV            = varset($template['nextprev']);
//            $DL_VIEW_PAGETITLE            = varset($template['pagetitle']);
//            $DL_VIEW_CAPTION            = varset($template['caption'],"{DOWNLOAD_VIEW_CAPTION}");
        }
        else // Legacy v1.x 
        {
            $DOWNLOAD_CAT_TABLE_START     = null;
            $DOWNLOAD_CAT_PARENT_TABLE    = null;
            $DOWNLOAD_CAT_CHILD_TABLE    = null;
            $DOWNLOAD_CAT_SUBSUB_TABLE    = null;
            $DOWNLOAD_CAT_TABLE_END        = null;


            $template_name = 'download_template.php';
            
            if (is_readable(THEME."templates/".$template_name))
            {
                require_once(THEME."templates/".$template_name);
            }
            elseif (is_readable(THEME.$template_name))
            {
                require_once(THEME.$template_name);
            }
            else
            {
                require_once(e_PLUGIN."download/templates/".$template_name);
            }    
        }

        /** @var download_shortcodes $sc */
        $sc = e107::getScBatch('download',true);
        $sc->wrapper('download/categories');
        $sc->breadcrumb();
        $sc->qry     = $this->qry;    
        
    
        
        if(!defined("DL_IMAGESTYLE")){ define("DL_IMAGESTYLE","border:1px solid blue");}

       // Read in tree of categories which this user is allowed to see
        $dlcat = new downloadCategory(varset($pref['download_subsub'],1),USERCLASS_LIST, null ,varset($pref['download_incinfo'],FALSE));

        if ($dlcat->down_count == 0)
           {

            return $ns->tablerender(LAN_PLUGIN_DOWNLOAD_NAME, "<div class='alert alert-warning' style='text-align:center'>".LAN_NO_RECORDS_FOUND."</div>",'download-categories',true);
        }
                
        $download_cat_table_string = "";
        foreach($dlcat->cat_tree as $dlrow)  // Display main category headings, then sub-categories, optionally with sub-sub categories expanded
        {
            $sc->setVars($dlrow); 
            $download_cat_table_string .= $tp->parseTemplate($DOWNLOAD_CAT_PARENT_TABLE, TRUE, vartrue($sc));
            
            foreach($dlrow['subcats'] as $dlsubrow)
            {
                $sc->dlsubrow = $dlsubrow;
                
                
                $download_cat_table_string .= $tp->parseTemplate($DOWNLOAD_CAT_CHILD_TABLE, TRUE, $sc);
                
                foreach($dlsubrow['subsubcats'] as $dlsubsubrow)
                {
                    $sc->dlsubsubrow = $dlsubsubrow;
                    $download_cat_table_string .= $tp->parseTemplate($DOWNLOAD_CAT_SUBSUB_TABLE, TRUE, $sc);
                }
            }
       }

    //    e107::getDebug()->log($dlcat->cat_tree);

      
        $dl_text = $tp->parseTemplate($this->templateHeader, TRUE, $sc);
        $dl_text .= $tp->parseTemplate($DOWNLOAD_CAT_TABLE_START, TRUE, $sc);
        $dl_text .= $download_cat_table_string;
        $dl_text .= $tp->parseTemplate($DOWNLOAD_CAT_TABLE_END, TRUE, $sc);
       
        $caption = varset($DOWNLOAD_CAT_CAPTION) ? $tp->parseTemplate($DOWNLOAD_CAT_CAPTION, TRUE, $sc) : LAN_PLUGIN_DOWNLOAD_NAME;
        
        //ob_start();
        
        $dl_text .= $tp->parseTemplate($this->templateFooter, TRUE, $sc);


       
        return $ns->tablerender($caption, $dl_text, 'download-categories',true);

      // $cache_data = ob_get_flush();
     //  $e107cache->set("download_cat".$maincatval, $cache_data);    
        
        
    }


    /**
     * Meta for 'view' mode..to be expanded to handle list and maincats etc.
     * @param array $row
     * @todo modes for different actions based on $this->qry['action']
     */
    private function setMeta($row)
    {
        $tp = e107::getParser();

        $metaImage                      = $tp->thumbUrl($row['download_image'], array('w'=>500), null, true);

        // $metaDescription                = $tp->toHTML($row['download_description'],true);
        // $metaDescription                 = preg_replace('/\v(?:[\v\h]+)/', '', $metaDescription); // remove all line-breaks and excess whitespace
        // $metaDescription                 = $tp->text_truncate($metaDescription, 290); // + '...'

        $metaDescription = e107::getParser()->toText($row['download_description']); 
        $metaDescription = e107::getParser()->truncate($metaDescription, 150);

        e107::meta('description',       $metaDescription);
        e107::meta('keywords',          $row['download_keywords']);
        e107::meta('og:description',    $metaDescription);
        e107::meta('og:image',          $metaImage);
        e107::meta('twitter:image:src', $metaImage);

    }


    private function loadReport()
    {
        $sql = e107::getDb();

        $query = "
        SELECT d.*, dc.* FROM #download AS d
        LEFT JOIN #download_category AS dc ON d.download_category = dc.download_category_id
        WHERE d.download_id = {$this->qry['id']}
          AND download_active > 0
        LIMIT 1";

        if(!$sql->gen($query))
        {
            return;
        }

        $this->rows = $sql->fetch();

        if (isset($_POST['report_download']))
        {
            define("e_PAGETITLE", LAN_PLUGIN_DOWNLOAD_NAME." / ".LAN_dl_45);
            return null;
        }

        $download_name = e107::getParser()->toDB($this->rows['download_name']);
        define("e_PAGETITLE", LAN_PLUGIN_DOWNLOAD_NAME." / ".LAN_dl_45." / ".$download_name);

    }



    /**
     * @return null
     */
    private function loadList()
    {
        if($dlrow = $this->getCategory($this->qry['id']))
        {
            e107::title(LAN_PLUGIN_DOWNLOAD_NAME." / ".$dlrow['download_category_name']);
            e107::canonical('download', 'category', $dlrow);
        //    define("e_PAGETITLE", LAN_PLUGIN_DOWNLOAD_NAME." / ".$dlrow['download_category_name']);
        }
        else
        {  // No access to this category
            e107::title(LAN_PLUGIN_DOWNLOAD_NAME);
            //define("e_PAGETITLE", LAN_PLUGIN_DOWNLOAD_NAME);
        }

        return null;
    }


    /**
     * @return null
     */
    private function loadView()
    {
        if(deftrue('BOOTSTRAP')) // v2.x
        {
            $this->template = e107::getTemplate('download','download','view');
        }
        else // Legacy v1.x
        {
            $template_name = 'download_template.php';

            $DOWNLOAD_VIEW_TABLE_START = null;
            $DOWNLOAD_VIEW_TABLE        = null;
            $DOWNLOAD_VIEW_TABLE_END    = null;
            $DL_VIEW_NEXTPREV            = null;
            $DL_VIEW_PAGETITLE            = null;
            $DL_VIEW_CAPTION            = null;

            if (is_readable(THEME."templates/".$template_name))
            {
                require_once(THEME."templates/".$template_name);
            }
            elseif (is_readable(THEME.$template_name))
            {
                require_once(THEME.$template_name);
            }
            else
            {
                require_once(e_PLUGIN."download/templates/".$template_name);
            }

            $this->template['start']      = $DOWNLOAD_VIEW_TABLE_START;
            $this->template['item']       = $DOWNLOAD_VIEW_TABLE;
            $this->template['end']        = $DOWNLOAD_VIEW_TABLE_END;
            $this->template['nextprev']   = $DL_VIEW_NEXTPREV;
            $this->template['pagetitle']  = $DL_VIEW_PAGETITLE;
            $this->template['caption']    = varset($DL_VIEW_CAPTION,"{DOWNLOAD_VIEW_CAPTION}");

        }

        if(empty($this->template['newprev']))
        {
            $this->template['newprev'] = "
            <div style='text-align:center'>
                <table style='".USER_WIDTH."'>
                <tr>
                <td style='width:40%;'>{DOWNLOAD_VIEW_PREV}</td>
                <td style='width:20%; text-align: center;'>{DOWNLOAD_BACK_TO_LIST}</td>
                <td style='width:40%; text-align: right;'>{DOWNLOAD_VIEW_NEXT}</td>
                </tr>
                </table>
                </div>
                ";
       }

        if(empty($this->template['pagetitle']))
        {
            $this->template['pagetitle'] = "{DOWNLOAD_VIEW_NAME} / {DOWNLOAD_CATEGORY} / ".LAN_PLUGIN_DOWNLOAD_NAME;
        }


        // load data

        $sql = e107::getDb();
        $gen = new convert;

        /** @var download_shortcodes $sc */
        $sc = e107::getScBatch('download',true);
        $sc->wrapper('download/view');
        $sc->breadcrumb();
        $sc->qry     = $this->qry;

        $highlight_search = FALSE;
        if (isset($_POST['highlight_search']))
        {
            $highlight_search = TRUE;
        }

        $query = "
            SELECT d.*, dc.* FROM #download AS d
            LEFT JOIN #download_category AS dc ON d.download_category = dc.download_category_id
            WHERE d.download_id = {$this->qry['id']} AND d.download_active > 0
            AND d.download_visible IN (".USERCLASS_LIST.")
            AND dc.download_category_class IN (".USERCLASS_LIST.")
            LIMIT 1";

        if(!$sql->gen($query))
        {
            return null;
        }

        if(!defined("DL_IMAGESTYLE"))
        {
            define("DL_IMAGESTYLE","border:0px");
        }

        $dlrow = $sql->fetch();

        $sc->parent = $this->getParent($dlrow['download_category_id']);

        if(!empty( $sc->parent['download_category_parent']))
        {
            $sc->grandparent = $this->getParent( $sc->parent['download_category_id']);
        }


        $sc->setVars($dlrow);
        $this->setMeta($dlrow);



        $this->sc = $sc;
        $this->rows = $dlrow;

        // set Page Title;

        $DL_TITLE = e107::getParser()->parseTemplate($this->template['pagetitle'], true, $sc);

    //    define("e_PAGETITLE", $DL_TITLE);
        e107::title($DL_TITLE);
        e107::canonical('download', 'item', $dlrow);

        return null;
    }


    /**
     * Render a single download
     * @todo cache
     */
    private function renderView()
    {

        $tp = e107::getParser();
        $ns = e107::getRender();
        /** @var download_shortcodes $sc */
        $sc = $this->sc;


        // @see: #3056 fixes fatal error in case $sc is empty (what happens, if no record was found)
        $count = empty($sc) ? 0 : $sc->getVars();

        if(empty($count))
        {
            return $ns->tablerender(LAN_PLUGIN_DOWNLOAD_NAME, "<div style='text-align:center'>".LAN_NO_RECORDS_FOUND."</div>", 'download-view', true);
        }

        $sc->breadcrumb();

        $DL_TEMPLATE = $this->template['start'].$this->template['item'].$this->template['end'];
        
        $text = $tp->parseTemplate($this->templateHeader, TRUE, $sc);
        $text .= $tp->parseTemplate($DL_TEMPLATE, TRUE, $sc);

        
            // ------- Next/Prev -----------
           $text .= $tp->parseTemplate($this->template['nextprev'], TRUE, $sc);
        $caption = $tp->parseTemplate($this->template['caption'], TRUE, $sc);
        
        $text .= $tp->parseTemplate($this->templateFooter, TRUE, $sc);
        
        $ret = $ns->tablerender($caption, $text, 'download-view', true);
    
        unset($text);

        $dlrow = $this->rows;
    
        if ($dlrow['download_comment']) 
        {            
            $comments = e107::getComment()->compose_comment("download", "comment", $dlrow['download_id'], null, $dlrow['download_name'], FALSE, true);
            $ret .= $ns->tablerender($comments['caption'], $comments['comment'].$comments['comment_form'], 'download-comments', true);
        }    
        
        
        
    //    print_a($comments);
        
        return $ret;
        
    }










    
    /**
     * Render a list of files in a particular download category. 
     * 
     */
    private function renderList()
    {
        
        if(deftrue('BOOTSTRAP')) // v2.x 
        {
            $template = e107::getTemplate('download','download');
            
            $DOWNLOAD_LIST_CAPTION         = $template['list']['caption'];    
            $DOWNLOAD_LIST_TABLE_START     = $template['list']['start'];    
            $DOWNLOAD_LIST_TABLE         = $template['list']['item'];
            $DOWNLOAD_LIST_TABLE_END     = $template['list']['end'];        
            $DOWNLOAD_LIST_NEXTPREV        = $template['list']['nextprev'];
            
            $DOWNLOAD_CAT_TABLE_START     = varset($template['categories']['start']);
        //    $DOWNLOAD_CAT_PARENT_TABLE    = $template['categories']['parent'];
        //    $DOWNLOAD_CAT_CHILD_TABLE    = $template['categories']['child'];
            $DOWNLOAD_CAT_SUBSUB_TABLE    = $template['categories']['subchild'];
            $DOWNLOAD_CAT_TABLE_END        = varset($template['categories']['end']);
        }
        else // Legacy v1.x 
        {
            $template_name = 'download_template.php';    
            
            if (is_readable(THEME."templates/".$template_name))
            {
                require_once(THEME."templates/".$template_name);
            }
            elseif (is_readable(THEME.$template_name))
            {
                require_once(THEME.$template_name);
            }
            else
            {
                require_once(e_PLUGIN."download/templates/".$template_name);
            }    
        }
        
        
        $sql = e107::getDb('dlrow');
        $tp = e107::getParser();
        $ns = e107::getRender();
        $pref = e107::getPref();
        

        /** @var download_shortcodes $sc */
        $sc = e107::getScBatch('download',true);
        $sc->wrapper('download/list');

        $sc->qry     = $this->qry;

        

        //if (!isset($this->qry['from'])) $this->qry['from'] = 0;

          // Get category type, page title
    //    if ($sql->select("download_category", "download_category_name,download_category_sef,download_category_description,download_category_parent,download_category_class", "(download_category_id='{$this->qry['id']}') AND (download_category_class IN (".USERCLASS_LIST."))") )

        if($dlrow = $this->getCategory($this->qry['id']))
        {
             //  $dlrow = $sql->fetch();

            $catRows = $dlrow;
              $sc->setVars($dlrow);    // Used below for header / breadcrumb.

              $sc->parent = $this->getParent($this->qry['id']);

              if(!empty( $sc->parent['download_category_parent']))
           {
                $sc->grandparent = $this->getParent( $sc->parent['download_category_id']);
           }

            $sc->breadcrumb();

       //       $type = $dlrow['download_category_name'];


           $this->qry['name'] = $dlrow['download_category_sef'];
           
       //       define("e_PAGETITLE", LAN_PLUGIN_DOWNLOAD_NAME." / ".$dlrow['download_category_name']);
        }
        else
        {  // No access to this category
           //   define("e_PAGETITLE", LAN_PLUGIN_DOWNLOAD_NAME);
              return $ns->tablerender(LAN_PLUGIN_DOWNLOAD_NAME, "<div class='alert alert-info' style='text-align:center'>".LAN_NO_RECORDS_FOUND."</div>",'download-list',true);
        }
        
        //if ($dlrow['download_category_parent'] == 0)  // It's a main category - change the listing type required
       //   {
          //   $action = 'maincats';
      //            $maincatval = $id;
    //    }
        
        $dl_text = $tp->parseTemplate($this->templateHeader, TRUE, $sc);
                        
        $total_downloads = $sql->count("download", "(*)", "WHERE download_category = '{$this->qry['id']}' AND download_active > 0 AND download_visible REGEXP '" . e_CLASS_REGEXP . "'");
        
        
        /* SHOW SUBCATS ... */
        if($this->getChildren($this->qry['id']))
        {

            /* there are subcats - display them ... */
            $qry = "
            SELECT dc.*, dc2.download_category_name AS parent_name, dc2.download_category_icon as parent_icon, SUM(d.download_filesize) AS d_size,
            COUNT(d.download_id) AS d_count,
            MAX(d.download_datestamp) as d_last,
            SUM(d.download_requested) as d_requests
            FROM #download_category AS dc
            LEFT JOIN #download AS d ON dc.download_category_id = d.download_category AND d.download_active > 0 AND d.download_visible IN (" . USERCLASS_LIST . ")
            LEFT JOIN #download_category as dc2 ON dc2.download_category_id='{$this->qry['id']}'
            WHERE dc.download_category_class IN (" . USERCLASS_LIST . ") AND dc.download_category_parent='{$this->qry['id']}'
            GROUP by dc.download_category_id ORDER by dc.download_category_order
            ";
            
            if($sql->gen($qry))
            {
                
                $scArray = $sql->db_getList();

                $subText = "";
                                
                /** @DEPRECATED **/
            //    if(!defined("DL_IMAGESTYLE"))
            //    {
            //        define("DL_IMAGESTYLE", "border:1px solid blue");
            //    }
    
                $download_cat_table_string = "";

                if(!empty($DOWNLOAD_CAT_TABLE_PRE)) // 0.8 BC Fix.
                {
                    $subText .= $tp->parseTemplate($DOWNLOAD_CAT_TABLE_PRE, TRUE, $sc);
                }
                $subText .= $tp->parseTemplate($DOWNLOAD_CAT_TABLE_START, TRUE, $sc);
                
                foreach($scArray as $dlsubsubrow)
                {
                    $sc->dlsubsubrow = $dlsubsubrow;
                    $sc->dlsubrow = $dlsubsubrow;
                    $subText .= $tp->parseTemplate($DOWNLOAD_CAT_SUBSUB_TABLE, TRUE, $sc);
                    
                }
                
                $subText .= $tp->parseTemplate($DOWNLOAD_CAT_TABLE_END, TRUE, $sc);
                
              //  $dl_text .= $ns->tablerender($dl_title, $subText, 'download-list', true);
                  $dl_text .=  $subText;
            }
            
        }// End of subcategory display

        // Now display individual downloads
        $download_category_class = 0;
        
        if(!check_class($download_category_class))
        {
            $ns->tablerender(LAN_PLUGIN_DOWNLOAD_NAME, "<div class='alert alert-info'>    " . LAN_NO_RECORDS_FOUND . "</div>");
            return null;
        }

        if($total_downloads < $this->qry['view'])
        {
            $this->qry['from'] = 0;
        }

        if(!defined("DL_IMAGESTYLE"))
        {
            define("DL_IMAGESTYLE", "border:1px solid blue");
        }

        require_once (e_HANDLER . "rate_class.php");
        $dltdownloads = 0;

        // $this->qry['from'] - first entry to show  (note - can get reset due to reuse of query,
        // even if values overridden this time)
        // $this->qry['view'] - number of entries per page
        // $total_downloads - total number of entries matching search criteria
        $filetotal = $sql->select("download", "*", "download_category='{$this->qry['id']}' AND download_active > 0 AND download_visible IN (" . USERCLASS_LIST . ") ORDER BY download_{$this->qry['order']} {$this->qry['sort']} LIMIT {$this->qry['from']}, ".$this->qry['view']);


        $caption = varset($DOWNLOAD_LIST_CAPTION) ? $tp->parseTemplate($DOWNLOAD_LIST_CAPTION, TRUE, $sc) : LAN_PLUGIN_DOWNLOAD_NAME;

        if(empty($filetotal))
        {

            $dl_text .= $tp->parseTemplate($this->templateFooter, TRUE, $sc);
            return ($dl_text) ? $ns->tablerender($caption, $dl_text, 'download-list', true) : '';
        }


        // Only show list if some files in it
        $dl_text .= $tp->parseTemplate($DOWNLOAD_LIST_TABLE_START, TRUE, $sc);
            
        global $dlft, $dltdownloads;
            
        $dlft = ($filetotal < $this->qry['view'] ? $filetotal: $this->qry['view']);

        $current_row = 1;

        while($dlrow = $sql->fetch())
        {
                $sc->setVars($dlrow);

                $agreetext = $tp->toHTML($pref['agree_text'], TRUE, 'DESCRIPTION');
                $current_row = ($current_row) ? 0: 1;
                // Alternating CSS for each row.(backwards compatible)
                $template = ($current_row == 1)? $DOWNLOAD_LIST_TABLE: str_replace("forumheader3", "forumheader3 forumheader3_alt", $DOWNLOAD_LIST_TABLE);
                
                $dltdownloads += $dlrow['download_requested'];
                
                $dl_text .= $tp->parseTemplate($template, TRUE, $sc);
        }

        $dl_text .= $tp->parseTemplate($DOWNLOAD_LIST_TABLE_END, TRUE, $sc);
        $dl_text .= $tp->parseTemplate($this->templateFooter, TRUE, $sc);

        $text = $ns->tablerender($caption, $dl_text, 'download-list', true);


        if(!isset($DOWNLOAD_LIST_NEXTPREV))
        {
            $sc_style['DOWNLOAD_LIST_NEXTPREV']['pre'] = "
            <div class='nextprev'>
                ";
                        $sc_style['DOWNLOAD_LIST_NEXTPREV']['post'] = "
            </div>";
            
                        $DOWNLOAD_LIST_NEXTPREV = "
            <div style='text-align:center;margin-left:auto;margin-right:auto'>
                {DOWNLOAD_BACK_TO_CATEGORY_LIST}
                <br />
                <br />
                {DOWNLOAD_LIST_NEXTPREV}
            </div>";
        }


        $nextprevQry = $this->qry;
        $nextprevQry['from'] = '[FROM]';
        unset($nextprevQry['id'],$nextprevQry['name'],$nextprevQry['action']);

        $newUrl = e107::url('download','category',$catRows, array('query'=>$nextprevQry));

        $nextprev = array(
                'tmpl_prefix'    =>'default',
                'total'            => $total_downloads,
                'amount'        => intval($this->qry['view']),
                'current'        => $this->qry['from'],
                'url'            => urldecode($newUrl)
        );

        global $nextprev_parms;
    
        $nextprev_parms  = http_build_query($nextprev,false); // 'tmpl_prefix='.deftrue('NEWS_NEXTPREV_TMPL', 'default').'&total='. $total_downloads.'&amount='.$amount.'&current='.$newsfrom.$nitems.'&url='.$url;

        $text .= $tp->parseTemplate($DOWNLOAD_LIST_NEXTPREV, TRUE, $sc);    

        return $text;
        
    }



    /**
     * Render a 'Broken Download' Report form. 
     */
    private function renderReport()
    {
        $sql     = e107::getDb();
        $tp     = e107::getParser();
        $ns     = e107::getRender();
        $frm     = e107::getForm();
        $pref     = e107::getPref();
        $mes     = e107::getMessage();
                        
        $dlrow = $this->rows;
    
        // Check if user is allowed to make reports, and if user is allowed to view the actual download item
        if(!check_class($dlrow['download_class']) || !check_class($pref['download_reportbroken']))
        {    
            $mes->addError(LAN_dl_79);
            return $ns->tablerender(LAN_PLUGIN_DOWNLOAD_NAME, $mes->render(), 'download-report', true);
        }

        $download_name     = $tp->toDB($dlrow['download_name']);
        $download_sef     = $dlrow['download_sef'];
        $download_id     = (int) $dlrow['download_id'];

        $breadcrumb     = array();
        $breadcrumb[]    = array('text' => LAN_PLUGIN_DOWNLOAD_NAME,            'url' => e107::url('download','index', $dlrow));
        $breadcrumb[]    = array('text' => $dlrow['download_category_name'],    'url' => e107::url('download','category', $dlrow)); 
        $breadcrumb[]    = array('text' => $dlrow['download_name'],            'url' => e107::url('download','item', $dlrow)); 
        $breadcrumb[]    = array('text' => LAN_dl_45,                        'url' => null);

        e107::breadcrumb($breadcrumb);
    
        if (isset($_POST['report_download'])) 
        {
            $report_add = $tp->toDB($_POST['report_add']);
            $user         = USER ? USERNAME : LAN_GUEST;
            $ip         = e107::getIPHandler()->getIP(false); 
        
            // Replaced by e_notify 
            /*
            if ($pref['download_email']) 
            {    // this needs to be moved into the NOTIFY, with an event.
                require_once(e_HANDLER."mail.php");
                $subject = LAN_dl_60." ".SITENAME;
                $report = LAN_dl_58." ".SITENAME.":\n".(substr(SITEURL, -1) == "/" ? SITEURL : SITEURL."/")."download.php?view.".$download_id."\n
                ".LAN_dl_59." ".$user."\n".$report_add;
                sendemail(SITEADMINEMAIL, $subject, $report);
            }*/

            $brokendownload_data = array(
                'download_id'     => $download_id,
                'download_sef'  => $download_sef,
                'download_name' => $download_name, 
                'report_add'     => $report_add,
                'user'            => $user,
                'ip'            => $ip, 
            );

            e107::getEvent()->trigger('user_download_brokendownload_reported', $brokendownload_data);

            $sql->insert('generic', "0, 'Broken Download', ".time().",'".USERID."', '{$download_name}', {$download_id}, '{$report_add}'");
    

            $text = $frm->breadcrumb($breadcrumb);
    
            $text .= "<div class='alert alert-success'>".LAN_dl_48."</div>
            <a class='btn btn-primary' href='".e107::url('download','item', $dlrow)."'>".LAN_dl_49."</a>";

            return $ns->tablerender(LAN_PLUGIN_DOWNLOAD_NAME, $text, 'download-report', true);
        }
        else 
        {
            $text = $frm->breadcrumb($breadcrumb);


            $formUrl = e107::url('download', 'report', $dlrow);
            $fileUrl = e107::url('download', 'view', $dlrow);

            $text .= "<form action='".$formUrl."' method='post'>
               <div class='form-group'>
                        <p> ".LAN_DOWNLOAD.": <a href='".$fileUrl."'>".$download_name."</a></p>
                    <p>".LAN_dl_54."<br />".LAN_dl_55."</p>
              </div>
               <div class='form-group clearfix'> ".$frm->textarea('report_add', '')."</div>
                <div class='form-group text-center'>
                    ".$frm->button('report_download',LAN_dl_45)."
                </div>
           </form>";
                 
            return $ns->tablerender(LAN_PLUGIN_DOWNLOAD_NAME, $text, 'download-report', true);
        }
    }
                
            
    /**
     * Render Download Mirrors for the selected file. 
     */
    private function renderMirror()
    {
        
        $sql = e107::getDb();
        $tp = e107::getParser();
        $ns = e107::getRender();
        $pref = e107::getPref();
        
        if(deftrue('BOOTSTRAP')) // v2.x 
        {
            $template = e107::getTemplate('download','download','mirror');
            
            $DOWNLOAD_MIRROR_START         = $template['start'];    
            $DOWNLOAD_MIRROR             = $template['item'];
            $DOWNLOAD_MIRROR_END         = $template['end'];        

        }
        else // Legacy v1.x 
        {
            $template_name = 'download_template.php';    
            
            if (is_readable(THEME."templates/".$template_name))
            {
                require_once(THEME."templates/".$template_name);
            }
            elseif (is_readable(THEME.$template_name))
            {
                require_once(THEME.$template_name);
            }
            else
            {
                require_once(e_PLUGIN."download/templates/".$template_name);
            }    
        
        }

        /** @var download_shortcodes $sc */
        $sc = e107::getScBatch('download',true);
        $sc->wrapper('download/mirror');
        $sc->breadcrumb();
        $sc->qry     = $this->qry;
        
    //    $load_template = 'download_template';
    //    if (!isset($DOWNLOAD_MIRROR_START)) eval($template_load_core);
    
        $sql->select("download_mirror");
        $mirrorList = $sql->db_getList("ALL", 0, 200, "mirror_id");
    
        $query = "
            SELECT d.*, dc.* FROM #download AS d
            LEFT JOIN #download_category AS dc ON d.download_category = dc.download_category_id
            WHERE d.download_id = ".$this->qry['id']."
            LIMIT 1";
    
    //    global $dlmirrorfile, $dlmirror;    
    
    
        if($sql->gen($query))
        {
            $dlrow = $sql->fetch();
        //    $dlrow['mirrorlist'] = $mirrorList;
            $sc->setVars($dlrow);

            
            $array = explode(chr(1), $dlrow['download_mirror']);
            
            if (2 == varset($pref['mirror_order']))
            {
             // Order by name, sort array manually
                usort($array, "sort_download_mirror_order");
            }
          //elseif (1 == varset($pref['mirror_order']))
          //{
          //   // Order by ID  - do nothing order is as stored in DB
          //}
            elseif (0 == varset($pref['mirror_order'], 0))
            {
                   // Shuffle the mirror list into a random order
                   $c = count($array);
                   for ($i=1; $i<$c; $i++)
                   {
                     $d = mt_rand(0, $i);
                     $tmp = $array[$i];
                     $array[$i] = $array[$d];
                     $array[$d] = $tmp;
                   }
            }
    
            $dl_text = $tp->parseTemplate($this->templateHeader, TRUE, $sc);
    
               $dl_text .= $tp->parseTemplate($DOWNLOAD_MIRROR_START, TRUE, $sc);
            $download_mirror = 1;
                
        
                
            foreach($array as $mirrorstring)
            {
                if($mirrorstring)
                {
                    $dlmirrorfile = explode(",", $mirrorstring);
                //    $dlmirror = $mirrorList[$dlmirrorfile[0]];
                    
                    $sc->mirror['dlmirrorfile'] = $dlmirrorfile;
                    $sc->mirror['dlmirror'] = $mirrorList[$dlmirrorfile[0]];
                    
                    $dl_text .= $tp->parseTemplate($DOWNLOAD_MIRROR, TRUE, $sc);
                }
            }
               
            $dl_text .= $tp->parseTemplate($DOWNLOAD_MIRROR_END, TRUE, $sc);
            
            $dl_text .= $tp->parseTemplate($this->templateFooter, TRUE, $sc);
            
               return $ns->tablerender(LAN_PLUGIN_DOWNLOAD_NAME, $dl_text, 'download-mirror', true);    
        
        
        }


    }


    /**
     * Render Download Errors. 
     */
    private function renderError()
    {
        $ns = e107::getRender();
        $pref = e107::getPref();
        $tp = e107::getParser();
        
        $sc = e107::getScBatch('download',true);
        
        $header = $tp->parseTemplate($this->templateHeader,true, $sc);
        $footer = $tp->parseTemplate($this->templateFooter,true, $sc);
        
        switch ($this->qry['error'])
        {
            case 1 :    // No permissions
                if (strlen($pref['download_denied']) > 0) 
                {
                    $errmsg = $tp->toHTML($pref['download_denied'],true, 'DESCRIPTION');
                     } 
                     else 
                     {
                    $errmsg = LAN_dl_63;
                }
            break;
              
            case 2 :    // Quota exceeded
                $errmsg = LAN_dl_62;
            break;
            
            default: // Generic error - shouldn't happen
                $errmsg = LAN_ERROR." ".$this->qry['error'];        
        }
        
        return $ns->tablerender(LAN_PLUGIN_DOWNLOAD_NAME, $header. "<div class='alert alert-error alert-danger alert-block' style='text-align:center'>".$errmsg."</div>". $footer, 'download-error', true);
        
    }
   
   
   
   
   function getCategorySelectList($currentID=0, $incSubSub=true, $groupOnMain=true, $blankText="&nbsp;", $name="download_category")
   {
      global $sql,$parm;
         $boxinfo = "\n";
         $qry = "
            SELECT dc.download_category_name, dc.download_category_order, dc.download_category_id, dc.download_category_parent,
            dc1.download_category_parent AS d_parent1
            FROM #download_category AS dc
            LEFT JOIN #download_category as dc1 ON dc1.download_category_id=dc.download_category_parent AND dc1.download_category_class IN (".USERCLASS_LIST.")
         LEFT JOIN #download_category as dc2 ON dc2.download_category_id=dc1.download_category_parent ";
      if (ADMIN === FALSE) $qry .= " WHERE dc.download_category_class IN (".USERCLASS_LIST.") ";
      $qry .= " ORDER by dc2.download_category_order, dc1.download_category_order, dc.download_category_order";   // This puts main categories first, then sub-cats, then sub-sub cats
      if (!$sql->gen($qry))
      {
            return "Error reading categories<br />";
            exit;
      }
      $boxinfo .= "<select name='{$name}' id='download_category' class='tbox form-control'>
          <option value=''>{$blankText}</option>\n";
      // Its a structured display option - need a 2-step process to create a tree
      $catlist = array();
      while ($dlrow = $sql->fetch())
      {
         $tmp = $dlrow['download_category_parent'];
            if ($tmp == '0')
            {
           $dlrow['subcats'] = array();
              $catlist[$dlrow['download_category_id']] = $dlrow;
            }
            else
            {
              if (isset($catlist[$tmp]))
              {  // Sub-Category
                $catlist[$tmp]['subcats'][$dlrow['download_category_id']] = $dlrow;
                $catlist[$tmp]['subcats'][$dlrow['download_category_id']]['subsubcats'] = array();
              }
              else
              {  // Its a sub-sub category
                if (isset($catlist[$dlrow['d_parent1']]['subcats'][$tmp]))
                {
                     $catlist[$dlrow['d_parent1']]['subcats'][$tmp]['subsubcats'][$dlrow['download_category_id']] = $dlrow;
                }
              }
            }
      }
          // Now generate the options
      foreach ($catlist as $thiscat)
      {  // Main categories
         if (count($thiscat['subcats']) > 0)
         {
            if ($groupOnMain)
            {
                $boxinfo .= "<optgroup label='".htmlspecialchars($thiscat['download_category_name'])."'>";
                 $scprefix = '';
            }
            else
            {
                $boxinfo .= "<option value='".$thiscat['download_category_id']."'";
                if ($currentID == $thiscat['download_category_id']) {
                   $boxinfo .= " selected='selected'";
                }
               $boxinfo .= ">".htmlspecialchars($thiscat['download_category_name'])."</option>\n";
                 $scprefix = '&nbsp;&nbsp;&nbsp;';
            }
            foreach ($thiscat['subcats'] as $sc)
            {  // Sub-categories
                $sscprefix = '--> ';
                $boxinfo .= "<option value='".$sc['download_category_id']."'";
                if ($currentID == $sc['download_category_id']) {
                   $boxinfo .= " selected='selected'";
                }
               $boxinfo .= ">".$scprefix.htmlspecialchars($sc['download_category_name'])."</option>\n";
               if ($incSubSub)
               {  // Sub-sub categories
                   foreach ($sc['subsubcats'] as $ssc)
                   {
                         $boxinfo .= "<option value='".$ssc['download_category_id']."'";
                         if ($currentID == $ssc['download_category_id']) { $boxinfo .= " selected='selected'"; }
                         $boxinfo .= ">".htmlspecialchars($sscprefix.$ssc['download_category_name'])."</option>\n";
                   }
               }
            }
            if ($groupOnMain)
            {
               $boxinfo .= "</optgroup>\n";
            }
         }
         else
         {
             $sel = ($currentID == $thiscat['download_category_id']) ? " selected='selected'" : "";
               $boxinfo .= "<option value='".$thiscat['download_category_id']."' {$sel}>".htmlspecialchars($thiscat['download_category_name'])."</option>\n";
         }
      }
      $boxinfo .= "</select>\n";
      return $boxinfo;
   }
}

function sort_download_mirror_order($a, $b)
{
   $a = explode(",", $a);
   $b = explode(",", $b);
   if ($a[1] == $b[1]) {
      return 0;
   }
   return ($a[1] < $b[1]) ? -1 : 1;
}