This commit is contained in:
Max Kostjukevich 2013-07-24 03:31:21 -07:00
commit 9dc5497247
32 changed files with 637 additions and 2 deletions

View File

@ -108,6 +108,8 @@ class Fenom {
"iterable" => 'Fenom\Modifier::isIterable'
);
protected $_plugins = array();
/**
* @var array of allowed PHP functions
*/
@ -466,7 +468,14 @@ class Fenom {
return $this->_modifiers[$modifier];
} elseif($this->isAllowedFunction($modifier)) {
return $modifier;
} else {
}
$path = __DIR__ . DIRECTORY_SEPARATOR . 'plugins'. DIRECTORY_SEPARATOR . 'modifier.'. $modifier . '.php';
if (is_file($path) && is_readable($path)) {
$this->_plugins['fenom_modifier_'.$modifier] = $path;
require_once $path;
return 'fenom_modifier_'. $modifier;
} else {
throw new \Exception("Modifier $modifier not found");
}
}
@ -546,6 +555,11 @@ class Fenom {
return $this->_options;
}
public function getPlugins() {
return $this->_plugins;
}
/**
* @param bool|string $scm
* @return Fenom\ProviderInterface

View File

@ -375,12 +375,34 @@ class Template extends Render {
), true).");\n";
}
/**
* Return PHP code for saving plugins include to file
*
* @return string
*/
public function getPluginsCode() {
$plugins_code = "<?php "."\n";
foreach ($this->_fenom->getPlugins() as $name=>$path){
$plugins_code .= "if (!is_callable('".$name."')) {include_once '".$path."';}"."\n";
}
$plugins_code .= " ?>"."\n";
return $plugins_code;
}
/**
* Return closure code
* @return string
*/
private function _getClosureSource() {
return "function (\$tpl) {\n?>{$this->_body}<?php\n}";
$plugins_code = $this->getPluginsCode();
return "function (\$tpl) {\n?>{$plugins_code}\n{$this->_body}<?php\n}";
}
/**

View File

@ -0,0 +1,44 @@
<?php
/**
* Fenom plugin
*
* @package Fenom
* @subpackage PluginsModifier
*/
/**
* Fenom capitalize modifier plugin
*
* Type: modifier<br>
* Name: capitalize<br>
* Purpose: capitalize words in the string
*
* @link http://www.fenom.ru/docs/language.modifiers.tpl#language.modifier.capitalize
* @author
*
* @param string $string string to capitalize
* @param boolean $uc_digits also capitalize "x123" to "X123"
* @param boolean $lc_rest capitalize first letters, lowercase all following letters "aAa" to "Aaa"
* @return string capitalized string
*
*/
function fenom_modifier_capitalize($string, $uc_digits = false) {
fenom_modifier_capitalize_ucfirst(NULL, $uc_digits);
return preg_replace_callback('!\'?\b\w(\w|\')*\b!', 'fenome_modifier_capitalize_ucfirst', $string);
}
function fenom_modifier_capitalize_ucfirst($string, $uc_digits = null) {
static $_uc_digits = FALSE;
if (isset($uc_digits)) {
$_uc_digits = $uc_digits;
return;
}
if (substr($string[0], 0, 1) != '\'' && !preg_match('!\d!', $string[0]) || $_uc_digits) {
return ucfirst($string[0]);
}
else {
return $string[0];
}
}

View File

@ -0,0 +1,40 @@
<?php
/**
* Fenom plugin
*
* @package Fenom
* @subpackage PluginsModifier
*/
/**
* Fenom count_characters modifier plugin
*
* Type: modifier<br>
* Name: count_characters<br>
* Purpose: count the number of characters in a text
*
* @link http://www.fenom.ru/docs/language.modifiers.tpl#language.modifier.capitalize
* @author
*
* @param string $string string to count characters
* @param boolean $inckule_spaces flag count whitespaces
* @param boolean $lc_rest capitalize first letters, lowercase all following letters "aAa" to "Aaa"
* @return integer count characters in string
*
*/
function fenom_modifier_count_characters($string, $include_spaces = FALSE) {
if ($include_spaces) {
return strlen($string);
}
return preg_match_all('~\S~', $string, $match);
}
?>

