Skip to content

Commit

Permalink
Pull in changes and refactoring from Scott Woods
Browse files Browse the repository at this point in the history
Refactor into a properly instantiated class
Clean up some repitition in the xml building
  • Loading branch information
rich committed Jan 23, 2010
1 parent a27d563 commit a1fb731
Showing 1 changed file with 81 additions and 108 deletions.
189 changes: 81 additions & 108 deletions Services/Hoptoad.php
Expand Up @@ -34,6 +34,12 @@ class Services_Hoptoad
const NOTIFIER_URL = 'http://github.com/rich/php-hoptoad-notifier'; const NOTIFIER_URL = 'http://github.com/rich/php-hoptoad-notifier';
const NOTIFIER_API_VERSION = '2.0'; const NOTIFIER_API_VERSION = '2.0';


protected $error_class;
protected $message;
protected $file;
protected $line;
protected $trace;

/** /**
* Report E_STRICT * Report E_STRICT
* *
Expand Down Expand Up @@ -90,13 +96,8 @@ public static function errorHandler($code, $message, $file, $line)
{ {
if ($code == E_STRICT && self::$reportESTRICT === false) return; if ($code == E_STRICT && self::$reportESTRICT === false) return;


$trace = self::tracer(); $hoptoad = new Services_Hoptoad($code, $message, $file, $line, debug_backtrace());
self::notify( $hoptoad->notify();
$message,
$file,
$line,
$trace
);
} }


/** /**
Expand All @@ -108,32 +109,19 @@ public static function errorHandler($code, $message, $file, $line)
*/ */
public static function exceptionHandler($exception) public static function exceptionHandler($exception)
{ {
$trace = self::tracer($exception->getTrace()); $hoptoad = new Services_Hoptoad(get_class($exception), $exception->getMessage(), $exception->getFile(), $exception->getLine(), $exception->getTrace());

$hoptoad->notify();
self::notify(
$exception->getMessage(),
$exception->getFile(),
$exception->getLine(),
$trace,
get_class($exception)
);
}

/**
* Extract the line, method and class from a trace line
* @param string $line
* @return array
* @author Rich Cavanaugh
**/
public static function extractLineMethodAndClass($line)
{
if (preg_match('/^([0-9]+)\sin\sfunction\s(.*)\sin\sclass\s(.*)$/', $line, $matches)) {
return array($matches[1], $matches[2], $matches[3]);
} else {
return array($line, NULL, NULL);
}
} }


function __construct($error_class, $message, $file, $line, $trace, $component=NULL) {
$this->error_class = $error_class;
$this->message = $message;
$this->file = $file;
$this->line = $line;
$this->trace = $trace;
$this->component = $component;
}

