| Total Complexity | 233 |
| Total Lines | 1767 |
| Duplicated Lines | 0 % |
| Changes | 16 | ||
| Bugs | 1 | Features | 0 |
Complex classes like General often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use General, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 10 | class General |
||
| 11 | { |
||
| 12 | /** |
||
| 13 | * Convert any special characters into their entity equivalents. Since |
||
| 14 | * Symphony 2.3, this function assumes UTF-8 and will not double |
||
| 15 | * encode strings. |
||
| 16 | * |
||
| 17 | * @uses htmlspecialchars() |
||
| 18 | * @param string $source |
||
| 19 | * a string to operate on. |
||
| 20 | * @return string |
||
| 21 | * the encoded version of the string. |
||
| 22 | */ |
||
| 23 | public static function sanitize($source) |
||
| 24 | { |
||
| 25 | $source = htmlspecialchars($source, ENT_COMPAT, 'UTF-8', false); |
||
| 26 | |||
| 27 | return $source; |
||
| 28 | } |
||
| 29 | |||
| 30 | /** |
||
| 31 | * Convert any special characters into their entity equivalents. |
||
| 32 | * Contrary to `sanitize()`, this version does double encode existing entities. |
||
| 33 | * |
||
| 34 | * @since Symphony 2.7.5 |
||
| 35 | * @uses htmlspecialchars() |
||
| 36 | * @param string $source |
||
| 37 | * a string to operate on. |
||
| 38 | * @return string |
||
| 39 | * the fully encoded version of the string. |
||
| 40 | */ |
||
| 41 | public static function sanitizeDouble($source) |
||
| 46 | } |
||
| 47 | |||
| 48 | /** |
||
| 49 | * Revert any html entities to their character equivalents. |
||
| 50 | * |
||
| 51 | * @param string $str |
||
| 52 | * a string to operate on |
||
| 53 | * @return string |
||
| 54 | * the decoded version of the string |
||
| 55 | */ |
||
| 56 | public static function reverse_sanitize($str) |
||
| 57 | { |
||
| 58 | return htmlspecialchars_decode($str, ENT_COMPAT); |
||
| 59 | } |
||
| 60 | |||
| 61 | /** |
||
| 62 | * Validate a string against a set of regular expressions. |
||
| 63 | * |
||
| 64 | * @param array|string $string |
||
| 65 | * string to operate on |
||
| 66 | * @param array|string $rule |
||
| 67 | * a single rule or array of rules |
||
| 68 | * @return boolean |
||
| 69 | * false if any of the rules in $rule do not match any of the strings in |
||
| 70 | * `$string`, return true otherwise. |
||
| 71 | */ |
||
| 72 | public static function validateString($string, $rule) |
||
| 73 | { |
||
| 74 | if (!is_array($rule) && ($rule == '' || $rule == null)) { |
||
| 75 | return true; |
||
| 76 | } |
||
| 77 | |||
| 78 | if (!is_array($string) && ($string == '' || $rule == null)) { |
||
| 79 | return true; |
||
| 80 | } |
||
| 81 | |||
| 82 | if (!is_array($rule)) { |
||
| 83 | $rule = array($rule); |
||
| 84 | } |
||
| 85 | |||
| 86 | if (!is_array($string)) { |
||
| 87 | $string = array($string); |
||
| 88 | } |
||
| 89 | |||
| 90 | foreach ($rule as $r) { |
||
| 91 | foreach ($string as $s) { |
||
| 92 | if (!preg_match($r, $s)) { |
||
| 93 | return false; |
||
| 94 | } |
||
| 95 | } |
||
| 96 | } |
||
| 97 | return true; |
||
| 98 | } |
||
| 99 | |||
| 100 | /** |
||
| 101 | * Replace the tabs with spaces in the input string. |
||
| 102 | * |
||
| 103 | * @param string $string |
||
| 104 | * the string in which to replace the tabs with spaces. |
||
| 105 | * @param integer $spaces (optional) |
||
| 106 | * the number of spaces to replace each tab with. This argument is optional |
||
| 107 | * with a default of 4. |
||
| 108 | * @return string |
||
| 109 | * the resulting string. |
||
| 110 | */ |
||
| 111 | public static function tabsToSpaces($string, $spaces = 4) |
||
| 112 | { |
||
| 113 | return str_replace("\t", str_pad(null, $spaces), $string); |
||
| 114 | } |
||
| 115 | |||
| 116 | /** |
||
| 117 | * Checks an xml document for well-formedness. |
||
| 118 | * |
||
| 119 | * @param string $data |
||
| 120 | * filename, xml document as a string, or arbitrary string |
||
| 121 | * @param pointer &$errors |
||
|
|
|||
| 122 | * pointer to an array which will contain any validation errors |
||
| 123 | * @param boolean $isFile (optional) |
||
| 124 | * if this is true, the method will attempt to read from a file, `$data` |
||
| 125 | * instead. |
||
| 126 | * @param XsltProcess $xsltProcessor (optional) |
||
| 127 | * if set, the validation will be done using this XSLT processor rather |
||
| 128 | * than the built in XML parser. the default is null. |
||
| 129 | * @param string $encoding (optional) |
||
| 130 | * if no XML header is expected, than this should be set to match the |
||
| 131 | * encoding of the XML |
||
| 132 | * @return boolean |
||
| 133 | * true if there are no errors in validating the XML, false otherwise. |
||
| 134 | */ |
||
| 135 | public static function validateXML($data, &$errors, $isFile = true, $xsltProcessor = null, $encoding = 'UTF-8') |
||
| 136 | { |
||
| 137 | $_data = ($isFile) ? file_get_contents($data) : $data; |
||
| 138 | $_data = preg_replace('/<!DOCTYPE[-.:"\'\/\\w\\s]+>/', null, $_data); |
||
| 139 | |||
| 140 | if (strpos($_data, '<?xml') === false) { |
||
| 141 | $_data = '<?xml version="1.0" encoding="'.$encoding.'"?><rootelement>'.$_data.'</rootelement>'; |
||
| 142 | } |
||
| 143 | |||
| 144 | if (is_object($xsltProcessor)) { |
||
| 145 | $xsl = '<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> |
||
| 146 | |||
| 147 | <xsl:template match="/"></xsl:template> |
||
| 148 | |||
| 149 | </xsl:stylesheet>'; |
||
| 150 | |||
| 151 | $xsltProcessor->process($_data, $xsl); |
||
| 152 | |||
| 153 | if ($xsltProcessor->isErrors()) { |
||
| 154 | $errors = $xsltProcessor->getError(true); |
||
| 155 | return false; |
||
| 156 | } |
||
| 157 | } else { |
||
| 158 | $_parser = xml_parser_create(); |
||
| 159 | xml_parser_set_option($_parser, XML_OPTION_SKIP_WHITE, 0); |
||
| 160 | xml_parser_set_option($_parser, XML_OPTION_CASE_FOLDING, 0); |
||
| 161 | |||
| 162 | if (!xml_parse($_parser, $_data)) { |
||
| 163 | $errors = array('error' => xml_get_error_code($_parser) . ': ' . xml_error_string(xml_get_error_code($_parser)), |
||
| 164 | 'col' => xml_get_current_column_number($_parser), |
||
| 165 | 'line' => (xml_get_current_line_number($_parser) - 2)); |
||
| 166 | return false; |
||
| 167 | } |
||
| 168 | |||
| 169 | xml_parser_free($_parser); |
||
| 170 | } |
||
| 171 | |||
| 172 | return true; |
||
| 173 | } |
||
| 174 | |||
| 175 | /** |
||
| 176 | * Check that a string is a valid URL. |
||
| 177 | * |
||
| 178 | * @param string $url |
||
| 179 | * string to operate on |
||
| 180 | * @return string |
||
| 181 | * a blank string or a valid URL |
||
| 182 | */ |
||
| 183 | public static function validateURL($url = null) |
||
| 184 | { |
||
| 185 | $url = trim($url); |
||
| 186 | |||
| 187 | if (is_null($url) || $url == '') { |
||
| 188 | return $url; |
||
| 189 | } |
||
| 190 | |||
| 191 | if (!preg_match('#^http[s]?:\/\/#i', $url)) { |
||
| 192 | $url = 'http://' . $url; |
||
| 193 | } |
||
| 194 | |||
| 195 | include TOOLKIT . '/util.validators.php'; |
||
| 196 | |||
| 197 | if (!preg_match($validators['URI'], $url)) { |
||
| 198 | $url = ''; |
||
| 199 | } |
||
| 200 | |||
| 201 | return $url; |
||
| 202 | } |
||
| 203 | |||
| 204 | /** |
||
| 205 | * Strip any slashes from all array values. |
||
| 206 | * |
||
| 207 | * @param array &$arr |
||
| 208 | * Pointer to an array to operate on. Can be multi-dimensional. |
||
| 209 | */ |
||
| 210 | public static function cleanArray(array &$arr) |
||
| 211 | { |
||
| 212 | foreach ($arr as $k => $v) { |
||
| 213 | if (is_array($v)) { |
||
| 214 | self::cleanArray($arr[$k]); |
||
| 215 | } else { |
||
| 216 | $arr[$k] = stripslashes($v); |
||
| 217 | } |
||
| 218 | } |
||
| 219 | } |
||
| 220 | |||
| 221 | /** |
||
| 222 | * Flatten the input array. Any elements of the input array that are |
||
| 223 | * themselves arrays will be removed and the contents of the removed array |
||
| 224 | * inserted in its place. The keys for the inserted values will be the |
||
| 225 | * concatenation of the keys in the original arrays in which it was embedded. |
||
| 226 | * The elements of the path are separated by periods (.). For example, |
||
| 227 | * given the following nested array structure: |
||
| 228 | * ` |
||
| 229 | * array(1 => |
||
| 230 | * array('key' => 'value'), |
||
| 231 | * 2 => |
||
| 232 | * array('key2' => 'value2', 'key3' => 'value3') |
||
| 233 | * ) |
||
| 234 | * ` |
||
| 235 | * will flatten to: |
||
| 236 | * `array('1.key' => 'value', '2.key2' => 'value2', '2.key3' => 'value3')` |
||
| 237 | * |
||
| 238 | * @param array &$source |
||
| 239 | * The array to flatten, passed by reference |
||
| 240 | * @param array &$output (optional) |
||
| 241 | * The array in which to store the flattened input, passed by reference. |
||
| 242 | * if this is not provided then a new array will be created. |
||
| 243 | * @param string $path (optional) |
||
| 244 | * the current prefix of the keys to insert into the output array. this |
||
| 245 | * defaults to null. |
||
| 246 | */ |
||
| 247 | public static function flattenArray(array &$source, &$output = null, $path = null) |
||
| 248 | { |
||
| 249 | if (is_null($output)) { |
||
| 250 | $output = array(); |
||
| 251 | } |
||
| 252 | |||
| 253 | foreach ($source as $key => $value) { |
||
| 254 | if (is_int($key)) { |
||
| 255 | $key = (string)($key + 1); |
||
| 256 | } |
||
| 257 | |||
| 258 | if (!is_null($path)) { |
||
| 259 | $key = $path . '.' . (string)$key; |
||
| 260 | } |
||
| 261 | |||
| 262 | if (is_array($value)) { |
||
| 263 | self::flattenArray($value, $output, $key); |
||
| 264 | } else { |
||
| 265 | $output[$key] = $value; |
||
| 266 | } |
||
| 267 | } |
||
| 268 | |||
| 269 | $source = $output; |
||
| 270 | } |
||
| 271 | |||
| 272 | /** |
||
| 273 | * Flatten the input array. Any elements of the input array that are |
||
| 274 | * themselves arrays will be removed and the contents of the removed array |
||
| 275 | * inserted in its place. The keys for the inserted values will be the |
||
| 276 | * concatenation of the keys in the original arrays in which it was embedded. |
||
| 277 | * The elements of the path are separated by colons (:). For example, given |
||
| 278 | * the following nested array structure: |
||
| 279 | * ` |
||
| 280 | * array(1 => |
||
| 281 | * array('key' => 'value'), |
||
| 282 | * 2 => |
||
| 283 | * array('key2' => 'value2', 'key3' => 'value3') |
||
| 284 | * ) |
||
| 285 | * ` |
||
| 286 | * will flatten to: |
||
| 287 | * `array('1:key' => 'value', '2:key2' => 'value2', '2:key3' => 'value3')` |
||
| 288 | * |
||
| 289 | * |
||
| 290 | * @param array &$output |
||
| 291 | * The array in which to store the flattened input, passed by reference. |
||
| 292 | * @param array &$source |
||
| 293 | * The array to flatten, passed by reference |
||
| 294 | * @param string $path |
||
| 295 | * the current prefix of the keys to insert into the output array. |
||
| 296 | */ |
||
| 297 | protected static function flattenArraySub(array &$output, array &$source, $path) |
||
| 298 | { |
||
| 299 | foreach ($source as $key => $value) { |
||
| 300 | $key = $path . ':' . $key; |
||
| 301 | |||
| 302 | if (is_array($value)) { |
||
| 303 | self::flattenArraySub($output, $value, $key); |
||
| 304 | } else { |
||
| 305 | $output[$key] = $value; |
||
| 306 | } |
||
| 307 | } |
||
| 308 | } |
||
| 309 | |||
| 310 | /** |
||
| 311 | * Given a string, this will clean it for use as a Symphony handle. Preserves multi-byte characters. |
||
| 312 | * |
||
| 313 | * @since Symphony 2.2.1 |
||
| 314 | * @param string $string |
||
| 315 | * String to be cleaned up |
||
| 316 | * @param integer $max_length |
||
| 317 | * The maximum number of characters in the handle |
||
| 318 | * @param string $delim |
||
| 319 | * All non-valid characters will be replaced with this |
||
| 320 | * @param boolean $uriencode |
||
| 321 | * Force the resultant string to be uri encoded making it safe for URLs |
||
| 322 | * @param array $additional_rule_set |
||
| 323 | * An array of REGEX patterns that should be applied to the `$string`. This |
||
| 324 | * occurs after the string has been trimmed and joined with the `$delim` |
||
| 325 | * @return string |
||
| 326 | * Returns resultant handle |
||
| 327 | */ |
||
| 328 | public static function createHandle($string, $max_length = 255, $delim = '-', $uriencode = false, $additional_rule_set = null) |
||
| 329 | { |
||
| 330 | $max_length = intval($max_length); |
||
| 331 | |||
| 332 | // Strip out any tag |
||
| 333 | $string = strip_tags($string); |
||
| 334 | |||
| 335 | // Replace existing delimiters in the string with a space |
||
| 336 | $string = str_replace($delim, ' ', $string); |
||
| 337 | |||
| 338 | // Remove punctuation |
||
| 339 | $string = preg_replace('/[\\.\'",!?]+/u', null, $string); |
||
| 340 | |||
| 341 | // Remove weird characters |
||
| 342 | $string = preg_replace('/[^\w-\s]+/u', null, $string); |
||
| 343 | |||
| 344 | // Replace spaces (tab, newline etc) with the delimiter |
||
| 345 | $string = preg_replace('/[\s]+/u', $delim, $string); |
||
| 346 | |||
| 347 | // Allow for custom rules |
||
| 348 | if (is_array($additional_rule_set) && !empty($additional_rule_set)) { |
||
| 349 | foreach ($additional_rule_set as $rule => $replacement) { |
||
| 350 | $string = preg_replace($rule, $replacement, $string); |
||
| 351 | } |
||
| 352 | } |
||
| 353 | |||
| 354 | // Trim it |
||
| 355 | if ($max_length > 0) { |
||
| 356 | $string = General::limitWords($string, $max_length); |
||
| 357 | } |
||
| 358 | |||
| 359 | // Remove leading or trailing delim characters |
||
| 360 | $string = trim($string, $delim); |
||
| 361 | |||
| 362 | // Encode it for URI use |
||
| 363 | if ($uriencode) { |
||
| 364 | $string = urlencode($string); |
||
| 365 | } |
||
| 366 | |||
| 367 | // Make it lowercase |
||
| 368 | $string = strtolower($string); |
||
| 369 | |||
| 370 | return $string; |
||
| 371 | } |
||
| 372 | |||
| 373 | /** |
||
| 374 | * Given a string, this will clean it for use as a filename. Preserves multi-byte characters. |
||
| 375 | * |
||
| 376 | * @since Symphony 2.2.1 |
||
| 377 | * @param string $string |
||
| 378 | * String to be cleaned up |
||
| 379 | * @param string $delim |
||
| 380 | * All non-valid characters will be replaced with this |
||
| 381 | * @return string |
||
| 382 | * Returns created filename |
||
| 383 | */ |
||
| 384 | public static function createFilename($string, $delim = '-') |
||
| 385 | { |
||
| 386 | // Strip out any tag |
||
| 387 | $string = strip_tags($string); |
||
| 388 | |||
| 389 | // Find all legal characters |
||
| 390 | $count = preg_match_all('/[\p{L}\w:;.,+=~]+/u', $string, $matches); |
||
| 391 | if ($count <= 0 || $count == false) { |
||
| 392 | preg_match_all('/[\w:;.,+=~]+/', $string, $matches); |
||
| 393 | } |
||
| 394 | |||
| 395 | // Join only legal character with the $delim |
||
| 396 | $string = implode($delim, $matches[0]); |
||
| 397 | |||
| 398 | // Remove leading or trailing delim characters |
||
| 399 | $string = trim($string, $delim); |
||
| 400 | |||
| 401 | // Make it lowercase |
||
| 402 | $string = strtolower($string); |
||
| 403 | |||
| 404 | return $string; |
||
| 405 | } |
||
| 406 | |||
| 407 | /** |
||
| 408 | * Computes the length of the string. |
||
| 409 | * This function will attempt to use PHP's `mbstring` functions if they are available. |
||
| 410 | * This function also forces utf-8 encoding. |
||
| 411 | * |
||
| 412 | * @since Symphony 2.5.0 |
||
| 413 | * @param string $str |
||
| 414 | * the string to operate on |
||
| 415 | * @return int |
||
| 416 | * the string's length |
||
| 417 | */ |
||
| 418 | public static function strlen($str) |
||
| 419 | { |
||
| 420 | if (function_exists('mb_strlen')) { |
||
| 421 | return mb_strlen($str, 'utf-8'); |
||
| 422 | } |
||
| 423 | return strlen($str); |
||
| 424 | } |
||
| 425 | |||
| 426 | /** |
||
| 427 | * Finds position of the first occurrence of a string in a string. |
||
| 428 | * This function will attempt to use PHP's `mbstring` functions if they are available. |
||
| 429 | * This function also forces utf-8 encoding for mbstring. |
||
| 430 | * |
||
| 431 | * @since Symphony 2.7.0 |
||
| 432 | * @param string $haystack |
||
| 433 | * the string to look into |
||
| 434 | * @param string $needle |
||
| 435 | * the string to look for |
||
| 436 | * @param int $offset |
||
| 437 | * the search offset. If it is not specified, 0 is used. |
||
| 438 | * A negative offset counts from the end of the string. |
||
| 439 | * @return int |
||
| 440 | * the numeric position of the first occurrence of needle in the haystack |
||
| 441 | */ |
||
| 442 | public static function strpos($haystack, $needle, $offset = 0) |
||
| 443 | { |
||
| 444 | if (function_exists('mb_strpos')) { |
||
| 445 | return mb_strpos($haystack, $needle, $offset, 'utf-8'); |
||
| 446 | } |
||
| 447 | return strpos($haystack, $needle, $offset); |
||
| 448 | } |
||
| 449 | |||
| 450 | /** |
||
| 451 | * Creates a sub string. |
||
| 452 | * This function will attempt to use PHP's `mbstring` functions if they are available. |
||
| 453 | * This function also forces utf-8 encoding. |
||
| 454 | * |
||
| 455 | * @since Symphony 2.5.0 |
||
| 456 | * @param string $str |
||
| 457 | * the string to operate on |
||
| 458 | * @param int $start |
||
| 459 | * the starting offset |
||
| 460 | * @param int $length |
||
| 461 | * the length of the substring |
||
| 462 | * @return string |
||
| 463 | * the resulting substring |
||
| 464 | */ |
||
| 465 | public static function substr($str, $start, $length = null) |
||
| 466 | { |
||
| 467 | if (function_exists('mb_substr')) { |
||
| 468 | return mb_substr($str, $start, $length, 'utf-8'); |
||
| 469 | } |
||
| 470 | if ($length === null) { |
||
| 471 | return substr($str, $start); |
||
| 472 | } |
||
| 473 | return substr($str, $start, $length); |
||
| 474 | } |
||
| 475 | |||
| 476 | /** |
||
| 477 | * Extract the first `$val` characters of the input string. If `$val` |
||
| 478 | * is larger than the length of the input string then the original |
||
| 479 | * input string is returned. |
||
| 480 | * |
||
| 481 | * @param string $str |
||
| 482 | * the string to operate on |
||
| 483 | * @param integer $val |
||
| 484 | * the number to compare lengths with |
||
| 485 | * @return string|boolean |
||
| 486 | * the resulting string or false on failure. |
||
| 487 | */ |
||
| 488 | public static function substrmin($str, $val) |
||
| 489 | { |
||
| 490 | return self::substr($str, 0, min(self::strlen($str), $val)); |
||
| 491 | } |
||
| 492 | |||
| 493 | /** |
||
| 494 | * Extract the first `$val` characters of the input string. If |
||
| 495 | * `$val` is larger than the length of the input string then |
||
| 496 | * the original input string is returned |
||
| 497 | * |
||
| 498 | * @param string $str |
||
| 499 | * the string to operate on |
||
| 500 | * @param integer $val |
||
| 501 | * the number to compare lengths with |
||
| 502 | * @return string|boolean |
||
| 503 | * the resulting string or false on failure. |
||
| 504 | */ |
||
| 505 | public static function substrmax($str, $val) |
||
| 506 | { |
||
| 507 | return self::substr($str, 0, max(self::strlen($str), $val)); |
||
| 508 | } |
||
| 509 | |||
| 510 | /** |
||
| 511 | * Extract the last `$num` characters from a string. |
||
| 512 | * |
||
| 513 | * @param string $str |
||
| 514 | * the string to extract the characters from. |
||
| 515 | * @param integer $num |
||
| 516 | * the number of characters to extract. |
||
| 517 | * @return string|boolean |
||
| 518 | * a string containing the last `$num` characters of the |
||
| 519 | * input string, or false on failure. |
||
| 520 | */ |
||
| 521 | public static function right($str, $num) |
||
| 522 | { |
||
| 523 | $str = self::substr($str, self::strlen($str)-$num, $num); |
||
| 524 | return $str; |
||
| 525 | } |
||
| 526 | |||
| 527 | /** |
||
| 528 | * Extract the first `$num` characters from a string. |
||
| 529 | * |
||
| 530 | * @param string $str |
||
| 531 | * the string to extract the characters from. |
||
| 532 | * @param integer $num |
||
| 533 | * the number of characters to extract. |
||
| 534 | * @return string|boolean |
||
| 535 | * a string containing the last `$num` characters of the |
||
| 536 | * input string, or false on failure. |
||
| 537 | */ |
||
| 538 | public static function left($str, $num) |
||
| 539 | { |
||
| 540 | $str = self::substr($str, 0, $num); |
||
| 541 | return $str; |
||
| 542 | } |
||
| 543 | |||
| 544 | /** |
||
| 545 | * Create all the directories as specified by the input path. If the current |
||
| 546 | * directory already exists, this function will return true. |
||
| 547 | * |
||
| 548 | * @param string $path |
||
| 549 | * the path containing the directories to create. |
||
| 550 | * @param string|integer $mode (optional) |
||
| 551 | * the permissions (in octal) of the directories to create. Defaults to 0755 |
||
| 552 | * @param boolean $silent (optional) |
||
| 553 | * true if an exception should be raised if an error occurs, false |
||
| 554 | * otherwise. this defaults to true. |
||
| 555 | * @throws Exception |
||
| 556 | * @return boolean |
||
| 557 | */ |
||
| 558 | public static function realiseDirectory($path, $mode = 0755, $silent = true) |
||
| 559 | { |
||
| 560 | if (is_dir($path)) { |
||
| 561 | return true; |
||
| 562 | } |
||
| 563 | |||
| 564 | try { |
||
| 565 | $current_umask = umask(0); |
||
| 566 | $success = @mkdir($path, intval($mode, 8), true); |
||
| 567 | umask($current_umask); |
||
| 568 | |||
| 569 | return $success; |
||
| 570 | } catch (Exception $ex) { |
||
| 571 | if ($silent === false) { |
||
| 572 | throw new Exception(__('Unable to create path - %s', array($path))); |
||
| 573 | } |
||
| 574 | |||
| 575 | return false; |
||
| 576 | } |
||
| 577 | } |
||
| 578 | |||
| 579 | /** |
||
| 580 | * Recursively deletes all files and directories given a directory. This |
||
| 581 | * function has two path. This function optionally takes a `$silent` parameter, |
||
| 582 | * which when `false` will throw an `Exception` if there is an error deleting a file |
||
| 583 | * or folder. |
||
| 584 | * |
||
| 585 | * @since Symphony 2.3 |
||
| 586 | * @param string $dir |
||
| 587 | * the path of the directory to delete |
||
| 588 | * @param boolean $silent (optional) |
||
| 589 | * true if an exception should be raised if an error occurs, false |
||
| 590 | * otherwise. this defaults to true. |
||
| 591 | * @throws Exception |
||
| 592 | * @return boolean |
||
| 593 | */ |
||
| 594 | public static function deleteDirectory($dir, $silent = true) |
||
| 595 | { |
||
| 596 | try { |
||
| 597 | if (!@file_exists($dir)) { |
||
| 598 | return true; |
||
| 599 | } |
||
| 600 | |||
| 601 | if (!@is_dir($dir)) { |
||
| 602 | return @unlink($dir); |
||
| 603 | } |
||
| 604 | |||
| 605 | foreach (scandir($dir) as $item) { |
||
| 606 | if ($item == '.' || $item == '..') { |
||
| 607 | continue; |
||
| 608 | } |
||
| 609 | |||
| 610 | if (!self::deleteDirectory($dir.DIRECTORY_SEPARATOR.$item)) { |
||
| 611 | return false; |
||
| 612 | } |
||
| 613 | } |
||
| 614 | |||
| 615 | return rmdir($dir); |
||
| 616 | } catch (Exception $ex) { |
||
| 617 | if ($silent === false) { |
||
| 618 | throw new Exception(__('Unable to remove - %s', array($dir))); |
||
| 619 | } |
||
| 620 | |||
| 621 | return false; |
||
| 622 | } |
||
| 623 | } |
||
| 624 | |||
| 625 | /** |
||
| 626 | * Search a multi-dimensional array for a value. |
||
| 627 | * |
||
| 628 | * @param mixed $needle |
||
| 629 | * the value to search for. |
||
| 630 | * @param array $haystack |
||
| 631 | * the multi-dimensional array to search. |
||
| 632 | * @return boolean |
||
| 633 | * true if `$needle` is found in `$haystack`. |
||
| 634 | * true if `$needle` == `$haystack`. |
||
| 635 | * true if `$needle` is found in any of the arrays contained within `$haystack`. |
||
| 636 | * false otherwise. |
||
| 637 | */ |
||
| 638 | public static function in_array_multi($needle, $haystack) |
||
| 639 | { |
||
| 640 | if ($needle == $haystack) { |
||
| 641 | return true; |
||
| 642 | } |
||
| 643 | |||
| 644 | if (is_array($haystack)) { |
||
| 645 | foreach ($haystack as $key => $val) { |
||
| 646 | if (is_array($val)) { |
||
| 647 | if (self::in_array_multi($needle, $val)) { |
||
| 648 | return true; |
||
| 649 | } |
||
| 650 | } elseif (!strcmp($needle, $key) || !strcmp($needle, $val)) { |
||
| 651 | return true; |
||
| 652 | } |
||
| 653 | } |
||
| 654 | } |
||
| 655 | |||
| 656 | return false; |
||
| 657 | } |
||
| 658 | |||
| 659 | /** |
||
| 660 | * Search an array for multiple values. |
||
| 661 | * |
||
| 662 | * @param array $needles |
||
| 663 | * the values to search the `$haystack` for. |
||
| 664 | * @param array $haystack |
||
| 665 | * the in which to search for the `$needles` |
||
| 666 | * @return boolean |
||
| 667 | * true if any of the `$needles` are in `$haystack`, |
||
| 668 | * false otherwise. |
||
| 669 | */ |
||
| 670 | public static function in_array_all($needles, $haystack) |
||
| 671 | { |
||
| 672 | foreach ($needles as $n) { |
||
| 673 | if (!in_array($n, $haystack)) { |
||
| 674 | return false; |
||
| 675 | } |
||
| 676 | } |
||
| 677 | |||
| 678 | return true; |
||
| 679 | } |
||
| 680 | |||
| 681 | /** |
||
| 682 | * Transform a multi-dimensional array to a flat array. The input array |
||
| 683 | * is expected to conform to the structure of the `$_FILES` variable. |
||
| 684 | * |
||
| 685 | * @param array $filedata |
||
| 686 | * the raw `$_FILES` data structured array |
||
| 687 | * @return array |
||
| 688 | * the flattened array. |
||
| 689 | */ |
||
| 690 | public static function processFilePostData($filedata) |
||
| 691 | { |
||
| 692 | $result = array(); |
||
| 693 | |||
| 694 | foreach ($filedata as $key => $data) { |
||
| 695 | foreach ($data as $handle => $value) { |
||
| 696 | if (is_array($value)) { |
||
| 697 | foreach ($value as $index => $pair) { |
||
| 698 | if (!is_array($result[$handle][$index])) { |
||
| 699 | $result[$handle][$index] = array(); |
||
| 700 | } |
||
| 701 | |||
| 702 | if (!is_array($pair)) { |
||
| 703 | $result[$handle][$index][$key] = $pair; |
||
| 704 | } else { |
||
| 705 | $result[$handle][$index][array_pop(array_keys($pair))][$key] = array_pop(array_values($pair)); |
||
| 706 | } |
||
| 707 | } |
||
| 708 | } else { |
||
| 709 | $result[$handle][$key] = $value; |
||
| 710 | } |
||
| 711 | } |
||
| 712 | } |
||
| 713 | |||
| 714 | return $result; |
||
| 715 | } |
||
| 716 | |||
| 717 | /** |
||
| 718 | * Merge `$_POST` with `$_FILES` to produce a flat array of the contents |
||
| 719 | * of both. If there is no merge_file_post_data function defined then |
||
| 720 | * such a function is created. This is necessary to overcome PHP's ability |
||
| 721 | * to handle forms. This overcomes PHP's convoluted `$_FILES` structure |
||
| 722 | * to make it simpler to access `multi-part/formdata`. |
||
| 723 | * |
||
| 724 | * @return array |
||
| 725 | * a flat array containing the flattened contents of both `$_POST` and |
||
| 726 | * `$_FILES`. |
||
| 727 | */ |
||
| 728 | public static function getPostData() |
||
| 729 | { |
||
| 730 | if (!function_exists('merge_file_post_data')) { |
||
| 731 | function merge_file_post_data($type, array $file, &$post) |
||
| 732 | { |
||
| 733 | foreach ($file as $key => $value) { |
||
| 734 | if (!isset($post[$key])) { |
||
| 735 | $post[$key] = array(); |
||
| 736 | } |
||
| 737 | |||
| 738 | if (is_array($value)) { |
||
| 739 | merge_file_post_data($type, $value, $post[$key]); |
||
| 740 | } else { |
||
| 741 | $post[$key][$type] = $value; |
||
| 742 | } |
||
| 743 | } |
||
| 744 | } |
||
| 745 | } |
||
| 746 | |||
| 747 | $files = array( |
||
| 748 | 'name' => array(), |
||
| 749 | 'type' => array(), |
||
| 750 | 'tmp_name' => array(), |
||
| 751 | 'error' => array(), |
||
| 752 | 'size' => array() |
||
| 753 | ); |
||
| 754 | $post = $_POST; |
||
| 755 | |||
| 756 | if (is_array($_FILES) && !empty($_FILES)) { |
||
| 757 | foreach ($_FILES as $key_a => $data_a) { |
||
| 758 | if (!is_array($data_a)) { |
||
| 759 | continue; |
||
| 760 | } |
||
| 761 | |||
| 762 | foreach ($data_a as $key_b => $data_b) { |
||
| 763 | $files[$key_b][$key_a] = $data_b; |
||
| 764 | } |
||
| 765 | } |
||
| 766 | } |
||
| 767 | |||
| 768 | foreach ($files as $type => $data) { |
||
| 769 | merge_file_post_data($type, $data, $post); |
||
| 770 | } |
||
| 771 | |||
| 772 | return $post; |
||
| 773 | } |
||
| 774 | |||
| 775 | /** |
||
| 776 | * Find the next available index in an array. Works best with numeric keys. |
||
| 777 | * The next available index is the minimum integer such that the array does |
||
| 778 | * not have a mapping for that index. Uses the increment operator on the |
||
| 779 | * index type of the input array, whatever that may do. |
||
| 780 | * |
||
| 781 | * @param array $array |
||
| 782 | * the array to find the next index for. |
||
| 783 | * @param mixed $seed (optional) |
||
| 784 | * the object with which the search for an empty index is initialized. this |
||
| 785 | * defaults to null. |
||
| 786 | * @return integer |
||
| 787 | * the minimum empty index into the input array. |
||
| 788 | */ |
||
| 789 | public static function array_find_available_index($array, $seed = null) |
||
| 790 | { |
||
| 791 | if (!is_null($seed)) { |
||
| 792 | $index = $seed; |
||
| 793 | } else { |
||
| 794 | $keys = array_keys($array); |
||
| 795 | sort($keys); |
||
| 796 | $index = array_pop($keys); |
||
| 797 | } |
||
| 798 | |||
| 799 | if (isset($array[$index])) { |
||
| 800 | do { |
||
| 801 | $index++; |
||
| 802 | } while (isset($array[$index])); |
||
| 803 | } |
||
| 804 | |||
| 805 | return $index; |
||
| 806 | } |
||
| 807 | |||
| 808 | /** |
||
| 809 | * Filter the duplicate values from an array into a new array, optionally |
||
| 810 | * ignoring the case of the values (assuming they are strings?). A new array |
||
| 811 | * is returned, the input array is left unchanged. |
||
| 812 | * |
||
| 813 | * @param array $array |
||
| 814 | * the array to filter. |
||
| 815 | * @param boolean $ignore_case |
||
| 816 | * true if the case of the values in the array should be ignored, false otherwise. |
||
| 817 | * @return array |
||
| 818 | * a new array containing only the unique elements of the input array. |
||
| 819 | */ |
||
| 820 | public static function array_remove_duplicates(array $array, $ignore_case = false) |
||
| 821 | { |
||
| 822 | return ($ignore_case === true ? self::array_iunique($array) : array_unique($array)); |
||
| 823 | } |
||
| 824 | |||
| 825 | /** |
||
| 826 | * Test whether a value is in an array based on string comparison, ignoring |
||
| 827 | * the case of the values. |
||
| 828 | * |
||
| 829 | * @param mixed $needle |
||
| 830 | * the object to search the array for. |
||
| 831 | * @param array $haystack |
||
| 832 | * the array to search for the `$needle`. |
||
| 833 | * @return boolean |
||
| 834 | * true if the `$needle` is in the `$haystack`, false otherwise. |
||
| 835 | */ |
||
| 836 | public static function in_iarray($needle, array $haystack) |
||
| 837 | { |
||
| 838 | foreach ($haystack as $key => $value) { |
||
| 839 | if (strcasecmp($value, $needle) == 0) { |
||
| 840 | return true; |
||
| 841 | } |
||
| 842 | } |
||
| 843 | return false; |
||
| 844 | } |
||
| 845 | |||
| 846 | /** |
||
| 847 | * Filter the input array for duplicates, treating each element in the array |
||
| 848 | * as a string and comparing them using a case insensitive comparison function. |
||
| 849 | * |
||
| 850 | * @param array $array |
||
| 851 | * the array to filter. |
||
| 852 | * @return array |
||
| 853 | * a new array containing only the unique elements of the input array. |
||
| 854 | */ |
||
| 855 | public static function array_iunique(array $array) |
||
| 856 | { |
||
| 857 | $tmp = array(); |
||
| 858 | |||
| 859 | foreach ($array as $key => $value) { |
||
| 860 | if (!self::in_iarray($value, $tmp)) { |
||
| 861 | $tmp[$key] = $value; |
||
| 862 | } |
||
| 863 | } |
||
| 864 | |||
| 865 | return $tmp; |
||
| 866 | } |
||
| 867 | |||
| 868 | /** |
||
| 869 | * Function recursively apply a function to an array's values. |
||
| 870 | * This will not touch the keys, just the values. |
||
| 871 | * |
||
| 872 | * @since Symphony 2.2 |
||
| 873 | * @param string $function |
||
| 874 | * @param array $array |
||
| 875 | * @return array |
||
| 876 | * a new array with all the values passed through the given `$function` |
||
| 877 | */ |
||
| 878 | public static function array_map_recursive($function, array $array) |
||
| 879 | { |
||
| 880 | $tmp = array(); |
||
| 881 | |||
| 882 | foreach ($array as $key => $value) { |
||
| 883 | if (is_array($value)) { |
||
| 884 | $tmp[$key] = self::array_map_recursive($function, $value); |
||
| 885 | } else { |
||
| 886 | $tmp[$key] = call_user_func($function, $value); |
||
| 887 | } |
||
| 888 | } |
||
| 889 | |||
| 890 | return $tmp; |
||
| 891 | } |
||
| 892 | |||
| 893 | /** |
||
| 894 | * Keyed version of php's array_map function. |
||
| 895 | * The callback's signature is: |
||
| 896 | * `function ($key, $value, $array)` |
||
| 897 | * |
||
| 898 | * @since Symphony 3.0.0 |
||
| 899 | * @param string $function |
||
| 900 | * @param array $array |
||
| 901 | * @return array |
||
| 902 | * a new array with all the values passed through the given `$function` |
||
| 903 | */ |
||
| 904 | public static function array_map($function, array $array) |
||
| 909 | } |
||
| 910 | |||
| 911 | /** |
||
| 912 | * Convert an array into an XML fragment and append it to an existing |
||
| 913 | * XML element. Any arrays contained as elements in the input array will |
||
| 914 | * also be recursively formatted and appended to the input XML fragment. |
||
| 915 | * The input XML element will be modified as a result of calling this. |
||
| 916 | * |
||
| 917 | * @param XMLElement $parent |
||
| 918 | * the XML element to append the formatted array data to. |
||
| 919 | * @param array $data |
||
| 920 | * the array to format and append to the XML fragment. |
||
| 921 | * @param boolean $validate |
||
| 922 | * true if the formatted array data should be validated as it is |
||
| 923 | * constructed, false otherwise. |
||
| 924 | */ |
||
| 925 | public static function array_to_xml(XMLElement $parent, array $data, $validate = false) |
||
| 952 | } |
||
| 953 | } |
||
| 954 | |||
| 955 | /** |
||
| 956 | * Create a file at the input path with the (optional) input permissions |
||
| 957 | * with the input content. This function will ignore errors in opening, |
||
| 958 | * writing, closing and changing the permissions of the resulting file. |
||
| 959 | * If opening or writing the file fail then this will return false. |
||
| 960 | * This method calls `General::checkFileWritable()` which properly checks |
||
| 961 | * for permissions. |
||
| 962 | * |
||
| 963 | * @uses General::checkFileWritable() |
||
| 964 | * @param string $file |
||
| 965 | * the path of the file to write. |
||
| 966 | * @param mixed $data |
||
| 967 | * the data to write to the file. |
||
| 968 | * @param integer|string $perm (optional) |
||
| 969 | * the permissions as an octal number to set set on the resulting file. |
||
| 970 | * this defaults to 0644 (if omitted or set to null) |
||
| 971 | * @param string $mode (optional) |
||
| 972 | * the mode that the file should be opened with, defaults to 'w'. See modes |
||
| 973 | * at http://php.net/manual/en/function.fopen.php |
||
| 974 | * @param boolean $trim (optional) |
||
| 975 | * removes tripple linebreaks |
||
| 976 | * @return boolean |
||
| 977 | * true if the file is successfully opened, written to, closed and has the |
||
| 978 | * required permissions set. false, otherwise. |
||
| 979 | */ |
||
| 980 | public static function writeFile($file, $data, $perm = 0644, $mode = 'w', $trim = false) |
||
| 1018 | } |
||
| 1019 | |||
| 1020 | /** |
||
| 1021 | * Checks that the file is readable. |
||
| 1022 | * It first checks to see if the $file path exists |
||
| 1023 | * and if it does, checks that it is readable. |
||
| 1024 | * |
||
| 1025 | * @uses clearstatcache() |
||
| 1026 | * @since Symphony 2.7.0 |
||
| 1027 | * @param string $file |
||
| 1028 | * The path of the file |
||
| 1029 | * @return boolean |
||
| 1030 | */ |
||
| 1031 | public static function checkFileReadable($file) |
||
| 1032 | { |
||
| 1033 | clearstatcache(); |
||
| 1034 | // Reading a file requires that is exists and can be read |
||
| 1035 | return @file_exists($file) && @is_readable($file); |
||
| 1036 | } |
||
| 1037 | |||
| 1038 | /** |
||
| 1039 | * Checks that the file is writable. |
||
| 1040 | * It first checks to see if the $file path exists |
||
| 1041 | * and if it does, checks that is it writable. If the file |
||
| 1042 | * does not exits, it checks that the directory exists and if it does, |
||
| 1043 | * checks that it is writable. |
||
| 1044 | * |
||
| 1045 | * @uses clearstatcache() |
||
| 1046 | * @since Symphony 2.7.0 |
||
| 1047 | * @param string $file |
||
| 1048 | * The path of the file |
||
| 1049 | * @return boolean |
||
| 1050 | */ |
||
| 1051 | public static function checkFileWritable($file) |
||
| 1052 | { |
||
| 1053 | clearstatcache(); |
||
| 1054 | if (@file_exists($file)) { |
||
| 1055 | // Writing to an existing file does not require write |
||
| 1056 | // permissions on the directory. |
||
| 1057 | return @is_writable($file); |
||
| 1058 | } |
||
| 1059 | $dir = dirname($file); |
||
| 1060 | // Creating a file requires write permissions on the directory. |
||
| 1061 | return @file_exists($dir) && @is_writable($dir); |
||
| 1062 | } |
||
| 1063 | |||
| 1064 | /** |
||
| 1065 | * Checks that the file is deletable. |
||
| 1066 | * It first checks to see if the $file path exists |
||
| 1067 | * and if it does, checks that is it writable. |
||
| 1068 | * |
||
| 1069 | * @uses clearstatcache() |
||
| 1070 | * @since Symphony 2.7.0 |
||
| 1071 | * @param string $file |
||
| 1072 | * The path of the file |
||
| 1073 | * @return boolean |
||
| 1074 | */ |
||
| 1075 | public static function checkFileDeletable($file) |
||
| 1082 | } |
||
| 1083 | |||
| 1084 | /** |
||
| 1085 | * Delete a file at a given path, silently ignoring errors depending |
||
| 1086 | * on the value of the input variable $silent. |
||
| 1087 | * |
||
| 1088 | * @uses General::checkFileDeletable() |
||
| 1089 | * @param string $file |
||
| 1090 | * the path of the file to delete |
||
| 1091 | * @param boolean $silent (optional) |
||
| 1092 | * true if an exception should be raised if an error occurs, false |
||
| 1093 | * otherwise. this defaults to true. |
||
| 1094 | * @throws Exception |
||
| 1095 | * @return boolean |
||
| 1096 | * true if the file is successfully unlinked, if the unlink fails and |
||
| 1097 | * silent is set to true then an exception is thrown. if the unlink |
||
| 1098 | * fails and silent is set to false then this returns false. |
||
| 1099 | */ |
||
| 1100 | public static function deleteFile($file, $silent = true) |
||
| 1101 | { |
||
| 1102 | try { |
||
| 1103 | if (static::checkFileDeletable($file) === false) { |
||
| 1104 | throw new Exception(__('Denied by permission')); |
||
| 1105 | } |
||
| 1106 | if (!@file_exists($file)) { |
||
| 1107 | return true; |
||
| 1108 | } |
||
| 1109 | return @unlink($file); |
||
| 1110 | } catch (Exception $ex) { |
||
| 1111 | if ($silent === false) { |
||
| 1112 | throw new Exception(__('Unable to remove file - %s', array($file)), 0, $ex); |
||
| 1113 | } |
||
| 1114 | |||
| 1115 | return false; |
||
| 1116 | } |
||
| 1117 | } |
||
| 1118 | |||
| 1119 | /** |
||
| 1120 | * Extract the file extension from the input file path. |
||
| 1121 | * |
||
| 1122 | * @param string $file |
||
| 1123 | * the path of the file to extract the extension of. |
||
| 1124 | * @return array |
||
| 1125 | * an array with a single key 'extension' and a value of the extension |
||
| 1126 | * of the input path. |
||
| 1127 | */ |
||
| 1128 | public static function getExtension($file) |
||
| 1129 | { |
||
| 1130 | return pathinfo($file, PATHINFO_EXTENSION); |
||
| 1131 | } |
||
| 1132 | |||
| 1133 | /** |
||
| 1134 | * Gets mime type of a file. |
||
| 1135 | * |
||
| 1136 | * For email attachments, the mime type is very important. |
||
| 1137 | * Uses the PHP 5.3 function `finfo_open` when available, otherwise falls |
||
| 1138 | * back to using a mapping of known of common mimetypes. If no matches |
||
| 1139 | * are found `application/octet-stream` will be returned. |
||
| 1140 | * |
||
| 1141 | * @author Michael Eichelsdoerfer |
||
| 1142 | * @author Huib Keemink |
||
| 1143 | * @param string $file |
||
| 1144 | * @return string|boolean |
||
| 1145 | * the mime type of the file, or false is none found |
||
| 1146 | */ |
||
| 1147 | public function getMimeType($file) |
||
| 1148 | { |
||
| 1149 | if (!empty($file)) { |
||
| 1150 | // in PHP 5.3 we can use 'finfo' |
||
| 1151 | if (PHP_VERSION_ID >= 50300 && function_exists('finfo_open')) { |
||
| 1152 | $finfo = finfo_open(FILEINFO_MIME_TYPE); |
||
| 1153 | $mime_type = finfo_file($finfo, $file); |
||
| 1154 | finfo_close($finfo); |
||
| 1155 | } else { |
||
| 1156 | // A few mimetypes to "guess" using the file extension. |
||
| 1157 | $mimetypes = array( |
||
| 1158 | 'txt' => 'text/plain', |
||
| 1159 | 'csv' => 'text/csv', |
||
| 1160 | 'pdf' => 'application/pdf', |
||
| 1161 | 'doc' => 'application/msword', |
||
| 1162 | 'docx' => 'application/msword', |
||
| 1163 | 'xls' => 'application/vnd.ms-excel', |
||
| 1164 | 'ppt' => 'application/vnd.ms-powerpoint', |
||
| 1165 | 'eps' => 'application/postscript', |
||
| 1166 | 'zip' => 'application/zip', |
||
| 1167 | 'gif' => 'image/gif', |
||
| 1168 | 'jpg' => 'image/jpeg', |
||
| 1169 | 'jpeg' => 'image/jpeg', |
||
| 1170 | 'png' => 'image/png', |
||
| 1171 | 'mp3' => 'audio/mpeg', |
||
| 1172 | 'mp4a' => 'audio/mp4', |
||
| 1173 | 'aac' => 'audio/x-aac', |
||
| 1174 | 'aif' => 'audio/x-aiff', |
||
| 1175 | 'aiff' => 'audio/x-aiff', |
||
| 1176 | 'wav' => 'audio/x-wav', |
||
| 1177 | 'wma' => 'audio/x-ms-wma', |
||
| 1178 | 'mpeg' => 'video/mpeg', |
||
| 1179 | 'mpg' => 'video/mpeg', |
||
| 1180 | 'mp4' => 'video/mp4', |
||
| 1181 | 'mov' => 'video/quicktime', |
||
| 1182 | 'avi' => 'video/x-msvideo', |
||
| 1183 | 'wmv' => 'video/x-ms-wmv', |
||
| 1184 | ); |
||
| 1185 | |||
| 1186 | $extension = substr(strrchr($file, '.'), 1); |
||
| 1187 | |||
| 1188 | if ($mimetypes[strtolower($extension)] !== null) { |
||
| 1189 | $mime_type = $mimetypes[$extension]; |
||
| 1190 | } else { |
||
| 1191 | $mime_type = 'application/octet-stream'; |
||
| 1192 | } |
||
| 1193 | } |
||
| 1194 | |||
| 1195 | return $mime_type; |
||
| 1196 | } |
||
| 1197 | return false; |
||
| 1198 | } |
||
| 1199 | |||
| 1200 | /** |
||
| 1201 | * Construct a multi-dimensional array that reflects the directory |
||
| 1202 | * structure of a given path. |
||
| 1203 | * |
||
| 1204 | * @param string $dir (optional) |
||
| 1205 | * the path of the directory to construct the multi-dimensional array |
||
| 1206 | * for. this defaults to '.'. |
||
| 1207 | * @param string $filter (optional) |
||
| 1208 | * A regular expression to filter the directories. This is positive filter, ie. |
||
| 1209 | * if the filter matches, the directory is included. Defaults to null. |
||
| 1210 | * @param boolean $recurse (optional) |
||
| 1211 | * true if sub-directories should be traversed and reflected in the |
||
| 1212 | * resulting array, false otherwise. |
||
| 1213 | * @param mixed $strip_root (optional) |
||
| 1214 | * If null, the full path to the file will be returned, otherwise the value |
||
| 1215 | * of `strip_root` will be removed from the file path. |
||
| 1216 | * @param array $exclude (optional) |
||
| 1217 | * ignore directories listed in this array. this defaults to an empty array. |
||
| 1218 | * @param boolean $ignore_hidden (optional) |
||
| 1219 | * ignore hidden directory (i.e.directories that begin with a period). this defaults |
||
| 1220 | * to true. |
||
| 1221 | * @return null|array |
||
| 1222 | * return the array structure reflecting the input directory or null if |
||
| 1223 | * the input directory is not actually a directory. |
||
| 1224 | */ |
||
| 1225 | public static function listDirStructure($dir = '.', $filter = null, $recurse = true, $strip_root = null, $exclude = array(), $ignore_hidden = true) |
||
| 1226 | { |
||
| 1227 | if (!is_dir($dir)) { |
||
| 1228 | return null; |
||
| 1229 | } |
||
| 1230 | |||
| 1231 | $files = array(); |
||
| 1232 | |||
| 1233 | foreach (scandir($dir) as $file) { |
||
| 1234 | if ( |
||
| 1235 | ($file == '.' || $file == '..') |
||
| 1236 | || ($ignore_hidden && $file{0} == '.') |
||
| 1237 | || !is_dir("$dir/$file") |
||
| 1238 | || in_array($file, $exclude) |
||
| 1239 | || in_array("$dir/$file", $exclude) |
||
| 1240 | ) { |
||
| 1241 | continue; |
||
| 1242 | } |
||
| 1243 | |||
| 1244 | if (!is_null($filter)) { |
||
| 1245 | if (!preg_match($filter, $file)) { |
||
| 1246 | continue; |
||
| 1247 | } |
||
| 1248 | } |
||
| 1249 | |||
| 1250 | $files[] = rtrim(str_replace($strip_root, '', $dir), '/') ."/$file/"; |
||
| 1251 | |||
| 1252 | if ($recurse) { |
||
| 1253 | $files = @array_merge($files, self::listDirStructure("$dir/$file", $filter, $recurse, $strip_root, $exclude, $ignore_hidden)); |
||
| 1254 | } |
||
| 1255 | } |
||
| 1256 | |||
| 1257 | return $files; |
||
| 1258 | } |
||
| 1259 | |||
| 1260 | /** |
||
| 1261 | * Construct a multi-dimensional array that reflects the directory |
||
| 1262 | * structure of a given path grouped into directory and file keys |
||
| 1263 | * matching any input constraints. |
||
| 1264 | * |
||
| 1265 | * @param string $dir (optional) |
||
| 1266 | * the path of the directory to construct the multi-dimensional array |
||
| 1267 | * for. this defaults to '.'. |
||
| 1268 | * @param array|string $filters (optional) |
||
| 1269 | * either a regular expression to filter the files by or an array of |
||
| 1270 | * files to include. |
||
| 1271 | * @param boolean $recurse (optional) |
||
| 1272 | * true if sub-directories should be traversed and reflected in the |
||
| 1273 | * resulting array, false otherwise. |
||
| 1274 | * @param string $sort (optional) |
||
| 1275 | * 'asc' if the resulting filelist array should be sorted, anything else otherwise. |
||
| 1276 | * this defaults to 'asc'. |
||
| 1277 | * @param mixed $strip_root (optional) |
||
| 1278 | * If null, the full path to the file will be returned, otherwise the value |
||
| 1279 | * of `strip_root` will be removed from the file path. |
||
| 1280 | * @param array $exclude (optional) |
||
| 1281 | * ignore files listed in this array. this defaults to an empty array. |
||
| 1282 | * @param boolean $ignore_hidden (optional) |
||
| 1283 | * ignore hidden files (i.e. files that begin with a period). this defaults |
||
| 1284 | * to true. |
||
| 1285 | * @return null|array |
||
| 1286 | * return the array structure reflecting the input directory or null if |
||
| 1287 | * the input directory is not actually a directory. |
||
| 1288 | */ |
||
| 1289 | public static function listStructure($dir = ".", $filters = array(), $recurse = true, $sort = "asc", $strip_root = null, $exclude = array(), $ignore_hidden = true) |
||
| 1290 | { |
||
| 1291 | if (!is_dir($dir)) { |
||
| 1292 | return null; |
||
| 1293 | } |
||
| 1294 | |||
| 1295 | // Check to see if $filters is a string containing a regex, or an array of file types |
||
| 1296 | if (is_array($filters) && !empty($filters)) { |
||
| 1297 | $filter_type = 'file'; |
||
| 1298 | } elseif (is_string($filters)) { |
||
| 1299 | $filter_type = 'regex'; |
||
| 1300 | } else { |
||
| 1301 | $filter_type = null; |
||
| 1302 | } |
||
| 1303 | $files = array(); |
||
| 1304 | |||
| 1305 | $prefix = str_replace($strip_root, '', $dir); |
||
| 1306 | |||
| 1307 | if ($prefix !== "" && substr($prefix, -1) !== "/") { |
||
| 1308 | $prefix .= "/"; |
||
| 1309 | } |
||
| 1310 | |||
| 1311 | $files['dirlist'] = array(); |
||
| 1312 | $files['filelist'] = array(); |
||
| 1313 | |||
| 1314 | foreach (scandir($dir) as $file) { |
||
| 1315 | if ( |
||
| 1316 | ($file == '.' || $file === '..') |
||
| 1317 | || ($ignore_hidden && $file{0} === '.') |
||
| 1318 | || in_array($file, $exclude) |
||
| 1319 | || in_array("$dir/$file", $exclude) |
||
| 1320 | ) { |
||
| 1321 | continue; |
||
| 1322 | } |
||
| 1323 | |||
| 1324 | $dir = rtrim($dir, '/'); |
||
| 1325 | |||
| 1326 | if (is_dir("$dir/$file")) { |
||
| 1327 | if ($recurse) { |
||
| 1328 | $files["$prefix$file/"] = self::listStructure("$dir/$file", $filters, $recurse, $sort, $strip_root, $exclude, $ignore_hidden); |
||
| 1329 | } |
||
| 1330 | |||
| 1331 | $files['dirlist'][] = "$prefix$file/"; |
||
| 1332 | } elseif ($filter_type === 'regex') { |
||
| 1333 | if (preg_match($filters, $file)) { |
||
| 1334 | $files['filelist'][] = "$prefix$file"; |
||
| 1335 | } |
||
| 1336 | } elseif ($filter_type === 'file') { |
||
| 1337 | if (in_array(self::getExtension($file), $filters)) { |
||
| 1338 | $files['filelist'][] = "$prefix$file"; |
||
| 1339 | } |
||
| 1340 | } elseif (is_null($filter_type)) { |
||
| 1341 | $files['filelist'][] = "$prefix$file"; |
||
| 1342 | } |
||
| 1343 | } |
||
| 1344 | |||
| 1345 | if (is_array($files['filelist'])) { |
||
| 1346 | ($sort == 'desc') ? rsort($files['filelist']) : sort($files['filelist']); |
||
| 1347 | } |
||
| 1348 | |||
| 1349 | return $files; |
||
| 1350 | } |
||
| 1351 | |||
| 1352 | /** |
||
| 1353 | * Count the number of words in a string. Words are delimited by "spaces". |
||
| 1354 | * The characters included in the set of "spaces" are: |
||
| 1355 | * ' ', ' ', ' ', ' ', |
||
| 1356 | * ' ', ' ', ' ', ' ', |
||
| 1357 | * '​', '𠀯', ' ' |
||
| 1358 | * Any html/xml tags are first removed by strip_tags() and any included html |
||
| 1359 | * entities are decoded. The resulting string is then split by the above set |
||
| 1360 | * of spaces and the resulting size of the resulting array returned. |
||
| 1361 | * |
||
| 1362 | * @param string $string |
||
| 1363 | * the string from which to count the contained words. |
||
| 1364 | * @return integer |
||
| 1365 | * the number of words contained in the input string. |
||
| 1366 | */ |
||
| 1367 | public static function countWords($string) |
||
| 1368 | { |
||
| 1369 | $string = strip_tags($string); |
||
| 1370 | |||
| 1371 | // Strip spaces: |
||
| 1372 | $string = html_entity_decode($string, ENT_NOQUOTES, 'UTF-8'); |
||
| 1373 | $spaces = array( |
||
| 1374 | ' ', ' ', ' ', ' ', |
||
| 1375 | ' ', ' ', ' ', ' ', |
||
| 1376 | '​', '𠀯', ' ' |
||
| 1377 | ); |
||
| 1378 | |||
| 1379 | foreach ($spaces as &$space) { |
||
| 1380 | $space = html_entity_decode($space, ENT_NOQUOTES, 'UTF-8'); |
||
| 1381 | } |
||
| 1382 | |||
| 1383 | $string = str_replace($spaces, ' ', $string); |
||
| 1384 | $string = preg_replace('/[^\w\s]/i', '', $string); |
||
| 1385 | |||
| 1386 | return str_word_count($string); |
||
| 1387 | } |
||
| 1388 | |||
| 1389 | /** |
||
| 1390 | * Truncate a string to a given length, respecting word boundaries. The returned |
||
| 1391 | * string will always be less than `$maxChars`. Newlines, HTML elements and |
||
| 1392 | * leading or trailing spaces are removed from the string. |
||
| 1393 | * |
||
| 1394 | * @param string $string |
||
| 1395 | * the string to truncate. |
||
| 1396 | * @param integer $maxChars (optional) |
||
| 1397 | * the maximum length of the string to truncate the input string to. this |
||
| 1398 | * defaults to 200 characters. |
||
| 1399 | * @param boolean $appendHellip (optional) |
||
| 1400 | * true if the ellipses should be appended to the result in circumstances |
||
| 1401 | * where the result is shorter than the input string. false otherwise. this |
||
| 1402 | * defaults to false. |
||
| 1403 | * @return null|string |
||
| 1404 | * if the resulting string contains only spaces then null is returned. otherwise |
||
| 1405 | * a string that satisfies the input constraints. |
||
| 1406 | */ |
||
| 1407 | public static function limitWords($string, $maxChars = 200, $appendHellip = false) |
||
| 1408 | { |
||
| 1409 | if ($appendHellip) { |
||
| 1410 | $maxChars -= 1; |
||
| 1411 | } |
||
| 1412 | |||
| 1413 | $string = trim(strip_tags(nl2br($string))); |
||
| 1414 | $original_length = strlen($string); |
||
| 1415 | |||
| 1416 | if ($original_length == 0) { |
||
| 1417 | return null; |
||
| 1418 | } elseif ($original_length <= $maxChars) { |
||
| 1419 | return $string; |
||
| 1420 | } |
||
| 1421 | |||
| 1422 | // Compute the negative offset |
||
| 1423 | $offset = $maxChars - $original_length; |
||
| 1424 | // Find the first word break char before the maxChars limit is hit. |
||
| 1425 | $word_break = array_filter(array_map(function ($wb) use ($string, $offset) { |
||
| 1426 | return strrpos($string, $wb, $offset); |
||
| 1427 | }, array(' ', '-', ',', '.', '!', '?', PHP_EOL))); |
||
| 1428 | |||
| 1429 | // If no word break is found |
||
| 1430 | if (empty($word_break)) { |
||
| 1431 | $last_word_break = $maxChars; |
||
| 1432 | } else { |
||
| 1433 | $last_word_break = max($word_break); |
||
| 1434 | } |
||
| 1435 | |||
| 1436 | // Create the sub string |
||
| 1437 | $result = substr($string, 0, $last_word_break); |
||
| 1438 | |||
| 1439 | if ($appendHellip) { |
||
| 1440 | $result .= "…"; |
||
| 1441 | } |
||
| 1442 | |||
| 1443 | return $result; |
||
| 1444 | } |
||
| 1445 | |||
| 1446 | /** |
||
| 1447 | * Move a file from the source path to the destination path and name and |
||
| 1448 | * set its permissions to the input permissions. This will ignore errors |
||
| 1449 | * in the `is_uploaded_file()`, `move_uploaded_file()` and `chmod()` functions. |
||
| 1450 | * |
||
| 1451 | * @uses General::checkFileWritable() |
||
| 1452 | * @param string $dest_path |
||
| 1453 | * the file path to which the source file is to be moved. |
||
| 1454 | * @param string $dest_name |
||
| 1455 | * the file name within the file path to which the source file is to be moved. |
||
| 1456 | * @param string $tmp_name |
||
| 1457 | * the full path name of the source file to move. |
||
| 1458 | * @param integer|string $perm (optional) |
||
| 1459 | * the permissions to apply to the moved file. this defaults to 0644 @since |
||
| 1460 | * Symphony 2.7.0. It was 0777 in 2.6.x and less. |
||
| 1461 | * @return boolean |
||
| 1462 | * true if the file was moved and its permissions set as required. false otherwise. |
||
| 1463 | */ |
||
| 1464 | public static function uploadFile($dest_path, $dest_name, $tmp_name, $perm = 0644) |
||
| 1465 | { |
||
| 1466 | // Upload the file |
||
| 1467 | if (@is_uploaded_file($tmp_name)) { |
||
| 1468 | $dest_path = rtrim($dest_path, '/') . '/'; |
||
| 1469 | $dest = $dest_path . $dest_name; |
||
| 1470 | |||
| 1471 | // Check that destination is writable |
||
| 1472 | if (!static::checkFileWritable($dest)) { |
||
| 1473 | return false; |
||
| 1474 | } |
||
| 1475 | // Try place the file in the correction location |
||
| 1476 | if (@move_uploaded_file($tmp_name, $dest)) { |
||
| 1477 | if (is_null($perm)) { |
||
| 1478 | $perm = 0644; |
||
| 1479 | } |
||
| 1480 | @chmod($dest, intval($perm, 8)); |
||
| 1481 | return true; |
||
| 1482 | } |
||
| 1483 | } |
||
| 1484 | |||
| 1485 | // Could not move the file |
||
| 1486 | return false; |
||
| 1487 | } |
||
| 1488 | |||
| 1489 | /** |
||
| 1490 | * Format a number of bytes in human readable format. This will append MB as |
||
| 1491 | * appropriate for values greater than 1,024*1,024, KB for values between |
||
| 1492 | * 1,024 and 1,024*1,024-1 and bytes for values between 0 and 1,024. |
||
| 1493 | * |
||
| 1494 | * @param integer $file_size |
||
| 1495 | * the number to format. |
||
| 1496 | * @return string |
||
| 1497 | * the formatted number. |
||
| 1498 | */ |
||
| 1499 | public static function formatFilesize($file_size) |
||
| 1500 | { |
||
| 1501 | $file_size = intval($file_size); |
||
| 1502 | |||
| 1503 | if ($file_size >= (1024 * 1024)) { |
||
| 1504 | $file_size = number_format($file_size * (1 / (1024 * 1024)), 2) . ' MB'; |
||
| 1505 | } elseif ($file_size >= 1024) { |
||
| 1506 | $file_size = intval($file_size * (1/1024)) . ' KB'; |
||
| 1507 | } else { |
||
| 1508 | $file_size = intval($file_size) . ' bytes'; |
||
| 1509 | } |
||
| 1510 | |||
| 1511 | return $file_size; |
||
| 1512 | } |
||
| 1513 | |||
| 1514 | /** |
||
| 1515 | * Gets the number of bytes from 'human readable' size value. Supports |
||
| 1516 | * the output of `General::formatFilesize` as well as reading values |
||
| 1517 | * from the PHP configuration. eg. 1 MB or 1M |
||
| 1518 | * |
||
| 1519 | * @since Symphony 2.5.2 |
||
| 1520 | * @param string $file_size |
||
| 1521 | * @return integer |
||
| 1522 | */ |
||
| 1523 | public static function convertHumanFileSizeToBytes($file_size) |
||
| 1524 | { |
||
| 1525 | $file_size = str_replace( |
||
| 1526 | array(' MB', ' KB', ' bytes'), |
||
| 1527 | array('M', 'K', 'B'), |
||
| 1528 | trim($file_size) |
||
| 1529 | ); |
||
| 1530 | |||
| 1531 | $last = strtolower($file_size[strlen($file_size)-1]); |
||
| 1532 | |||
| 1533 | $file_size = (int) $file_size; |
||
| 1534 | |||
| 1535 | switch ($last) { |
||
| 1536 | case 'g': |
||
| 1537 | $file_size *= 1024; |
||
| 1538 | case 'm': |
||
| 1539 | $file_size *= 1024; |
||
| 1540 | case 'k': |
||
| 1541 | $file_size *= 1024; |
||
| 1542 | } |
||
| 1543 | |||
| 1544 | return $file_size; |
||
| 1545 | } |
||
| 1546 | |||
| 1547 | /** |
||
| 1548 | * Construct an XML fragment that reflects the structure of the input timestamp. |
||
| 1549 | * |
||
| 1550 | * @param integer $timestamp |
||
| 1551 | * the timestamp to construct the XML element from. |
||
| 1552 | * @param string $element (optional) |
||
| 1553 | * the name of the element to append to the namespace of the constructed XML. |
||
| 1554 | * this defaults to "date". |
||
| 1555 | * @param string $date_format (optional) |
||
| 1556 | * the format to apply to the date, defaults to `Y-m-d`. |
||
| 1557 | * if empty, uses DateTimeObj settings. |
||
| 1558 | * @param string $time_format (optional) |
||
| 1559 | * the format to apply to the date, defaults to `H:i`. |
||
| 1560 | * if empty, uses DateTimeObj settings. |
||
| 1561 | * @param string $namespace (optional) |
||
| 1562 | * the namespace in which the resulting XML entity will reside. this defaults |
||
| 1563 | * to null. |
||
| 1564 | * @return boolean|XMLElement |
||
| 1565 | * false if there is no XMLElement class on the system, the constructed XML element |
||
| 1566 | * otherwise. |
||
| 1567 | */ |
||
| 1568 | public static function createXMLDateObject($timestamp, $element = 'date', $date_format = 'Y-m-d', $time_format = 'H:i', $namespace = null) |
||
| 1569 | { |
||
| 1570 | if (!class_exists('XMLElement')) { |
||
| 1571 | return false; |
||
| 1572 | } |
||
| 1573 | |||
| 1574 | if (empty($date_format)) { |
||
| 1575 | $date_format = DateTimeObj::getSetting('date_format'); |
||
| 1576 | } |
||
| 1577 | if (empty($time_format)) { |
||
| 1578 | $time_format = DateTimeObj::getSetting('time_format'); |
||
| 1579 | } |
||
| 1580 | |||
| 1581 | $xDate = new XMLElement( |
||
| 1582 | (!is_null($namespace) ? $namespace . ':' : '') . $element, |
||
| 1583 | DateTimeObj::get($date_format, $timestamp), |
||
| 1584 | array( |
||
| 1585 | 'iso' => DateTimeObj::get('c', $timestamp), |
||
| 1586 | 'timestamp' => DateTimeObj::get('U', $timestamp), |
||
| 1587 | 'time' => DateTimeObj::get($time_format, $timestamp), |
||
| 1588 | 'weekday' => DateTimeObj::get('N', $timestamp), |
||
| 1589 | 'offset' => DateTimeObj::get('O', $timestamp) |
||
| 1590 | ) |
||
| 1591 | ); |
||
| 1592 | |||
| 1593 | return $xDate; |
||
| 1594 | } |
||
| 1595 | |||
| 1596 | /** |
||
| 1597 | * Construct an XML fragment that describes a pagination structure. |
||
| 1598 | * |
||
| 1599 | * @param integer $total_entries (optional) |
||
| 1600 | * the total number of entries that this structure is paginating. this |
||
| 1601 | * defaults to 0. |
||
| 1602 | * @param integer $total_pages (optional) |
||
| 1603 | * the total number of pages within the pagination structure. this defaults |
||
| 1604 | * to 0. |
||
| 1605 | * @param integer $entries_per_page (optional) |
||
| 1606 | * the number of entries per page. this defaults to 1. |
||
| 1607 | * @param integer $current_page (optional) |
||
| 1608 | * the current page within the total number of pages within this pagination |
||
| 1609 | * structure. this defaults to 1. |
||
| 1610 | * @return XMLElement |
||
| 1611 | * the constructed XML fragment. |
||
| 1612 | */ |
||
| 1613 | public static function buildPaginationElement($total_entries = 0, $total_pages = 0, $entries_per_page = 1, $current_page = 1) |
||
| 1614 | { |
||
| 1615 | $pageinfo = new XMLElement('pagination'); |
||
| 1616 | |||
| 1617 | $pageinfo->setAttribute('total-entries', $total_entries); |
||
| 1618 | $pageinfo->setAttribute('total-pages', $total_pages); |
||
| 1619 | $pageinfo->setAttribute('entries-per-page', $entries_per_page); |
||
| 1620 | $pageinfo->setAttribute('current-page', $current_page); |
||
| 1621 | |||
| 1622 | return $pageinfo; |
||
| 1623 | } |
||
| 1624 | |||
| 1625 | /** |
||
| 1626 | * Uses `SHA1` or `MD5` to create a hash based on some input |
||
| 1627 | * This function is currently very basic, but would allow |
||
| 1628 | * future expansion. Salting the hash comes to mind. |
||
| 1629 | * |
||
| 1630 | * @param string $input |
||
| 1631 | * the string to be hashed |
||
| 1632 | * @param string $algorithm |
||
| 1633 | * This function supports 'sha1' and 'pbkdf2'. Any |
||
| 1634 | * other algorithm will default to 'pbkdf2'. |
||
| 1635 | * @return string |
||
| 1636 | * the hashed string |
||
| 1637 | */ |
||
| 1638 | public static function hash($input, $algorithm = 'sha1') |
||
| 1639 | { |
||
| 1640 | switch ($algorithm) { |
||
| 1641 | case 'sha1': |
||
| 1642 | return SHA1::hash($input); |
||
| 1643 | case 'pbkdf2': |
||
| 1644 | return PBKDF2::hash($input); |
||
| 1645 | default: |
||
| 1646 | return Cryptography::hash($input); |
||
| 1647 | } |
||
| 1648 | } |
||
| 1649 | |||
| 1650 | /** |
||
| 1651 | * Helper to cut down on variables' type check. |
||
| 1652 | * Currently known types are the PHP defaults. |
||
| 1653 | * Uses `is_XXX()` functions internally. |
||
| 1654 | * |
||
| 1655 | * @since Symphony 2.3 |
||
| 1656 | * |
||
| 1657 | * @param array $params - an array of arrays containing variables info |
||
| 1658 | * |
||
| 1659 | * Array[ |
||
| 1660 | * $key1 => $value1 |
||
| 1661 | * $key2 => $value2 |
||
| 1662 | * ... |
||
| 1663 | * ] |
||
| 1664 | * |
||
| 1665 | * $key = the name of the variable |
||
| 1666 | * $value = Array[ |
||
| 1667 | * 'var' => the variable to check |
||
| 1668 | * 'type' => enforced type. Must match the XXX part from an `is_XXX()` function |
||
| 1669 | * 'optional' => boolean. If this is set, the default value of the variable must be null |
||
| 1670 | * ] |
||
| 1671 | * |
||
| 1672 | * @throws InvalidArgumentException if validator doesn't exist. |
||
| 1673 | * @throws InvalidArgumentException if variable type validation fails. |
||
| 1674 | * |
||
| 1675 | * @example |
||
| 1676 | * $color = 'red'; |
||
| 1677 | * $foo = null; |
||
| 1678 | * $bar = 21; |
||
| 1679 | * |
||
| 1680 | * General::ensureType(array( |
||
| 1681 | * 'color' => array('var' => $color, 'type'=> 'string'), // success |
||
| 1682 | * 'foo' => array('var' => $foo, 'type'=> 'int', 'optional' => true), // success |
||
| 1683 | * 'bar' => array('var' => $bar, 'type'=> 'string') // fail |
||
| 1684 | * )); |
||
| 1685 | */ |
||
| 1686 | public static function ensureType(array $params) |
||
| 1687 | { |
||
| 1688 | foreach ($params as $name => $param) { |
||
| 1689 | if (isset($param['optional']) && ($param['optional'] === true)) { |
||
| 1690 | if (empty($param['var'])) { |
||
| 1691 | continue; |
||
| 1692 | } |
||
| 1693 | // if not null, check it's type |
||
| 1694 | } |
||
| 1695 | |||
| 1696 | if (empty($param['type'])) { |
||
| 1697 | $param['type'] = 'Undefined'; |
||
| 1698 | } |
||
| 1699 | |||
| 1700 | // validate the validator |
||
| 1701 | $validator = 'is_'.$param['type']; |
||
| 1702 | |||
| 1703 | if (!function_exists($validator)) { |
||
| 1704 | throw new InvalidArgumentException(__('Enforced type `%1$s` for argument `$%2$s` does not match any known variable types.', array($param['type'], $name))); |
||
| 1705 | } |
||
| 1706 | |||
| 1707 | // validate variable type |
||
| 1708 | if (!call_user_func($validator, $param['var'])) { |
||
| 1709 | throw new InvalidArgumentException(__('Argument `$%1$s` is not of type `%2$s`, given `%3$s`.', array($name, $param['type'], gettype($param['var'])))); |
||
| 1710 | } |
||
| 1711 | } |
||
| 1712 | } |
||
| 1713 | |||
| 1714 | |||
| 1715 | /** |
||
| 1716 | * Wrap a value in CDATA tags for XSL output of non encoded data, only |
||
| 1717 | * if not already wrapped. |
||
| 1718 | * |
||
| 1719 | * @since Symphony 2.3.2 |
||
| 1720 | * |
||
| 1721 | * @param string $value |
||
| 1722 | * The string to wrap in CDATA |
||
| 1723 | * @return string |
||
| 1724 | * The wrapped string |
||
| 1725 | */ |
||
| 1726 | public static function wrapInCDATA($value) |
||
| 1727 | { |
||
| 1728 | if (empty($value)) { |
||
| 1729 | return $value; |
||
| 1730 | } |
||
| 1731 | |||
| 1732 | $startRegExp = '/^' . preg_quote(CDATA_BEGIN) . '/'; |
||
| 1733 | $endRegExp = '/' . preg_quote(CDATA_END) . '$/'; |
||
| 1734 | |||
| 1735 | if (!preg_match($startRegExp, $value)) { |
||
| 1736 | $value = CDATA_BEGIN . $value; |
||
| 1737 | } |
||
| 1738 | |||
| 1739 | if (!preg_match($endRegExp, $value)) { |
||
| 1740 | $value .= CDATA_END; |
||
| 1741 | } |
||
| 1742 | |||
| 1743 | return $value; |
||
| 1744 | } |
||
| 1745 | |||
| 1746 | /** |
||
| 1747 | * Unwrap a value from CDATA tags to return the raw string |
||
| 1748 | * |
||
| 1749 | * @since Symphony 2.3.4 |
||
| 1750 | * @param string $value |
||
| 1751 | * The string to unwrap from CDATA |
||
| 1752 | * @return string |
||
| 1753 | * The unwrapped string |
||
| 1754 | */ |
||
| 1755 | public static function unwrapCDATA($value) |
||
| 1758 | } |
||
| 1759 | |||
| 1760 | /** |
||
| 1761 | * Converts a value to a positive integer. This method makes sure that the |
||
| 1762 | * value is a valid positive integer representation before doing the cast. |
||
| 1763 | * |
||
| 1764 | * @since Symphony 2.5 |
||
| 1765 | * @param mixed $value |
||
| 1766 | * The value to cast to an integer |
||
| 1767 | * @return int |
||
| 1768 | * The casted integer value if the input is valid, -1 otherwise. |
||
| 1769 | */ |
||
| 1770 | public static function intval($value) |
||
| 1771 | { |
||
| 1777 | } |
||
| 1778 | } |
||
| 1779 |
The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g.
excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths