/** * Gets a cookie value from `$_COOKIE`, while allowing a default value to be provided * * @param string $name The name of the cookie to retrieve * @param mixed $default_value If there is no cookie with the name provided, return this value instead * @return mixed The value */ public static function get($name, $default_value = NULL) { if (isset($_COOKIE[$name])) { $value = fUTF8::clean($_COOKIE[$name]); if (get_magic_quotes_gpc()) { $value = stripslashes($value); } return $value; } return $default_value; }
/** * Gets a value from the `DELETE`/`PUT` post data, `$_POST` or `$_GET` superglobals (in that order) * * A value that exactly equals `''` and is not cast to a specific type will * become `NULL`. * * Valid `$cast_to` types include: * - `'string'`, * - `'int'` * - `'integer'` * - `'bool'` * - `'boolean'` * - `'array'` * - `'date'` * - `'time'` * - `'timestamp'` * * It is also possible to append a `?` to a data type to return `NULL` * whenever the `$key` was not specified in the request, or if the value * was a blank string. * * All text values are interpreted as UTF-8 string and appropriately * cleaned. * * @param string $key The key to get the value of * @param string $cast_to Cast the value to this data type - see method description for details * @param mixed $default_value If the parameter is not set in the `DELETE`/`PUT` post data, `$_POST` or `$_GET`, use this value instead. This value will get cast if a `$cast_to` is specified. * @return mixed The value */ public static function get($key, $cast_to = NULL, $default_value = NULL) { self::initPutDelete(); $value = $default_value; $array_dereference = NULL; if (strpos($key, '[')) { $bracket_pos = strpos($key, '['); $array_dereference = substr($key, $bracket_pos); $key = substr($key, 0, $bracket_pos); } if (isset(self::$put_delete[$key])) { $value = self::$put_delete[$key]; } elseif (isset($_POST[$key])) { $value = $_POST[$key]; } elseif (isset($_GET[$key])) { $value = $_GET[$key]; } if ($array_dereference) { preg_match_all('#(?<=\\[)[^\\[\\]]+(?=\\])#', $array_dereference, $array_keys, PREG_SET_ORDER); $array_keys = array_map('current', $array_keys); foreach ($array_keys as $array_key) { if (!is_array($value) || !isset($value[$array_key])) { $value = $default_value; break; } $value = $value[$array_key]; } } // This allows for data_type? casts to allow NULL through if ($cast_to !== NULL && substr($cast_to, -1) == '?') { if ($value === NULL || $value === '') { return $value; } $cast_to = substr($cast_to, 0, -1); } if (get_magic_quotes_gpc() && (self::isPost() || self::isGet())) { if (is_array($value)) { $value = array_map('stripslashes', $value); } else { $value = stripslashes($value); } } // This normalizes an empty element to NULL if ($cast_to === NULL && $value === '') { $value = NULL; } elseif ($cast_to == 'date') { try { $value = new fDate($value); } catch (fValidationException $e) { $value = new fDate(); } } elseif ($cast_to == 'time') { try { $value = new fTime($value); } catch (fValidationException $e) { $value = new fTime(); } } elseif ($cast_to == 'timestamp') { try { $value = new fTimestamp($value); } catch (fValidationException $e) { $value = new fTimestamp(); } } elseif ($cast_to == 'array' && is_string($value) && strpos($value, ',') !== FALSE) { $value = explode(',', $value); } elseif ($cast_to == 'array' && ($value === NULL || $value === '')) { $value = array(); } elseif ($cast_to == 'bool' || $cast_to == 'boolean') { if (strtolower($value) == 'f' || strtolower($value) == 'false' || strtolower($value) == 'no' || !$value) { $value = FALSE; } else { $value = TRUE; } } elseif (($cast_to == 'int' || $cast_to == 'integer') && preg_match('#^-?\\d+$#D', $value)) { // If the cast is an integer and the value is digits, don't cast to prevent // truncation due to 32 bit integer limits } elseif ($cast_to) { settype($value, $cast_to); } // Clean values coming in to ensure we don't have invalid UTF-8 if (($cast_to === NULL || $cast_to == 'string' || $cast_to == 'array') && $value !== NULL) { $value = fUTF8::clean($value); } return $value; }
/** * Prints out a piece of a template * * @param string $template The name of the template to print * @param string $piece The piece of the template to print * @param array $data The data to replace the variables with * @return void */ private static function printPiece($template, $name, $data) { if (!isset(self::$templates[$template]['pieces'][$name])) { throw new fProgrammerException('The template piece, %s, was not specified when defining the %s template', $name, $template); } $piece = self::$templates[$template]['pieces'][$name]; preg_match_all('#\\{\\{ (\\w+)((?:\\|\\w+)+)? \\}\\}#', $piece, $matches, PREG_SET_ORDER); foreach ($matches as $match) { $variable = $match[1]; $value = !isset($data[$variable]) ? NULL : $data[$variable]; if (isset($match[2])) { $filters = array_slice(explode('|', $match[2]), 1); foreach ($filters as $filter) { if (!in_array($filter, self::$filters)) { throw new fProgrammerException('The filter specified, %1$s, is invalid. Must be one of: %2$s.', $filter, join(', ', self::$filters)); } if (!strlen($value)) { continue; } if ($filter == 'inflect') { $value = fGrammar::inflectOnQuantity($data['total_records'], $value); } elseif ($filter == 'lower') { $value = fUTF8::lower($value); } elseif ($filter == 'url_encode') { $value = urlencode($value); } elseif ($filter == 'humanize') { $value = fGrammar::humanize($value); } } } $piece = preg_replace('#' . preg_quote($match[0], '#') . '#', fHTML::encode($value), $piece, 1); } echo $piece; }
/** * Allows adding a custom header to the email * * If the method is called multiple times with the same name, the last * value will be used. * * Please note that this class will properly format the header, including * adding the `:` between the name and value and wrapping values that are * too long for a single line. * * @param string $name The name of the header * @param string $value The value of the header * @param array :$headers An associative array of `{name} => {value}` * @return fEmail The email object, to allow for method chaining */ public function addCustomHeader($name, $value = NULL) { if ($value === NULL && is_array($name)) { foreach ($name as $key => $value) { $this->addCustomHeader($key, $value); } return; } $lower_name = fUTF8::lower($name); $this->custom_headers[$lower_name] = array($name, $value); return $this; }
/** * A usort callback to sort by methods on records * * @param fActiveRecord $a The first record to compare * @param fActiveRecord $b The second record to compare * @return integer < 0 if `$a` is less than `$b`, 0 if `$a` = `$b`, > 0 if `$a` is greater than `$b` */ private function sortCallback($a, $b) { if ($this->sort_direction == 'asc') { return fUTF8::inatcmp($a->{$this->sort_method}(), $b->{$this->sort_method}()); } return fUTF8::inatcmp($b->{$this->sort_method}(), $a->{$this->sort_method}()); }
/** * Checks to see if a record matches a condition * * @internal * * @param string $operator The record to check * @param mixed $value The value to compare to * @param mixed $result The result of the method call(s) * @return boolean If the comparison was successful */ private static function checkCondition($operator, $value, $result) { $was_array = is_array($value); if (!$was_array) { $value = array($value); } foreach ($value as $i => $_value) { if (is_object($_value)) { if ($_value instanceof fActiveRecord) { continue; } if (method_exists($_value, '__toString')) { $value[$i] = $_value->__toString(); } } } if (!$was_array) { $value = $value[0]; } $was_array = is_array($result); if (!$was_array) { $result = array($result); } foreach ($result as $i => $_result) { if (is_object($_result)) { if ($_result instanceof fActiveRecord) { continue; } if (method_exists($_result, '__toString')) { $result[$i] = $_result->__toString(); } } } if (!$was_array) { $result = $result[0]; } $match_all = $operator == '&~'; $negate_like = $operator == '!~'; switch ($operator) { case '&~': case '!~': case '~': if (!$match_all && !$negate_like && !is_array($value) && is_array($result)) { $value = fORMDatabase::parseSearchTerms($value, TRUE); } settype($value, 'array'); settype($result, 'array'); if (count($result) > 1) { foreach ($value as $_value) { $found = FALSE; foreach ($result as $_result) { if (fUTF8::ipos($_result, $_value) !== FALSE) { $found = TRUE; } } if (!$found) { return FALSE; } } } else { $found = FALSE; foreach ($value as $_value) { if (fUTF8::ipos($result[0], $_value) !== FALSE) { $found = TRUE; } elseif ($match_all) { return FALSE; } } if (!$negate_like && !$found || $negate_like && $found) { return FALSE; } } break; case '=': if ($value instanceof fActiveRecord && $result instanceof fActiveRecord) { if (get_class($value) != get_class($result) || !$value->exists() || !$result->exists() || self::hash($value) != self::hash($result)) { return FALSE; } } elseif (is_array($value) && !in_array($result, $value)) { return FALSE; } elseif (!is_array($value) && $result != $value) { return FALSE; } break; case '!': if ($value instanceof fActiveRecord && $result instanceof fActiveRecord) { if (get_class($value) == get_class($result) && $value->exists() && $result->exists() && self::hash($value) == self::hash($result)) { return FALSE; } } elseif (is_array($value) && in_array($result, $value)) { return FALSE; } elseif (!is_array($value) && $result == $value) { return FALSE; } break; case '<': if ($result >= $value) { return FALSE; } break; case '<=': if ($result > $value) { return FALSE; } break; case '>': if ($result <= $value) { return FALSE; } break; case '>=': if ($result < $value) { return FALSE; } break; } return TRUE; }
/** * Changes a string into a URL-friendly string * * @param string $string The string to convert * @param interger $max_length The maximum length of the friendly URL * @return string The URL-friendly version of the string */ public static function makeFriendly($string, $max_length = NULL) { $string = fHTML::decode(fUTF8::ascii($string)); $string = strtolower(trim($string)); $string = str_replace("'", '', $string); $string = preg_replace('#[^a-z0-9\\-]+#', '_', $string); $string = preg_replace('#_{2,}#', '_', $string); $string = preg_replace('#_-_#', '-', $string); $string = preg_replace('#(^_+|_+$)#D', '', $string); $length = strlen($string); if ($max_length && $length > $max_length) { $last_pos = strrpos($string, '_', ($length - $max_length - 1) * -1); if ($last_pos < ceil($max_length / 2)) { $last_pos = $max_length; } $string = substr($string, 0, $last_pos); } return $string; }
/** * Checks to see if a record matches a condition * * @internal * * @param string $operator The record to check * @param mixed $value The value to compare to * @param mixed $result The result of the method call(s) * @return boolean If the comparison was successful */ private static function checkCondition($operator, $value, $result) { $was_array = is_array($value); if (!$was_array) { $value = array($value); } foreach ($value as $i => $_value) { if (is_object($_value)) { if ($_value instanceof fActiveRecord) { continue; } if (method_exists($_value, '__toString')) { $value[$i] = $_value->__toString(); } } } if (!$was_array) { $value = $value[0]; } $was_array = is_array($result); if (!$was_array) { $result = array($result); } foreach ($result as $i => $_result) { if (is_object($_result)) { if ($_result instanceof fActiveRecord) { continue; } if (method_exists($_result, '__toString')) { $result[$i] = $_result->__toString(); } } } if (!$was_array) { $result = $result[0]; } if ($operator == '~' && !is_array($value) && is_array($result)) { $value = fORMDatabase::parseSearchTerms($value, TRUE); } if (in_array($operator, array('~', '&~', '!~', '^~', '$~'))) { settype($value, 'array'); settype($result, 'array'); } switch ($operator) { case '&~': foreach ($value as $_value) { if (fUTF8::ipos($result[0], $_value) === FALSE) { return FALSE; } } break; case '~': // Handles fuzzy search on multiple method calls if (count($result) > 1) { foreach ($value as $_value) { $found = FALSE; foreach ($result as $_result) { if (fUTF8::ipos($_result, $_value) !== FALSE) { $found = TRUE; } } if (!$found) { return FALSE; } } break; } // No break exists since a ~ on a single method call acts // similar to the other LIKE operators // No break exists since a ~ on a single method call acts // similar to the other LIKE operators case '!~': case '^~': case '$~': if ($operator == '$~') { $result_len = fUTF8::len($result[0]); } foreach ($value as $_value) { $pos = fUTF8::ipos($result[0], $_value); if ($operator == '^~' && $pos === 0) { return TRUE; } elseif ($operator == '$~' && $pos === $result_len - fUTF8::len($_value)) { return TRUE; } elseif ($pos !== FALSE) { return $operator != '!~'; } } if ($operator != '!~') { return FALSE; } break; case '=': if ($value instanceof fActiveRecord && $result instanceof fActiveRecord) { if (get_class($value) != get_class($result) || !$value->exists() || !$result->exists() || self::hash($value) != self::hash($result)) { return FALSE; } } elseif (is_array($value) && !in_array($result, $value)) { return FALSE; } elseif (!is_array($value) && $result != $value) { return FALSE; } break; case '!': if ($value instanceof fActiveRecord && $result instanceof fActiveRecord) { if (get_class($value) == get_class($result) && $value->exists() && $result->exists() && self::hash($value) == self::hash($result)) { return FALSE; } } elseif (is_array($value) && in_array($result, $value)) { return FALSE; } elseif (!is_array($value) && $result == $value) { return FALSE; } break; case '<': if ($result >= $value) { return FALSE; } break; case '<=': if ($result > $value) { return FALSE; } break; case '>': if ($result <= $value) { return FALSE; } break; case '>=': if ($result < $value) { return FALSE; } break; } return TRUE; }
/** * Reorders list items in an html string based on their contents * * @internal * * @param string $class The class to reorder messages for * @param array $messages An array of the messages * @return array The reordered messages */ public static function reorderMessages($class, $messages) { if (!isset(self::$message_orders[$class])) { return $messages; } $matches = self::$message_orders[$class]; $ordered_items = array_fill(0, sizeof($matches), array()); $other_items = array(); foreach ($messages as $key => $message) { foreach ($matches as $num => $match_string) { $string = is_array($message) ? $message['name'] : $message; if (fUTF8::ipos($string, $match_string) !== FALSE) { $ordered_items[$num][$key] = $message; continue 2; } } $other_items[$key] = $message; } $final_list = array(); foreach ($ordered_items as $ordered_item) { $final_list = array_merge($final_list, $ordered_item); } return array_merge($final_list, $other_items); }
/** * @dataProvider ucwordsProvider */ public function testUcwords($input, $output) { $this->assertEquals($output, fUTF8::ucwords($input)); }
/** * Callback for custom SQLite function; creates a substring * * @internal * * @param string $string The string to take a substring of * @param integer $start The one-based position to start the substring at * @param integer $length The length of the substring to take * @return string The substring */ public static function sqliteSubstr($string, $start, $length) { return fUTF8::sub($string, $start - 1, $length); }
/** * Created a unicode code point from a JS escaped unicode character * * @param array $match A regex match containing the 4 digit code referenced by the key `1` * @return string The U+{digits} unicode code point */ private static function makeUnicodeCodePoint($match) { return fUTF8::chr("U+" . $match[1]); }
/** * Gets a value from the `DELETE`/`PUT` post data, `$_POST` or `$_GET` superglobals (in that order) * * A value that exactly equals `''` and is not cast to a specific type will * become `NULL`. * * Valid `$cast_to` types include: * - `'string'`, * - `'int'` * - `'integer'` * - `'bool'` * - `'boolean'` * - `'array'` * - `'date'` * - `'time'` * - `'timestamp'` * * It is also possible to append a `?` to a data type to return `NULL` * whenever the `$key` was not specified in the request, or if the value * was a blank string. * * All text values are interpreted as UTF-8 string and appropriately * cleaned. * * @param string $key The key to get the value of * @param string $cast_to Cast the value to this data type - see method description for details * @param mixed $default_value If the parameter is not set in the `DELETE`/`PUT` post data, `$_POST` or `$_GET`, use this value instead. This value will get cast if a `$cast_to` is specified. * @return mixed The value */ public static function get($key, $cast_to = NULL, $default_value = NULL) { self::initPutDelete(); $value = $default_value; if (isset(self::$put_delete[$key])) { $value = self::$put_delete[$key]; } elseif (isset($_POST[$key])) { $value = $_POST[$key]; } elseif (isset($_GET[$key])) { $value = $_GET[$key]; } // This allows for data_type? casts to allow NULL through if ($cast_to !== NULL && substr($cast_to, -1) == '?') { if ($value === NULL || $value === '') { return $value; } $cast_to = substr($cast_to, 0, -1); } if (get_magic_quotes_gpc() && (self::isPost() || self::isGet())) { if (is_array($value)) { $value = array_map('stripslashes', $value); } else { $value = stripslashes($value); } } // This normalizes an empty element to NULL if ($cast_to === NULL && $value === '') { $value = NULL; } elseif ($cast_to == 'date') { try { $value = new fDate($value); } catch (fValidationException $e) { $value = new fDate(); } } elseif ($cast_to == 'time') { try { $value = new fTime($value); } catch (fValidationException $e) { $value = new fTime(); } } elseif ($cast_to == 'timestamp') { try { $value = new fTimestamp($value); } catch (fValidationException $e) { $value = new fTimestamp(); } } elseif ($cast_to == 'array' && is_string($value) && strpos($value, ',') !== FALSE) { $value = explode(',', $value); } elseif ($cast_to == 'array' && ($value === NULL || $value === '')) { $value = array(); } elseif ($cast_to == 'bool' || $cast_to == 'boolean') { if (strtolower($value) == 'f' || strtolower($value) == 'false' || strtolower($value) == 'no' || !$value) { $value = FALSE; } else { $value = TRUE; } } elseif ($cast_to) { settype($value, $cast_to); } // Clean values coming in to ensure we don't have invalid UTF-8 if (($cast_to === NULL || $cast_to == 'string' || $cast_to == 'array') && $value !== NULL) { $value = fUTF8::clean($value); } return $value; }
/** * Recursively handles casting values * * @param string|array $value The value to be casted * @param string $cast_to The data type to cast to * @param integer $level The nesting level of the call * @return mixed The casted `$value` */ private static function cast($value, $cast_to, $level = 0) { $level++; $strict_array = substr($cast_to, -2) == '[]'; $array_type = $cast_to == 'array' || $strict_array; if ($level == 1 && $array_type) { if (is_string($value) && strpos($value, ',') !== FALSE) { $value = explode(',', $value); } elseif ($value === NULL || $value === '') { $value = array(); } else { settype($value, 'array'); } } // Iterate through array values and cast them individually if (is_array($value) && ($cast_to == 'array' || $cast_to === NULL || $strict_array && $level == 1)) { if ($value === array()) { return $value; } foreach ($value as $key => $sub_value) { $value[$key] = self::cast($sub_value, $cast_to, $level); } return $value; } if ($array_type) { $cast_to = preg_replace('#\\[\\]$#D', '', $cast_to); } if ($cast_to == 'array' && $level > 1) { $cast_to = 'string'; } if (get_magic_quotes_gpc() && (self::isPost() || self::isGet())) { $value = self::stripSlashes($value); } // This normalizes an empty element to NULL if ($cast_to === NULL && $value === '') { $value = NULL; } elseif ($cast_to == 'date') { try { $value = new fDate($value); } catch (fValidationException $e) { $value = new fDate(); } } elseif ($cast_to == 'time') { try { $value = new fTime($value); } catch (fValidationException $e) { $value = new fTime(); } } elseif ($cast_to == 'timestamp') { try { $value = new fTimestamp($value); } catch (fValidationException $e) { $value = new fTimestamp(); } } elseif ($cast_to == 'bool' || $cast_to == 'boolean') { if (strtolower($value) == 'f' || strtolower($value) == 'false' || strtolower($value) == 'no' || !$value) { $value = FALSE; } else { $value = TRUE; } } elseif (($cast_to == 'int' || $cast_to == 'integer') && is_string($value) && preg_match('#^-?\\d+$#D', $value)) { // Only explicitly cast integers than can be represented by a real // PHP integer to prevent truncation due to 32 bit integer limits if (strval(intval($value)) == $value) { $value = (int) $value; } // This patches PHP bug #53632 for vulnerable versions of PHP - http://bugs.php.net/bug.php?id=53632 } elseif ($cast_to == 'float' && $value === "2.2250738585072011e-308") { static $vulnerable_to_53632 = NULL; if ($vulnerable_to_53632 === NULL) { $running_version = preg_replace('#^(\\d+\\.\\d+\\.\\d+).*$#D', '\\1', PHP_VERSION); $vulnerable_to_53632 = version_compare($running_version, '5.2.17', '<') || version_compare($running_version, '5.3.5', '<') && version_compare($running_version, '5.3.0', '>='); } if ($vulnerable_to_53632) { $value = "2.2250738585072012e-308"; } settype($value, 'float'); } elseif ($cast_to != 'binary' && $cast_to !== NULL) { $cast_to = str_replace('integer!', 'integer', $cast_to); settype($value, $cast_to); } // Clean values coming in to ensure we don't have invalid UTF-8 if (($cast_to === NULL || $cast_to == 'string' || $cast_to == 'array') && $value !== NULL) { $value = self::stripLowOrderBytes($value); $value = fUTF8::clean($value); } return $value; }
/** * Changes a string into a URL-friendly string * * @param string $string The string to convert * @return void */ public static function makeFriendly($string) { $string = fHTML::decode(fUTF8::ascii($string)); $string = strtolower(trim($string)); $string = str_replace("'", '', $string); $string = preg_replace('#[^a-z0-9\\-]+#', '_', $string); $string = preg_replace('#_{2,}#', '_', $string); $string = preg_replace('#_-_#', '-', $string); return preg_replace('#(^_+|_+$)#D', '', $string); }
/** * Reorders an array of messages based on the requested order * * @param array $messages An array of the messages * @return array The reordered messages */ private function reorderMessages($messages) { if (!$this->message_order) { return $messages; } $ordered_items = array_fill(0, sizeof($this->message_order), array()); $other_items = array(); foreach ($messages as $key => $message) { foreach ($this->message_order as $num => $match_string) { if (fUTF8::ipos($message, $match_string) !== FALSE) { $ordered_items[$num][$key] = $message; continue 2; } } $other_items[$key] = $message; } $final_list = array(); foreach ($ordered_items as $ordered_item) { $final_list = array_merge($final_list, $ordered_item); } return array_merge($final_list, $other_items); }
/** * Resets the configuration of the class * * @internal * * @return void */ public static function reset() { self::$mbstring_available = NULL; }
/** * Uses the Porter Stemming algorithm to create the stem of a word, which is useful for searching * * See http://tartarus.org/~martin/PorterStemmer/ for details about the * algorithm. * * @param string $word The word to get the stem of * @return string The stem of the word */ public static function stem($word) { $s_v = '^([^aeiou][^aeiouy]*)?[aeiouy]'; $mgr0 = $s_v . '[aeiou]*[^aeiou][^aeiouy]*'; $s_v_regex = '#' . $s_v . '#'; $mgr0_regex = '#' . $mgr0 . '#'; $meq1_regex = '#' . $mgr0 . '([aeiouy][aeiou]*)?$#'; $mgr1_regex = '#' . $mgr0 . '[aeiouy][aeiou]*[^aeiou][^aeiouy]*#'; $word = fUTF8::ascii($word); $word = strtolower($word); if (strlen($word) < 3) { return $word; } if ($word[0] == 'y') { $word = 'Y' . substr($word, 1); } // Step 1a $word = preg_replace('#^(.+?)(?:(ss|i)es|([^s])s)$#', '\\1\\2\\3', $word); // Step 1b if (preg_match('#^(.+?)eed$#', $word, $match)) { if (preg_match($mgr0_regex, $match[1])) { $word = substr($word, 0, -1); } } elseif (preg_match('#^(.+?)(ed|ing)$#', $word, $match)) { if (preg_match($s_v_regex, $match[1])) { $word = $match[1]; if (preg_match('#(at|bl|iz)$#', $word)) { $word .= 'e'; } elseif (preg_match('#([^aeiouylsz])\\1$#', $word)) { $word = substr($word, 0, -1); } elseif (preg_match('#^[^aeiou][^aeiouy]*[aeiouy][^aeiouwxy]$#', $word)) { $word .= 'e'; } } } // Step 1c if (substr($word, -1) == 'y') { $stem = substr($word, 0, -1); if (preg_match($s_v_regex, $stem)) { $word = $stem . 'i'; } } // Step 2 if (preg_match('#^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$#', $word, $match)) { if (preg_match($mgr0_regex, $match[1])) { $word = $match[1] . strtr($match[2], array('ational' => 'ate', 'tional' => 'tion', 'enci' => 'ence', 'anci' => 'ance', 'izer' => 'ize', 'bli' => 'ble', 'alli' => 'al', 'entli' => 'ent', 'eli' => 'e', 'ousli' => 'ous', 'ization' => 'ize', 'ation' => 'ate', 'ator' => 'ate', 'alism' => 'al', 'iveness' => 'ive', 'fulness' => 'ful', 'ousness' => 'ous', 'aliti' => 'al', 'iviti' => 'ive', 'biliti' => 'ble', 'logi' => 'log')); } } // Step 3 if (preg_match('#^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$#', $word, $match)) { if (preg_match($mgr0_regex, $match[1])) { $word = $match[1] . strtr($match[2], array('icate' => 'ic', 'ative' => '', 'alize' => 'al', 'iciti' => 'ic', 'ical' => 'ic', 'ful' => '', 'ness' => '')); } } // Step 4 if (preg_match('#^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize|(?<=[st])ion)$#', $word, $match) && preg_match($mgr1_regex, $match[1])) { $word = $match[1]; } // Step 5 if (substr($word, -1) == 'e') { $stem = substr($word, 0, -1); if (preg_match($mgr1_regex, $stem)) { $word = $stem; } elseif (preg_match($meq1_regex, $stem) && !preg_match('#^[^aeiou][^aeiouy]*[aeiouy][^aeiouwxy]$#', $stem)) { $word = $stem; } } if (preg_match('#ll$#', $word) && preg_match($mgr1_regex, $word)) { $word = substr($word, 0, -1); } if ($word[0] == 'Y') { $word = 'y' . substr($word, 1); } return $word; }
/** * Changes a string into a URL-friendly string * * @param string $string The string to convert * @param integer $max_length The maximum length of the friendly URL * @param string $delimiter The delimiter to use between words, defaults to `_` * @param string |$string * @param string |$delimiter * @return string The URL-friendly version of the string */ public static function makeFriendly($string, $max_length = NULL, $delimiter = NULL) { // This allows omitting the max length, but including a delimiter if ($max_length && !is_numeric($max_length)) { $delimiter = $max_length; $max_length = NULL; } $string = fHTML::decode(fUTF8::ascii($string)); $string = strtolower(trim($string)); $string = str_replace("'", '', $string); if (!strlen($delimiter)) { $delimiter = '_'; } $delimiter_replacement = strtr($delimiter, array('\\' => '\\\\', '$' => '\\$')); $delimiter_regex = preg_quote($delimiter, '#'); $string = preg_replace('#[^a-z0-9\\-_]+#', $delimiter_replacement, $string); $string = preg_replace('#' . $delimiter_regex . '{2,}#', $delimiter_replacement, $string); $string = preg_replace('#_-_#', '-', $string); $string = preg_replace('#(^' . $delimiter_regex . '+|' . $delimiter_regex . '+$)#D', '', $string); $length = strlen($string); if ($max_length && $length > $max_length) { $last_pos = strrpos($string, $delimiter, ($length - $max_length - 1) * -1); if ($last_pos < ceil($max_length / 2)) { $last_pos = $max_length; } $string = substr($string, 0, $last_pos); } return $string; }
/** * Encodes a PHP value into a JSON string * * @param mixed $value The PHP value to encode * @return string The JSON string that is equivalent to the PHP value */ public static function encode($value) { if (is_resource($value)) { return 'null'; } if (function_exists('json_encode')) { return json_encode($value); } if (is_int($value)) { return (string) $value; } if (is_float($value)) { return (string) $value; } if (is_bool($value)) { return $value ? 'true' : 'false'; } if (is_null($value)) { return 'null'; } if (is_string($value)) { if (!preg_match('#^.*$#usD', $value)) { return 'null'; } $char_array = fUTF8::explode($value); $output = '"'; foreach ($char_array as $char) { if (isset(self::$control_character_map[$char])) { $output .= self::$control_character_map[$char]; } elseif (strlen($char) < 2) { $output .= $char; } else { $output .= '\\u' . substr(strtolower(fUTF8::ord($char)), 2); } } $output .= '"'; return $output; } // Detect if an array is associative, which would mean it needs to be encoded as an object $is_assoc_array = FALSE; if (is_array($value) && $value) { $looking_for = 0; foreach ($value as $key => $val) { if (!is_numeric($key) || $key != $looking_for) { $is_assoc_array = TRUE; break; } $looking_for++; } } if (is_object($value) || $is_assoc_array) { $output = '{'; $members = array(); foreach ($value as $key => $val) { $members[] = self::encode((string) $key) . ':' . self::encode($val); } $output .= join(',', $members); $output .= '}'; return $output; } if (is_array($value)) { $output = '['; $members = array(); foreach ($value as $key => $val) { $members[] = self::encode($val); } $output .= join(',', $members); $output .= ']'; return $output; } }