| 1 |
<?php |
| 2 |
|
| 3 |
/** |
| 4 |
* An exception caused by a data not matching a rule or set of rules |
| 5 |
* |
| 6 |
* @copyright Copyright (c) 2007-2010 Will Bond, others |
| 7 |
* @author Will Bond [wb] <will@flourishlib.com> |
| 8 |
* @author Will Bond, iMarc LLC [wb-imarc] <will@imarc.net> |
| 9 |
* @license http://flourishlib.com/license |
| 10 |
* |
| 11 |
* @package Flourish |
| 12 |
* @link http://flourishlib.com/fValidationException |
| 13 |
* |
| 14 |
* @version 1.0.0b4 |
| 15 |
* @changes 1.0.0b4 Added support for nested error arrays [wb-imarc, 2010-10-03] |
| 16 |
* @changes 1.0.0b3 Added ::removeFieldNames() [wb, 2010-05-26] |
| 17 |
* @changes 1.0.0b2 Added a custom ::__construct() to handle arrays of messages [wb, 2009-09-17] |
| 18 |
* @changes 1.0.0b The initial implementation [wb, 2007-06-14] |
| 19 |
*/ |
| 20 |
class fValidationException extends fExpectedException { |
| 21 |
|
| 22 |
const formatField = 'fValidationException::formatField'; |
| 23 |
const removeFieldNames = 'fValidationException::removeFieldNames'; |
| 24 |
const setFieldFormat = 'fValidationException::setFieldFormat'; |
| 25 |
|
| 26 |
/** |
| 27 |
* The formatting string to use for field names |
| 28 |
* |
| 29 |
* @var string |
| 30 |
*/ |
| 31 |
static protected $field_format = '%s: '; |
| 32 |
|
| 33 |
/** |
| 34 |
* Accepts a field name and formats it based on the formatting string set via ::setFieldFormat() |
| 35 |
* |
| 36 |
* @param string $field The name of the field to format |
| 37 |
* @return string The formatted field name |
| 38 |
*/ |
| 39 |
static public function formatField($field) { |
| 40 |
return sprintf(self::$field_format, $field); |
| 41 |
} |
| 42 |
|
| 43 |
/** |
| 44 |
* Removes the field names from normal validation messages, leaving just the message part |
| 45 |
* |
| 46 |
* @param array $messages The messages to remove the field names from |
| 47 |
* @return array The messages without field names |
| 48 |
*/ |
| 49 |
static public function removeFieldNames($messages) { |
| 50 |
$token_field = self::formatField('__TOKEN__'); |
| 51 |
$replace_regex = '#^' . str_replace('__TOKEN__', '(.*?)', preg_quote($token_field, '#')) . '#'; |
| 52 |
|
| 53 |
$output = array(); |
| 54 |
foreach ($messages as $column => $message) { |
| 55 |
if (is_array($message)) { |
| 56 |
$message['errors'] = self::removeFieldNames($message['errors']); |
| 57 |
$output[$column] = $message; |
| 58 |
} else { |
| 59 |
$output[$column] = preg_replace($replace_regex, '', $message); |
| 60 |
} |
| 61 |
} |
| 62 |
|
| 63 |
return $output; |
| 64 |
} |
| 65 |
|
| 66 |
/** |
| 67 |
* Set the format to be applied to all field names used in fValidationExceptions |
| 68 |
* |
| 69 |
* The format should contain exactly one `%s` |
| 70 |
* [http://php.net/sprintf sprintf()] conversion specification, which will |
| 71 |
* be replaced with the field name. Any literal `%` characters should be |
| 72 |
* written as `%%`. |
| 73 |
* |
| 74 |
* The default format is just `%s: `, which simply inserts a `:` and space |
| 75 |
* after the field name. |
| 76 |
* |
| 77 |
* @param string $format A string to format the field name with - `%s` will be replaced with the field name |
| 78 |
* @return void |
| 79 |
*/ |
| 80 |
static public function setFieldFormat($format) { |
| 81 |
if (substr_count(str_replace('%%', '', $format), '%') != 1 || strpos($format, '%s') === FALSE) { |
| 82 |
throw new fProgrammerException( |
| 83 |
'The format, %s, has more or less than exactly one %%s sprintf() conversion specification', $format |
| 84 |
); |
| 85 |
} |
| 86 |
self::$field_format = $format; |
| 87 |
} |
| 88 |
|
| 89 |
/** |
| 90 |
* Sets the message for the exception, allowing for custom formatting beyond fException |
| 91 |
* |
| 92 |
* If this method receives exactly two parameters, a string and an array, |
| 93 |
* the string will be used as a message in a HTML `<p>` tag and the array |
| 94 |
* will be turned into an unorder list `<ul>` tag with each element in the |
| 95 |
* array being an `<li>` tag. It is possible to pass an optional exception |
| 96 |
* code as a third parameter. |
| 97 |
* |
| 98 |
* The following PHP: |
| 99 |
* |
| 100 |
* {{{ |
| 101 |
* #!php |
| 102 |
* throw new fValidationException( |
| 103 |
* 'The following problems were found:', |
| 104 |
* array( |
| 105 |
* 'Please provide your name', |
| 106 |
* 'Please provide your email address' |
| 107 |
* ) |
| 108 |
* ); |
| 109 |
* }}} |
| 110 |
* |
| 111 |
* Would create the message: |
| 112 |
* |
| 113 |
* {{{ |
| 114 |
* #!text/html |
| 115 |
* <p>The following problems were found:</p> |
| 116 |
* <ul> |
| 117 |
* <li>Please provide your name</li> |
| 118 |
* <li>Please provide your email address</li> |
| 119 |
* </ul> |
| 120 |
* }}} |
| 121 |
* |
| 122 |
* If the parameters are anything else, they will be passed to |
| 123 |
* fException::__construct(). |
| 124 |
* |
| 125 |
* @param string $message The beginning message for the exception. This will be placed in a `<p>` tag. |
| 126 |
* @param array $sub_messages An array of strings to place in a `<ul>` tag |
| 127 |
* @param mixed $code The optional exception code |
| 128 |
* @return fException |
| 129 |
*/ |
| 130 |
public function __construct($message = '') { |
| 131 |
$params = func_get_args(); |
| 132 |
|
| 133 |
if ((count($params) == 2 || count($params) == 3) && is_string($params[0]) && is_array($params[1])) { |
| 134 |
|
| 135 |
|
| 136 |
$message = sprintf("<p>%1\$s</p>\n<ul>\n<li>%2\$s</li>\n</ul>", self::compose($params[0]), join("</li>\n<li>", $this->formatErrorArray($params[1]))); |
| 137 |
|
| 138 |
$params = array_merge( |
| 139 |
// This escapes % signs since fException is going to look for sprintf formatting codes |
| 140 |
array(str_replace('%', '%%', $message)), |
| 141 |
// This grabs the exception code if one is defined |
| 142 |
array_slice($params, 2) |
| 143 |
); |
| 144 |
} |
| 145 |
|
| 146 |
call_user_func_array( |
| 147 |
array($this, 'fException::__construct'), $params |
| 148 |
); |
| 149 |
} |
| 150 |
|
| 151 |
/** |
| 152 |
* Takes an error array that may or may not be nested and returns a HTML string representation |
| 153 |
* |
| 154 |
* @param array $errors An array of (possibly nested) child record errors |
| 155 |
* @return array An array of string error messages |
| 156 |
*/ |
| 157 |
private function formatErrorArray($errors) { |
| 158 |
$new_errors = array(); |
| 159 |
foreach ($errors as $error) { |
| 160 |
if (!is_array($error)) { |
| 161 |
$new_errors[] = $error; |
| 162 |
} else { |
| 163 |
$new_errors[] = sprintf("<span>%1\$s</span>\n<ul>\n<li>%2\$s</li>\n</ul>", $error['name'], join("</li>\n<li>", $this->formatErrorArray($error['errors']))); |
| 164 |
} |
| 165 |
} |
| 166 |
return $new_errors; |
| 167 |
} |
| 168 |
|
| 169 |
} |
| 170 |
|
| 171 |
/** |
| 172 |
* Copyright (c) 2007-2010 Will Bond <will@flourishlib.com>, others |
| 173 |
* |
| 174 |
* Permission is hereby granted, free of charge, to any person obtaining a copy |
| 175 |
* of this software and associated documentation files (the "Software"), to deal |
| 176 |
* in the Software without restriction, including without limitation the rights |
| 177 |
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| 178 |
* copies of the Software, and to permit persons to whom the Software is |
| 179 |
* furnished to do so, subject to the following conditions: |
| 180 |
* |
| 181 |
* The above copyright notice and this permission notice shall be included in |
| 182 |
* all copies or substantial portions of the Software. |
| 183 |
* |
| 184 |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 185 |
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 186 |
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| 187 |
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| 188 |
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| 189 |
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
| 190 |
* THE SOFTWARE. |
| 191 |
*/ |