diff --git a/actions/DisplayAction.php b/actions/DisplayAction.php index 8ac5fe8d..fc5e9da0 100644 --- a/actions/DisplayAction.php +++ b/actions/DisplayAction.php @@ -146,20 +146,61 @@ class DisplayAction extends ActionAbstract { } catch(Error $e) { error_log($e); - if(Configuration::getConfig('error', 'output') === 'feed') { - $item = new \FeedItem(); + if(logBridgeError($bridge::NAME, $e->getCode()) >= Configuration::getConfig('error', 'report_limit')) { + if(Configuration::getConfig('error', 'output') === 'feed') { + $item = new \FeedItem(); - // Create "new" error message every 24 hours - $this->userData['_error_time'] = urlencode((int)(time() / 86400)); + // Create "new" error message every 24 hours + $this->userData['_error_time'] = urlencode((int)(time() / 86400)); - // Error 0 is a special case (i.e. "trying to get property of non-object") - if($e->getCode() === 0) { - $item->setTitle( - 'Bridge encountered an unexpected situation! (' - . $this->userData['_error_time'] - . ')' + // Error 0 is a special case (i.e. "trying to get property of non-object") + if($e->getCode() === 0) { + $item->setTitle( + 'Bridge encountered an unexpected situation! (' + . $this->userData['_error_time'] + . ')' + ); + } else { + $item->setTitle( + 'Bridge returned error ' + . $e->getCode() + . '! (' + . $this->userData['_error_time'] + . ')' + ); + } + + $item->setURI( + (isset($_SERVER['REQUEST_URI']) ? parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH) : '') + . '?' + . http_build_query($this->userData) ); - } else { + + $item->setTimestamp(time()); + $item->setContent(buildBridgeException($e, $bridge)); + + $items[] = $item; + } elseif(Configuration::getConfig('error', 'output') === 'http') { + header('Content-Type: text/html', true, $e->getCode()); + die(buildTransformException($e, $bridge)); + } + } + } catch(Exception $e) { + error_log($e); + + if(logBridgeError($bridge::NAME, $e->getCode()) >= Configuration::getConfig('error', 'report_limit')) { + if(Configuration::getConfig('error', 'output') === 'feed') { + $item = new \FeedItem(); + + // Create "new" error message every 24 hours + $this->userData['_error_time'] = urlencode((int)(time() / 86400)); + + $item->setURI( + (isset($_SERVER['REQUEST_URI']) ? parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH) : '') + . '?' + . http_build_query($this->userData) + ); + $item->setTitle( 'Bridge returned error ' . $e->getCode() @@ -167,51 +208,14 @@ class DisplayAction extends ActionAbstract { . $this->userData['_error_time'] . ')' ); + $item->setTimestamp(time()); + $item->setContent(buildBridgeException($e, $bridge)); + + $items[] = $item; + } elseif(Configuration::getConfig('error', 'output') === 'http') { + header('Content-Type: text/html', true, $e->getCode()); + die(buildTransformException($e, $bridge)); } - - $item->setURI( - (isset($_SERVER['REQUEST_URI']) ? parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH) : '') - . '?' - . http_build_query($this->userData) - ); - - $item->setTimestamp(time()); - $item->setContent(buildBridgeException($e, $bridge)); - - $items[] = $item; - } elseif(Configuration::getConfig('error', 'output') === 'http') { - header('Content-Type: text/html', true, $e->getCode()); - die(buildTransformException($e, $bridge)); - } - } catch(Exception $e) { - error_log($e); - - if(Configuration::getConfig('error', 'output') === 'feed') { - $item = new \FeedItem(); - - // Create "new" error message every 24 hours - $this->userData['_error_time'] = urlencode((int)(time() / 86400)); - - $item->setURI( - (isset($_SERVER['REQUEST_URI']) ? parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH) : '') - . '?' - . http_build_query($this->userData) - ); - - $item->setTitle( - 'Bridge returned error ' - . $e->getCode() - . '! (' - . $this->userData['_error_time'] - . ')' - ); - $item->setTimestamp(time()); - $item->setContent(buildBridgeException($e, $bridge)); - - $items[] = $item; - } elseif(Configuration::getConfig('error', 'output') === 'http') { - header('Content-Type: text/html', true, $e->getCode()); - die(buildTransformException($e, $bridge)); } } diff --git a/config.default.ini.php b/config.default.ini.php index 61b53931..7d0bdaaa 100644 --- a/config.default.ini.php +++ b/config.default.ini.php @@ -70,6 +70,9 @@ password = "" ; "none" = No errors are reported output = "feed" +; Defines how often an error must occur before it is reported to the user +report_limit = 1 + ; --- Cache specific configuration --------------------------------------------- [SQLiteCache] diff --git a/lib/Configuration.php b/lib/Configuration.php index 969e9bac..8978ea70 100644 --- a/lib/Configuration.php +++ b/lib/Configuration.php @@ -204,6 +204,10 @@ final class Configuration { if(!is_string(self::getConfig('error', 'output'))) self::reportConfigurationError('error', 'output', 'Is not a valid String'); + if(!is_numeric(self::getConfig('error', 'report_limit')) + || self::getConfig('error', 'report_limit') < 1) + self::reportConfigurationError('admin', 'report_limit', 'Value is invalid'); + } /** diff --git a/lib/error.php b/lib/error.php index 9a0756f9..4b7110f0 100644 --- a/lib/error.php +++ b/lib/error.php @@ -41,3 +41,37 @@ function returnClientError($message){ function returnServerError($message){ returnError($message, 500); } + +/** + * Stores bridge-specific errors in a cache file. + * + * @param string $bridgeName The name of the bridge that failed. + * @param int $code The error code + * + * @return int The total number the same error has appeared + */ +function logBridgeError($bridgeName, $code) { + $cacheFac = new CacheFactory(); + $cacheFac->setWorkingDir(PATH_LIB_CACHES); + + $cache = $cacheFac->create(Configuration::getConfig('cache', 'type')); + $cache->setScope('error_reporting'); + $cache->setkey($bridgeName . '_' . $code); + $cache->purgeCache(86400); // 24 hours + + if($report = $cache->loadData()) { + $report = json_decode($report, true); + $report['time'] = time(); + $report['count']++; + } else { + $report = array( + 'error' => $code, + 'time' => time(), + 'count' => 1, + ); + } + + $cache->saveData(json_encode($report)); + + return $report['count']; +}