/** /**
* Pass the error and environment data on to Hoptoad * Pass the error and environment data on to Hoptoad
* *
Expand All @@ -148,20 +136,18 @@ public static function extractLineMethodAndClass($line)
* @author Rich Cavanaugh * @author Rich Cavanaugh
* @todo Handle response (e.g. errors) * @todo Handle response (e.g. errors)
*/ */
public static function notify($message, $file, $line, $trace, $error_class=null) function notify()
{ {
array_unshift($trace, "$file:$line");

$url = "http://hoptoadapp.com/notifier_api/v2/notices"; $url = "http://hoptoadapp.com/notifier_api/v2/notices";
$headers = array( $headers = array(
'Accept' => 'text/xml, application/xml', 'Accept' => 'text/xml, application/xml',
'Content-Type' => 'text/xml' 'Content-Type' => 'text/xml'
); );
$body = self::buildXmlNotice($message, $trace, $error_class); $body = $this->buildXmlNotice();


try { try {
$status = call_user_func_array(array('Services_Hoptoad', self::$client . 'Request'), array($url, $headers, $body)); $status = call_user_func_array(array($this, self::$client . 'Request'), array($url, $headers, $body));
if ($status != 200) self::handleErrorResponse($status); if ($status != 200) $this->handleErrorResponse($status);
} catch (RuntimeException $e) { } catch (RuntimeException $e) {
// TODO do something reasonable with the runtime exception. // TODO do something reasonable with the runtime exception.
// we can't really throw our runtime exception since we're likely in // we can't really throw our runtime exception since we're likely in
Expand All @@ -175,7 +161,7 @@ public static function notify($message, $file, $line, $trace, $error_class=null)
* @return string * @return string
* @author Rich Cavanaugh * @author Rich Cavanaugh
**/ **/
public static function buildXmlNotice($message, $trace, $error_class, $component='') function buildXmlNotice()
{ {
$doc = new SimpleXMLElement('<notice />'); $doc = new SimpleXMLElement('<notice />');
$doc->addAttribute('version', self::NOTIFIER_API_VERSION); $doc->addAttribute('version', self::NOTIFIER_API_VERSION);
Expand All @@ -187,51 +173,18 @@ public static function buildXmlNotice($message, $trace, $error_class, $component
$notifier->addChild('url', self::NOTIFIER_URL); $notifier->addChild('url', self::NOTIFIER_URL);


$error = $doc->addChild('error'); $error = $doc->addChild('error');
$error->addChild('class', $error_class); $error->addChild('class', $this->error_class);
$error->addChild('message', $message); $error->addChild('message', $this->message);

$this->addXmlBacktrace($error);
$backtrace = $error->addChild('backtrace');
foreach ($trace as $line) {
$line_node = $backtrace->addChild('line');
list($file, $number) = explode(':', $line);
$line_node->addAttribute('file', $file);
list($number, $method, $class) = self::extractLineMethodAndClass($number);
$line_node->addAttribute('number', $number);
$line_node->addAttribute('method', $method);
}


$request = $doc->addChild('request'); $request = $doc->addChild('request');
$request->addChild('url', "http://{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}"); $request->addChild('url', $this->request_uri());
$request->addChild('component', $component); $request->addChild('component', $this->component);

if (isset($_REQUEST) && !empty($_REQUEST)) {
$params = $request->addChild('params');
foreach ($_REQUEST as $key => $val) {
$var_node = $params->addChild('var', $val);
$var_node->addAttribute('key', $key);
}
}


if (isset($_SESSION) && !empty($_SESSION)) { if (isset($_REQUEST)) $this->addXmlVars($request, 'params', $_REQUEST);
$session = $request->addChild('session'); if (isset($_SESSION)) $this->addXmlVars($request, 'session', $_SESSION);
foreach ($_SESSION as $key => $val) { if (isset($_SERVER)) $this->addXmlVars($request, 'cgi-data', $_SERVER);
$var_node = $session->addChild('var', $val); if (isset($_ENV)) $this->addXmlVars($request, 'cgi-data', $_ENV);
$var_node->addAttribute('key', $key);
}
}

$cgi_data = $request->addChild('cgi-data');
foreach ($_SERVER as $key => $val) {
$var_node = $cgi_data->addChild('var', $val);
$var_node->addAttribute('key', $key);
}

if (isset($_ENV) && !empty($_ENV)) {
foreach ($_ENV as $key => $val) {
$var_node = $cgi_data->addChild('var', $val);
$var_node->addAttribute('key', $key);
}
}


$env = $doc->addChild('server-environment'); $env = $doc->addChild('server-environment');
$env->addChild('project-root', $_SERVER['DOCUMENT_ROOT']); $env->addChild('project-root', $_SERVER['DOCUMENT_ROOT']);
Expand All @@ -241,47 +194,67 @@ public static function buildXmlNotice($message, $trace, $error_class, $component
} }


/** /**
* Build a trace that is formatted in the way Hoptoad expects * addXmlVars
*
* @param string $trace
* @return void * @return void
* @author Rich Cavanaugh * @author Rich Cavanaugh
*/ **/
public static function tracer($trace = NULL) function addXmlVars($parent, $key, $source)
{ {
$lines = Array(); if (empty($source)) return;


$trace = $trace ? $trace : debug_backtrace(); $node = $parent->addChild($key);

foreach ($source as $key => $val) {
$indent = ''; $var_node = $node->addChild('var', $val);
$func = ''; $var_node->addAttribute('key', $key);

}
foreach($trace as $val) { }
if (isset($val['class']) && $val['class'] == 'Services_Hoptoad') continue;


$file = isset($val['file']) ? $val['file'] : 'Unknown file'; /**
$line_number = isset($val['line']) ? $val['line'] : ''; * addXmlBacktrace
$func = isset($val['function']) ? $val['function'] : ''; * @return void
$class = isset($val['class']) ? $val['class'] : ''; * @author Rich Cavanaugh
**/
function addXmlBacktrace($parent)
{
$backtrace = $parent->addChild('backtrace');
$line_node = $backtrace->addChild('line');
$line_node->addAttribute('file', $this->file);
$line_node->addAttribute('number', $this->line);


$line = $file; foreach ($this->trace as $entry) {
if ($line_number) $line .= ':' . $line_number; if (isset($entry['class']) && $entry['class'] == 'Services_Hoptoad') continue;
if ($func) $line .= ' in function ' . $func;
if ($class) $line .= ' in class ' . $class;


$lines[] = $line; $line_node = $backtrace->addChild('line');
$line_node->addAttribute('file', $entry['file']);
$line_node->addAttribute('number', $entry['line']);
$line_node->addAttribute('method', $entry['function']);
} }

return $lines;
} }


/**
* get the request uri
* @return string
* @author Scott Woods
**/
function request_uri() {
if (isset($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] == 443) {
$protocol = 'https';
} else {
$protocol = 'http';
}
$host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '';
$path = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '';
$query_string = isset($_SERVER['QUERY_STRING']) && !empty($_SERVER['QUERY_STRING']) ? ('?' . $_SERVER['QUERY_STRING']) : '';
return "{$protocol}://{$host}{$path}{$query_string}";
}

/** /**
* @param mixed $code The HTTP status code from Hoptoad. * @param mixed $code The HTTP status code from Hoptoad.
* *
* @return void * @return void
* @throws RuntimeException Error message from hoptoad, translated to a RuntimeException. * @throws RuntimeException Error message from hoptoad, translated to a RuntimeException.
*/ */
protected static function handleErrorResponse($code) protected function handleErrorResponse($code)
{ {
switch ($code) { switch ($code) {
case '403': case '403':
Expand All @@ -306,7 +279,7 @@ protected static function handleErrorResponse($code)
* @return integer * @return integer
* @author Rich Cavanaugh * @author Rich Cavanaugh
**/ **/
public static function pearRequest($url, $headers, $body) public function pearRequest($url, $headers, $body)
{ {
if (!class_exists('HTTP_Request2')) require_once('HTTP/Request2.php'); if (!class_exists('HTTP_Request2')) require_once('HTTP/Request2.php');
if (!class_exists('HTTP_Request2_Adapter_Socket')) require_once 'HTTP/Request2/Adapter/Socket.php'; if (!class_exists('HTTP_Request2_Adapter_Socket')) require_once 'HTTP/Request2/Adapter/Socket.php';
Expand All @@ -324,7 +297,7 @@ public static function pearRequest($url, $headers, $body)
* @return integer * @return integer
* @author Rich Cavanaugh * @author Rich Cavanaugh
**/ **/
public static function curlRequest($url, $headers, $body) public function curlRequest($url, $headers, $body)
{ {
$header_strings = array(); $header_strings = array();
foreach ($headers as $key => $val) { foreach ($headers as $key => $val) {
Expand All @@ -350,7 +323,7 @@ public static function curlRequest($url, $headers, $body)
* @return integer * @return integer
* @author Rich Cavanaugh * @author Rich Cavanaugh
**/ **/
public static function zendRequest($url, $headers, $body) public function zendRequest($url, $headers, $body)
{ {
$header_strings = array(); $header_strings = array();
foreach ($headers as $key => $val) { foreach ($headers as $key => $val) {
Expand Down

0 comments on commit a1fb731

Please sign in to comment.