/** * Close all old threads that were not closed by some reasons. */ public static function closeOldThreads() { if (Settings::get('thread_lifetime') == 0) { // Threads live forever. return; } // We need to run only one instance of cleaning process. $lock = new ProcessLock('threads_close_old'); if ($lock->get()) { $query = "SELECT * FROM {thread} " . "WHERE istate <> :state_closed " . "AND istate <> :state_left " . "AND ABS(:now - dtmcreated) > :thread_lifetime " . "AND ( " . "( " . "lastpingagent <> 0 " . "AND lastpinguser <> 0 " . "AND ABS(:now - lastpinguser) > :thread_lifetime " . "AND ABS(:now - lastpingagent) > :thread_lifetime " . ") OR ( " . "lastpingagent = 0 " . "AND lastpinguser <> 0 " . "AND ABS(:now - lastpinguser) > :thread_lifetime " . ") OR ( " . "lastpinguser = 0 " . "AND lastpingagent <> 0 " . "AND ABS(:now - lastpingagent) > :thread_lifetime " . ") OR ( " . "lastpinguser = 0 " . "AND lastpingagent = 0 " . ") " . ")"; // Get appropriate threads $now = time(); $rows = Database::getInstance()->query($query, array(':now' => $now, ':state_closed' => self::STATE_CLOSED, ':state_left' => self::STATE_LEFT, ':thread_lifetime' => Settings::get('thread_lifetime')), array('return_rows' => Database::RETURN_ALL_ROWS)); // Perform the cleaning $revision = self::nextRevision(); foreach ($rows as $row) { $thread = Thread::createFromDbInfo($row); $thread->lastRevision = $revision; $thread->modified = $now; $thread->closed = $now; $thread->state = self::STATE_CLOSED; $thread->save(); unset($thread); } // Release the lock $lock->release(); } }
/** * Close old invitations. * * Triggers {@link \Mibew\EventDispatcher\Events::INVITATION_IGNORE} event. */ function invitation_close_old() { // Run only one instance of cleaning process. $lock = new ProcessLock('invitations_close_old'); if ($lock->get()) { // Freeze the time for the whole cleaning process. $now = time(); $db = Database::getInstance(); // Remove links between visitors and invitations that will be closed. $db->query("UPDATE {sitevisitor} v, {thread} t SET " . "v.threadid = NULL " . "WHERE t.istate = :state_invited " . "AND t.invitationstate = :invitation_wait " . "AND (:now - t.dtmcreated) > :lifetime", array(':invitation_wait' => Thread::INVITATION_WAIT, ':state_invited' => Thread::STATE_INVITED, ':lifetime' => Settings::get('invitation_lifetime'), ':now' => $now)); // Get all invitations to close $threads = $db->query("SELECT * FROM {thread} " . "WHERE istate = :state_invited " . "AND invitationstate = :invitation_wait " . "AND (:now - dtmcreated) > :lifetime", array(':invitation_wait' => Thread::INVITATION_WAIT, ':state_invited' => Thread::STATE_INVITED, ':lifetime' => Settings::get('invitation_lifetime'), ':now' => $now), array('return_rows' => Database::RETURN_ALL_ROWS)); // Close the invitations foreach ($threads as $thread_info) { $thread = Thread::createFromDbInfo($thread_info); $thread->invitationState = Thread::INVITATION_IGNORED; $thread->state = Thread::STATE_CLOSED; $thread->closed = $now; $thread->save(); // Notify the operator about autoclosing $thread->postMessage(Thread::KIND_FOR_AGENT, getlocal('Visitor ignored invitation and it was closed automatically', null, $thread->locale, true)); $args = array('invitation' => $thread); EventDispatcher::getInstance()->triggerEvent(Events::INVITATION_IGNORE, $args); unset($thread); } // Release the lock $lock->release(); } }
/** * Remove old visitors. * * Triggers {@link \Mibew\EventDispatcher\Events::VISITOR_DELETE_OLD} event. */ function track_remove_old_visitors() { $lock = new ProcessLock('visitors_remove_old'); if ($lock->get()) { // Freeze the time for the whole process $now = time(); $db = Database::getInstance(); // Remove associations of visitors with closed threads $db->query("UPDATE {sitevisitor} SET threadid = NULL " . "WHERE threadid IS NOT NULL AND " . "(SELECT count(*) FROM {thread} " . "WHERE threadid = {sitevisitor}.threadid " . "AND istate <> " . Thread::STATE_CLOSED . " " . "AND istate <> " . Thread::STATE_LEFT . ") = 0 "); // Get all visitors that will be removed. They will be used in the // "delete" event later. $rows = $db->query("SELECT visitorid FROM {sitevisitor} " . "WHERE (:now - lasttime) > :lifetime " . "AND threadid IS NULL", array(':lifetime' => Settings::get('tracking_lifetime'), ':now' => $now), array('return_rows' => Database::RETURN_ALL_ROWS)); $removed_visitors = array(); foreach ($rows as $row) { $removed_visitors[] = $row['visitorid']; } // Remove old visitors $db->query("DELETE FROM {sitevisitor} " . "WHERE (:now - lasttime) > :lifetime " . "AND threadid IS NULL", array(':lifetime' => Settings::get('tracking_lifetime'), ':now' => $now)); // Trigger the "delete" event only if visitors was removed. if (count($removed_visitors) > 0) { $args = array('visitors' => $removed_visitors); EventDispatcher::getInstance()->triggerEvent(Events::VISITOR_DELETE_OLD, $args); } // Release the lock $lock->release(); } }