- upgraded "Fat Free Framework" PHP core framework v3.6.4v3.6.5

This commit is contained in:
Mark Friedrich
2018-12-26 14:29:37 +01:00
parent 58db5962fb
commit e56740e8a0
22 changed files with 394 additions and 245 deletions

View File

@@ -45,7 +45,7 @@ final class Base extends Prefab implements ArrayAccess {
//@{ Framework details
const
PACKAGE='Fat-Free Framework',
VERSION='3.6.4-Release';
VERSION='3.6.5-Release';
//@}
//@{ HTTP status codes (RFC 2616)
@@ -207,11 +207,13 @@ final class Base extends Prefab implements ArrayAccess {
}
/**
* cast string variable to php type or constant
* Cast string variable to PHP type or constant
* @param $val
* @return mixed
*/
function cast($val) {
if (preg_match('/^(?:0x[0-9a-f]+|0[0-7]+|0b[01]+)$/i',$val))
return intval($val,0);
if (is_numeric($val))
return $val+0;
$val=trim($val);
@@ -241,13 +243,13 @@ final class Base extends Prefab implements ArrayAccess {
$out='['.
(isset($sub[3])?
$this->compile($sub[3]):
var_export($sub[1],TRUE)).
$this->export($sub[1])).
']';
}
else
$out=function_exists($sub[1])?
$sub[0]:
('['.var_export($sub[1],TRUE).']'.$sub[2]);
('['.$this->export($sub[1]).']'.$sub[2]);
return $out;
},
$expr[2]
@@ -680,7 +682,7 @@ final class Base extends Prefab implements ArrayAccess {
$str='';
foreach (get_object_vars($arg) as $key=>$val)
$str.=($str?',':'').
var_export($key,TRUE).'=>'.
$this->export($key).'=>'.
$this->stringify($val,
array_merge($stack,[$arg]));
return get_class($arg).'::__set_state(['.$str.'])';
@@ -690,11 +692,11 @@ final class Base extends Prefab implements ArrayAccess {
ctype_digit(implode('',array_keys($arg)));
foreach ($arg as $key=>$val)
$str.=($str?',':'').
($num?'':(var_export($key,TRUE).'=>')).
($num?'':($this->export($key).'=>')).
$this->stringify($val,array_merge($stack,[$arg]));
return '['.$str.']';
default:
return var_export($arg,TRUE);
return $this->export($arg);
}
}
@@ -890,8 +892,14 @@ final class Base extends Prefab implements ArrayAccess {
return $expr[0];
if (isset($type)) {
if (isset($this->hive['FORMATS'][$type]))
return $this->call($this->hive['FORMATS'][$type],
[$args[$pos],isset($mod)?$mod:null,isset($prop)?$prop:null]);
return $this->call(
$this->hive['FORMATS'][$type],
[
$args[$pos],
isset($mod)?$mod:null,
isset($prop)?$prop:null
]
);
switch ($type) {
case 'plural':
preg_match_all('/(?<tag>\w+)'.
@@ -964,16 +972,22 @@ final class Base extends Prefab implements ArrayAccess {
$args[$pos]*100,0,$decimal_point,
$thousands_sep).'%';
}
$frac=$args[$pos]-(int)$args[$pos];
return number_format(
$args[$pos],isset($prop)?$prop:2,
$args[$pos],
isset($prop)?
$prop:
$frac?strlen($frac)-2:0,
$decimal_point,$thousands_sep);
case 'date':
$prop='%d %B %Y';
if (empty($mod) || $mod=='short')
$prop='%x';
elseif ($mod=='long')
$prop='%A, %d %B %Y';
elseif ($mod=='full')
$prop='%A, '.$prop;
return strftime($prop,$args[$pos]);
case 'time':
$prop='%r';
if (empty($mod) || $mod=='short')
$prop='%X';
return strftime($prop,$args[$pos]);
@@ -987,6 +1001,15 @@ final class Base extends Prefab implements ArrayAccess {
);
}
/**
* Return string representation of expression
* @return string
* @param $expr mixed
**/
function export($expr) {
return var_export($expr,TRUE);
}
/**
* Assign/auto-detect language
* @return string
@@ -1244,7 +1267,8 @@ final class Base extends Prefab implements ArrayAccess {
if (!is_array($loggable))
$loggable=$this->split($loggable);
foreach ($loggable as $status)
if ($status=='*' || preg_match('/^'.preg_replace('/\D/','\d',$status).'$/',$code)) {
if ($status=='*' ||
preg_match('/^'.preg_replace('/\D/','\d',$status).'$/',$code)) {
error_log($text);
foreach (explode("\n",$trace) as $nexus)
if ($nexus)
@@ -1270,7 +1294,14 @@ final class Base extends Prefab implements ArrayAccess {
'beforeroute,afterroute')===FALSE) &&
!$prior && !$this->hive['CLI'] && !$this->hive['QUIET'])
echo $this->hive['AJAX']?
json_encode(array_diff_key($this->hive['ERROR'],$this->hive['DEBUG']?[]:['trace'=>1])):
json_encode(
array_diff_key(
$this->hive['ERROR'],
$this->hive['DEBUG']?
[]:
['trace'=>1]
)
):
('<!DOCTYPE html>'.$eol.
'<html>'.$eol.
'<head>'.
@@ -1557,7 +1588,7 @@ final class Base extends Prefab implements ArrayAccess {
$cors=$this->hive['CORS'];
header('Access-Control-Allow-Origin: '.$cors['origin']);
header('Access-Control-Allow-Credentials: '.
var_export($cors['credentials'],TRUE));
$this->export($cors['credentials']));
$preflight=
isset($this->hive['HEADERS']['Access-Control-Request-Method']);
}
@@ -1674,12 +1705,15 @@ final class Base extends Prefab implements ArrayAccess {
// URL doesn't match any route
$this->error(404);
elseif (!$this->hive['CLI']) {
// Unhandled HTTP method
header('Allow: '.implode(',',array_unique($allowed)));
if (!preg_grep('/Allow:/',$headers_send=headers_list()))
// Unhandled HTTP method
header('Allow: '.implode(',',array_unique($allowed)));
if ($cors) {
header('Access-Control-Allow-Methods: OPTIONS,'.
implode(',',$allowed));
if ($cors['headers'])
if (!preg_grep('/Access-Control-Allow-Methods:/',$headers_send))
header('Access-Control-Allow-Methods: OPTIONS,'.
implode(',',$allowed));
if ($cors['headers'] &&
!preg_grep('/Access-Control-Allow-Headers:/',$headers_send))
header('Access-Control-Allow-Headers: '.
(is_array($cors['headers'])?
implode(',',$cors['headers']):
@@ -1733,7 +1767,9 @@ final class Base extends Prefab implements ArrayAccess {
}
/**
* Disconnect HTTP client
* Disconnect HTTP client;
* Set FcgidOutputBufferSize to zero if server uses mod_fcgid;
* Disable mod_deflate when rendering text/html output
**/
function abort() {
if (!headers_sent() && session_status()!=PHP_SESSION_ACTIVE)
@@ -1741,9 +1777,10 @@ final class Base extends Prefab implements ArrayAccess {
$out='';
while (ob_get_level())
$out=ob_get_clean().$out;
header('Content-Encoding: none');
header('Content-Length: '.strlen($out));
header('Connection: close');
if (!headers_sent()) {
header('Content-Length: '.strlen($out));
header('Connection: close');
}
session_commit();
echo $out;
flush();
@@ -1771,11 +1808,13 @@ final class Base extends Prefab implements ArrayAccess {
$parts[1]=call_user_func([$container,'get'],$parts[1]);
elseif (is_callable($container))
$parts[1]=call_user_func($container,$parts[1],$args);
elseif (is_string($container) && is_subclass_of($container,'Prefab'))
$parts[1]=call_user_func($container.'::instance')->get($parts[1]);
elseif (is_string($container) &&
is_subclass_of($container,'Prefab'))
$parts[1]=call_user_func($container.'::instance')->
get($parts[1]);
else
user_error(sprintf(self::E_Class,
$this->stringify($container)),
$this->stringify($parts[1])),
E_USER_ERROR);
}
else {
@@ -1916,7 +1955,8 @@ final class Base extends Prefab implements ArrayAccess {
call_user_func_array(
[$this,$cmd[1]],
array_merge([$match['lval']],
str_getcsv($cmd[1]=='config'?$this->cast($match['rval']):
str_getcsv($cmd[1]=='config'?
$this->cast($match['rval']):
$match['rval']))
);
}
@@ -1931,9 +1971,11 @@ final class Base extends Prefab implements ArrayAccess {
$args=array_map(
function($val) {
$val=$this->cast($val);
return is_string($val)
? preg_replace('/\\\\"/','"',$val)
: $val;
if (is_string($val))
$val=strlen($val)?
preg_replace('/\\\\"/','"',$val):
NULL;
return $val;
},
// Mark quoted strings with 0x00 whitespace
str_getcsv(preg_replace(
@@ -2221,6 +2263,7 @@ final class Base extends Prefab implements ArrayAccess {
);
if (!isset($_SERVER['SERVER_NAME']) || $_SERVER['SERVER_NAME']==='')
$_SERVER['SERVER_NAME']=gethostname();
$headers=[];
if ($cli=PHP_SAPI=='cli') {
// Emulate HTTP request
$_SERVER['REQUEST_METHOD']='GET';
@@ -2251,33 +2294,30 @@ final class Base extends Prefab implements ArrayAccess {
$_SERVER['REQUEST_URI']=$req;
parse_str($query,$GLOBALS['_GET']);
}
$headers=[];
if (!$cli) {
if (function_exists('getallheaders')) {
foreach (getallheaders() as $key=>$val) {
$tmp=strtoupper(strtr($key,'-','_'));
// TODO: use ucwords delimiters for php 5.4.32+ & 5.5.16+
$key=strtr(ucwords(strtolower(strtr($key,'-',' '))),' ','-');
$headers[$key]=$val;
if (isset($_SERVER['HTTP_'.$tmp]))
$headers[$key]=&$_SERVER['HTTP_'.$tmp];
}
}
else {
if (isset($_SERVER['CONTENT_LENGTH']))
$headers['Content-Length']=&$_SERVER['CONTENT_LENGTH'];
if (isset($_SERVER['CONTENT_TYPE']))
$headers['Content-Type']=&$_SERVER['CONTENT_TYPE'];
foreach (array_keys($_SERVER) as $key)
if (substr($key,0,5)=='HTTP_')
$headers[strtr(ucwords(strtolower(strtr(
substr($key,5),'_',' '))),' ','-')]=&$_SERVER[$key];
elseif (function_exists('getallheaders')) {
foreach (getallheaders() as $key=>$val) {
$tmp=strtoupper(strtr($key,'-','_'));
// TODO: use ucwords delimiters for php 5.4.32+ & 5.5.16+
$key=strtr(ucwords(strtolower(strtr($key,'-',' '))),' ','-');
$headers[$key]=$val;
if (isset($_SERVER['HTTP_'.$tmp]))
$headers[$key]=&$_SERVER['HTTP_'.$tmp];
}
}
else {
if (isset($_SERVER['CONTENT_LENGTH']))
$headers['Content-Length']=&$_SERVER['CONTENT_LENGTH'];
if (isset($_SERVER['CONTENT_TYPE']))
$headers['Content-Type']=&$_SERVER['CONTENT_TYPE'];
foreach (array_keys($_SERVER) as $key)
if (substr($key,0,5)=='HTTP_')
$headers[strtr(ucwords(strtolower(strtr(
substr($key,5),'_',' '))),' ','-')]=&$_SERVER[$key];
}
if (isset($headers['X-HTTP-Method-Override']))
$_SERVER['REQUEST_METHOD']=$headers['X-HTTP-Method-Override'];
elseif ($_SERVER['REQUEST_METHOD']=='POST' && isset($_POST['_method']))
$_SERVER['REQUEST_METHOD']=$_POST['_method'];
$_SERVER['REQUEST_METHOD']=strtoupper($_POST['_method']);
$scheme=isset($_SERVER['HTTPS']) && $_SERVER['HTTPS']=='on' ||
isset($headers['X-Forwarded-Proto']) &&
$headers['X-Forwarded-Proto']=='https'?'https':'http';
@@ -2493,10 +2533,9 @@ class Cache extends Prefab {
if (!$this->dsn)
return TRUE;
$ndx=$this->prefix.'.'.$key;
$time=microtime(TRUE);
if ($cached=$this->exists($key))
list($time,$ttl)=$cached;
$data=$fw->serialize([$val,$time,$ttl]);
$ttl=$cached[1];
$data=$fw->serialize([$val,microtime(TRUE),$ttl]);
$parts=explode('=',$this->dsn,2);
switch ($parts[0]) {
case 'apc':
@@ -2513,7 +2552,8 @@ class Cache extends Prefab {
case 'xcache':
return xcache_set($ndx,$data,$ttl);
case 'folder':
return $fw->write($parts[1].str_replace(['/','\\'],'',$ndx),$data);
return $fw->write($parts[1].
str_replace(['/','\\'],'',$ndx),$data);
}
return FALSE;
}
@@ -2824,6 +2864,7 @@ class Preview extends View {
'c'=>'$this->c',
'esc'=>'$this->esc',
'raw'=>'$this->raw',
'export'=>'Base::instance()->export',
'alias'=>'Base::instance()->alias',
'format'=>'Base::instance()->format'
];
@@ -2833,7 +2874,7 @@ class Preview extends View {
$interpolation=true;
/**
* enable/disable markup parsing interpolation
* Enable/disable markup parsing interpolation
* mainly used for adding appropriate newlines
* @param $bool bool
*/
@@ -2867,16 +2908,18 @@ class Preview extends View {
$str,$parts)) {
$str=trim($parts[1]);
foreach ($fw->split(trim($parts[2],"\xC2\xA0")) as $func)
$str=is_string($cmd=$this->filter($func))?
$str=((empty($this->filter[$cmd=$func]) &&
function_exists($cmd)) ||
is_string($cmd=$this->filter($func)))?
$cmd.'('.$str.')':
'Base::instance()->'.
'call($this->filter(\''.$func.'\'),['.$str.'])';
'call($this->filter(\''.$func.'\'),['.$str.'])';
}
return $str;
}
/**
* Register or get (a specific one or all) token filters
* Register or get (one specific or all) token filters
* @param string $key
* @param string|closure $func
* @return array|closure|string