View File

@ -0,0 +1,7 @@
<?php
function fenom_modifier_count_paragraphs($string) {
return sizeof(preg_split('~[\r\n]+~', $string));
}

View File

@ -0,0 +1,7 @@
<?php
function fenom_modifier_count_sentences($string) {
return preg_match_all('~\S\.(?!\w)~', $string, $match);
}

View File

@ -0,0 +1,6 @@
<?php
function fenom_modifier_count_words($string) {
return sizeof(preg_grep('~[a-zA-Z0-9\\x80-\\xff]~', preg_split('~\s+~', $string)));
}

View File

@ -0,0 +1,21 @@
<?php
require_once __DIR__.'shared.make_timestamp';
function fenom_modifier_date_format($string, $format = "%b %e, %Y", $default_date = null) {
if (substr(PHP_OS, 0, 3) == 'WIN') {
$hours = strftime('%I', $string);
$short_hours = ($hours < 10) ? substr($hours, -1) : $hours;
$_win_from = array('%e', '%T', '%D', '%l');
$_win_to = array('%#d', '%H:%M:%S', '%m/%d/%y', $short_hours);
$format = str_replace($_win_from, $_win_to, $format);
}
if ($string != '') {
return strftime($format, fenom_make_timestamp($string));
}
elseif (isset($default_date) && $default_date != '') {
return strftime($format, fenom_make_timestamp($default_date));
}
else {
return;
}
}

View File

@ -0,0 +1,7 @@
<?php
function fenom_modifier_default($string, $default = '') {
if ($string === FALSE || $string === NULL || $string === '') {
return $default;
}
return $string;
}

View File

@ -0,0 +1,72 @@
<?php
function fenom_modifier_escape($string, $esc_type = 'html', $char_set = 'UTF-8') {
if ($esc_type == 'html') {
return htmlspecialchars($string, ENT_QUOTES, $char_set);
}
if ($esc_type == 'htmlall') {
return htmlentities($string, ENT_QUOTES, $char_set);
}
if ($esc_type == 'url') {
return rawurlencode($string);
}
if ($esc_type == 'urlencode') {
return urlencode($string);
}
if ($esc_type == 'urldecode') {
return urldecode($string);
}
if ($esc_type == 'urlpathinfo') {
return str_replace('%2F', '/', rawurlencode($string));
}
if ($esc_type == 'quotes') {
// escape unescaped single quotes
return preg_replace("%(?<!\\\\)'%", "\\'", $string);
}
if ($esc_type == 'hex') {
// escape every character into hex
$return = '';
for ($x = 0; $x < strlen($string); $x++) {
$return .= '%' . bin2hex($string[$x]);
}
return $return;
}
if ($esc_type == 'hexentity') {
$return = '';
for ($x = 0; $x < strlen($string); $x++) {
$return .= '&#x' . bin2hex($string[$x]) . ';';
}
return $return;
}
if ($esc_type == 'decentity') {
$return = '';
for ($x = 0; $x < strlen($string); $x++) {
$return .= '&#' . ord($string[$x]) . ';';
}
return $return;
}
if ($esc_type == 'javascript') {
// escape quotes and backslashes, newlines, etc.
return strtr($string, array('\\' => '\\\\', "'" => "\\'", '"' => '\\"', "\r" => '\\r', "\n" => '\\n', '</' => '<\/'));
}
if ($esc_type == 'mail') {
// safe way to display e-mail address on a web page
return str_replace(array('@', '.'), array(' [AT] ', ' [DOT] '), $string);
}
if ($esc_type == 'nonstd') {
// escape non-standard chars, such as ms document quotes
$_res = '';
for ($_i = 0, $_len = strlen($string); $_i < $_len; $_i++) {
$_ord = ord(substr($string, $_i, 1));
// non-standard char, escape it
if ($_ord >= 126) {
$_res .= '&#' . $_ord . ';';
}
else {
$_res .= substr($string, $_i, 1);
}
}
return $_res;
}
return $string;
}

