Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Improve Mustache exception types, catchability.

 * Subclass common exception types (runtime, logic, invalid argument).
 * Add new "unknown x" exceptions for filters, helpers and templates.
 * Make all Mustache exceptions implement Mustache_Exception interface… Gotta catch 'em all!
  • Loading branch information...
commit 0436c59477eb2dd5195162fb2af338324c099a6a 1 parent 5e69e63
@bobthecow authored
View
8 src/Mustache/Compiler.php
@@ -50,7 +50,7 @@ public function compile($source, array $tree, $name, $customEscape = false, $cha
/**
* Helper function for walking the Mustache token parse tree.
*
- * @throws InvalidArgumentException upon encountering unknown token types.
+ * @throws Mustache_Exception_SyntaxException upon encountering unknown token types.
*
* @param array $tree Parse tree of Mustache tokens
* @param int $level (default: 0)
@@ -113,7 +113,7 @@ private function walk(array $tree, $level = 0)
break;
default:
- throw new InvalidArgumentException('Unknown node type: '.json_encode($node));
+ throw new Mustache_Exception_SyntaxException(sprintf('Unknown token type: %s', $node[Mustache_Tokenizer::TYPE]), $node);
}
}
@@ -316,7 +316,7 @@ private function getFilters($id, $level)
const FILTER = '
$filter = $context->%s(%s);
if (is_string($filter) || !is_callable($filter)) {
- throw new UnexpectedValueException(%s);
+ throw new Mustache_Exception_UnknownFilterException(%s);
}
$value = call_user_func($filter, $value);%s
';
@@ -338,7 +338,7 @@ private function getFilter(array $filters, $level)
$name = array_shift($filters);
$method = $this->getFindMethod($name);
$filter = ($method !== 'last') ? var_export($name, true) : '';
- $msg = var_export(sprintf('Filter not found: %s', $name), true);
+ $msg = var_export($name, true);
return sprintf($this->prepare(self::FILTER, $level), $method, $filter, $msg, $this->getFilter($filters, $level));
}
View
22 src/Mustache/Engine.php
@@ -89,6 +89,8 @@ class Mustache_Engine
* 'logger' => new Mustache_StreamLogger('php://stderr'),
* );
*
+ * @throws Mustache_Exception_InvalidArgumentException If `escape` option is not callable.
+ *
* @param array $options (default: array())
*/
public function __construct(array $options = array())
@@ -123,7 +125,7 @@ public function __construct(array $options = array())
if (isset($options['escape'])) {
if (!is_callable($options['escape'])) {
- throw new InvalidArgumentException('Mustache Constructor "escape" option must be callable');
+ throw new Mustache_Exception_InvalidArgumentException('Mustache Constructor "escape" option must be callable');
}
$this->escape = $options['escape'];
@@ -233,7 +235,7 @@ public function getPartialsLoader()
/**
* Set partials for the current partials Loader instance.
*
- * @throws RuntimeException If the current Loader instance is immutable
+ * @throws Mustache_Exception_RuntimeException If the current Loader instance is immutable
*
* @param array $partials (default: array())
*/
@@ -241,7 +243,7 @@ public function setPartials(array $partials = array())
{
$loader = $this->getPartialsLoader();
if (!$loader instanceof Mustache_Loader_MutableLoader) {
- throw new RuntimeException('Unable to set partials on an immutable Mustache Loader instance');
+ throw new Mustache_Exception_RuntimeException('Unable to set partials on an immutable Mustache Loader instance');
}
$loader->setTemplates($partials);
@@ -254,14 +256,14 @@ public function setPartials(array $partials = array())
* any other valid Mustache context value. They will be prepended to the context stack, so they will be available in
* any template loaded by this Mustache instance.
*
- * @throws InvalidArgumentException if $helpers is not an array or Traversable
+ * @throws Mustache_Exception_InvalidArgumentException if $helpers is not an array or Traversable
*
* @param array|Traversable $helpers
*/
public function setHelpers($helpers)
{
if (!is_array($helpers) && !$helpers instanceof Traversable) {
- throw new InvalidArgumentException('setHelpers expects an array of helpers');
+ throw new Mustache_Exception_InvalidArgumentException('setHelpers expects an array of helpers');
}
$this->getHelpers()->clear();
@@ -343,12 +345,14 @@ public function removeHelper($name)
/**
* Set the Mustache Logger instance.
*
+ * @throws Mustache_Exception_InvalidArgumentException If logger is not an instance of Mustache_Logger or Psr\Log\LoggerInterface.
+ *
* @param Mustache_Logger|Psr\Log\LoggerInterface $logger
*/
public function setLogger($logger = null)
{
if ($logger !== null && !($logger instanceof Mustache_Logger || is_a($logger, 'Psr\\Log\\LoggerInterface'))) {
- throw new InvalidArgumentException('Expected an instance of Mustache_Logger or Psr\\Log\\LoggerInterface.');
+ throw new Mustache_Exception_InvalidArgumentException('Expected an instance of Mustache_Logger or Psr\\Log\\LoggerInterface.');
}
$this->logger = $logger;
@@ -636,7 +640,7 @@ private function getCacheFilename($source)
/**
* Helper method to dump a generated Mustache Template subclass to the file cache.
*
- * @throws RuntimeException if unable to create the cache directory or write to $fileName.
+ * @throws Mustache_Exception_RuntimeException if unable to create the cache directory or write to $fileName.
*
* @param string $fileName
* @param string $source
@@ -655,7 +659,7 @@ private function writeCacheFile($fileName, $source)
@mkdir($dirName, 0777, true);
if (!is_dir($dirName)) {
- throw new RuntimeException(sprintf('Failed to create cache directory "%s".', $dirName));
+ throw new Mustache_Exception_RuntimeException(sprintf('Failed to create cache directory "%s".', $dirName));
}
}
@@ -682,7 +686,7 @@ private function writeCacheFile($fileName, $source)
);
}
- throw new RuntimeException(sprintf('Failed to write cache file "%s".', $fileName));
+ throw new Mustache_Exception_RuntimeException(sprintf('Failed to write cache file "%s".', $fileName));
}
/**
View
18 src/Mustache/Exception.php
@@ -0,0 +1,18 @@
+<?php
+
+/*
+ * This file is part of Mustache.php.
+ *
+ * (c) 2013 Justin Hileman
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * A Mustache Exception interface.
+ */
+interface Mustache_Exception
+{
+ // This space intentionally left blank.
+}
View
18 src/Mustache/Exception/InvalidArgumentException.php
@@ -0,0 +1,18 @@
+<?php
+
+/*
+ * This file is part of Mustache.php.
+ *
+ * (c) 2013 Justin Hileman
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Invalid argument exception.
+ */
+class Mustache_Exception_InvalidArgumentException extends InvalidArgumentException implements Mustache_Exception
+{
+ // This space intentionally left blank.
+}
View
18 src/Mustache/Exception/LogicException.php
@@ -0,0 +1,18 @@
+<?php
+
+/*
+ * This file is part of Mustache.php.
+ *
+ * (c) 2013 Justin Hileman
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Logic exception.
+ */
+class Mustache_Exception_LogicException extends LogicException implements Mustache_Exception
+{
+ // This space intentionally left blank.
+}
View
18 src/Mustache/Exception/RuntimeException.php
@@ -0,0 +1,18 @@
+<?php
+
+/*
+ * This file is part of Mustache.php.
+ *
+ * (c) 2013 Justin Hileman
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Runtime exception.
+ */
+class Mustache_Exception_RuntimeException extends RuntimeException implements Mustache_Exception
+{
+ // This space intentionally left blank.
+}
View
29 src/Mustache/Exception/SyntaxException.php
@@ -0,0 +1,29 @@
+<?php
+
+/*
+ * This file is part of Mustache.php.
+ *
+ * (c) 2013 Justin Hileman
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Mustache syntax exception.
+ */
+class Mustache_Exception_SyntaxException extends LogicException implements Mustache_Exception
+{
+ protected $token;
+
+ public function __construct($msg, array $token)
+ {
+ $this->token = $token;
+ parent::__construct($msg);
+ }
+
+ public function getToken()
+ {
+ return $this->token;
+ }
+}
View
29 src/Mustache/Exception/UnknownFilterException.php
@@ -0,0 +1,29 @@
+<?php
+
+/*
+ * This file is part of Mustache.php.
+ *
+ * (c) 2013 Justin Hileman
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Unknown filter exception.
+ */
+class Mustache_Exception_UnknownFilterException extends UnexpectedValueException implements Mustache_Exception
+{
+ protected $filterName;
+
+ public function __construct($filterName)
+ {
+ $this->filterName = $filterName;
+ parent::__construct(sprintf('Unknown filter: %s', $filterName));
+ }
+
+ public function getFilterName()
+ {
+ return $this->filterName;
+ }
+}
View
29 src/Mustache/Exception/UnknownHelperException.php
@@ -0,0 +1,29 @@
+<?php
+
+/*
+ * This file is part of Mustache.php.
+ *
+ * (c) 2013 Justin Hileman
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Unknown helper exception.
+ */
+class Mustache_Exception_UnknownHelperException extends InvalidArgumentException implements Mustache_Exception
+{
+ protected $helperName;
+
+ public function __construct($helperName)
+ {
+ $this->helperName = $helperName;
+ parent::__construct(sprintf('Unknown helper: %s', $helperName));
+ }
+
+ public function getHelperName()
+ {
+ return $this->helperName;
+ }
+}
View
29 src/Mustache/Exception/UnknownTemplateException.php
@@ -0,0 +1,29 @@
+<?php
+
+/*
+ * This file is part of Mustache.php.
+ *
+ * (c) 2013 Justin Hileman
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Unknown template exception.
+ */
+class Mustache_Exception_UnknownTemplateException extends InvalidArgumentException implements Mustache_Exception
+{
+ protected $templateName;
+
+ public function __construct($templateName)
+ {
+ $this->templateName = $templateName;
+ parent::__construct(sprintf('Unknown template: %s', $templateName));
+ }
+
+ public function getTemplateName()
+ {
+ return $this->templateName;
+ }
+}
View
12 src/Mustache/HelperCollection.php
@@ -21,7 +21,7 @@ class Mustache_HelperCollection
*
* Optionally accepts an array (or Traversable) of `$name => $helper` pairs.
*
- * @throws InvalidArgumentException if the $helpers argument isn't an array or Traversable
+ * @throws Mustache_Exception_InvalidArgumentException if the $helpers argument isn't an array or Traversable
*
* @param array|Traversable $helpers (default: null)
*/
@@ -29,7 +29,7 @@ public function __construct($helpers = null)
{
if ($helpers !== null) {
if (!is_array($helpers) && !$helpers instanceof Traversable) {
- throw new InvalidArgumentException('HelperCollection constructor expects an array of helpers');
+ throw new Mustache_Exception_InvalidArgumentException('HelperCollection constructor expects an array of helpers');
}
foreach ($helpers as $name => $helper) {
@@ -79,6 +79,8 @@ public function __get($name)
/**
* Get a helper by name.
*
+ * @throws Mustache_Exception_UnknownHelperException If helper does not exist.
+ *
* @param string $name
*
* @return mixed Helper
@@ -86,7 +88,7 @@ public function __get($name)
public function get($name)
{
if (!$this->has($name)) {
- throw new InvalidArgumentException('Unknown helper: '.$name);
+ throw new Mustache_Exception_UnknownHelperException($name);
}
return $this->helpers[$name];
@@ -133,14 +135,14 @@ public function __unset($name)
/**
* Check whether a given helper is present in the collection.
*
- * @throws InvalidArgumentException if the requested helper is not present.
+ * @throws Mustache_Exception_UnknownHelperException if the requested helper is not present.
*
* @param string $name
*/
public function remove($name)
{
if (!$this->has($name)) {
- throw new InvalidArgumentException('Unknown helper: '.$name);
+ throw new Mustache_Exception_UnknownHelperException($name);
}
unset($this->helpers[$name]);
View
4 src/Mustache/Loader/ArrayLoader.php
@@ -43,6 +43,8 @@ public function __construct(array $templates = array())
/**
* Load a Template.
*
+ * @throws Mustache_Exception_UnknownTemplateException If a template file is not found.
+ *
* @param string $name
*
* @return string Mustache Template source
@@ -50,7 +52,7 @@ public function __construct(array $templates = array())
public function load($name)
{
if (!isset($this->templates[$name])) {
- throw new InvalidArgumentException('Template '.$name.' not found.');
+ throw new Mustache_Exception_UnknownTemplateException($name);
}
return $this->templates[$name];
View
8 src/Mustache/Loader/FilesystemLoader.php
@@ -42,7 +42,7 @@ class Mustache_Loader_FilesystemLoader implements Mustache_Loader
* 'extension' => '.ms',
* );
*
- * @throws RuntimeException if $baseDir does not exist.
+ * @throws Mustache_Exception_RuntimeException if $baseDir does not exist.
*
* @param string $baseDir Base directory containing Mustache template files.
* @param array $options Array of Loader options (default: array())
@@ -52,7 +52,7 @@ public function __construct($baseDir, array $options = array())
$this->baseDir = rtrim(realpath($baseDir), '/');
if (!is_dir($this->baseDir)) {
- throw new RuntimeException('FilesystemLoader baseDir must be a directory: '.$baseDir);
+ throw new Mustache_Exception_RuntimeException(sprintf('FilesystemLoader baseDir must be a directory: %s', $baseDir));
}
if (array_key_exists('extension', $options)) {
@@ -86,7 +86,7 @@ public function load($name)
/**
* Helper function for loading a Mustache file by name.
*
- * @throws InvalidArgumentException if a template file is not found.
+ * @throws Mustache_Exception_UnknownTemplateException If a template file is not found.
*
* @param string $name
*
@@ -97,7 +97,7 @@ protected function loadFile($name)
$fileName = $this->getFileName($name);
if (!file_exists($fileName)) {
- throw new InvalidArgumentException('Template '.$name.' not found.');
+ throw new Mustache_Exception_UnknownTemplateException($name);
}
return file_get_contents($fileName);
View
15 src/Mustache/Logger/StreamLogger.php
@@ -64,14 +64,14 @@ public function __destruct()
/**
* Set the minimum logging level.
*
- * @throws InvalidArgumentException if the logging level is unknown.
+ * @throws Mustache_Exception_InvalidArgumentException if the logging level is unknown.
*
* @param integer $level The minimum logging level which will be written
*/
public function setLevel($level)
{
if (!array_key_exists($level, self::$levels)) {
- throw new InvalidArgumentException('Unexpected logging level: ' . $level);
+ throw new Mustache_Exception_InvalidArgumentException(sprintf('Unexpected logging level: %s', $level));
}
$this->level = $level;
@@ -90,7 +90,7 @@ public function getLevel()
/**
* Logs with an arbitrary level.
*
- * @throws InvalidArgumentException if the logging level is unknown.
+ * @throws Mustache_Exception_InvalidArgumentException if the logging level is unknown.
*
* @param mixed $level
* @param string $message
@@ -99,7 +99,7 @@ public function getLevel()
public function log($level, $message, array $context = array())
{
if (!array_key_exists($level, self::$levels)) {
- throw new InvalidArgumentException('Unexpected logging level: ' . $level);
+ throw new Mustache_Exception_InvalidArgumentException(sprintf('Unexpected logging level: %s', $level));
}
if (self::$levels[$level] >= self::$levels[$this->level]) {
@@ -110,6 +110,9 @@ public function log($level, $message, array $context = array())
/**
* Write a record to the log.
*
+ * @throws Mustache_Exception_LogicException If neither a stream resource nor url is present.
+ * @throws Mustache_Exception_RuntimeException If the stream url cannot be opened.
+ *
* @param integer $level The logging level
* @param string $message The log message
* @param array $context The log context
@@ -118,13 +121,13 @@ protected function writeLog($level, $message, array $context = array())
{
if (!is_resource($this->stream)) {
if (!isset($this->url)) {
- throw new LogicException('Missing stream url, the stream can not be opened. This may be caused by a premature call to close().');
+ throw new Mustache_Exception_LogicException('Missing stream url, the stream can not be opened. This may be caused by a premature call to close().');
}
$this->stream = fopen($this->url, 'a');
if (!is_resource($this->stream)) {
// @codeCoverageIgnoreStart
- throw new UnexpectedValueException(sprintf('The stream or file "%s" could not be opened.', $this->url));
+ throw new Mustache_Exception_RuntimeException(sprintf('The stream or file "%s" could not be opened.', $this->url));
// @codeCoverageIgnoreEnd
}
}
View
13 src/Mustache/Parser.php
@@ -32,12 +32,12 @@ public function parse(array $tokens = array())
/**
* Helper method for recursively building a parse tree.
*
+ * @throws Mustache_Exception_SyntaxException when nesting errors or mismatched section tags are encountered.
+ *
* @param ArrayIterator $tokens Stream of Mustache tokens
* @param array $parent Parent token (default: null)
*
* @return array Mustache Token parse tree
- *
- * @throws LogicException when nesting errors or mismatched section tags are encountered.
*/
private function buildTree(ArrayIterator $tokens, array $parent = null)
{
@@ -58,11 +58,13 @@ private function buildTree(ArrayIterator $tokens, array $parent = null)
case Mustache_Tokenizer::T_END_SECTION:
if (!isset($parent)) {
- throw new LogicException('Unexpected closing tag: /'. $token[Mustache_Tokenizer::NAME]);
+ $msg = sprintf('Unexpected closing tag: /%s', $token[Mustache_Tokenizer::NAME]);
+ throw new Mustache_Exception_SyntaxException($msg, $token);
}
if ($token[Mustache_Tokenizer::NAME] !== $parent[Mustache_Tokenizer::NAME]) {
- throw new LogicException('Nesting error: ' . $parent[Mustache_Tokenizer::NAME] . ' vs. ' . $token[Mustache_Tokenizer::NAME]);
+ $msg = sprintf('Nesting error: %s vs. %s', $parent[Mustache_Tokenizer::NAME], $token[Mustache_Tokenizer::NAME]);
+ throw new Mustache_Exception_SyntaxException($msg, $token);
}
$parent[Mustache_Tokenizer::END] = $token[Mustache_Tokenizer::INDEX];
@@ -80,7 +82,8 @@ private function buildTree(ArrayIterator $tokens, array $parent = null)
} while ($tokens->valid());
if (isset($parent)) {
- throw new LogicException('Missing closing tag: ' . $parent[Mustache_Tokenizer::NAME]);
+ $msg = sprintf('Missing closing tag: %s', $parent[Mustache_Tokenizer::NAME]);
+ throw new Mustache_Exception_SyntaxException($msg, $parent);
}
return $nodes;
View
4 test/Mustache/Test/CompilerTest.php
@@ -85,9 +85,9 @@ public function getCompileValues()
}
/**
- * @expectedException InvalidArgumentException
+ * @expectedException Mustache_Exception_SyntaxException
*/
- public function testCompilerThrowsUnknownNodeTypeException()
+ public function testCompilerThrowsSyntaxException()
{
$compiler = new Mustache_Compiler;
$compiler->compile('', array(array(Mustache_Tokenizer::TYPE => 'invalid')), 'SomeClass');
View
8 test/Mustache/Test/EngineTest.php
@@ -141,7 +141,7 @@ public function testCache()
}
/**
- * @expectedException InvalidArgumentException
+ * @expectedException Mustache_Exception_InvalidArgumentException
* @dataProvider getBadEscapers
*/
public function testNonCallableEscapeThrowsException($escape)
@@ -158,7 +158,7 @@ public function getBadEscapers()
}
/**
- * @expectedException RuntimeException
+ * @expectedException Mustache_Exception_RuntimeException
*/
public function testImmutablePartialsLoadersThrowException()
{
@@ -223,7 +223,7 @@ public static function wrapWithUnderscores($text)
}
/**
- * @expectedException InvalidArgumentException
+ * @expectedException Mustache_Exception_InvalidArgumentException
*/
public function testSetHelpersThrowsExceptions()
{
@@ -232,7 +232,7 @@ public function testSetHelpersThrowsExceptions()
}
/**
- * @expectedException InvalidArgumentException
+ * @expectedException Mustache_Exception_InvalidArgumentException
*/
public function testSetLoggerThrowsExceptions()
{
View
2  test/Mustache/Test/FiveThree/Functional/FiltersTest.php
@@ -67,7 +67,7 @@ public function testInterpolateFirst()
}
/**
- * @expectedException UnexpectedValueException
+ * @expectedException Mustache_Exception_UnknownFilterException
* @dataProvider getBrokenPipes
*/
public function testThrowsExceptionForBrokenPipes($tpl, $data)
View
2  test/Mustache/Test/Loader/ArrayLoaderTest.php
@@ -42,7 +42,7 @@ public function testSetAndLoadTemplates()
}
/**
- * @expectedException InvalidArgumentException
+ * @expectedException Mustache_Exception_UnknownTemplateException
*/
public function testMissingTemplatesThrowExceptions()
{
View
4 test/Mustache/Test/Loader/FilesystemLoaderTest.php
@@ -44,7 +44,7 @@ public function testEmptyExtensionString()
}
/**
- * @expectedException RuntimeException
+ * @expectedException Mustache_Exception_RuntimeException
*/
public function testMissingBaseDirThrowsException()
{
@@ -52,7 +52,7 @@ public function testMissingBaseDirThrowsException()
}
/**
- * @expectedException InvalidArgumentException
+ * @expectedException Mustache_Exception_UnknownTemplateException
*/
public function testMissingTemplateThrowsException()
{
View
6 test/Mustache/Test/Logger/StreamLoggerTest.php
@@ -34,7 +34,7 @@ public function testAcceptsResource()
}
/**
- * @expectedException LogicException
+ * @expectedException Mustache_Exception_LogicException
*/
public function testPrematurelyClosedStreamThrowsException()
{
@@ -187,7 +187,7 @@ public function testChangeLoggingLevels()
}
/**
- * @expectedException InvalidArgumentException
+ * @expectedException Mustache_Exception_InvalidArgumentException
*/
public function testThrowsInvalidArgumentExceptionWhenSettingUnknownLevels()
{
@@ -196,7 +196,7 @@ public function testThrowsInvalidArgumentExceptionWhenSettingUnknownLevels()
}
/**
- * @expectedException InvalidArgumentException
+ * @expectedException Mustache_Exception_InvalidArgumentException
*/
public function testThrowsInvalidArgumentExceptionWhenLoggingUnknownLevels()
{
View
2  test/Mustache/Test/ParserTest.php
@@ -108,7 +108,7 @@ public function getTokenSets()
/**
* @dataProvider getBadParseTrees
- * @expectedException LogicException
+ * @expectedException Mustache_Exception_SyntaxException
*/
public function testParserThrowsExceptions($tokens)
{
Please sign in to comment.
Something went wrong with that request. Please try again.