/** * 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)); } }
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'])) {
/** * 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)); }
/** * 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, ) ); }
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) ); }
/** * 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); }
/** * 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)); }
/** * 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); } }
/** * 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'])); }
/** * 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'])); }
/** * 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; }
/** * 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; }
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; }
/** * 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); } }
/** * 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; }
/** * 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); }
/** * 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); } }
/** * 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)); } }
/** * 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(); } }
/** * 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)); }