View File

@ -0,0 +1,36 @@
<?php
function fenom_modifier_get_query($params, $mode = '') {
$query = '';
$all = strpos($mode, 'a') !== FALSE;
$plain = strpos($mode, 'p') !== FALSE;
$separator = $plain ? '&' : '&amp;';
$params_from_get = array();
$params_sended = array();
foreach ($params as $k => $v) {
if (is_int($k) and isset($_GET[$k])) {
$params_from_get[$k] = $_GET[$k];
}
else {
$params_sended[$k] = $v;
}
}
if ($all) {
foreach ($_GET as $k => $v) {
if (isset($_REQUEST[$k])) {
$params_from_get[$k] = $v;
}
}
}
$params = array_merge($params_from_get, $params_sended);
foreach ($params as $k => $v) {
if ($v === NULL) {
continue;
}
$query .= ($query !== '' ? $separator : '?') . (is_array($v) ?
http_build_query(array($k => $v), '', $separator) :
$k . '=' . urlencode($v)
);
}
return $query;
}

View File

@ -0,0 +1,5 @@
<?php
function fenom_modifier_hexcolor($int) {
return sprintf('%06x', $int);
}

View File

@ -0,0 +1,7 @@
<?php
function fenom_modifier_indent($string, $chars = 4, $char = ' ') {
return preg_replace('~^~m', str_repeat($char, $chars), $string);
}

View File

@ -0,0 +1,5 @@
<?php
function fenom_modifier_ini_get($directive) {
return ini_get($directive);
}

View File

@ -0,0 +1,5 @@
<?php
function fenom_modifier_int2color($string) {
return sprintf('%06X', $string);
}

View File

@ -0,0 +1,30 @@
<?php
function fenom_modifier_mb_truncate($string, $length = 80, $etc = '...', $break_words = FALSE, $middle = FALSE, $encoding = 'UTF-8') {
if ($length == 0) {
return '';
}
$old = mb_internal_encoding();
if ($old != $encoding) {
mb_internal_encoding($encoding);
}
if (mb_strlen($string) > $length) {
$length -= mb_strlen($etc);
if (!$break_words && !$middle) {
$string = preg_replace('/\s+?(\S+)?$/', '', mb_substr($string, 0, $length + 1));
}
if (!$middle) {
$r = mb_substr($string, 0, $length) . $etc;
}
else {
$r = mb_substr($string, 0, $length / 2) . $etc . mb_substr($string, -$length / 2);
}
}
else {
$r = $string;
}
if ($old != $encoding) {
mb_internal_encoding($old);
}
return $r;
}

View File

@ -0,0 +1,6 @@
<?php
function fenom_modifier_natint($string) {
$int = intval($string);
return $int > 0 ? $int : 0;
}

View File

@ -0,0 +1,54 @@
<?php
function fenom_modifier_native_json_encode($a = NULL) {
return native_json_encode($a);
}
if (!function_exists('native_json_encode')) {
function native_json_encode($a = NULL) {
if (is_null($a)) {
return 'null';
}
if ($a === false) {
return 'false';
}
if ($a === true) {
return 'true';
}
if (is_scalar($a)) {
if (is_float($a)) {
// Always use "." for floats.
return floatval(str_replace(",", ".", strval($a)));
}
if (is_string($a)) {
static $jsonReplaces = array(array("\\", "/", "\n", "\t", "\r", "\b", "\f", '"'), array('\\\\', '\\/', '\\n', '\\t', '\\r', '\\b', '\\f', '\"'));
return '"' . str_replace($jsonReplaces[0], $jsonReplaces[1], $a) . '"';
}
else {
return $a;
}
}
$isList = true;
for ($i = 0, reset($a); $i < count($a); $i++, next($a)) {
if (key($a) !== $i) {
$isList = false;
break;
}
}
$result = array();
if ($isList) {
foreach ($a as $v) {
$result[] = native_json_encode($v);
}
return '[' . join(',', $result) . ']';
}
else {
foreach ($a as $k => $v) {
$result[] = native_json_encode($k) . ':' . native_json_encode($v);
}
return '{' . join(',', $result) . '}';
}
}
}
?>

