public function execute($query, $arguments = []) { $split = preg_split('/({\\w+})/', $query, -1, PREG_SPLIT_DELIM_CAPTURE); $count = count($split); for ($i = 1; $i < $count; $i += 2) { $key = $split[$i]; if (array_key_exists($key, $arguments)) { // found a replacement in $arguments. $split[$i] = $arguments[$key]; } } $query = join($split); // create a PDO statment $this->last_stmt = $st = $this->link->prepare($query); if ($st === false) { $this->last_stmt = null; return false; } // forward :args to PDO. $pdo_args = []; foreach ($arguments as $key => $value) { if ($key[0] == ':') { $pdo_args[$key] = $value; } } No2_Logger::debug('PDO->execute: ' . preg_replace('/\\s+/m', ' ', $query)); return $st->execute($pdo_args) ? $st : false; }
function test_output_format() { $date = preg_quote(date(DateTime::ISO8601), '/'); $reqid = preg_quote(No2_Logger::$reqid, '/'); $this->expectOutputRegex("/^\\[PHPUnit {$date} {$reqid}\\] DEBUG: test\$/"); No2_Logger::debug('test'); print file_get_contents(static::$LOGFILE_PATH); }
/** * make a SQL query to the database. the query should be properly escaped. * * @see http://php.net/manual/en/function.mysql-query.php */ public function query($query) { global $wpdb; if (preg_match('/\\s*select/i', $query)) { No2_Logger::debug('$wpdb->get_results: ' . preg_replace('/\\s+/m', ' ', $query)); $result = $wpdb->get_results($query, ARRAY_A); if (is_array($result)) { $index = count($this->results); $this->results[$index] = $result; $result = (object) array($index); // return the index as an object. } } else { No2_Logger::debug('$wpdb->query: ' . preg_replace('/\\s+/m', ' ', $query)); $result = $wpdb->query($query); } return $result; }
/** * find the associated controller to $alias. * * @param $alias * the alias to find a matching controller * * @param $action * The action (method) to perform. It will be passed to the respond_to() * method of the controller in order to check if it can handle it. * * @param $http_method * The HTTP verb, usually GET or POST. * * @return * a controller object that can handle $action. If there isn't any, null is * returned. */ public function find_route($alias, $action, $http_method) { if (!array_key_exists($alias, $this->mapping)) { return null; } $target = $this->mapping[$alias]; /* require the associated file if any */ if (!is_null($target['file'])) { require_once $target['file']; } // check if the controller responding to $alias can handle $action $klass = $target['controller']; try { $controller = new $klass($alias, $action, $http_method); } catch (Exception $e) { No2_Logger::warn(get_class($this) . '::find_route: ' . 'exception in controller ctor: ' . $e->getMessage()); return null; } return $controller; }
/** * save the current user id in the session. * * @param $user * a User object. The client is considered logged in as * <code>$user</code> when this function return. if NULL, the current * user is "logged out", meaning the session user id is unset. */ public static function current_is($user) { if (is_null($user)) { static::$current_user = NULL; if (session_active()) { unset($_SESSION['uid']); } } else { if ($user instanceof static) { static::$current_user = $user; if (session_active()) { $_SESSION['uid'] = $user->id; } } else { No2_Logger::err(get_called_class() . 'current_is: ' . 'Wrong user type: ' . get_class($user)); } } }
// load Composer stuff require_once PROJECTDIR . '/vendor/autoload.php'; // initialize no2 framework. require_once PROJECTDIR . '/no2/no2.inc.php'; // get the config stuff require_once APPDIR . '/config.class.php'; AppConfig::parse(PROJECTDIR . '/config/config.yml', array('{{APPDIR}}' => APPDIR, '{{PROJECTDIR}}' => PROJECTDIR, '{{WEBDIR}}' => WEBDIR)); // load the application's models. require_once APPDIR . '/models/user.class.php'; // load the application's helpers. require_once APPDIR . '/help.inc.php'; // set the timezone date_default_timezone_set(AppConfig::get('l10n.default_timezone')); // set the locale setlocale(LC_ALL, AppConfig::get('l10n.default_locale')); // start the logger if (!No2_Logger::setup(AppConfig::get('logger'))) { error_log('unable to setup Logger'); } // connect to the database. No2_SQLQuery::setup(AppConfig::get('database')); // try our best to hide the fact that we still use PHP in the 21th century. if (function_exists('header_remove')) { header_remove('X-Powered-By'); // PHP 5.3+ } else { @ini_set('expose_php', 'off'); } // start the session session_set_cookie_params(0, dirname($_SERVER['SCRIPT_NAME'])); session_start() or die('session_start()');
/** * Save the current Object. If the object was loaded by the database, an * UPDATE is performed and an INSERT otherwise. This method will call * is_valid() and ensure that true is returned before attempting to save * it. * * @param $do_validate * Control if the object's state should be validated (calling and * checking the return value of is_valid()). If $do_validate is true, * is_valid() is called and false is returned by save() if validation * failed. if $do_validate is false, then save() doesn't try to validate * the object. * * @return * false on error, true otherwise. */ public function save($do_validate = true) { $is_new_record = $this->is_new_record(); if ($do_validate && !$this->is_valid()) { return false; } // filter to only SET dirty properties. $properties = []; foreach ($this->__dirty_db_data as $prop => $dirty) { if ($dirty) { $properties[$prop] = $this->massage_for_storage($prop, $this->__db_data[$prop]); } } if (!$is_new_record && empty($properties)) { // We're doing an UPDATE with no new values. Don't commit anything // to the db and return true to notice the caller that somehow, // save was a success. $success = true; $rows = []; } else { $query = new No2_SQLQuery(get_class($this)); $query->query_on($this->__db_profile); if ($is_new_record) { $rows = $query->insert1($properties); } else { $rows = $query->set($properties)->id($this->id)->update(); } $success = !is_null($rows); } if (!$success) { /* * this is strange because we passed through is_valid(). There is * some inconsistancies between programmed validation and * database validation. */ No2_Logger::err(get_class($this) . '::save: ' . 'database failed to save me:' . print_r($this, true)); } else { // the database query was successful. // we're now a saved record, congrats. $this->__is_new_record = false; // load the row properties from the database response. This is // needed for database generated fields. foreach ($rows as $name => $value) { $this->{$name} = $value; } // reset the dirty properties, because the db now match them. $this->__dirty_db_data = []; } return $success; }
<?php die; } } $view = $controller->view(); if (No2_HTTP::is_error($view->status()) && !$controller->can_render_errors()) { /* * The controller declined error handling, so we load the default error * controller to generate the response. */ require_once APPDIR . '/controllers/error.class.php'; $controller = new ErrorController($view->status()); unset($view); goto invoke_it; } /* from this point, $controller and $view are set and valid. */ /* * Here we know the status code, log the request and render the requested ressource. */ No2_Logger::info("{$_SERVER['REMOTE_ADDR']} - {$_SERVER['REQUEST_METHOD']} - {$_SERVER['REQUEST_URI']} - {$view->status()}"); /* kindly ask the view to render the response */ try { /* * Don't try to buffer the view's output using something like ob_start(), * it will OOM PHP if the response is moderately big. */ $view->render(); die; } catch (Exception $e) { No2_Logger::err('view rendering exception: ' . $e->getMessage()); }
/** * partial render. */ protected function render_debug() { if (No2_Logger::$level >= No2_Logger::DEBUG) { No2_Logger::to_html('debugger'); } }
/** * perform a redirection the the location property if this object. */ protected function render_redirect() { No2_Logger::no2debug(get_class($this) . "::render_redirect: redirecting to {$this->__redirect_location}"); header("Location: {$this->__redirect_location}"); }
/** * execute an UPDATE instruction. set() should have been called before. * * @return * false on error, true otherwise. */ public function update() { $this->restrict_to(self::UPDATE); if (empty($this->set)) { No2_Logger::warn(get_class($this) . '::update: ' . 'called without previous set() call.'); } $klass = $this->klass; $arguments = array_merge($this->arguments, ['{__table}' => $klass::$table]); $options = ['profile' => $this->profile]; $db = static::_database_or_throw($this->profile); $updated = false; if ($db->has_returning()) { $sql = "UPDATE {__table} {$this->set} {$this->where} RETURNING *"; $updated = static::execute($sql, $arguments, $options); } else { // XXX: asume MySQL, hacky. $last_insert_id_hack = (empty($this->set) ? 'SET' : ',') . ' id = LAST_INSERT_ID(id)'; $sql = "UPDATE {__table} {$this->set} {$last_insert_id_hack} {$this->where}"; if (static::execute($sql, $arguments, $options) !== false) { $updated = static::execute('SELECT * FROM {__table} WHERE id = LAST_INSERT_ID()', $arguments, $options); } } if ($updated !== false) { return $updated; } else { No2_Logger::warn(get_class($this) . '::update: ' . "SQL query returned FALSE: {$sql}"); No2_Logger::warn('error message: ' . $db->error()); return null; } }
/** * This method is called by the view before rendering a zone. * * The view is asked by the template to render a zone. It first call its * controller pre_render() method with the zone to render. pre_render() * will setup views properties if needed (setup). To do the rendering it * can either output data or return a file (like a template file) that will * be included (or both). It can also control if the zone should be * rendered or not (for example based on authorization) and return a file * or not accordingly. * * This implementation will call the magic protected method render_$zone if * it exist. All subclasses are expected to define such method instead of * overriding pre_render(). * * @param $zone * The zone the view has been asked to render. * * @return * a (template) file to be included or null if nothing has to be done by * the view. */ public function pre_render($zone) { $method = "render_{$zone}"; $tpl = null; if ($this->has_protected_method($method)) { $tpl = $this->{$method}(); } if (!is_null($tpl)) { No2_Logger::no2debug(get_class($this) . "::pre_render(zone={$zone}): " . "sending template " . basename($tpl) . " back to view"); } return $tpl; }
/** * make a SQL query to the database. the query should be properly escaped * since it will be directly passed to mysql_query(). * * @see http://php.net/manual/en/function.mysql-query.php */ public function query($query) { No2_Logger::debug('mysql_query: ' . preg_replace('/\\s+/m', ' ', $query)); $result = mysql_query($query, $this->link); return $result; }