function fetchAll() { if ($this->cursor === null) { throw new DbException("Query must be executed first"); } Events::trigger('db_fetch_all_start', $this->query); $result = $this->cursor->fetchAll(); Events::trigger('db_fetch_all_end', $this->query); return $result; }
/** * We can bind and then unbind. */ function testBindThenUnbind() { $bind = Events::on('test_simple', array($this, 'onTestSimple')); try { Events::trigger('test_simple', "cat"); $this->assertEquals(array("cat"), $this->last_simple_data); } finally { Events::unbind($bind); } Events::trigger('test_simple', "dog"); $this->assertEquals(array("cat"), $this->last_simple_data); // hasn't changed }
/** * Send an email with the given template to the given user or address. * The subject of the e-mail is obtained from the first line of the text e-mail template, or the * <title> of the HTML template. * * TODO support mock mailing * TODO support i18n * TODO service wrapper to allow emails to be queued * * @param $to_or_user either an email address, or something with getEmail() and optionally getName() * @throws MailerException if the mail could not be immediately sent (e.g. technical error, invalid e-mail address...) * @return the email result object, which is also sent to the `email_sent` event trigger */ static function send($to_or_user, $template_id, $arguments = array()) { // add any global arguments foreach (static::$global_arguments as $name => $callback) { if (!isset($arguments[$name])) { $arguments[$name] = call_user_func($callback, $arguments); } } $to_name = false; $to_id = null; if (is_object($to_or_user)) { $to_email = $to_or_user->getEmail(); if (method_exists($to_or_user, 'getName')) { $to_name = $to_or_user->getName(); } if (method_exists($to_or_user, 'getId')) { $to_id = $to_or_user->getId(); } } else { if (is_string($to_or_user)) { $to_email = $to_or_user; } else { throw new MailerException("Unknown 'to' type " . gettype($to_or_user)); } } if (!$to_name) { $to_name = $to_email; } // default arguments if (!isset($arguments['email'])) { $arguments['email'] = $to_email; } if (!isset($arguments['name'])) { $arguments['name'] = $to_name; } $compiled = self::compile($template_id, $arguments); $template = $compiled['text']; $html_template = $compiled['html']; $subject = $compiled['subject']; // now send the email // may throw MailerException if (self::$mock_mailer) { $message_id = call_user_func(self::$mock_mailer, $to_email, $to_name, $subject, $template, $html_template); } else { $message_id = Email::phpmailer($to_email, $to_name, $subject, $template, $html_template); } // allow others to capture this event $result = array("user_id" => $to_id, "to_name" => $to_name, "to_email" => $to_email, "subject" => $subject, "template_id" => $template_id, "arguments" => $arguments, "message_id" => $message_id); \Openclerk\Events::trigger('email_sent', $result); return $result; }
/** * Execute OAuth2 authentication and return the user. */ static function auth(ProviderInterface $provider) { if (!require_get("code", false)) { redirect($provider->getAuthorizationUrl()); return false; } else { // optionally check for abuse etc if (!\Openclerk\Events::trigger('oauth2_auth', $provider)) { throw new UserAuthenticationException("Login was cancelled by the system."); } $token = $provider->getAccessToken('authorization_code', array('code' => require_get("code"))); // now find the relevant user return $provider->getUserDetails($token); } }
function prepare($query) { if ($this->shouldUseMaster($query)) { if ($this->isWriteQuery($query)) { // update the session, but only for write queries $_SESSION['master_slave_data'][$this->getTable($query)] = time(); } $this->lastConnection = $this->master; Events::trigger('db_prepare_master', $query); return new ReplicatedQuery($this->master, $query, true); } else { $this->lastConnection = $this->slave; Events::trigger('db_prepare_slave', $query); return new ReplicatedQuery($this->slave, $query, false); } }
/** * Log an Exception into the {@code uncaught_exceptions} table. * If the exception is a {@link TypedException}, or the {@code argument_id} and * {@code argument_type} parameters are provided, this argument ID/type will be inserted as well. * * @param $argument_id optional argument type * @param $argmuent_type optional argument id */ function log_uncaught_exception($e, $argument_type = null, $argument_id = null) { // check db() is defined $db = openclerk_exceptions_check_db($e); // events Events::trigger('exception_uncaught', $e); $extra_args = array(); $extra_query = ""; // logging if ($argument_id !== null && $argument_type !== null) { // unwrap it $extra_args[] = $argument_id; $extra_args[] = $argument_type; $extra_query .= ", argument_id=?, argument_type=?"; } else { if ($e instanceof \Openclerk\TypedException) { // unwrap it $extra_args[] = $e->getArgumentId(); $extra_args[] = $e->getArgumentType(); $extra_query .= ", argument_id=?, argument_type=?"; } } if (get_class($e) !== false) { $extra_args[] = get_class($e); $extra_query .= ", class_name=?"; } $q = $db->prepare("INSERT INTO uncaught_exceptions SET\n message=?,\n previous_message=?,\n filename=?,\n line_number=?,\n raw=?,\n created_at=NOW() {$extra_query}"); try { $serialized = serialize($e); } catch (\Exception $e2) { if (preg_match("#Serialization of .+ is not allowed#im", $e2->getMessage())) { $serialized = serialize($e2->getMessage()); } else { $serialized = serialize($e->getMessage()); } } $args = array_merge(array(mb_substr($e->getMessage(), 0, 255), mb_substr($e->getPrevious() ? $e->getPrevious()->getMessage() : "", 0, 255), mb_substr($e->getFile(), 0, 255), $e->getLine(), mb_substr($serialized, 0, 65535)), $extra_args); return $q->execute($args); }
/** * Delete the given user. Triggers a 'user_deleted' event with the * current user as an argument. */ function delete(\Db\Connection $db) { // delete all possible identities $q = $db->prepare("DELETE FROM user_passwords WHERE user_id=?"); $q->execute(array($this->getId())); $q = $db->prepare("DELETE FROM user_openid_identities WHERE user_id=?"); $q->execute(array($this->getId())); $q = $db->prepare("DELETE FROM user_oauth2_identities WHERE user_id=?"); $q->execute(array($this->getId())); $q = $db->prepare("DELETE FROM user_valid_keys WHERE user_id=?"); $q->execute(array($this->getId())); $q = $db->prepare("DELETE FROM users WHERE id=?"); $q->execute(array($this->getId())); \Openclerk\Events::trigger('user_deleted', $this); }
static function tWithoutCategory($key = false, $args = array()) { $locale = self::getCurrentLocale(); // remove any unnecessary whitespace in the key that won't be displayed $key = self::stripKey($key); if ($locale != 'en' && !isset(self::$global_loaded_locales[$locale])) { if (!isset(self::$locales[$locale])) { throw new LocaleException("No known locale '{$locale}'"); } $localeInstance = self::$locales[$locale]; $loaded = $localeInstance->load(); self::$global_loaded_locales[$locale] = $loaded; } if (!is_array($args)) { throw new LocaleException("Expected array argument"); } foreach ($args as $k => $value) { if (is_numeric($k)) { throw new LocaleException("Did not expect numeric key '{$k}'"); } if (substr($k, 0, 1) !== ":") { throw new LocaleException("Did not expect non-parameterised key '{$k}'"); } } // add default arguments (but keep any existing keys used) $args += self::$default_keys; if (!isset(self::$global_loaded_locales[$locale][$key])) { if ($locale != 'en') { \Openclerk\Events::trigger('i18n_missing_string', array("locale" => $locale, "key" => $key)); } // if (is_admin() && get_site_config('show_i18n')) { // return "[" . strtr($key, $args) . "]"; // } else { return strtr($key, $args); // } } // if (is_admin() && get_site_config('show_i18n')) { // return "[" . strtr(self::$global_loaded_locales[$locale][$key], $args) . "]"; // } else { return strtr(self::$global_loaded_locales[$locale][$key], $args); // } }
/** * Wraps {@link #file_get_contents()} with timeout information etc. * May throw a {@link ExternalAPIException} if something unexpected occured. */ function crypto_get_contents($url, $options = array()) { \Openclerk\Events::trigger('curl_start', $url); // normally file_get_contents is OK, but if URLs are down etc, the timeout has no value and we can just stall here forever // this also means we don't have to enable OpenSSL on windows for file_get_contents('https://...'), which is just a bit of a mess $ch = crypto_curl_init(); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; Openclerk PHP client; ' . php_uname('s') . '; PHP/' . phpversion() . ')'); curl_setopt($ch, CURLOPT_URL, $url); // curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data); // curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); curl_setopt($ch, CURLOPT_ENCODING, "gzip,deflate"); // enable gzip decompression if necessary curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); foreach ($options as $key => $value) { curl_setopt($ch, $key, $value); } // run the query $res = curl_exec($ch); \Openclerk\Events::trigger('curl_end', $url); if ($res === false) { throw new ExternalAPIException('Could not get reply: ' . curl_error($ch)); } crypto_check_response($res); return $res; }
/** * Try do OpenID validation (with the given redirect). * @return the validated LightOpenID object on success * @throws UserSignupException if anything bad happened */ static function validateOpenID($openid, $redirect) { if (!is_valid_url($openid)) { throw new UserSignupException("That is not a valid OpenID identity."); } if (!$redirect) { throw new \InvalidArgumentException("No redirect provided."); } $light = new \LightOpenID(\Openclerk\Config::get("openid_host")); if (!$light->mode) { // we still need to authenticate $light->identity = $openid; $light->returnUrl = $redirect; redirect($light->authUrl()); return false; } else { if ($light->mode == 'cancel') { // user has cancelled throw new UserSignupException("User has cancelled authentication."); } else { // otherwise login as necessary // optionally check for abuse etc if (!\Openclerk\Events::trigger('openid_validate', $light)) { throw new UserSignupException("Login was cancelled by the system."); } if ($light->validate()) { return $light; } else { $error = $light->validate_error ? $light->validate_error : "Please try again."; throw new UserSignupException("OpenID validation was not successful: " . $error); } } } }
/** * Render the given template. * * Searches for templates within each template directory, with the following * search order: {@code .php}, {@code .haml.php}, {@code .haml}. */ static function requireTemplate($template, $arguments = array()) { if (!is_array($arguments)) { throw new \InvalidArgumentException("Arguments '{$arguments}' need to be an array, not " . gettype($arguments)); } Events::trigger('pages_template_start', $arguments + array('template' => $template)); // so sub-templates can access all parent arguments if (self::$argument_stack) { $arguments += self::$argument_stack[count(self::$argument_stack) - 1]; } // add to argument stack array_push(self::$argument_stack, $arguments); foreach (self::$templates as $dir) { // either include templates as direct PHP files... $file = $dir . "/" . $template . ".php"; if (file_exists($file)) { // create locally scoped variables for all arguments foreach ($arguments as $key => $value) { ${$key} = $value; } require $file; Events::trigger('pages_template_end', $arguments + array('template' => $template, 'filetype' => 'php')); // and then remove from argument stack array_pop(self::$argument_stack); return; } // ... or as HAML templates foreach (array($dir . "/" . $template . ".php.haml", $dir . "/" . $template . ".haml") as $file) { if (file_exists($file)) { if (self::$executor === null) { $haml = new \MtHaml\Environment('php', self::$haml_options); self::$executor = new \MtHaml\Support\Php\Executor($haml, array('cache' => sys_get_temp_dir() . '/haml')); } // Compiles and executes the HAML template, with variables given as second argument self::$executor->display($file, $arguments); Events::trigger('pages_template_end', $arguments + array('template' => $template, 'filetype' => 'haml')); // and then remove from argument stack array_pop(self::$argument_stack); return; } } } throw new TemplateNotFoundException("Could not find template '{$template}'", new TemplateNotFoundException("No template '{$template}' found in [" . implode(", ", self::$templates) . "]")); }