View File

@ -0,0 +1,5 @@
<?php
function fenom_modifier_nl2br($string) {
return nl2br($string);
}

View File

@ -0,0 +1,10 @@
<?php
function fenom_modifier_regex_replace($string, $pattern, $replace) {
if (preg_match('~^([a-z]*)(.)(.*)\2([a-z]*)$~si', str_replace("\x00", '\x00', $pattern), $q)) {
return preg_replace($q[2] . $q[3] . $q[2] . str_replace('e', '', $q[1] . $q[4]), $replace, $string);
}
else {
return FALSE;
}
}

View File

@ -0,0 +1,6 @@
<?php
function fenom_modifier_replace($string, $search, $replace) {
return str_replace($search, $replace, $string);
}

View File

@ -0,0 +1,10 @@
<?php
function fenom_modifier_safe_uri($uri) {
$uri = trim($uri);
if (preg_match('~^(?:java|vb)script:~i', preg_replace('~\s+~', '', $uri))) {
return '/';
}
return $uri;
}

View File

@ -0,0 +1,7 @@
<?php
function fenom_modifier_signedint($int) {
$int = intval($int);
return ($int > 0 ? '+' : '') . $int;
}

View File

@ -0,0 +1,6 @@
<?php
function fenom_modifier_spacify($string, $spacify_char = ' ') {
return implode($spacify_char, preg_split('//', $string, -1, PREG_SPLIT_NO_EMPTY));
}

View File

@ -0,0 +1,13 @@
<?php
function fenom_modifier_spellcount($num, $one, $two, $many)
{
if ($num % 10 == 1 && $num % 100 != 11) {
echo $num . ' ' . $one;
} elseif ($num % 10 >= 2 && $num % 10 <= 4 && ($num % 100 < 10 || $num % 100 >= 20)) {
echo $num . ' ' . $two;
} else {
echo $num . ' ' . $many;
}
}
?>

View File

@ -0,0 +1,6 @@
<?php
function fenom_modifier_string_format($string, $format) {
return sprintf($format, $string);
}

View File

@ -0,0 +1,6 @@
<?php
function fenom_modifier_strip($text, $replace = ' ') {
return preg_replace('~\s+~', $replace, $text);
}

View File

@ -0,0 +1,10 @@
<?php
function fenom_modifier_strip_tags($string, $replace_with_space = TRUE) {
if ($replace_with_space) {
return preg_replace('~<[^>]*?>~', ' ', $string);
}
else {
return strip_tags($string);
}
}

View File

@ -0,0 +1,52 @@
<?php
/**
* Fenom plugin
*
* @package Fenom
* @subpackage PluginsModifier
*/
/**
* Fenom truncate modifier plugin
*
* Type: modifier<br>
* Name: truncate<br>
* Purpose: Truncate a string to a certain length if necessary,
* optionally splitting in the middle of a word, and
* appending the $etc string or inserting $etc into the middle.
* @param string $string input string
* @param integer $length length of truncated text
* @param string $etc end string
* @param boolean $by_words truncate at word boundary
* @param boolean $middle truncate in the middle of text
* @return string truncated string
*
* @link http://www.fenom.ru/docs/language.modifier.truncate.tpl truncate
* @author
*/
function fenom_modifier_truncate($string, $length = 80, $etc = '...', $by_words = false, $middle = false) {
if($middle) {
if(preg_match('#^(.{'.$length.'}).*?(.{'.$length.'})?$#usS', $string, $match)) {
if(count($match) == 3) {
if($by_words) {
return preg_replace('#\s.*$#usS', "", $match[1]).$etc.preg_replace('#^.*\s#usS', "", $match[2]);
} else {
return $match[1].$etc.$match[2];
}
}
}
} else {
if(preg_match('#^(.{'.$length.'})#usS', $string, $match)) {
if($by_words) {
return preg_replace('#\s.*$#usS', "", $match[1]).$etc;
} else {
return $match[1].$etc;
}
}
}
return $string;
}

