本文整理汇总了PHP中Q::log方法的典型用法代码示例。如果您正苦于以下问题:PHP Q::log方法的具体用法?PHP Q::log怎么用?PHP Q::log使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类Q
的用法示例。
在下文中一共展示了Q::log方法的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的PHP代码示例。
示例1: Q_errors_native
function Q_errors_native($params)
{
echo Q::view('Q/errors.php', $params);
$app = Q_Config::expect('Q', 'app');
Q::log("{$app}: Errors in " . ceil(Q::milliseconds()) . "ms\n");
Q::log($params);
}
示例2: log_shard_query
function log_shard_query($params)
{
foreach ($params['queries'] as $shard => $query) {
if ($query->className === 'Users_Session') {
continue;
}
$connection = $query->db->connectionName();
if ($begin = $query->getClause('BEGIN') and $query->nestedTransactionCount == 1) {
Q::log($begin);
}
$duration = ceil($query->endedTime - $query->startedTime);
Q::log("Query {$connection} on shard \"{$shard}\":\n{$params['sql']}\n(duration: {$duration} ms)\n\n");
if ($commit = $query->getClause('COMMIT') and $query->nestedTransactionCount == 0) {
Q::log($commit);
}
if (!empty($params['exception'])) {
Q::log("ROLLBACK (due to exception)");
Q::log("query was: " . $params['sql']);
Q::log($params['exception']);
} else {
if ($rollback = $query->getClause('ROLLBACK')) {
Q::log($rollback);
}
}
}
}
示例3: execute
/**
* Excecute web request
* @method execute
* @static
*/
static function execute()
{
// Fixes for different platforms:
if (isset($_SERVER['HTTP_X_REWRITE_URL'])) {
// ISAPI 3.0
$_SERVER['REQUEST_URI'] = $_SERVER['HTTP_X_REWRITE_URL'];
}
// Get the base URL
$base_url = Q_Request::baseUrl();
if (Q::$controller === 'Q_ActionController') {
// we detected action.php in the URL, but
// a misconfigured web server executed index.php instead
return Q_ActionController::execute();
}
// Set the controller that is being used
if (!isset(Q::$controller)) {
Q::$controller = 'Q_WebController';
}
try {
$slots = Q_Request::slotNames(false);
$slots = $slots ? ' slots: (' . implode(',', $slots) . ') from' : '';
$method = Q_Request::method();
Q::log("{$method}{$slots} url: " . Q_Request::url(true), null, null, array('maxLength' => 10000));
Q_Dispatcher::dispatch();
$dispatchResult = Q_Dispatcher::result();
if (!isset($dispatchResult)) {
$dispatchResult = 'Ran dispatcher';
}
$uri = Q_Request::uri();
$module = $uri->module;
$action = $uri->action;
if ($module and $action) {
$slotNames = Q_Request::slotNames();
$returned_slots = empty($slotNames) ? '' : implode(',', $slotNames);
Q::log("~" . ceil(Q::milliseconds()) . 'ms+' . ceil(memory_get_peak_usage() / 1000) . 'kb.' . " {$dispatchResult} for {$module}/{$action}" . " ({$returned_slots})", null, null, array('maxLength' => 10000));
} else {
Q::log("~" . ceil(Q::milliseconds()) . 'ms+' . ceil(memory_get_peak_usage() / 1000) . 'kb.' . " {$dispatchResult} No route for " . $_SERVER['REQUEST_URI'], null, null, array('maxLength' => 10000));
}
} catch (Exception $exception) {
/**
* @event Q/exception
* @param {Exception} exception
*/
Q::event('Q/exception', compact('exception'));
}
}
示例4: log
/**
* Logs a message.
*
* @param $sMessage @type string The message.
*/
public function log($sMessage)
{
Q::log(trim($sMessage), 'apns');
}
示例5: Q_exception_native
function Q_exception_native($params)
{
extract($params);
/**
* @var Exception $exception
*/
if ($is_ajax = Q_Request::isAjax()) {
$json = @Q::json_encode(array('errors' => Q_Exception::toArray(array($exception))));
$callback = Q_Request::callback();
switch (strtolower($is_ajax)) {
case 'iframe':
// Render an HTML layout for ajax
if (!Q_Response::$batch) {
header("Content-type: text/html");
}
echo <<<EOT
<!doctype html><html lang=en>
<head><meta charset=utf-8><title>Q Result</title></head>
<body>
<script type="text/javascript">
window.result = function () { return {$json} };
</script>
</body>
</html>
EOT;
break;
case 'json':
// Render a JSON layout for ajax
// Render a JSON layout for ajax
default:
header("Content-type: " . ($callback ? "application/javascript" : "application/json"));
echo $callback ? "{$callback}({$json})" : $json;
}
} else {
if (Q::textMode()) {
echo Q_Exception::coloredString($exception);
exit;
}
$message = $exception->getMessage();
$file = $exception->getFile();
$line = $exception->getLine();
if (is_callable(array($exception, 'getTraceAsStringEx'))) {
$trace_string = $exception->getTraceAsStringEx();
} else {
$trace_string = $exception->getTraceAsString();
}
if ($exception instanceof Q_Exception_PhpError or !empty($exception->messageIsHtml)) {
// do not sanitize $message
} else {
$message = Q_Html::text($message);
}
$content = "<h1 class='exception_message'>{$message}</h1>";
if (Q_Config::get('Q', 'exception', 'showFileAndLine', true)) {
$content .= "<h3 class='exception_fileAndLine'>in {$file} ({$line})</h3>";
}
if (Q_Config::get('Q', 'exception', 'showTrace', true)) {
$content .= "<pre class='exception_trace'>{$trace_string}</pre>";
}
$content .= str_repeat(' ', 512);
// because of chrome
$title = "Exception occurred";
$dashboard = "";
echo Q::view('Q/layout/html.php', compact('content', 'dashboard', 'title'));
}
$app = Q_Config::get('Q', 'app', null);
$colored = Q_Exception::coloredString($exception);
Q::log("{$app}: Exception in " . ceil(Q::milliseconds()) . "ms:\n\n{$colored}\n", null, true, array('maxLength' => 10000));
}
示例6: Streams_interest_post
/**
* Used to create a new stream
*
* @param {array} $_REQUEST
* @param {String} [$_REQUEST.title] Required. The title of the interest.
* @param {String} [$_REQUEST.publisherId] Optional. Defaults to the app name.
* @param {String} [$_REQUEST.subscribe] Optional. Defauls to false. Whether to subscribe rather than just join the interest stream.
* @return {void}
*/
function Streams_interest_post()
{
$user = Users::loggedInUser(true);
$title = Q::ifset($_REQUEST, 'title', null);
if (!isset($title)) {
throw new Q_Exception_RequiredField(array('field' => 'title'));
}
$app = Q_Config::expect('Q', 'app');
$publisherId = Q::ifset($_REQUEST, 'publisherId', $app);
$name = 'Streams/interest/' . Q_Utils::normalize($title);
$stream = Streams::fetchOne(null, $publisherId, $name);
if (!$stream) {
$stream = Streams::create($publisherId, $publisherId, 'Streams/interest', array('name' => $name, 'title' => $title));
$parts = explode(': ', $title, 2);
$keywords = implode(' ', $parts);
try {
$data = Q_Image::pixabay($keywords, array('orientation' => 'horizontal', 'min_width' => '500', 'safesearch' => 'true', 'image_type' => 'photo'), true);
} catch (Exception $e) {
Q::log("Exception during Streams/interest post: " . $e->getMessage());
$data = null;
}
if (!empty($data)) {
$sizes = Q_Config::expect('Streams', 'icons', 'sizes');
ksort($sizes);
$params = array('data' => $data, 'path' => "plugins/Streams/img/icons", 'subpath' => $name, 'save' => $sizes, 'skipAccess' => true);
Q_Image::save($params);
$stream->icon = $name;
}
$stream->save();
}
$subscribe = !!Q::ifset($_REQUEST, 'subscribe', false);
if ($subscribe) {
if (!$stream->subscription($user->id)) {
$stream->subscribe();
}
} else {
$stream->join();
}
$myInterestsName = 'Streams/user/interests';
$myInterests = Streams::fetchOne($user->id, $user->id, $myInterestsName);
if (!$myInterests) {
$myInterests = new Streams_Stream();
$myInterests->publisherId = $user->id;
$myInterests->name = $myInterestsName;
$myInterests->type = 'Streams/category';
$myInterests->title = 'My Interests';
$myInterests->save();
}
Streams::relate($user->id, $user->id, 'Streams/user/interests', 'Streams/interest', $publisherId, $name, array('weight' => '+1'));
Q_Response::setSlot('publisherId', $publisherId);
Q_Response::setSlot('streamName', $name);
/**
* Occurs when the logged-in user has successfully added an interest via HTTP
* @event Streams/interest/post {after}
* @param {string} publisherId The publisher of the interest stream
* @param {string} title The title of the interest
* @param {boolean} subscribe Whether the user subscribed to the interest stream
* @param {Users_User} user The logged-in user
* @param {Streams_Stream} stream The interest stream
* @param {Streams_Stream} myInterests The user's "Streams/user/interests" stream
*/
Q::event("Streams/interest/add", compact('publisherId', 'title', 'subscribe', 'user', 'stream', 'myInterests'), 'after');
}
示例7: shutdownFunction
/**
* @method shutdownFunction
* @static
*/
static function shutdownFunction()
{
if ($error = error_get_last()) {
Q::log($error, 'fatal');
header('PHP Fatal Error', true, 500);
// do not expose the error contents
}
/**
* @event Q/shutdown {before}
*/
Q::event('Q/shutdown', compact('error'), 'before');
Q_Cache::shutdownFunction();
if (Q_Session::id()) {
session_write_close();
}
}
示例8: writeHandler
/**
* @method writeHandler
* @static
* @param {string} $id
* @param {string} $sess_data
* @return {boolean}
*/
static function writeHandler($id, $sess_data)
{
try {
// if the request is AJAX request that came without session cookie, then do not write session, ignore it
if (Q_Request::isAjax() && !isset($_COOKIE[self::name()])) {
return false;
}
// don't save sessions when running from command-line (cli)
if (php_sapi_name() == 'cli') {
return false;
}
$our_SESSION = $_SESSION;
$old_data = self::$sess_data;
$changed = $sess_data !== $old_data;
$result = false;
/**
* @event Q/session/write {before}
* @param {string} id
* @param {string} sess_data
* @param {string} old_data
* @param {boolean} changed
* @return {boolean}
*/
if (false === Q::event('Q/session/write', compact('id', 'sess_data', 'old_data', 'changed'), 'before')) {
return false;
}
if (empty(self::$session_save_path)) {
self::$session_save_path = self::savePath();
}
if (!empty(self::$session_db_connection)) {
// Create a new row to be saved in the session table
$db_row_class = self::$session_db_row_class;
// Make sure it has a primary key!
if (count(self::$session_db_row->getPrimaryKey()) != 1) {
throw new Q_Exception("The primary key of " . self::$session_db_row_class . " has to consist of exactly 1 field!");
}
$id_field = self::$session_db_id_field;
$data_field = self::$session_db_data_field;
$updated_field = self::$session_db_updated_field;
$duration_field = self::$session_db_duration_field;
$row = self::$session_db_row;
$row->{$id_field} = $id;
} else {
$duration_name = self::durationName();
$id1 = substr($id, 0, 4);
$id2 = substr($id, 4);
$ssp = self::$session_save_path;
$sess_file = $ssp . DS . "{$duration_name}/{$id1}/{$id2}";
$dir = $ssp . DS . "{$duration_name}/{$id1}/";
}
if ($changed) {
// Apparently, we want to save some changes.
// The convention to avoid locking is that everything
// stored in sessions must be mergeable using the
// Q_Tree merge algorithm.
// So we will retrieve the latest session data again,
// merge our changes over it, and save.
$params = array('id_field' => $id_field, 'data_field' => $data_field, 'updated_field' => $updated_field, 'duration_field' => $duration_field, 'changed' => $changed, 'sess_data' => $sess_data, 'old_data' => $old_data);
if (!empty(self::$session_db_connection)) {
$row->retrieve();
$existing_data = Q::ifset($row, $data_field, "");
$params['row'] = $row;
} else {
if (!is_dir($dir)) {
mkdir($dir, fileperms($ssp), true);
}
if (!is_writable($dir)) {
// alert the developer to this problem
Q::log("{$sess_file} is not writable", 'fatal');
die("{$sess_file} is not writable");
}
$file = fopen($sess_file, "w");
if (!$file) {
return false;
}
$params['row'] = $row;
$maxlength = Q_Config::get('Q', 'session', 'maxlength', 4095);
$existing_data = fread($file, $maxlength);
}
$_SESSION = session_decode($existing_data);
if (!$_SESSION) {
$_SESSION = array();
}
$t = new Q_Tree($_SESSION);
$t->merge($our_SESSION);
$_SESSION = $t->getAll();
$params['existing_data'] = $existing_data;
$params['merged_data'] = $merged_data = session_encode();
/**
* @event Q/session/save {before}
* @param {string} sess_data
* @param {string} old_data
* @param {string} existing_data
//.........这里部分代码省略.........
示例9: setCookie
/**
* @method setCookie
* @static
* @param {string} $name
* @param {string} $value
* @param {string} [$expires=0]
* @param {string} [$path=false]
* @return {string}
*/
static function setCookie($name, $value, $expires = 0, $path = false)
{
if (empty($_SERVER['HTTP_HOST'])) {
Q::log('Warning: Ignoring call to Q_Response::setCookie() without $_SERVER["HTTP_HOST"]' . PHP_EOL);
return false;
}
if (isset($_COOKIE[$name]) and $_COOKIE[$name] === $value) {
return;
}
$parts = parse_url(Q_Request::baseUrl());
$path = $path ? $path : !empty($parts['path']) ? $parts['path'] : '/';
$domain = '.' . $parts['host'];
setcookie($name, $value, $expires, $path, $domain);
$_COOKIE[$name] = $value;
$header = 'P3P: CP="IDC DSP COR CURa ADMa OUR IND PHY ONL COM STA"';
$header = Q::event('Q/Response/setCookie', compact('name', 'value', 'expires', 'path', 'header'), 'before', false, $header);
header($header);
return $value;
}
示例10: sendMessage
/**
* @method sendMessage
* @param {string} $view
* The name of a view for the message. Fields are passed to this array.
* @param {array} $fields=array()
* The fields referenced in the subject and/or view
* @param {array} $options=array()
* Array of options. Can include:<br/>
* "delay" => A delay, in milliseconds, to wait until sending email. Only works if Node server is listening.
* @return {boolean}
* @throws {Q_Exception_WrongType}
* If phone number is invalid
*/
function sendMessage($view, $fields = array(), $options = array())
{
/**
* @event Users/sms/sendMessage {before}
* @param {string} view
* @param {array} fields
* @param {array} options
* @return {boolean}
*/
$result = Q::event('Users/sms/sendMessage', compact('view', 'fields', 'options'), 'before');
if (isset($result)) {
return $result;
}
if (!Q_Valid::phone($this->number, $number)) {
throw new Q_Exception_WrongType(array('field' => '$this->number', 'type' => 'mobile number', 'mobileNumber' => $this->number));
}
$app = Q_Config::expect('Q', 'app');
$body = Q::view($view, $fields);
$overrideLog = Q::event('Users/mobile/log', compact('mobileNumber', 'body'), 'before');
if (is_null($overrideLog) and $key = Q_Config::get('Users', 'mobile', 'log', 'key', null)) {
Q::log("\nSent mobile message to {$this->number}:\n{$body}", $key);
}
$sent = false;
if (!empty($options['delay'])) {
// Try to use Node.js to send the message
$sent = Q_Utils::sendToNode(array("Q/method" => "Users/sendMessage", "delay" => $options['delay'], "mobileNumber" => $number, "body" => $body, "options" => $options));
}
if (!$sent) {
$from = Q::ifset($options, 'from', Q_Config::get('Users', 'mobile', 'from', null));
if (!isset($from)) {
// deduce from base url
$url_parts = parse_url(Q_Request::baseUrl());
$domain = $url_parts['host'];
$from = array("notifications@{$domain}", $domain);
}
$sid = Q_Config::get('Users', 'mobile', 'twilio', 'sid', null);
$token = Q_Config::get('Users', 'mobile', 'twilio', 'token', null);
if ($sid and $token) {
$client = new Services_Twilio($sid, $token);
$message = $client->account->sms_messages->create($from, $number, Q::view($view, $fields));
} else {
if (!Q_Config::get('Users', 'email', 'smtp', null)) {
Q_Response::setNotice("Q/mobile", "Please set up transport in Users/mobile/twilio as in docs", false);
return true;
}
if (!is_array($from)) {
$from = array($from, "{$app} activation");
}
// Set up the default mail transport
$host = Q_Config::get('Users', 'email', 'smtp', 'host', 'sendmail');
if ($host === 'sendmail') {
$transport = new Zend_Mail_Transport_Sendmail('-f' . reset($from));
} else {
if (is_array($host)) {
$smtp = $host;
$host = $smtp['host'];
unset($smtp['host']);
} else {
$smtp = null;
}
$transport = new Zend_Mail_Transport_Smtp($host, $smtp);
}
$mail = new Zend_Mail();
$from_name = reset($from);
$mail->setFrom(next($from), $from_name);
$gateways = Q_Config::get('Users', 'mobile', 'gateways', array('at&t' => 'txt.att.net', 'sprint' => 'messaging.sprintpcs.com', 'verizon' => 'vtext.com', 't-mobile' => 'tmomail.net'));
$number2 = substr($this->number, 2);
foreach ($gateways as $k => $v) {
$mail->addTo($number2 . '@' . $v);
}
$mail->setBodyText($body);
try {
$mail->send($transport);
} catch (Exception $e) {
throw new Users_Exception_MobileMessage(array('error' => $e->getMessage()));
}
}
}
/**
* @event Users/sms/sendMessage {after}
* @param {string} view
* @param {array} fields
* @param {array} options
* @param {string} mail
*/
Q::event('Users/email/sendMessage', compact('view', 'fields', 'options', 'mail', 'app'), 'after');
return true;
//.........这里部分代码省略.........
示例11: pdo
/**
* Gets the key into the associative $pdo_array
* corresponding to some database credentials.
* @method pdo
* @protected
* @static
* @param {string} $dsn The dsn to create PDO
* @param {string} $username Username for connection
* @param {string} $password Passwork for connection
* @param {array} $driver_options Driver options
* @return {PDO}
*/
protected static function pdo($dsn, $username, $password, $driver_options)
{
$key = $dsn . $username . $password . serialize($driver_options);
if (isset(self::$pdo_array[$key])) {
return self::$pdo_array[$key];
}
// Make a new connection to a database!
try {
self::$pdo_array[$key] = @new PDO($dsn, $username, $password, $driver_options);
} catch (Exception $e) {
if (class_exists('Q_Config') and Q_Config::get('Db', 'exceptions', 'log', true)) {
Q::log($e);
}
throw $e;
}
return self::$pdo_array[$key];
}
示例12: smartTag
/**
* Renders a different tag based on what you specified.
* @method smartTag
* @static
* @param {string} $type The type of the tag. Could be one of
* 'static', 'boolean', 'text', 'email', 'tel',
* 'textarea', 'password', 'select',
* 'radios', 'checkboxes', 'buttons', 'submit_buttons',
* 'submit', 'hidden', 'image', or the name of a tag.
* @param {array|string} [$attributes=array()] The attributes for the resulting element. Should at least include the name. You can also just pass the name as a string here.
* @param {array} [$value=null] The value to start out with in the resulting element. If there are options present, this should be the value of one of the options.
* @param {array} [$options=null] Associative array of options, used if the tag type is 'select', 'radios' or 'checkboxes'.
* @param {array} [$params=array()] Additional parameters to pass to the corresponding function
* @return {string} The generated markup
*/
static function smartTag($type, $attributes = array(), $value = null, $options = null, $params = array())
{
if (!isset($type)) {
throw new Q_Exception_RequiredField(array('field' => 'type'));
}
if (is_string($attributes)) {
$attributes = array('name' => $attributes);
}
if (!is_array($attributes)) {
$attributes = array();
}
$id = isset($attributes['id']) ? $attributes['id'] : null;
switch ($type) {
case 'hidden':
return self::hidden($value, isset($attributes['name']) ? $attributes['name'] : null, isset($params[0]) ? $params[0] : true);
case 'static':
unset($attributes['name']);
if (empty($options['date'])) {
$display = isset($options[$value]) ? $options[$value] : $value;
} else {
$v = is_numeric($value) ? $value : strtotime($value);
$display = (!empty($v) and substr($v, 0, 4) !== '0000') ? date($options['date'], $v) : '';
Q::log("\n\n{$v}\n{$display}\n\n");
}
return self::tag('span', $attributes, $display);
case 'boolean':
$attributes['type'] = 'checkbox';
if (!empty($value)) {
$attributes['checked'] = 'checked';
}
return self::tag('input', $attributes);
case 'text':
case 'submit':
case 'email':
case 'tel':
$attributes['type'] = $type;
$attributes['value'] = $value;
return self::tag('input', $attributes);
case 'textarea':
if (!isset($attributes['rows'])) {
$attributes['rows'] = 5;
}
if (!isset($attributes['cols'])) {
$attributes['cols'] = 20;
}
return self::tag('textarea', $attributes, self::text($value));
case 'password':
$attributes['type'] = 'password';
$attributes['maxlength'] = 64;
$attributes['value'] = '';
// passwords should be cleared
return self::tag('input', $attributes);
case 'select':
return self::tag('select', $attributes) . self::options($options, $id, $value, isset($params[0]) ? $params[0] : null, isset($params[1]) ? $params[1] : '', isset($params[2]) ? $params[2] : array()) . "</select>";
case 'radios':
unset($attributes['value']);
return "<div>" . self::radios($attributes['name'], $options, $id, $value, "</div><div>", $attributes, isset($params[0]) ? $params[0] : array()) . "</div>";
case 'checkboxes':
unset($attributes['value']);
return "<div>" . self::checkboxes($attributes['name'], $options, $id, $value, "</div><div>", $attributes) . "</div>";
case 'buttons':
unset($attributes['value']);
return "<div>" . self::buttons($attributes['name'], $options, $id, '', $attributes) . "</div>";
case 'submit_buttons':
unset($attributes['value']);
$attributes['type'] = 'submit';
return "<div>" . self::buttons($attributes['name'], $options, $id, '', $attributes) . "</div>";
case 'image':
$attributes['src'] = $value;
$attributes['alt'] = $type;
return self::tag('img', $attributes);
case 'date':
return self::date($attributes['name'], $value, $options, $attributes);
default:
return self::tag($type, $attributes, $value);
}
}
示例13: setCookie
/**
* @method setCookie
* @static
* @param {string} $name The name of the cookie
* @param {string} $value The value of the cookie
* @param {string} [$expires=0] The number of seconds since the epoch, 0 means never expires
* @param {string} [$path=false] You can specify a path on the server here for the cookie
* @return {string}
*/
static function setCookie($name, $value, $expires = 0, $path = false)
{
if (empty($_SERVER['HTTP_HOST'])) {
Q::log('Warning: Ignoring call to Q_Response::setCookie() without $_SERVER["HTTP_HOST"]' . PHP_EOL);
return false;
}
if (isset($_COOKIE[$name]) and $_COOKIE[$name] === $value) {
return;
}
if (Q_Dispatcher::$startedResponse) {
throw new Q_Exception("Q_Response::setCookie must be called before Q/response event");
}
// see https://bugs.php.net/bug.php?id=38104
self::$cookies[$name] = array($value, $expires, $path);
$_COOKIE[$name] = $value;
return $value;
}
示例14: dirname
/**
* Front controller for Q
*/
include dirname(__FILE__) . DIRECTORY_SEPARATOR . 'Q.inc.php';
//
// Handle batch request
//
$urls = Q::ifset($_REQUEST['urls'], array());
Q::log("Batch request for " . count($urls) . " urls");
header("Content-type: application/json");
Q_Response::$batch = true;
echo "[";
$original_request = $_REQUEST;
foreach ($urls as $i => $url) {
$request = parse_url($url);
parse_str($request['query'], $_REQUEST);
$request = explode('?', $url);
echo "[";
if (!empty($request[0])) {
Q_ActionController::execute($request[0]);
}
echo "]";
if (isset($urls[$i + 1])) {
echo ',';
}
}
$_REQUEST = $original_request;
echo "]";
Q::log("~" . ceil(Q::milliseconds()) . 'ms+' . ceil(memory_get_peak_usage() / 1000) . 'kb.' . " batch complete.");
示例15: Streams_before_Q_objects
function Streams_before_Q_objects()
{
$token = Q_Request::special('Streams.token', null);
if ($token === null) {
return;
}
$invite = Streams_Invite::fromToken($token);
if (!$invite) {
throw new Q_Exception_MissingRow(array('table' => 'invite', 'criteria' => "token = '{$token}"), 'token');
}
// did invite expire?
$ts = Streams_Invite::db()->select("CURRENT_TIMESTAMP")->fetchAll(PDO::FETCH_NUM);
if (isset($invite->expireTime) and $invite->expireTime < $ts[0][0]) {
$invite->state = 'expired';
$invite->save();
}
// is invite still pending?
if ($invite->state !== 'pending') {
switch ($invite->state) {
case 'expired':
$exception = new Streams_Exception_AlreadyExpired(null, 'token');
break;
case 'accepted':
$exception = new Streams_Exception_AlreadyAccepted(null, 'token');
break;
case 'declined':
$exception = new Streams_Exception_AlreadyDeclined(null, 'token');
break;
case 'forwarded':
$exception = new Streams_Exception_AlreadyForwarded(null, 'token');
break;
default:
$exception = new Q_Exception("This invite has already been " . $invite->state, 'token');
break;
}
$shouldThrow = Q::event('Streams/objects/inviteException', compact('invite', 'exception'), 'before');
if ($shouldThrow === null) {
Q_Response::setNotice('Streams/objects', $exception->getMessage(), true);
} else {
if ($shouldThrow === true) {
throw $exception;
}
}
}
// now process the invite
$invitedUser = Users_User::fetch($invite->userId, true);
$stream = Streams::fetchOne($invitedUser->id, $invite->publisherId, $invite->streamName);
if (!$stream) {
throw new Q_Exception_MissingRow(array('table' => 'stream', 'criteria' => "publisherId = '{$invite->publisherId}', name = '{$invite->streamName}'"));
}
$byUser = Users_User::fetch($invite->invitingUserId, true);
$byStream = Streams::fetchOne($byUser->id, $invite->publisherId, $invite->streamName);
if (!$byStream) {
throw new Q_Exception_MissingRow(array('table' => 'stream', 'criteria' => "publisherId = '{$invite->publisherId}', name = '{$invite->streamName}'"));
}
$access = new Streams_Access();
$access->publisherId = $byStream->publisherId;
$access->streamName = $byStream->name;
$access->ofUserId = $invite->userId;
$specified_access = false;
foreach (array('readLevel', 'writeLevel', 'adminLevel') as $level_type) {
$access->{$level_type} = -1;
if (empty($invite->{$level_type})) {
continue;
}
// Give access level from the invite.
// However, if inviting user has a lower access level now,
// then give that level instead, unless it is lower than
// what the invited user would have had otherwise.
$min = min($invite->{$level_type}, $byStream->get($level_type, 0));
if ($min > $stream->get($level_type, 0)) {
$access->{$level_type} = $min;
$specified_access = true;
}
}
if ($specified_access) {
$access->save(true);
}
// now log invited user in
$user = Users::loggedInUser();
if (empty($user) or $user->id !== $invite->userId) {
$user = new Users_User();
$user->id = $invite->userId;
if (!$user->retrieve()) {
// The user who was invited doesn't exist
// This shouldn't happen. We just silently log it and return.
Q::log("Sanity check failed: invite with {$invite->token} pointed to nonexistent user");
return;
}
Users::setLoggedInUser($user);
}
// accept invite and autosubscribe if first time
if ($invite->accept() and !$stream->subscription($user->id)) {
$stream->subscribe();
}
// retain the invite object for further processing
Streams::$followedInvite = $invite;
}