railpage/railpagecore

View on GitHub
lib/PrivateMessages/Folder.php

Summary

Maintainability
D
2 days
Test Coverage
<?php
    /**
     * Private Messages folder
     * @since Version 3.8.7
     * @package Railpage
     * @author Michael Greenhill
     */
    
    namespace Railpage\PrivateMessages;
    
    use DateTime;
    use Exception;
    use Railpage\Users\User;
    use Railpage\Users\Factory as UserFactory;
    use Railpage\Url;
    
    /** 
     * Private Messages - index / outbox / sentbox / savebox
     * @since Version 3.3
     * @version 3.3
     */
    
    class Folder extends PrivateMessages {
        
        /**
         * Do we want to cache the contents of this folder?
         * @since Version 3.9.1
         * @var boolean $cachepms
         */
        
        public $cachepms = false;
        
        /**
         * Inbox type
         * @since Version 3.3
         * @var string $folder
         */
        
        public $folder; 
        
        /**
         * Folder name
         * @since Version 3.8.7
         * @var string $name
         */
        
        public $name;
        
        /**
         * Constructor
         * @since Version 3.3
         * @version 3.3
         * @param 
         */
        
        public function __construct($folder = PM_INBOX) {
            parent::__construct();
            
            $this->folder = $folder;
            $this->name = ucwords($folder);
            $this->url = new Url(sprintf("/messages/%s", $folder));
        }
        
        /**
         * List the contents of this folder
         * @since Version 3.3
         * @version 3.3
         * @return array
         * @param int $page
         * @param int $items_per_page
         */
        
        public function getContents($page = 1, $items_per_page = 25) {
            if (empty($this->folder)) {
                throw new Exception("Cannot get folder contents - no folder specified"); 
            } 
            
            if (!$this->User instanceof User) {
                throw new Exception("Cannot get folder contents - User object not provided"); 
            }
            
            if (!$this->User->enable_privmsg) {
                throw new Exception("Private messages not available to this user"); 
            }
     
            if (RP_DEBUG) {
                global $site_debug;
                $debug_timer_start_z = microtime(true);
            }
            
            /**
             * Which page of the folder are we viewing?
             */
            
            $start = $page === 1 ? 0 : $page * $items_per_page; 
            
            /**
             * Set our intial response
             */
            
            $return = array(); 
            $return['stat'] = "ok";
            $return['page'] = $page; 
            $return['perpage'] = $items_per_page; 
            $return['messages'] = array(); 
            
            /**
             * Get the contents of this folder from the database
             */
            
            $folderContents = $this->fetchMessages(); 
            
            /**
             * If we don't have any PMs return now and save some bother
             */
            
            if (count($folderContents) === 0) {
                return $return;
            }
            
            /**
             * Group the PMs we do have into conversations
             */
            
            foreach ($folderContents as $row) {
                $row['privmsgs_subject'] = str_replace("Re: ", "", $row['privmsgs_subject']);
                
                $pm_from = $row['privmsgs_from_userid'] == $this->User->id ? $row['privmsgs_to_userid'] : $row['privmsgs_from_userid'];
                
                $privmsg_id = md5($row['privmsgs_subject'] . $pm_from);
                
                $return['messages'][$privmsg_id] = $row;                
            }
                    
            /**
             * Sort by PM date
             */
            
            uasort($return['messages'], function($a, $b) {
                return strnatcmp($b['privmsgs_date'], $a['privmsgs_date']); 
            });
            
            $return['total']    = count($return['messages']);
            $return['messages'] = array_slice($return['messages'], $start, $items_per_page);
                
            /**
             * Process these after the slice otherwise we're fetching avatars and processing text for every single message sent to/from this user
             */
            
            $return['messages'] = $this->processConversations($return['messages']);
            
            if (RP_DEBUG) {
                $site_debug[] = "Railpage: " . __CLASS__ . "(" . $this->folder . ") instantiated in " . round(microtime(true) - $debug_timer_start_z, 5) . "s";
            }
            
            return $return;
        }
        
        /**
         * Yield the conversation threads in this folder
         * @since Version 3.9
         * @package Railpage
         * @author Michael Greenhill
         */
        
        public function yieldConversations($items_per_page, $page) {
            if (!$this->User instanceof User) {
                throw new Exception("Cannot fetch " . __METHOD__ . " beause no user object has been set");
            }
            
            
        }
        
        /**
         * Generate the SQL query for fetching the contents of this folder
         * @since Version 3.9.1
         * @return string
         */
        
        private function generateSQLQuery() {
            
            /**
             * Fetch message IDs that have been "deleted" by this user
             */
            
            $deleted = $this->getDeleted($this->User->id); 
            $exclude_sql = count($deleted) === 0 ? "" : " AND privmsgs_id NOT IN ('".implode("', '", $deleted)."') ";
            
            /**
             * Different SQL base queries for different folders
             */
            
            if ($this->folder == PM_INBOX) {
                $pm_folder_sql = "pm.privmsgs_to_userid = ".$this->User->id." AND (pm.privmsgs_type = ".PRIVMSGS_READ_MAIL." OR pm.privmsgs_type = ".PRIVMSGS_NEW_MAIL." OR pm.privmsgs_type = ".PRIVMSGS_UNREAD_MAIL." )";
            } elseif ($this->folder == PM_OUTBOX) {
                $pm_folder_sql = "pm.privmsgs_from_userid = ".$this->User->id." AND (pm.privmsgs_type = ".PRIVMSGS_NEW_MAIL." OR pm.privmsgs_type = ".PRIVMSGS_UNREAD_MAIL.")"; 
            } elseif ($this->folder == PM_SENTBOX) {
                $pm_folder_sql = "pm.privmsgs_from_userid = ".$this->User->id." AND (pm.privmsgs_type = ".PRIVMSGS_READ_MAIL." OR pm.privmsgs_type = ".PRIVMSGS_SENT_MAIL.")"; 
            } elseif ($this->folder == PM_SAVEBOX) {
                $pm_folder_sql = "((pm.privmsgs_to_userid = ".$this->User->id." AND pm.privmsgs_type = ".PRIVMSGS_SAVED_IN_MAIL.") OR (pm.privmsgs_from_userid = ".$this->User->id." AND pm.privmsgs_type = ".PRIVMSGS_SAVED_OUT_MAIL."))";
            }
            
            // Done checking - get the PMs - sort by date ASC because the uasort() function will fix them up properly
            $query = "SELECT pm.*, pmt.*, ufrom.username AS username_from, ufrom.user_id AS user_id_from, ufrom.user_avatar AS user_avatar_from, 
                            uto.username AS username_to, uto.user_id AS user_id_from, uto.user_avatar AS user_avatar_to
                        FROM nuke_bbprivmsgs AS pm
                            INNER JOIN nuke_bbprivmsgs_text AS pmt ON pm.privmsgs_id = pmt.privmsgs_text_id
                            INNER JOIN nuke_users AS ufrom ON ufrom.user_id = privmsgs_from_userid
                            INNER JOIN nuke_users AS uto ON uto.user_id = privmsgs_to_userid
                        WHERE ".$pm_folder_sql."
                            ".$exclude_sql."";
            
            return $query;
            
        }
        
        /**
         * Process and format each conversation in this folder, in this page
         * @since Version 3.9.1
         * @param array $row
         * @return array
         */
        
        private function processConversations($conversations) {
            foreach ($conversations as $id => $row) {
                $row['privmsgs_text'] = function_exists("convert_to_utf8") ? convert_to_utf8($row['privmsgs_text']) : $row['privmsgs_text'];
                $row['user_avatar_from'] = function_exists("format_avatar") ? format_avatar($row['user_avatar_from'], 40, 40) : $row['user_avatar_from']; 
                $row['user_avatar_to'] = function_exists("format_avatar") ? format_avatar($row['user_avatar_to'], 40, 40) : $row['user_avatar_to']; 
                
                $conversations[$id] = $row;
            }
            
            return $conversations;
        }
        
        /**
         * Fetch the folder contents from the database
         * @since Version 3.9.1
         * return array
         */
        
        private function fetchMessages() {

            /**
             * Caching
             */
                        
            $mckey = sprintf("railpage:privatemessages;user_id=%d;folder=%s", $this->User->id, $this->folder);
            
            /**
             * Fetch the folder contents
             */
            
            if (!$this->cachepms || !$folderContents = $this->Redis->fetch($mckey)) {
                $query = $this->generateSQLQuery(); 
                $folderContents = $this->db->fetchAll($query);
                
                if ($this->cachepms) {
                    $this->Redis->save($mckey, $folderContents, strtotime("+12 hours"));
                }
            }
            
            return $folderContents;
        }
    }