View File

@ -0,0 +1,18 @@
<?php
function fenom_modifier_view_size($size) {
$size = intval($size);
if ($size >= 1073741824) {
$size = round($size / 1073741824 * 100) / 100 . ' GB';
}
elseif ($size >= 1048576) {
$size = round($size / 1048576 * 100) / 100 . ' MB';
}
elseif ($size >= 1024) {
$size = round($size / 1024 * 100) / 100 . ' KB';
}
else {
$size = $size . ' B';
}
return $size;
}

View File

@ -0,0 +1,68 @@
<?php
function fenom_modifier_wordwrap($string, $length = 80, $break = "\n", $cut = FALSE) {
return _wordwrap($string, $length, $break, $cut);
}
if (!function_exists('mb_wordwrap')) {
function _wordwrap($str, $width, $break) {
$formatted = '';
$position = -1;
$prev_position = 0;
$last_line = -1;
/// looping the string stop at each space
while ($position = mb_stripos($str, " ", ++$position, 'utf-8')) {
if ($position > $last_line + $width + 1) {
$formatted .= mb_substr($str, $last_line + 1, $prev_position - $last_line - 1, 'utf-8') . $break;
$last_line = $prev_position;
}
$prev_position = $position;
}
/// adding last line without the break
$formatted .= mb_substr($str, $last_line + 1, mb_strlen($str), 'utf-8');
return $formatted;
}
function strwidth($s) {
$ret = mb_strwidth($s, 'UTF-8');
return $ret;
}
function mb_wordwrap($str, $wid, $tag) {
$pos = 0;
$tok = array();
$l = mb_strlen($str, 'UTF-8');
if ($l == 0) {
return '';
}
$flag = false;
$tok[0] = mb_substr($str, 0, 1, 'UTF-8');
for ($i = 1; $i < $l; ++$i) {
$c = mb_substr($str, $i, 1, 'UTF-8');
if (!preg_match('/[a-z\'\"]/i', $c)) {
++$pos;
$flag = true;
}
elseif ($flag) {
++$pos;
$flag = false;
}
$tok[$pos] .= $c;
}
$linewidth = 0;
$pos = 0;
$ret = array();
$l = count($tok);
for ($i = 0; $i < $l; ++$i) {
if ($linewidth + ($w = strwidth($tok[$i])) > $wid) {
++$pos;
$linewidth = 0;
}
$ret[$pos] .= $tok[$i];
$linewidth += $w;
}
return implode($tag, $ret);
}
}

View File

@ -0,0 +1,30 @@
<?php
function fenom_make_timestamp($string) {
if (empty($string)) {
// use "now":
$time = time();
}
elseif (preg_match('/^\d{14}$/', $string)) {
// it is mysql timestamp format of YYYYMMDDHHMMSS?
$time = mktime(substr($string, 8, 2), substr($string, 10, 2), substr($string, 12, 2),
substr($string, 4, 2), substr($string, 6, 2), substr($string, 0, 4));
}
elseif (is_numeric($string)) {
// it is a numeric string, we handle it as timestamp
$time = (int)$string;
}
else {
// strtotime should handle it
$time = strtotime($string);
if ($time == -1 || $time === false) {
// strtotime() was not able to parse $string, use "now":
$time = time();
}
}
return $time;
}