1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

History v1.0

Discussion in 'XenForo Development Discussions' started by AndyB, Dec 15, 2013.

  1. AndyB

    AndyB Well-Known Member

    Purpose:

    The purpose of this thread is to provide additional information on the History v1.0 add-on.

    To download and install this add-on please visit the following XenForo Resource:

    http://xenforo.com/community/resources/history.2653/

    Description:

    This add-on will allow members to quickly return to previously viewed threads.

    Features:
    • Shows a list of last viewed threads
    • Highlights threads with new posts
    • Places History link in navigation bar for easy access
    • Fully phrased
    (Example of History link)

    pic001.jpg

    (Example of History page)

    pic002.jpg
     
    Mouth and Amaury like this.
  2. AndyB

    AndyB Well-Known Member

    The directory structure with the core files highlighted.

    library
    --Andy
    ----History
    ------ControllerPublic
    --------Thread.php
    ----Install.php
    ----Listener.php
    ----Model.php
    ----Uninstall.php
     
    Amaury likes this.
  3. AndyB

    AndyB Well-Known Member

    Create Add-on

    pic001.jpg
     
    Amaury likes this.
  4. AndyB

    AndyB Well-Known Member

    library/Andy/History/ControllerPublic/Thread.php

    PHP:
    <?php

    class Andy_History_ControllerPublic_Thread extends XFCP_Andy_History_ControllerPublic_Thread
    {
        public function 
    actionIndex()
        {
            
    // get parent
            
    $parent parent::actionIndex();
            
            
    //########################################
            // update xf_history table
            //########################################

            // get $userId
            
    $userId XenForo_Visitor::getUserId();
            
            
    // continue if member is logged in
            
    if ($userId 0)
            {
                
    // get database
                
    $db XenForo_Application::get('db');
                
                
    // get $threadId
                
    $threadId $this->_input->filterSingle('thread_id'XenForo_Input::UINT);    
                
                
    // define $dateline
                
    $dateline time();
                
                
    // insert row into xf_history
                
    $db->query("
                    INSERT INTO xf_history
                        (user_id, thread_id, thread_read_date)
                    VALUES
                        (?, ?, ?)
                    ON DUPLICATE KEY UPDATE
                        thread_read_date = VALUES(thread_read_date)
                "
    , array($userId$threadId$dateline));
            }

            
    // return parent
            
    return $parent;
        }        
                
        public function 
    actionHistory()
        {
            
    //########################################
            // display History page
            //########################################
                    
            // get $userId
            
    $userId XenForo_Visitor::getUserId();
            
            
    // throw error if no $userId
            
    if (!$userId){
                throw 
    $this->getNoPermissionResponseException();
            }        
            
            
    // get $threads data from model
            
    $threads $this->getModelFromCache('Andy_History_Model')->getHistoryThreads($userId);
            
            
    // prepare $viewParams for template
            
    $viewParams = array(
                
    'threads' => $threads,
            );        
            
            
    // send to template for display
            
    return $this->responseView('Andy_History_ViewPublic_History''andy_history'$viewParams);
        }
    }

    ?>
     
    Amaury likes this.
  5. AndyB

    AndyB Well-Known Member

    library/Andy/History/Install.php

    PHP:
    <?php

    class Andy_History_Install
    {
        public static function 
    install()
        {
            
    $db XenForo_Application::get('db');        
            
            try
            {    
                
    $db->query("
                    CREATE TABLE xf_history (
                    user_id INT( 10 ) UNSIGNED NOT NULL , 
                    thread_id INT( 10 ) UNSIGNED NOT NULL , 
                    thread_read_date INT( 10 ) UNSIGNED NOT NULL
                    ) ENGINE = InnoDB
                "
    );
            }
            catch (
    Zend_Db_Exception $e) {}
            
            try
            {    
                
    $db->query("
                    ALTER TABLE xf_history ADD UNIQUE user_id_thread_id ( user_id , thread_id ) 
                "
    );        
            }
            catch (
    Zend_Db_Exception $e) {}
        }
    }

    ?>
     
    Amaury likes this.
  6. AndyB

    AndyB Well-Known Member

    library/Andy/History/Listener.php

    PHP:
    <?php

    class Andy_History_Listener
    {
        public static function 
    Thread($class, array &$extend)
        {
            
    $extend[] = 'Andy_History_ControllerPublic_Thread';
        }    
    }

    ?>
     
    Amaury likes this.
  7. AndyB

    AndyB Well-Known Member

    library/Andy/History/Model.php

    PHP:
    <?php

    class Andy_History_Model extends XenForo_Model
    {
        public function 
    getHistoryThreads($userId)
        {        
            return 
    $this->_getDb()->fetchAll('
            SELECT xf_history.thread_id, 
            xf_history.thread_read_date AS history_read_date, 
            xf_thread.title, 
            xf_thread.reply_count, 
            xf_thread.view_count, 
            xf_thread.last_post_username, 
            xf_thread.last_post_date, 
            xf_node.title AS nodeTitle, 
            xf_thread_user_post.post_count AS user_post_count, 
            xf_user.user_id, xf_user.avatar_date
            FROM xf_history
            INNER JOIN xf_thread ON xf_thread.thread_id = xf_history.thread_id
            INNER JOIN xf_node ON xf_node.node_id = xf_thread.node_id
            LEFT JOIN xf_thread_user_post AS xf_thread_user_post
                ON (xf_thread_user_post.thread_id = xf_thread.thread_id
                AND xf_thread_user_post.user_id = ' 
    $userId ')            
            INNER JOIN xf_user ON xf_user.user_id = xf_thread.user_id
            WHERE xf_history.user_id = ' 
    $userId '
            ORDER BY xf_history.thread_read_date DESC 
            LIMIT 50'
    );
        }        
    }

    ?>
     
    Amaury likes this.
  8. AndyB

    AndyB Well-Known Member

    library/Andy/History/Uninstall.php

    PHP:
    <?php

    class Andy_History_Uninstall
    {
        public static function 
    uninstall()
        {
            
    $db XenForo_Application::get('db');
            
            try
            {        
                
    $db->query("
                    DROP TABLE xf_history
                "
    );
            }
            catch (
    Zend_Db_Exception $e) {}
        }
    }

    ?>
     
    Amaury likes this.
  9. AndyB

    AndyB Well-Known Member

    Code Event Listener

    pic001.jpg
     
    Amaury likes this.
  10. AndyB

    AndyB Well-Known Member

    andy_history template

    Code:
    <xen:require css="andy_history.css" />
    
    {xen:phrase history_last_50_threads_you_have_visited}
    <br /><br />
    
    <table class="dataTable">
    
        <tr class="dataRow">
            <th width="42"></th>
            <th>{xen:phrase title}</th>
            <th>{xen:phrase replies}</th>
            <th>{xen:phrase views}</th>
            <th>{xen:phrase last_reply_from}</th>
            <th>{xen:phrase forum}</th>
        </tr>
        
        <xen:foreach loop="$threads" value="$thread">
        <tr class="dataRow">
        
            <td class="history_avatarContainer">
            <xen:avatar user="$thread" size="s" img="true" class="history_avatar"/>
            <xen:if is="{$thread.user_post_count}"><xen:avatar user="$visitor" size="s" img="true" class="history_miniMe" title="{xen:phrase you_have_posted_x_messages_in_this_thread, 'count={xen:number $thread.user_post_count}'}" /></xen:if>
            </td>
            
            <xen:if is="{$thread.last_post_date} <= {$thread.history_read_date} OR {$thread.last_post_username} == {$visitor.username}">
            <td><a href="{xen:link 'threads',  $thread}" />{$thread.title}</a></td>
            </xen:if>
            
            <xen:if is="{$thread.last_post_date} > {$thread.history_read_date} AND {$thread.last_post_username} != {$visitor.username}">
            <td class="history_title_unread"><a href="{xen:link 'threads/unread',  $thread}" />{$thread.title}</a></td>
            </xen:if>  
            
            <td>{$thread.reply_count}</td>     
            <td>{$thread.view_count}</td>
            <td>{$thread.last_post_username}</td>
            <td>{$thread.nodeTitle}</td>
        
        </tr>
        </xen:foreach>
        
    </table>
    
     
    Amaury likes this.
  11. AndyB

    AndyB Well-Known Member

    andy_history.css

    Code:
    .dataTable a:link {
        font-size: 11pt;
    }
    
    history_avatar_th {
        width:42px;
    }
    
    .history_avatarContainer {
        display: block;
        position: relative;
        padding:5px 5px 5px 5px;
        background: url("styles/default/xenforo/gradients/category-23px-light.png") repeat-x scroll center top #F0F7FC;   
    }
    
    .history_avatar img {
        display: block;
        height: 36px;
        width: 36px;
        background-color: #ffffff;
        border: 1px solid #a5cae4;
        border-radius: 4px 4px 4px 4px;
        padding: 2px;
    }
    
    .history_miniMe img {
        max-width:20px;
        max-height:20px;
        margin: 0px 0px 1px 5px;
        position: absolute;
        border:none;
        border-radius: 0px 0px 0px 0px;
        bottom: 1px;
        left: 29px;
        padding:none;
        z-index: 10;
    }
    
    .history_miniMe img {
        border: 1px none #000000;
        border-radius: 2px;
        box-shadow: 1px 1px 5px rgba(0, 0, 0, 0.5);
        height: 20px;
        padding: 1px;
        width: 20px;
    }
    
    .history_title_unread a:link {
        font-weight:bold;
        font-size:12pt;
    }
    
     
    Amaury likes this.
  12. AndyB

    AndyB Well-Known Member

    Template Modification

    pic001.jpg
     
    Amaury likes this.
  13. Slavik

    Slavik XenForo Moderator Staff Member

    You should prefix correctly to avoid any issues with potential XenForo Core updates.

    Using xf_tablename is poor practice. You should use something like andyb_history or xf_andyb_history.
     
    Alfa1 and xf_phantom like this.
  14. Jeremy

    Jeremy XenForo Moderator Staff Member

    The second one is the better practice. You should always prefix your prefixed table names with xf_.
     
    Amaury likes this.
  15. Alfa1

    Alfa1 Well-Known Member

    Will it be possible for staff to see the browsing history of specific members? I have such functionality on vbulletin and we use it a lot when encountering problematic members.
     
  16. Alfa1

    Alfa1 Well-Known Member

    Could you explain why?
    I always find it much easier to spot the differences between addons and core if the prefix starts with the addon name. This will sort the addon before or after the core tables, instead of mixing it in.
     
    Matthew Hawley and xf_phantom like this.
  17. Brogan

    Brogan XenForo Moderator Staff Member

    http://xenforo.com/community/threads/xf_-table-prefix.19408/#post-249606

     
  18. Matthew Hawley

    Matthew Hawley Well-Known Member

    That would be great! @AndyB plz add this feature!
     

Share This Page