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); }
/** * 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')); } }
/** * The standard action front controller * @method execute * @static * @throws {Q_Exception_BadUrl} * @throws {Q_Exception} * @throws {Q_Exception_MissingConfig} */ static function execute($url = null) { // Fixes for different platforms: if (isset($_SERVER['HTTP_X_REWRITE_URL'])) { // ISAPI 3.0 $_SERVER['REQUEST_URI'] = $_SERVER['HTTP_X_REWRITE_URL']; } // Set the controller that is being used if (!isset(Q::$controller)) { Q::$controller = 'Q_ActionController'; } 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)); $tail = Q_Request::tail($url); if (!isset($tail)) { // Bad url was requested somehow $url = Q_Request::url(true); $base_url = Q_Request::baseUrl(true); throw new Q_Exception_BadUrl(compact('base_url', 'url')); } $parts = explode('/', $tail); $parts_len = count($parts); if ($parts_len >= 1) { $module = $parts[0]; } if ($parts_len >= 2) { $action = $parts[1]; } if (empty($module) or empty($action)) { throw new Q_Exception("Not implemented"); } // Make sure the 'Q'/'web' config fields are set, // otherwise URLs will be formed pointing to the wrong // controller script. $ar = Q_Config::get('Q', 'web', 'appRootUrl', null); if (!isset($ar)) { throw new Q_Exception_MissingConfig(array('fieldpath' => 'Q/web/appRootUrl')); } // Dispatch the request $uri = Q_Uri::from(compact('module', 'action')); Q_Dispatcher::dispatch($uri); $dispatchResult = Q_Dispatcher::result(); if (!isset($dispatchResult)) { $dispatchResult = 'Ran dispatcher'; } if ($module and $action) { $slotNames = Q_Request::slotNames(); $requestedSlots = empty($slotNames) ? '' : implode(',', $slotNames); Q::log("~" . ceil(Q::milliseconds()) . 'ms+' . ceil(memory_get_peak_usage() / 1000) . 'kb.' . " {$dispatchResult} for {$module}/{$action}" . " ({$requestedSlots})"); } else { Q::log("~" . ceil(Q::milliseconds()) . 'ms+' . ceil(memory_get_peak_usage() / 1000) . 'kb.' . " No route for " . $_SERVER['REQUEST_URI']); } } catch (Exception $exception) { /** * @event Q/exception * @param {Exception} exception */ Q::event('Q/exception', compact('exception')); } }
<div id='content'> <h1>Welcome!</h1> To start a new app, you should follow the instructions <a href="https://qbix.com/platform">here</a>.<br> Oh, and by the way, this rendered in <?php echo ceil(Q::milliseconds()); ?> ms. Refresh the page a few times and see how efficient the Qbix Platform can be. In fact, it can execute <a href="fast.php">even faster</a>. </div>
<?php include "Q.inc.php"; $ms = ceil(Q::milliseconds()); echo <<<EOT \t<!DOCTYPE html> \t<html lang="en" xmlns:og="http://ogp.me/ns#" xmlns:fb="http://www.facebook.com/2008/fbml" class='Q_notTouchscreen Q_notMobile Q_notIE Q_notIE8OrBelow'> \t<head> \t\t<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> \t\t<title>Fast loading page</title> \t\t<link rel="shortcut icon" href="http://gmba.local/First/favicon.ico" type="image/x-icon"> \t</head> \t<body> \t\t<h1>Even Faster Loading Page</h1> \t\t<p> \t\t\tThis is a naked PHP script that includes the Qbix Platform as a library, like this: \t\t</p> \t\t<pre> \t\t\t<?php include ("Q.inc.php") ?> \t\t</pre> \t\t<p> \t\t\tIn this scenario, the entire Qbix environment is ready to go in <strong>{$ms} milliseconds</strong>! \t\t</p> \t\t<p> \t\t\tTry refreshing this page, and it will probably load even faster. \t\t</p> \t</body>
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)); }
/** * Executes a query against the database and returns the result set. * @method excecute * @param {boolean} [$prepareStatement=false] If true, a PDO statement will be prepared * from the query before it is executed. It is also saved for future invocations to use. * Do this only if the statement will be executed many times with * different parameters. Basically you would use ->bind(...) between * invocations of ->execute(). * @return {Db_Result} The Db_Result object containing the PDO statement that resulted from the query. */ function execute($prepareStatement = false) { if (class_exists('Q')) { /** * @event Db/query/execute {before} * @param {Db_Query_Mysql} query * @return {Db_Result} */ $result = Q::event('Db/query/execute', array('query' => $this), 'before'); } if (isset($result)) { return $result; } $stmts = array(); // make sure SQL template will be ready for sharding. reallyConnect will add new values unset($this->replacements['{$dbname}']); unset($this->replacements['{$prefix}']); $this->startedTime = Q::milliseconds(true); if ($prepareStatement) { // Prepare the query into a SQL statement // this takes two round-trips to the database // Preparing the statement if it wasn't yet set if (!isset($this->statement)) { if ($q = $this->build()) { $pdo = $this->reallyConnect(); $this->statement = $pdo->prepare($q); if ($this->statement === false) { if (!isset($sql)) { $sql = $this->getSQL(); } if (class_exists('Q_Exception_DbQuery')) { throw new Exception("query could not be prepared"); } throw new Exception("query could not be prepared [query was: {$sql} ]", -1); } } } // Bind the parameters foreach ($this->parameters as $key => $value) { $this->statement->bindValue($key, $value); } } $sql_template = $this->getSQL(null, true); $queries = $this->shard(); $connection = $this->db->connectionName(); if (!empty($queries["*"])) { $shard_names = Q_Config::get('Db', 'connections', $connection, 'shards', array('' => '')); $q = $queries["*"]; foreach ($shard_names as $k => $v) { $queries[$k] = $q; } unset($queries['*']); } foreach ($queries as $shard_name => $query) { $upcoming = Q_Config::get('Db', 'upcoming', $connection, false); if ($query->type !== Db_Query::TYPE_SELECT && $query->type !== Db_Query::TYPE_RAW) { if (!empty($upcoming['block']) && $shard_name === $upcoming['shard']) { throw new Db_Exception_Blocked(compact('shard_name', 'connection')); } } $query->startedTime = Q::milliseconds(true); $pdo = $query->reallyConnect($shard_name); $connInfo = Db::getConnection($connection); $dsn = $connInfo['dsn']; $nt =& self::$nestedTransactions[$dsn]; if (!isset($nt)) { self::$nestedTransactions[$dsn] = 0; $nt =& self::$nestedTransactions[$dsn]; } $sql = $query->getSQL(); try { if (!empty($query->clauses["BEGIN"])) { if (++$nt == 1) { $pdo->beginTransaction(); } } else { if (!empty($query->clauses["ROLLBACK"])) { $pdo->rollBack(); $nt = 0; } } if ($query->type !== Db_Query::TYPE_ROLLBACK) { if ($prepareStatement) { // Execute the statement try { $query->statement->execute(); $stmt = $query->statement; } catch (Exception $e) { if (class_exists('Q_Exception_DbQuery')) { throw $e; } throw new Exception($e->getMessage() . "\n... Query was: {$sql}", -1); } } else { // Obtain the full SQL code ourselves // and send to the database, without preparing it there. if ($sql) { $stmt = $pdo->query($sql); } else { $stmt = true; } } $stmts[] = $stmt; if (!empty($query->clauses["COMMIT"]) && $nt) { // we commit only if no error occurred - warnings are permitted if (!$stmt or $stmt !== true and !in_array(substr($stmt->errorCode(), 0, 2), array('00', '01'))) { $err = $pdo->errorInfo(); throw new Exception($err[0], $err[1]); } if (--$nt == 0) { $pdo->commit(); } } } } catch (Exception $exception) { if ($nt) { $pdo->rollBack(); $nt = 0; } break; } $this->nestedTransactionCount = $nt; if (class_exists('Q') && isset($sql)) { // log query if shard split process is active // all activities will be done by node.js switch ($this->type) { case Db_Query::TYPE_SELECT: // SELECT queries don't need to be logged // SELECT queries don't need to be logged case Db_Query::TYPE_RAW: // Raw queries are run on shard '' - i.e. main db only // actually, raw query may get here only on initial sharding // when sharding has started raw queries are never run on shard break; default: if (!$upcoming or $shard_name !== $upcoming['shard']) { break; } $table = $this->table; foreach ($this->replacements as $k => $v) { $table = str_replace($k, $v, $table); } if ($table !== $upcoming['dbTable']) { break; } // node will determine new shard(s) names using // new sharding config which is available within split process $timestamp = $pdo->query("SELECT CURRENT_TIMESTAMP")->fetchAll(PDO::FETCH_COLUMN, 0); if ($timestamp === false || !isset($timestamp[0])) { $timestamp = date("Y-m-d H:i:s"); // backup solution } else { $timestamp = $timestamp[0]; } $sql_template = str_replace('CURRENT_TIMESTAMP', "'{$timestamp}'", $sql_template); $transaction = !empty($this->clauses['COMMIT']) ? 'COMMIT' : (!empty($this->clauses['BEGIN']) ? 'START TRANSACTION' : (!empty($this->clauses['ROLLBACK']) ? 'ROLLBACK' : '')); $upcoming_shards = array_keys($query->shard($upcoming['indexes'][$upcoming['table']])); $logServer = Q_Config::get('Db', 'internal', 'sharding', 'logServer', null); if (!empty($transaction) && $transaction !== 'COMMIT') { Q_Utils::sendToNode(array('Q/method' => 'Db/Shards/log', 'shards' => $upcoming_shards, 'sql' => "{$transaction};"), Q_Config::get('Db', 'internal', 'sharding', 'logServer', null)); } Q_Utils::sendToNode(array('Q/method' => 'Db/Shards/log', 'shards' => $upcoming_shards, 'sql' => trim(str_replace("\n", ' ', $sql_template))), Q_Config::get('Db', 'internal', 'sharding', 'logServer', null)); if (!empty($transaction) && $transaction === 'COMMIT') { Q_Utils::sendToNode(array('Q/method' => 'Db/Shards/log', 'shards' => $upcoming_shards, 'sql' => "{$transaction};"), $logServer, true); } } $query->endedTime = Q::milliseconds(true); } } $this->endedTime = Q::milliseconds(true); if (!empty($exception)) { /** * @event Db/query/exception {after} * @param {Db_Query_Mysql} query * @param {array} queries * @param {string} sql * @param {Exception} exception */ Q::event('Db/query/exception', compact('query', 'queries', 'sql', 'exception'), 'after'); if (!class_exists('Q_Exception_DbQuery')) { throw $exception; } throw new Q_Exception_DbQuery(array('sql' => $sql, 'message' => $exception->getMessage() . "[query was: {$sql}]")); } /** * @event Db/query/execute {after} * @param {Db_Query_Mysql} query * @param {array} queries * @param {string} sql */ Q::event('Db/query/execute', compact('query', 'queries', 'sql'), 'after'); return new Db_Result($stmts, $this); }
// Include core classes // require Q_CLASSES_DIR . DS . 'Q.php'; require Q_CLASSES_DIR . DS . 'Q' . DS . 'Cache.php'; require Q_CLASSES_DIR . DS . 'Q' . DS . 'Bootstrap.php'; require Q_CLASSES_DIR . DS . 'Q' . DS . 'Tree.php'; require Q_CLASSES_DIR . DS . 'Q' . DS . 'Config.php'; require Q_CLASSES_DIR . DS . 'Q' . DS . 'Exception.php'; require Q_CLASSES_DIR . DS . 'Q' . DS . 'Exception' . DS . 'PhpError.php'; require Q_CLASSES_DIR . DS . 'Db.php'; require Q_CLASSES_DIR . DS . 'Db' . DS . 'Expression.php'; require Q_CLASSES_DIR . DS . 'Db' . DS . 'Query.php'; // // Set things up // Q::milliseconds(); Q_Bootstrap::registerShutdownFunction(); Q_Bootstrap::setDefaultTimezone(); Q_Bootstrap::setIncludePath(); Q_Bootstrap::registerAutoload(); Q_Bootstrap::defineFunctions(); Q_Bootstrap::registerExceptionHandler(); Q_Bootstrap::registerErrorHandler(); Q_Bootstrap::revertSlashes(); Q_Bootstrap::configure(); Q_Bootstrap::alertAboutLocalConfiguration(); Q_Bootstrap::setDefaultTimezone(); Q_Bootstrap::setResponseBuffered(); Q_Bootstrap::setUrls(); Q_Response::setIgnoreUserAbort(); if (defined('APP_WEB_DIR')) {
/** * 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.");