Example #1
0
 /**
  * Save the update to the database.
  */
 public function save()
 {
     $db = Database::getInstance();
     if (!$this->target) {
         throw new \RuntimeException('Update\'s target was not set');
     }
     if (!$this->url) {
         throw new \RuntimeException('Update\'s URL was not set');
     }
     if (!$this->version) {
         throw new \RuntimeException('Update\'s version was not set');
     }
     if (!$this->id) {
         // This update is new.
         $db->query("INSERT INTO {availableupdate} (target, version, url, description) " . "VALUES (:target, :version, :url, :description)", array(':target' => $this->target, ':version' => $this->version, ':url' => $this->url, ':description' => $this->description));
         $this->id = $db->insertedId();
     } else {
         // Update existing update
         $db->query("UPDATE {availableupdate} SET target = :target, url = :url, " . "version = :version, description = :description " . "WHERE id = :id", array(':id' => $this->id, ':target' => $this->target, ':version' => $this->version, ':url' => $this->url, ':description' => $this->description));
     }
 }
Example #2
0
if ($tmp_request->isSecure()) {
    @ini_set('session.cookie_secure', true);
}
@ini_set('session.cookie_path', $tmp_request->getBasePath() . "/");
@ini_set('session.name', 'MibewSessionID');
// Remove temporary request to keep global scope clean.
unset($tmp_request);
// Initialize user session
session_start();
if (function_exists("date_default_timezone_set")) {
    $timezone = !empty($configs['timezone']) ? $configs['timezone'] : (function_exists("date_default_timezone_get") ? @date_default_timezone_get() : "GMT");
    @date_default_timezone_set($timezone);
}
if (get_maintenance_mode() === false) {
    // Initialize the database
    \Mibew\Database::initialize($configs['database']['host'], $configs['database']['port'], $configs['database']['login'], $configs['database']['pass'], $configs['database']['use_persistent_connection'], $configs['database']['db'], $configs['database']['tables_prefix']);
}
// Load all other libraries
// TODO: Rewrite libs using Object-Oriented approach
require_once MIBEW_FS_ROOT . '/libs/canned.php';
require_once MIBEW_FS_ROOT . '/libs/captcha.php';
require_once MIBEW_FS_ROOT . '/libs/chat.php';
require_once MIBEW_FS_ROOT . '/libs/groups.php';
require_once MIBEW_FS_ROOT . '/libs/invitation.php';
require_once MIBEW_FS_ROOT . '/libs/operator.php';
require_once MIBEW_FS_ROOT . '/libs/pagination.php';
require_once MIBEW_FS_ROOT . '/libs/statistics.php';
require_once MIBEW_FS_ROOT . '/libs/track.php';
require_once MIBEW_FS_ROOT . '/libs/userinfo.php';
// Run plugins only after all libs are loaded.
if (get_maintenance_mode() === false && !empty($configs['plugins'])) {
Example #3
0
 /**
  * Deletes a state from the database.
  *
  * @throws \RuntimeException If the state is not stored in the database.
  */
 public function delete()
 {
     if (!$this->id) {
         throw new \RuntimeException('You cannot delete a plugin state without ID');
     }
     Database::getInstance()->query("DELETE FROM {plugin} WHERE id = :id LIMIT 1", array(':id' => $this->id));
 }
Example #4
0
/**
 * Disables specified locale.
 *
 * @param string $locale Locale code according to RFC 5646.
 */
function disable_locale($locale)
{
    Database::getInstance()->query(
        "UPDATE {locale} SET enabled = :enabled WHERE code = :code",
        array(
            ':enabled' => 0,
            ':code' => $locale,
        )
    );
}
Example #5
0
function get_operators_from_adjacent_groups($operator)
{
    $db = Database::getInstance();
    $query = "SELECT DISTINCT {operator}.operatorid, vclogin, "
            . "vclocalename,vccommonname, "
            . "istatus, idisabled, code, "
            . "(:now - dtmlastvisited) AS time "
        . "FROM {operator}, {operatortoopgroup} "
        . "WHERE {operator}.operatorid = {operatortoopgroup}.operatorid "
            . "AND {operatortoopgroup}.groupid IN ("
                . "SELECT g.groupid from {opgroup} g, "
                    . "(SELECT DISTINCT parent FROM {opgroup}, {operatortoopgroup} "
                    . "WHERE {opgroup}.groupid = {operatortoopgroup}.groupid "
                        . "AND {operatortoopgroup}.operatorid = :operatorid) i "
                . "WHERE g.groupid = i.parent OR g.parent = i.parent "
        . ") ORDER BY vclogin";

    return $db->query(
        $query,
        array(
            ':operatorid' => $operator['operatorid'],
            ':now' => time(),
        ),
        array('return_rows' => Database::RETURN_ALL_ROWS)
    );
}
Example #6
0
/**
 * Calculate aggregated 'by page' statistics
 */
function calculate_page_statistics()
{
    // Prepare database
    $db = Database::getInstance();
    $db_throw_exceptions = $db->throwExceptions(true);

    try {
        // Start transaction
        $db->query('START TRANSACTION');

        // Get last record date
        $result = $db->query(
            "SELECT MAX(date) as start FROM {visitedpagestatistics}",
            array(),
            array('return_rows' => Database::RETURN_ONE_ROW)
        );

        $start = empty($result['start']) ? 0 : $result['start'];
        $today = floor(time() / STATISTICS_AGGREGATION_INTERVAL) * STATISTICS_AGGREGATION_INTERVAL;

        $statistics = array();

        // Calculate statistics
        // Get main pages info
        $db_results = $db->query(
            ("SELECT FLOOR(visittime / :interval) * :interval AS date, "
                . "address, "
                . "COUNT(DISTINCT pageid) AS visits "
            . "FROM {visitedpage} "
            . "WHERE calculated = 0 "
                . "AND (visittime - :start) > :interval "
                . "AND (:today - visittime) > :interval "
            . "GROUP BY date, address"),
            array(
                ':start' => $start,
                ':today' => $today,
                ':interval' => STATISTICS_AGGREGATION_INTERVAL,
            ),
            array('return_rows' => Database::RETURN_ALL_ROWS)
        );

        // Store info in statistics data
        $statistics = extend_statistics_info(
            array(),
            $db_results,
            array('date', 'address')
        );

        // Get total chats count
        $db_results = $db->query(
            ("SELECT FLOOR(p.visittime / :interval) * :interval AS date, "
                . "p.address AS address, "
                . "COUNT(DISTINCT t.threadid) AS chats "
            . "FROM {visitedpage} p, {thread} t, "
                . "(SELECT "
                    . "COUNT(*) AS msgs, "
                    . "m.threadid "
                . "FROM {message} m "
                . "WHERE m.ikind = :kind_user OR m.ikind = :kind_agent "
                . "GROUP BY m.threadid) tmp "
            . "WHERE t.referer = p.address "
                . "AND p.calculated = 0 "
                . "AND t.threadid = tmp.threadid "
                . "AND tmp.msgs > 0 "
                . "AND t.dtmchatstarted <> 0 "
                . "AND (p.visittime - :start) > :interval "
                . "AND (:today - p.visittime) > :interval "
                . "AND DATE(FROM_UNIXTIME(p.visittime)) "
                    . "= DATE(FROM_UNIXTIME(t.dtmcreated)) "
                . "AND (t.invitationstate = :not_invited "
                    . "OR t.invitationstate = :invitation_accepted) "
            . "GROUP BY date, address"),
            array(
                ':start' => $start,
                ':today' => $today,
                ':interval' => STATISTICS_AGGREGATION_INTERVAL,
                ':not_invited' => Thread::INVITATION_NOT_INVITED,
                ':invitation_accepted' => Thread::INVITATION_ACCEPTED,
                ':kind_agent' => Thread::KIND_AGENT,
                ':kind_user' => Thread::KIND_USER,
            ),
            array('return_rows' => Database::RETURN_ALL_ROWS)
        );

        // Store info in statistics data
        $statistics = extend_statistics_info(
            $statistics,
            $db_results,
            array('date', 'address')
        );

        // Get info about accepted invitations
        $db_results = $db->query(
            ("SELECT FLOOR(p.visittime / :interval) * :interval AS date, "
                . "p.address AS address, "
                . "COUNT(DISTINCT t.threadid) AS invitations_accepted "
            . "FROM {visitedpage} p, {thread} t "
            . "WHERE t.referer = p.address "
                . "AND p.calculated = 0 "
                . "AND (p.visittime - :start) > :interval "
                . "AND (:today - p.visittime) > :interval "
                . "AND DATE(FROM_UNIXTIME(p.visittime)) "
                    . "= DATE(FROM_UNIXTIME(t.dtmcreated)) "
                . "AND t.invitationstate = :invitation_accepted "
            . "GROUP BY date, address"),
            array(
                ':start' => $start,
                ':today' => $today,
                ':interval' => STATISTICS_AGGREGATION_INTERVAL,
                ':invitation_accepted' => Thread::INVITATION_ACCEPTED,
            ),
            array('return_rows' => Database::RETURN_ALL_ROWS)
        );

        // Store info in statistics data
        $statistics = extend_statistics_info(
            $statistics,
            $db_results,
            array('date', 'address')
        );

        // Get info about rejected invitations
        $db_results = $db->query(
            ("SELECT FLOOR(p.visittime / :interval) * :interval AS date, "
                . "p.address AS address, "
                . "COUNT(DISTINCT t.threadid) AS invitations_rejected "
            . "FROM {visitedpage} p, {thread} t "
            . "WHERE t.referer = p.address "
                . "AND p.calculated = 0 "
                . "AND (p.visittime - :start) > :interval "
                . "AND (:today - p.visittime) > :interval "
                . "AND DATE(FROM_UNIXTIME(p.visittime)) "
                    . "= DATE(FROM_UNIXTIME(t.dtmcreated)) "
                . "AND t.invitationstate = :invitation_rejected "
            . "GROUP BY date, address"),
            array(
                ':start' => $start,
                ':today' => $today,
                ':interval' => STATISTICS_AGGREGATION_INTERVAL,
                ':invitation_rejected' => Thread::INVITATION_REJECTED,
            ),
            array('return_rows' => Database::RETURN_ALL_ROWS)
        );

        // Store info in statistics data
        $statistics = extend_statistics_info(
            $statistics,
            $db_results,
            array('date', 'address')
        );

        // Get info about ignored invitations
        $db_results = $db->query(
            ("SELECT FLOOR(p.visittime / :interval) * :interval AS date, "
                . "p.address AS address, "
                . "COUNT(DISTINCT t.threadid) AS invitations_ignored "
            . "FROM {visitedpage} p, {thread} t "
            . "WHERE t.referer = p.address "
                . "AND p.calculated = 0 "
                . "AND (p.visittime - :start) > :interval "
                . "AND (:today - p.visittime) > :interval "
                . "AND DATE(FROM_UNIXTIME(p.visittime)) "
                    . "= DATE(FROM_UNIXTIME(t.dtmcreated)) "
                . "AND t.invitationstate = :invitation_ignored "
            . "GROUP BY date, address"),
            array(
                ':start' => $start,
                ':today' => $today,
                ':interval' => STATISTICS_AGGREGATION_INTERVAL,
                ':invitation_ignored' => Thread::INVITATION_IGNORED,
            ),
            array('return_rows' => Database::RETURN_ALL_ROWS)
        );

        // Store info in statistics data
        $statistics = extend_statistics_info(
            $statistics,
            $db_results,
            array('date', 'address')
        );

        // Sort statistics by date before save it in the database
        ksort($statistics);

        foreach ($statistics as $row) {
            // Set default values
            $row += array(
                'visits' => 0,
                'chats' => 0,
                'invitations_accepted' => 0,
                'invitations_rejected' => 0,
                'invitations_ignored' => 0,
            );

            $row['invitations_sent'] = $row['invitations_accepted']
                + $row['invitations_rejected']
                + $row['invitations_ignored'];

            // Prepare data for insert
            $insert_data = array();
            foreach ($row as $field_name => $field_value) {
                $insert_data[':' . $field_name] = $field_value;
            }

            $db->query(
                ("INSERT INTO {visitedpagestatistics} ("
                    . "date, address, visits, chats, "
                    . "sentinvitations, acceptedinvitations, "
                    . "rejectedinvitations, ignoredinvitations "
                . ") VALUES ("
                    . ":date, :address, :visits, :chats, :invitations_sent, "
                    . ":invitations_accepted, :invitations_rejected, "
                    . ":invitations_ignored "
                . ")"),
                $insert_data
            );
        }

        // Mark all visited pages as 'calculated'
        $db->query(
            ("UPDATE {visitedpage} SET calculated = 1 "
                . "WHERE (:today - visittime) > :interval "
                . "AND calculated = 0"),
            array(
                ':today' => $today,
                ':interval' => STATISTICS_AGGREGATION_INTERVAL,
            )
        );

        // Remove old tracks from the system
        track_remove_old_tracks();
    } catch (Exception $e) {
        // Something went wrong: warn and rollback transaction.
        trigger_error(
            'Page statistics calculating faild: ' . $e->getMessage(),
            E_USER_WARNING
        );
        $db->query('ROLLBACK');

        // Set throw exceptions back
        $db->throwExceptions($db_throw_exceptions);

        return;
    }

    // Commit transaction
    $db->query('COMMIT');

    // Set throw exceptions back
    $db->throwExceptions($db_throw_exceptions);
}
Example #7
0
 /**
  * Returns initialized database object.
  *
  * @return \Mibew\Database|boolean A database class instance or boolean
  *   false if something went wrong.
  */
 protected function getDatabase()
 {
     try {
         $db = Database::getInstance();
         $db->throwExceptions(true);
         return $db;
     } catch (\Exception $e) {
         $this->errors[] = getlocal("Could not retrieve database instance. Error: {0}", array($e->getMessage()));
         return false;
     }
 }
    /**
     * Removes a canned message from the database.
     *
     * @param Request $request
     * @return string Rendered page content
     */
    public function deleteAction(Request $request)
    {
        // Check for CSRF attack
        csrf_check_token($request);

        // Remove message from the database.
        $db = Database::getInstance();

        $key = $request->attributes->getInt('message_id');
        $db->query("DELETE FROM {cannedmessage} WHERE id = ?", array($key));

        // Redirect user to canned messages list. Use only "lang" and "group"
        // get params for the target URL.
        $parameters = array_intersect_key(
            $request->query->all(),
            array_flip(array('lang', 'group'))
        );

        return $this->redirect($this->generateUrl('canned_messages', $parameters));
    }
Example #9
0
 /**
  * Save the ban to the database.
  *
  * Triggers {@link \Mibew\EventDispatcher\Events::BAN_CREATE} event.
  */
 public function save()
 {
     $db = Database::getInstance();
     if (!$this->id) {
         // This ban is new.
         $db->query("INSERT INTO {ban} (dtmcreated, dtmtill, address, comment) " . "VALUES (:created, :till, :address, :comment)", array(':created' => (int) $this->created, ':till' => (int) $this->till, ':address' => $this->address, ':comment' => $this->comment));
         $this->id = $db->insertedId();
         $args = array('ban' => $this);
         EventDispatcher::getInstance()->triggerEvent(Events::BAN_CREATE, $args);
     } else {
         // Get the original state of the ban for "update" event.
         $original_ban = Ban::load($this->id);
         // Update existing ban
         $db->query("UPDATE {ban} SET dtmtill = :till, address = :address, " . "comment = :comment WHERE banid = :id", array(':id' => $this->id, ':till' => (int) $this->till, ':address' => $this->address, ':comment' => $this->comment));
         $args = array('ban' => $this, 'original_ban' => $original_ban);
         EventDispatcher::getInstance()->triggerEvent(Events::BAN_UPDATE, $args);
     }
 }
Example #10
0
 /**
  * Loads callback function
  *
  * Callback is an associative array with following keys
  *  - 'function': function name to call.
  *  - 'arguments': additional arguments, that passed to the callback
  *    function.
  *
  * @param string $token Token of the request related to callback function
  * @return mixed callback function array or null if callback function not
  *   exists
  * @todo Create some unit tests
  */
 protected function loadCallback($token)
 {
     $db = Database::getInstance();
     $callback = $db->query("SELECT * FROM {requestcallback} WHERE token = :token", array(':token' => $token), array('return_rows' => Database::RETURN_ONE_ROW));
     if (!$callback) {
         return null;
     }
     return array('function' => $callback['function'], 'arguments' => unserialize($callback['arguments']));
 }
Example #11
0
 /**
  * Return updated visitors list. API function.
  *
  * Triggers
  * {@link \Mibew\EventDispatcher\Events::USERS_UPDATE_VISITORS_LOAD} and
  * {@link \Mibew\EventDispatcher\Events::USERS_UPDATE_VISITORS_ALTER}
  * events.
  *
  * @param array $args Associative array of arguments. It must contains the
  *   following keys:
  *    - 'agentId': Id of the agent related to users window
  *
  * @return array Array of results. It contains the following keys:
  *  - 'visitors': array of visitors on the site
  */
 protected function apiUpdateVisitors($args)
 {
     // Check access
     $this->checkOperator($args['agentId']);
     // Close old invitations
     invitation_close_old();
     // Remove old visitors
     track_remove_old_visitors();
     // Get instance of event dispatcher
     $dispatcher = EventDispatcher::getInstance();
     // Trigger load event
     $arguments = array('visitors' => false);
     $dispatcher->triggerEvent(Events::USERS_UPDATE_VISITORS_LOAD, $arguments);
     // Check if visiors list loaded by plugins
     if (!is_array($arguments['visitors'])) {
         // Load visitors list
         $db = Database::getInstance();
         // Load visitors
         $query = "SELECT v.visitorid, " . "v.userid, " . "v.username, " . "v.firsttime, " . "v.lasttime, " . "v.entry, " . "v.details, " . "t.invitationstate, " . "t.dtmcreated AS invitationtime, " . "t.agentId AS invitedby, " . "v.invitations, " . "v.chats " . "FROM {sitevisitor} v " . "LEFT OUTER JOIN {thread} t " . "ON t.threadid = v.threadid " . "WHERE v.threadid IS NULL " . "OR (t.istate = :state_invited " . "AND t.invitationstate = :invitation_wait)" . "ORDER BY t.invitationstate, v.lasttime DESC, v.invitations";
         $query .= Settings::get('visitors_limit') == '0' ? "" : " LIMIT " . Settings::get('visitors_limit');
         $rows = $db->query($query, array(':state_invited' => Thread::STATE_INVITED, ':invitation_wait' => Thread::INVITATION_WAIT), array('return_rows' => Database::RETURN_ALL_ROWS));
         $visitors = array();
         foreach ($rows as $row) {
             // Get visitor details
             $details = track_retrieve_details($row);
             // Get user agent
             $user_agent = get_user_agent_version($details['user_agent']);
             // Get user ip
             if (preg_match("/(\\d+\\.\\d+\\.\\d+\\.\\d+)/", $details['remote_host'], $matches) != 0) {
                 $user_ip = $matches[1];
             } else {
                 $user_ip = false;
             }
             // Get invitation info
             $row['invited'] = $row['invitationstate'] == Thread::INVITATION_WAIT;
             if ($row['invited']) {
                 $agent_name = get_operator_name(operator_by_id($row['invitedby']));
                 $invitation_info = array('time' => $row['invitationtime'], 'agentName' => $agent_name);
             } else {
                 $invitation_info = false;
             }
             // Create resulting visitor structure
             $visitors[] = array('id' => (int) $row['visitorid'], 'userId' => $row['userid'], 'userName' => $row['username'], 'userAgent' => $user_agent, 'userIp' => $user_ip, 'remote' => $details['remote_host'], 'firstTime' => $row['firsttime'], 'lastTime' => $row['lasttime'], 'invitations' => (int) $row['invitations'], 'chats' => (int) $row['chats'], 'invitationInfo' => $invitation_info);
         }
     } else {
         $visitors = $arguments['visitors'];
     }
     // Provide ability to alter visitors list
     $arguments = array('visitors' => $visitors);
     $dispatcher->triggerEvent(Events::USERS_UPDATE_VISITORS_ALTER, $arguments);
     // Send results back to the client. "array_values" function should be
     // used to avoid problems with JSON conversion. If there will be gaps in
     // keys (the keys are not serial) JSON Object will be produced instead
     // of an Array.
     return array('visitors' => array_values($arguments['visitors']));
 }
Example #12
0
 /**
  * Return next revision number (last revision number plus one)
  *
  * @return int revision number
  */
 protected static function nextRevision()
 {
     $db = Database::getInstance();
     $db->query("UPDATE {revision} SET id=LAST_INSERT_ID(id+1)");
     $val = $db->insertedId();
     return $val;
 }
 /**
  * Loads translated string from the database by its ID.
  *
  * @param int $id ID of the translated string in the database.
  * @return array|boolean Associative array with string info or boolean false
  *   it the string is not found.
  */
 protected function loadString($id)
 {
     $string = Database::getInstance()->query("SELECT * FROM {translation} WHERE translationid = :id", array(':id' => $id), array('return_rows' => Database::RETURN_ONE_ROW));
     return $string ? $string : false;
 }
Example #14
0
 /**
  * Returns initialized database object.
  *
  * @return \Mibew\Database|boolean A database class instance or boolean
  *   false if something went wrong.
  */
 protected function getDatabase()
 {
     if (!Database::isInitialized()) {
         try {
             Database::initialize($this->configs['database']['host'], $this->configs['database']['port'], $this->configs['database']['login'], $this->configs['database']['pass'], $this->configs['database']['use_persistent_connection'], $this->configs['database']['db'], $this->configs['database']['tables_prefix']);
         } catch (\PDOException $e) {
             $this->errors[] = getlocal("Could not connect. Please check server settings in config.yml. Error: {0}", array($e->getMessage()));
             return false;
         }
     }
     $db = Database::getInstance();
     $db->throwExceptions(true);
     return $db;
 }
Example #15
0
function get_operator_group_ids($operator_id)
{
    $rows = Database::getInstance()->query("SELECT groupid FROM {operatortoopgroup} WHERE operatorid = ?", array($operator_id), array('return_rows' => Database::RETURN_ALL_ROWS));
    $groups = array();
    foreach ($rows as $row) {
        $groups[] = $row['groupid'];
    }
    return $groups;
}
Example #16
0
/**
 * Updates set of groups the operator belongs to.
 *
 * Triggers {@link \Mibew\EventDispatcher\Events::GROUP_UPDATE_OPERATORS} event.
 *
 * @param int $operator_id ID of the operator.
 * @param array $new_value List of operator's groups IDs.
 */
function update_operator_groups($operator_id, $new_value)
{
    // Get difference of groups the operator belongs to before and after the
    // update.
    $original_groups = get_operator_group_ids($operator_id);
    $groups_union = array_unique(array_merge($original_groups, $new_value));
    $groups_intersect = array_intersect($original_groups, $new_value);
    $updated_groups = array_diff($groups_union, $groups_intersect);

    // Get members of all updated groups. It will be used to trigger the
    // "update" event later.
    $original_relations = array();
    foreach ($updated_groups as $group_id) {
        $original_relations[$group_id] = get_group_members($group_id);
    }

    // Update group members
    $db = Database::getInstance();
    $db->query(
        "DELETE FROM {operatortoopgroup} WHERE operatorid = ?",
        array($operator_id)
    );

    foreach ($new_value as $group_id) {
        $db->query(
            "INSERT INTO {operatortoopgroup} (groupid, operatorid) VALUES (?,?)",
            array($group_id, $operator_id)
        );
    }

    // Trigger the "update" event
    foreach ($original_relations as $group_id => $operators) {
        $args = array(
            'group' => group_by_id($group_id),
            'original_operators' => $operators,
            'operators' => get_group_members($group_id),
        );
        EventDispatcher::getInstance()->triggerEvent(Events::GROUP_UPDATE_OPERATORS, $args);
    }
}
Example #17
0
 /**
  * Redirects a chat thread to the operator with the specified ID.
  *
  * @param \Mibew\Thread $thread Chat thread to redirect.
  * @param int $group_id ID of the target operator.
  * @return boolean True if the thread was redirected and false on failure.
  */
 protected function redirectToOperator(Thread $thread, $operator_id)
 {
     if ($thread->state != Thread::STATE_CHATTING) {
         // We can redirect only threads which are in proggress now.
         return false;
     }
     // Redirect the thread
     $thread->state = Thread::STATE_WAITING;
     $thread->nextAgent = $operator_id;
     $thread->agentId = 0;
     // Check if the target operator belongs to the current thread's group.
     // If not reset the current thread's group.
     if ($thread->groupId != 0) {
         $db = Database::getInstance();
         list($groups_count) = $db->query("SELECT count(*) AS count " . "FROM {operatortoopgroup} " . "WHERE operatorid = ? AND groupid = ?", array($operator_id, $thread->groupId), array('return_rows' => Database::RETURN_ONE_ROW, 'fetch_type' => Database::FETCH_NUM));
         if ($groups_count === 0) {
             $thread->groupId = 0;
         }
     }
     $thread->save();
     // Send notification message
     $thread->postMessage(Thread::KIND_EVENTS, getlocal('Operator {0} redirected you to another operator. Please wait a while.', array(get_operator_name($this->getOperator())), $thread->locale, true));
     return true;
 }
Example #18
0
/**
 * Add new canned message to database
 *
 * @param string $locale RFC 5646 code for language
 * @param integer $group_id Group ID for the canned messages
 * @param string $title title of canned message
 * @param string $message body of canned message
 */
function add_canned_message($locale, $group_id, $title, $message)
{
    $db = Database::getInstance();
    $db->query("INSERT INTO {cannedmessage} (locale,groupid,vctitle,vcvalue) " . "VALUES (?, ?, ?, ?)", array($locale, $group_id ? $group_id : null, $title, $message));
}
 /**
  * Generates a page with a user history.
  *
  * @param Request $request
  * @return string Rendered page content
  */
 public function userAction(Request $request)
 {
     $operator = $this->getOperator();
     $user_id = $request->attributes->get('user_id', '');
     $page = array();
     if (!empty($user_id)) {
         $db = Database::getInstance();
         $query = "SELECT {thread}.* " . "FROM {thread} " . "WHERE userid=:user_id " . "AND (invitationstate = :invitation_accepted " . "OR invitationstate = :invitation_not_invited) " . "ORDER BY dtmcreated DESC";
         $found = $db->query($query, array(':user_id' => $user_id, ':invitation_accepted' => Thread::INVITATION_ACCEPTED, ':invitation_not_invited' => Thread::INVITATION_NOT_INVITED), array('return_rows' => Database::RETURN_ALL_ROWS));
     } else {
         $found = null;
     }
     $page = array_merge($page, prepare_menu($operator));
     // Setup pagination
     $pagination = setup_pagination($found, 6);
     $page['pagination'] = $pagination['info'];
     $page['pagination.items'] = $pagination['items'];
     if (!empty($page['pagination.items'])) {
         foreach ($page['pagination.items'] as $key => $item) {
             $thread = Thread::createFromDbInfo($item);
             $page['pagination.items'][$key] = array('threadId' => $thread->id, 'userName' => $thread->userName, 'userAddress' => get_user_addr($thread->remote), 'agentName' => $thread->agentName, 'chatTime' => $thread->modified - $thread->created, 'chatCreated' => $thread->created);
         }
     }
     $page['title'] = getlocal("Visit history");
     $page['menuid'] = "history";
     return $this->render('history_user', $page);
 }
Example #20
0
/**
 * Imports all locale's content (messages, mail templates, configs) to database.
 *
 * This function does not create the locale in database so you have to create it
 * by yourself.
 *
 * @param string $locale Code of the locale to import.
 */
function import_locale_content($locale)
{
    $config = (read_locale_config(MIBEW_FS_ROOT . '/locales/' . $locale . '/config.yml') ?: array()) + array('name' => $locale, 'rtl' => false, 'time_locale' => 'en_US', 'date_format' => array('full' => '%B %d, %Y %I:%M %p', 'date' => '%B %d, %Y', 'time' => '%I:%M %p'));
    Database::getInstance()->query('UPDATE {locale} SET ' . 'name = :name, rtl = :rtl, time_locale = :time_locale,' . 'date_format = :date_format ' . 'WHERE code = :code', array(':code' => $locale, ':name' => $config['name'], ':rtl' => $config['rtl'] ? 1 : 0, ':time_locale' => $config['time_locale'], ':date_format' => serialize($config['date_format'])));
    // Import localized messages to the just created locale
    import_messages($locale, MIBEW_FS_ROOT . '/locales/' . $locale . '/translation.po', true);
    // Import canned messages for the locale if they exist in the locale's
    // files.
    $canned_messages_file = MIBEW_FS_ROOT . '/locales/' . $locale . '/canned_messages.yml';
    if (is_readable($canned_messages_file)) {
        import_canned_messages($locale, $canned_messages_file);
    }
    // Import mail templates for the locale if they exist in the locale's
    // files.
    $mail_templates_file = MIBEW_FS_ROOT . '/locales/' . $locale . '/mail_templates.yml';
    if (is_readable($mail_templates_file)) {
        MailUtils::importTemplates($locale, $mail_templates_file);
    }
}
Example #21
0
 /**
  * Saves the template to database.
  */
 public function save()
 {
     $db = Database::getInstance();
     if (!$this->id) {
         // This template is new.
         $db->query('INSERT INTO {mailtemplate} (locale, name, subject, body) ' . 'VALUES (:locale, :name, :subject, :body)', array(':locale' => $this->locale, ':name' => $this->name, ':subject' => $this->subject, ':body' => $this->body));
         $this->id = $db->insertedId();
     } else {
         // Update the existing template
         $db->query('UPDATE {mailtemplate} SET locale = :locale, name = :name, ' . 'subject = :subject, body = :body WHERE templateid = :id', array(':id' => $this->id, ':locale' => $this->locale, ':name' => $this->name, ':subject' => $this->subject, ':body' => $this->body));
     }
 }
Example #22
0
/**
 * 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();
    }
}
Example #23
0
/**
 * Bind chat thread with visitor
 *
 * @param string $user_id User ID ({sitevisitor}.userid field) of the
 * visitor.
 * @param Thread $thread Chat thread object
 */
function track_visitor_bind_thread($user_id, $thread)
{
    $db = Database::getInstance();
    $db->query('UPDATE {sitevisitor} ' . 'SET threadid = :thread_id ' . 'WHERE userid = :user_id', array(':thread_id' => $thread->id, ':user_id' => $user_id));
}