function Overlay_before_Q_responseExtras() { $app = Q_Config::expect('Q', 'app'); Q_Response::addStylesheet('plugins/Q/css/Q.css'); Q_Response::addStylesheet('css/Overlay.css', '@end'); Q_Response::addStylesheet('http://fonts.googleapis.com/css?family=Open+Sans:400italic,400,300,700'); if (Q_Config::get('Q', 'firebug', false)) { Q_Response::addScript("https://getfirebug.com/firebug-lite-debug.js"); } Q_Response::addScript('js/Overlay.js'); Q_Response::setMeta("title", "Customize My Pic!"); Q_Response::setMeta("description", "Make a statement on Facebook by customizing your profile picture, even from your smartphone."); Q_Response::setMeta("image", Q_Html::themedUrl('img/icon/icon.png')); if (Q_Request::isIE()) { header("X-UA-Compatible", "IE=edge"); } header('Vary: User-Agent'); // running an event for loading action-specific extras (if there are any) $uri = Q_Dispatcher::uri(); $module = $uri->module; $action = $uri->action; $event = "{$module}/{$action}/response/responseExtras"; if (Q::canHandle($event)) { Q::event($event); } }
function Q_post($params) { $uri = Q_Dispatcher::uri(); $module = $uri->module; $action = $uri->action; if (!Q::canHandle("{$module}/{$action}/post")) { throw new Q_Exception_MethodNotSupported(array('method' => 'POST')); } if (isset($_SERVER['CONTENT_LENGTH'])) { $contentLength = (int) $_SERVER['CONTENT_LENGTH']; foreach (array('upload_max_filesize', 'post_max_size') as $name) { $value = ini_get($name); switch (substr($value, -1)) { case 'K': $value *= 1024; break; case 'M': $value *= 1024 * 1024; break; case 'B': $value *= 1024 * 1024 * 1024; break; } if ($contentLength > $value) { throw new Q_Exception_ContentLength(array('contentLength' => $contentLength, 'exceeds' => $name)); } } } return Q::event("{$module}/{$action}/post", $params); }
function Streams_publisher_validate($params) { // Protect against CSRF attacks: Q_Valid::nonce(true); $type = Streams::requestedType(); if ($type && Q::canHandle("Streams/validate/{$type}")) { return Q::event("Streams/validate/{$type}", $params); } }
function Users_importContacts_validate() { Q_Valid::nonce(true); if (empty($_GET['provider'])) { throw new Q_Exception('No provider specified'); } if (!Q::canHandle('Users/importContacts/providers/' . $_GET['provider'])) { throw new Q_Exception('Unsupported provider specified: ' . $_GET['provider']); } }
function Q_validate($params) { $uri = Q_Dispatcher::uri(); $module = $uri->module; $action = $uri->action; if (!Q::canHandle("{$module}/{$action}/validate")) { return null; } return Q::event("{$module}/{$action}/validate", $params); }
function Q_put($params) { $uri = Q_Dispatcher::uri(); $module = $uri->module; $action = $uri->action; if (!Q::canHandle("{$module}/{$action}/put")) { throw new Q_Exception_MethodNotSupported(array('method' => 'PUT')); } return Q::event("{$module}/{$action}/put", $params); }
function Q_delete($params) { $uri = Q_Dispatcher::uri(); $module = $uri->module; $action = $uri->action; if (!Q::canHandle("{$module}/{$action}/delete")) { throw new Q_Exception_MethodNotSupported(array('method' => 'DELETE')); } Q_Request::requireValidNonce(); return Q::event("{$module}/{$action}/delete", $params); }
/** * This tool generates an interface used for publishing messages to streams * It basically renders the Streams/player/$type tool, where $type is the stream's type. * * @param array $options * An associative array of parameters, containing: * "publisherId" => required. The id of the publisher of the stream to which to post the message. * "streamName" => required. The name of the stream to which to post the message. */ function Streams_player_tool($options) { extract($options); if (empty($stream)) { throw new Q_Exception("Missing stream object"); } if (!Q::canHandle('Streams/player/' . $stream->type . '/tool')) { throw new Q_Exception("No player tool has been implemented for streams of type {$stream->type}."); } return Q::tool('Streams/player/' . $stream->type, $options); }
function Streams_stream_validate($params) { // Protect against CSRF attacks: if (Q_Request::method() !== 'GET') { Q_Valid::nonce(true); } $type = Streams::requestedType(); if ($type && Q::canHandle("Streams/validate/{$type}")) { return Q::event("Streams/validate/{$type}", $params); } }
function Streams_player_tool($options) { extract($options); if (!isset($stream)) { throw new Q_Exception_MissingObject(array('name' => 'stream')); } if (!$stream->testReadLevel('content')) { $streamName_html = Q_Html::text($stream->name); return "<a href='#{$streamName_html}'>hidden</a>"; } $options['streamName'] = $stream->name; $parts = explode('/', $stream->type); switch ($parts[0]) { case 'Streams/text/small': case 'Streams/text/medium': case 'Streams/text': return $stream->content; case 'Streams/date': // TODO: localize if (isset($parts[1]) and $parts[1] === 'birthday') { return date('M j', strtotime($stream->content)); } return date('M j, Y', strtotime($stream->content)); case 'Streams/number': if (isset($parts[1]) and $parts[1] === 'age') { if (!empty($streams['Streams/user/birthday']->content)) { return Db::ageFromDateTime($streams['Streams/user/birthday']->content); } return null; } return $strem->content; case 'Streams/category': // TODO: implement // TODO: implement case 'Streams/chat': // TODO: implement // TODO: implement case 'Streams/community': // TODO: implement // TODO: implement default: $event = $stream->type . "/tool"; if (Q::canHandle($event)) { return Q::tool($stream->type, $options); } return Q_Html::tag('div', array('class' => 'Streams_player_stream_content'), Q_Html::text($stream->content)); } }
function Q_response_content() { $app = Q_Config::expect('Q', 'app'); $url = Q_Request::url(); $module = Q_Dispatcher::uri()->module; if (empty($module)) { return Q::event("{$app}/notFound/response/content"); } $action = Q_Dispatcher::uri()->action; $event = "{$module}/{$action}/response/content"; if (!Q::canHandle($event)) { return Q::event("{$app}/notFound/response/content"); } // Go ahead and fire the event, returning the result. return Q::event($event); }
function Q_response_content() { $app = Q_Config::expect('Q', 'app'); $url = Q_Request::url(); $module = Q_Dispatcher::uri()->module; if (empty($module)) { return Q::event("{$app}/notFound/response/content"); } $action = Q_Dispatcher::uri()->action; $event = "{$module}/{$action}/response/content"; if (!Q::canHandle($event)) { return Q::event("{$app}/notFound/response/content"); } Q_Response::setMeta('format-detection', 'telephone=no,date=no,address=no,email=no,url=no'); // Go ahead and fire the event, returning the result. return Q::event($event); }
function Trump_before_Q_responseExtras() { $app = Q_Config::expect('Q', 'app'); Q_Response::addStylesheet('plugins/Q/css/Q.css'); Q_Response::addStylesheet('css/html.css', '@end'); if (Q_Config::get('Q', 'firebug', false)) { Q_Response::addScript("https://getfirebug.com/firebug-lite-debug.js"); } Q_Response::addScript('js/Trump.js'); if (Q_Request::isIE()) { header("X-UA-Compatible: IE=edge"); } header('Vary: User-Agent'); // running an event for loading action-specific extras (if there are any) $uri = Q_Dispatcher::uri(); $module = $uri->module; $action = $uri->action; $event = "{$module}/{$action}/response/responseExtras"; if (Q::canHandle($event)) { Q::event($event); } }
function Q_response_default($params) { if (!isset($params['slotName'])) { throw new Q_Exception_RequiredField(array('field' => '$slotName')); } $slotName = $params['slotName']; $uri = Q_Dispatcher::uri(); $module = $uri->module; $action = $uri->action; if (!$module or !$action) { return "{$module}/{$action} is not a valid URI"; } $event = "{$module}/{$action}/response/{$slotName}"; $function_name = $module . '_' . $action . '_response_' . $slotName; if (function_exists($function_name)) { $result = Q::event($event); $result = isset($result) ? $result : "Don't return null from {$function_name}"; } if (Q::canHandle($event)) { return Q::event($event); } throw new Q_Exception_MissingSlot(compact('event')); }
/** * Default Q/response handler. * 1. Gets some slots, depending on what was requested. * 2. Renders them in a layout * The layout expects "title", "dashboard" and "contents" slots to be filled. */ function Q_response($params) { extract($params); /** * @var Exception $exception * @var array $errors */ if (empty($errors)) { $errors = Q_Response::getErrors(); } if (!empty($_GET['Q_ct'])) { Q_Response::setCookie('Q_ct', $_GET['Q_ct']); } // If output is set, use that $output = Q_Response::output(); if (isset($output)) { if ($output === true) { return; } if (is_string($output)) { echo $output; } return; } // Redirect to success page, if requested. $isAjax = Q_Request::isAjax(); if (empty($errors) and empty($exception)) { if (!$isAjax and null !== Q_Request::special('onSuccess', null)) { $onSuccess = Q_Request::special('onSuccess', null); if (Q_Config::get('Q', 'response', 'onSuccessShowFrom', true)) { $onSuccess = Q_Uri::url($onSuccess . '?Q.fromSuccess=' . Q_Dispatcher::uri()); } Q_Response::redirect($onSuccess); return; } } // Get the requested module $uri = Q_Dispatcher::uri(); if (!isset($module)) { $module = $uri->module; if (!isset($module)) { $module = 'Q'; Q_Dispatcher::uri()->module = 'Q'; } } if (!$isAjax || Q_Request::isLoadExtras()) { Q::event('Q/responseExtras', array(), 'before'); } // Get the main module (the app) $app = Q_Config::expect('Q', 'app'); $action = $uri->action; if (Q::canHandle("{$module}/{$action}/response")) { if (false === Q::event("{$module}/{$action}/response") and !$isAjax) { return; } } $slotNames = Q_Request::slotNames(true); $idPrefixes = array(); if ($temp = Q_Request::special('idPrefixes', null)) { foreach (explode(',', $temp) as $i => $prefix) { if (!isset($slotNames[$i])) { throw new Q_Exception("More id prefixes than slot names", "Q.idPrefixes"); } $idPrefixes[$slotNames[$i]] = $prefix; } } // What to do if this is an AJAX request if ($isAjax) { $to_encode = array(); if (Q_Response::$redirected) { // We already called Q_Response::redirect $to_encode['redirect']['url'] = Q_Uri::url(Q_Response::$redirected); try { $to_encode['redirect']['uri'] = Q_Uri::from(Q_Response::$redirected)->toArray(); } catch (Exception $e) { // couldn't get internal URI } } else { if (is_array($slotNames)) { foreach ($slotNames as $slotName) { Q_Response::fillSlot($slotName, 'default', Q::ifset($idPrefixes, $slotName, null)); } // Go through the slots again, because other handlers may have overwritten // their contents using Q_Response::setSlot() foreach ($slotNames as $sn) { Q_Response::fillSlot($sn, 'default', Q::ifset($idPrefixes, $slotName, null)); } if (Q_Response::$redirected) { // While rendering the slots we called Q_Redirect $to_encode['redirect']['url'] = Q_Uri::url(Q_Response::$redirected); try { $to_encode['redirect']['uri'] = Q_Uri::from(Q_Response::$redirected)->toArray(); } catch (Exception $e) { // couldn't get internal URI } } else { if (Q_Request::isLoadExtras()) { $to_encode['slots'] = Q_Response::slots(true); // add stylesheets, stylesinline, scripts, scriptlines, scriptdata, templates foreach (array_merge(array(''), $slotNames) as $slotName) { $temp = Q_Response::stylesheetsArray($slotName); if ($temp) { $to_encode['stylesheets'][$slotName] = $temp; } $temp = Q_Response::stylesInline($slotName); if ($temp) { $to_encode['stylesInline'][$slotName] = $temp; } $temp = Q_Response::scriptsArray($slotName); if ($temp) { $to_encode['scripts'][$slotName] = $temp; } $temp = Q_Response::scriptLines($slotName, true, "\n", false); if ($temp) { $to_encode['scriptLines'][$slotName] = $temp; } $temp = Q_Response::scriptData($slotName); if ($temp) { $to_encode['scriptData'][$slotName] = $temp; } $temp = Q_Response::templateData($slotName); if ($temp) { $to_encode['templates'][$slotName] = $temp; } } } else { $to_encode['slots'] = Q_Response::slots(true); // add stylesinline, scriptlines, scriptdata, templates foreach (array_merge(array(''), $slotNames) as $slotName) { $temp = Q_Response::stylesInline($slotName); if ($temp) { $to_encode['stylesInline'][$slotName] = $temp; } $temp = Q_Response::scriptData($slotName); if ($temp) { $to_encode['scriptData'][$slotName] = $temp; } $temp = Q_Response::scriptLines($slotName, true, "\n", false); if ($temp) { $to_encode['scriptLines'][$slotName] = $temp; } } } } } } $to_encode['timestamp'] = microtime(true); $echo = Q_Request::contentToEcho(); if (isset($echo)) { $to_encode['echo'] = $echo; } $json = Q::json_encode(Q::cutoff($to_encode)); $callback = Q_Request::callback(); switch (strtolower($isAjax)) { case 'iframe': 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': default: if (!Q_Response::$batch) { header("Content-type: " . ($callback ? "application/javascript" : "application/json")); } echo $callback ? "{$callback}({$json})" : $json; } return; } // If this is a request for a regular webpage, // fill the usual slots and render a layout. if (Q_Response::$redirected) { return; // If already set a redirect header, simply return -- no reason to output all this HTML } static $added_Q_init = false; if (!$added_Q_init) { Q_Response::addScriptLine("\n// Now, initialize Q\nQ.init();\n", null, 'Q'); $added_Q_init = true; } // Get all the usual slots for a webpage $slots = array(); foreach ($slotNames as $sn) { Q_Response::fillSlot($sn, 'default', Q::ifset($idPrefixes, $sn, null)); } // Go through the slots again, because other handlers may have overwritten // their contents using Q_Response::setSlot() foreach ($slotNames as $sn) { Q_Response::fillSlot($sn, 'default', Q::ifset($idPrefixes, $sn, null)); } $output = Q_Response::output(); if (isset($output)) { if ($output === true) { return; } if (is_string($output)) { echo $output; } return; } if (!$isAjax or Q_Request::isLoadExtras()) { Q::event('Q/responseExtras', array(), 'after'); } $slots = Q_Response::slots(false); // Render a full HTML layout $layout_view = Q_Response::layoutView(); echo Q::view($layout_view, $slots); }
/** * The default implementation. */ function Q_errors($params) { extract($params); /** * @var Exception $exception * @var boolean $startedResponse */ if (!empty($exception)) { Q_Response::addError($exception); } $errors = Q_Response::getErrors(); $errors_array = Q_Exception::toArray($errors); // Simply return the errors, if this was an AJAX request if ($is_ajax = Q_Request::isAjax()) { try { $errors_json = @Q::json_encode($errors_array); } catch (Exception $e) { $errors_array = array_slice($errors_array, 0, 1); unset($errors_array[0]['trace']); $errors_json = @Q::json_encode($errors_array); } $json = "{\"errors\": {$errors_json}}"; $callback = Q_Request::callback(); switch (strtolower($is_ajax)) { case 'iframe': 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': default: header("Content-type: " . ($callback ? "application/javascript" : "application/json")); echo $callback ? "{$callback}({$json})" : $json; } return; } // Forward internally, if it was requested if ($onErrors = Q_Request::special('onErrors', null)) { $uri1 = Q_Dispatcher::uri(); $uri2 = Q_Uri::from($onErrors); $url2 = $uri2->toUrl(); if (!isset($uri2)) { throw new Q_Exception_WrongValue(array('field' => 'onErrors', 'range' => 'an internal URI reachable from a URL')); } if ($uri1->toUrl() !== $url2) { Q_Dispatcher::forward($uri2); return; // we don't really need this, but it's here anyway } } $params2 = compact('errors', 'exception', 'errors_array', 'exception_array'); if (Q::eventStack('Q/response')) { // Errors happened while rendering response. Just render errors view. return Q::view('Q/errors.php', $params2); } if (!$startedResponse) { try { // Try rendering the response, expecting it to // display the errors along with the rest. $ob = new Q_OutputBuffer(); Q::event('Q/response', $params2); $ob->endFlush(); return; } catch (Exception $e) { if (get_class($e) === 'Q_Exception_DispatcherForward') { throw $e; // if forwarding was requested, do it // for all other errors, continue trying other things } $output = $ob->getClean(); } } if ($errors) { // Try rendering the app's errors response, if any. $app = Q::app(); if (Q::canHandle("{$app}/errors/response/content")) { Q_Dispatcher::forward("{$app}/errors"); } else { echo Q::view("Q/errors.php", compact('errors')); } } if (!empty($e)) { return Q::event('Q/exception', array('exception' => $e)); } }
/** * @method errors * @static * @protected * @param {Exception} $exception * @param {string} $module * @param {string} [$partial_response=null] */ protected static function errors($exception, $module, $partial_response = null) { self::$errors_occurred = true; $response_started = self::$response_started; $errors = Q_Response::getErrors(); Q::$toolWasRendered = array(); try { if (self::$handling_errors) { // We need to handle errors, but we // have already tried to do it. // Just show the errors view. Q::event('Q/errors/native', compact('errors', 'exception', 'partial_response', 'response_started')); return; } self::$handling_errors = true; if (Q::canHandle("{$module}/errors")) { /** * @event $module/errors * @param {Exception} exception * @param {string} module * @param {string} partial_response */ Q::event("{$module}/errors", compact('errors', 'exception', 'partial_response', 'response_started')); } else { /** * @event Q/errors * @param {Exception} exception * @param {string} module * @param {string} partial_response */ Q::event("Q/errors", compact('errors', 'exception', 'partial_response', 'response_started')); } } catch (Exception $e) { Q_Exception::rethrow($e, ''); // may be for forwarding /** * @event Q/exception * @param {Exception} exception */ Q::event('Q/exception', compact('exception')); // the original exception } }
/** * Gets the current content of a slot, if any. * If slot content is null, then raises an event * to try to fill the slot. If it is filled, * returns the content. Otherwise, returns null. * @method fillSlot * @static * @param {string|array} $slotName The name of the slot. * @param {boolean} [$default_slotName=null] If the slot named in $slotName returns null, * the handler corresponding to the default slot will be called, * passing it the requested slot's name in the 'slotName' parameter, * and its value will be returned instead. * Note: this does not fill the slot named $default_slotName! * That is to say, the computed value is not saved, so that * the slot's handler is called again if it is ever consulted again. * @param {string} [$prefix=null] Sets a prefix for the HTML ids of all the elements in the slot. * @return {string|null} */ static function fillSlot($slotName, $default_slotName = null, $prefix = null) { if (isset(self::$slots[$slotName])) { return self::$slots[$slotName]; } $prev_slotName = self::$slotName; self::$slotName = $slotName; if (isset($prefix)) { Q_Html::pushIdPrefix($prefix); } try { if (isset($default_slotName)) { if (!Q::canHandle("Q/response/{$slotName}")) { /** * @event Q/response/$default_slotName * @param {string} slotName * @return {string} */ $result = Q::event("Q/response/{$default_slotName}", compact('slotName')); if (isset(self::$slots[$slotName])) { // The slot was already filled, while we were rendering it // so discard the $result and return the slot's contents return self::$slots[$slotName]; } return self::$slots[$slotName] = $result; } } /** * @event Q/response/$slotName * @return {string} */ $result = Q::event("Q/response/{$slotName}"); } catch (Exception $e) { self::$slotName = $prev_slotName; if (isset($prefix)) { Q_Html::popIdPrefix(); } throw $e; } self::$slotName = $prev_slotName; if (isset($prefix)) { Q_Html::popIdPrefix(); } if (isset(self::$slots[$slotName])) { // The slot was already filled, while we were rendering it // so discard the $result and return the slot's contents return self::$slots[$slotName]; } if (isset($result)) { self::setSlot($slotName, $result); return $result; } // Otherwise, render default slot if (!isset($default_slotName)) { return null; } /** * @event Q/response/$default_slotName * @param {string} slotName * @return {string} */ return Q::event("Q/response/{$default_slotName}", compact('slotName')); }