- PHP Framework upgrade 3.5.0 -> 3.5.1 (fixes some issues with CREST cURL caching, and SESSION management)
- #138 added "cookie logout" to "logout" menu entry
This commit is contained in:
162
app/lib/base.php
162
app/lib/base.php
@@ -45,7 +45,7 @@ final class Base extends Prefab implements ArrayAccess {
|
||||
//@{ Framework details
|
||||
const
|
||||
PACKAGE='Fat-Free Framework',
|
||||
VERSION='3.5.0-Release';
|
||||
VERSION='3.5.1-Release';
|
||||
//@}
|
||||
|
||||
//@{ HTTP status codes (RFC 2616)
|
||||
@@ -179,8 +179,8 @@ final class Base extends Prefab implements ArrayAccess {
|
||||
}
|
||||
|
||||
/**
|
||||
* assemble url from alias name
|
||||
* @return NULL
|
||||
* Assemble url from alias name
|
||||
* @return string
|
||||
* @param $name string
|
||||
* @param $params array|string
|
||||
**/
|
||||
@@ -215,7 +215,7 @@ final class Base extends Prefab implements ArrayAccess {
|
||||
function compile($str) {
|
||||
$fw=$this;
|
||||
return preg_replace_callback(
|
||||
'/(?<!\w)@(\w(?:[\w\.\[\]\(]|\->|::)*)/',
|
||||
'/(?<!\w)@(\w(?:[\h\w\.\[\]\(]|\->|::)*)/',
|
||||
function($var) use($fw) {
|
||||
return '$'.preg_replace_callback(
|
||||
'/\.(\w+)\(|\.(\w+)|\[((?:[^\[\]]*|(?R))*)\]/',
|
||||
@@ -226,7 +226,7 @@ final class Base extends Prefab implements ArrayAccess {
|
||||
('['.var_export($expr[1],TRUE).']')).'('):
|
||||
('['.var_export(
|
||||
isset($expr[3])?
|
||||
$fw->compile($expr[3]):
|
||||
trim($fw->compile($expr[3])):
|
||||
(ctype_digit($expr[2])?
|
||||
(int)$expr[2]:
|
||||
$expr[2]),TRUE).']');
|
||||
@@ -305,10 +305,11 @@ final class Base extends Prefab implements ArrayAccess {
|
||||
|
||||
/**
|
||||
* Return TRUE if hive key is empty and not cached
|
||||
* @return bool
|
||||
* @param $key string
|
||||
* @param $val mixed
|
||||
* @return bool
|
||||
**/
|
||||
function devoid($key) {
|
||||
function devoid($key,&$val=NULL) {
|
||||
$val=$this->ref($key,FALSE);
|
||||
return empty($val) &&
|
||||
(!Cache::instance()->exists($this->hash($key).'.var',$val) ||
|
||||
@@ -422,8 +423,7 @@ final class Base extends Prefab implements ArrayAccess {
|
||||
// End session
|
||||
session_unset();
|
||||
session_destroy();
|
||||
unset($_COOKIE[session_name()]);
|
||||
header_remove('Set-Cookie');
|
||||
$this->clear('COOKIE.'.session_name());
|
||||
}
|
||||
$this->sync('SESSION');
|
||||
}
|
||||
@@ -679,6 +679,19 @@ final class Base extends Prefab implements ArrayAccess {
|
||||
return $num?($num/abs($num)):0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract values of an associative array whose keys start with the given prefix
|
||||
* @return array
|
||||
* @param $arr array
|
||||
* @param $prefix string
|
||||
**/
|
||||
function extract($arr,$prefix) {
|
||||
$out=array();
|
||||
foreach (preg_grep('/^'.preg_quote($prefix,'/').'/',array_keys($arr)) as $key)
|
||||
$out[substr($key,strlen($prefix))]=$arr[$key];
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert class constants to array
|
||||
* @return array
|
||||
@@ -687,14 +700,7 @@ final class Base extends Prefab implements ArrayAccess {
|
||||
**/
|
||||
function constants($class,$prefix='') {
|
||||
$ref=new ReflectionClass($class);
|
||||
$out=array();
|
||||
foreach (preg_grep('/^'.$prefix.'/',array_keys($ref->getconstants()))
|
||||
as $val) {
|
||||
$out[$key=substr($val,strlen($prefix))]=
|
||||
constant((is_object($class)?get_class($class):$class).'::'.$prefix.$key);
|
||||
}
|
||||
unset($ref);
|
||||
return $out;
|
||||
return $this->extract($ref->getconstants(),$prefix);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -843,9 +849,12 @@ final class Base extends Prefab implements ArrayAccess {
|
||||
return number_format(
|
||||
$args[$pos],0,'',$thousands_sep);
|
||||
case 'currency':
|
||||
if (function_exists('money_format'))
|
||||
$int=$cstm=false;
|
||||
if (isset($prop) && $cstm=!$int=($prop=='int'))
|
||||
$currency_symbol=$prop;
|
||||
if (!$cstm && function_exists('money_format'))
|
||||
return money_format(
|
||||
'%n',$args[$pos]);
|
||||
'%'.($int?'i':'n'),$args[$pos]);
|
||||
$fmt=array(
|
||||
0=>'(nc)',1=>'(n c)',
|
||||
2=>'(nc)',10=>'+nc',
|
||||
@@ -878,7 +887,8 @@ final class Base extends Prefab implements ArrayAccess {
|
||||
$frac_digits,
|
||||
$decimal_point,
|
||||
$thousands_sep),
|
||||
$currency_symbol),
|
||||
$int?$int_curr_symbol
|
||||
:$currency_symbol),
|
||||
$fmt[(int)(
|
||||
(${$pre.'_cs_precedes'}%2).
|
||||
(${$pre.'_sign_posn'}%5).
|
||||
@@ -891,8 +901,8 @@ final class Base extends Prefab implements ArrayAccess {
|
||||
$thousands_sep).'%';
|
||||
case 'decimal':
|
||||
return number_format(
|
||||
$args[$pos],$prop,$decimal_point,
|
||||
$thousands_sep);
|
||||
$args[$pos],isset($prop)?$prop:2,
|
||||
$decimal_point,$thousands_sep);
|
||||
}
|
||||
break;
|
||||
case 'date':
|
||||
@@ -1022,7 +1032,7 @@ final class Base extends Prefab implements ArrayAccess {
|
||||
**/
|
||||
function status($code) {
|
||||
$reason=@constant('self::HTTP_'.$code);
|
||||
if (PHP_SAPI!='cli')
|
||||
if (PHP_SAPI!='cli' && !headers_sent())
|
||||
header($_SERVER['SERVER_PROTOCOL'].' '.$code.' '.$reason);
|
||||
return $reason;
|
||||
}
|
||||
@@ -1089,11 +1099,12 @@ final class Base extends Prefab implements ArrayAccess {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return formatted stack trace
|
||||
* @return string
|
||||
* Return filtered, formatted stack trace
|
||||
* @return string|array
|
||||
* @param $trace array|NULL
|
||||
* @param $format bool
|
||||
**/
|
||||
function trace(array $trace=NULL) {
|
||||
function trace(array $trace=NULL, $format=TRUE) {
|
||||
if (!$trace) {
|
||||
$trace=debug_backtrace(FALSE);
|
||||
$frame=$trace[0];
|
||||
@@ -1111,6 +1122,8 @@ final class Base extends Prefab implements ArrayAccess {
|
||||
'__call|call_user_func)/',$frame['function']));
|
||||
}
|
||||
);
|
||||
if (!$format)
|
||||
return $trace;
|
||||
$out='';
|
||||
$eol="\n";
|
||||
// Analyze stack trace
|
||||
@@ -1369,7 +1382,7 @@ final class Base extends Prefab implements ArrayAccess {
|
||||
$url=$this->rel($this->hive['URI']);
|
||||
$case=$this->hive['CASELESS']?'i':'';
|
||||
preg_match('/^'.
|
||||
preg_replace('/@(\w+\b)/','(?P<\1>[^\/\?]+)',
|
||||
preg_replace('/((\\\{)?@(\w+\b)(?(2)\\\}))/','(?P<\3>[^\/\?]+)',
|
||||
str_replace('\*','([^\?]+)',preg_quote($pattern,'/'))).
|
||||
'\/?(?:\?.*)?$/'.$case.'um',$url,$args);
|
||||
return $args;
|
||||
@@ -1394,7 +1407,7 @@ final class Base extends Prefab implements ArrayAccess {
|
||||
array_multisort($paths,SORT_DESC,$keys,$vals);
|
||||
$this->hive['ROUTES']=array_combine($keys,$vals);
|
||||
// Convert to BASE-relative URL
|
||||
$req=$this->rel($this->hive['URI']);
|
||||
$req=$this->rel(urldecode($this->hive['URI']));
|
||||
if ($cors=(isset($this->hive['HEADERS']['Origin']) &&
|
||||
$this->hive['CORS']['origin'])) {
|
||||
$cors=$this->hive['CORS'];
|
||||
@@ -1428,7 +1441,7 @@ final class Base extends Prefab implements ArrayAccess {
|
||||
if (is_numeric($key) && $key)
|
||||
unset($args[$key]);
|
||||
// Capture values of route pattern tokens
|
||||
$this->hive['PARAMS']=$args=array_map('urldecode',$args);
|
||||
$this->hive['PARAMS']=$args;
|
||||
// Save matching route
|
||||
$this->hive['ALIAS']=$alias;
|
||||
$this->hive['PATTERN']=$pattern;
|
||||
@@ -1437,9 +1450,10 @@ final class Base extends Prefab implements ArrayAccess {
|
||||
implode(',',$cors['expose']):$cors['expose']));
|
||||
if (is_string($handler)) {
|
||||
// Replace route pattern tokens in handler if any
|
||||
$handler=preg_replace_callback('/@(\w+\b)/',
|
||||
$handler=preg_replace_callback('/({)?@(\w+\b)(?(1)})/',
|
||||
function($id) use($args) {
|
||||
return isset($args[$id[1]])?$args[$id[1]]:$id[0];
|
||||
$pid=count($id)>2?2:1;
|
||||
return isset($args[$id[$pid]])?$args[$id[$pid]]:$id[0];
|
||||
},
|
||||
$handler
|
||||
);
|
||||
@@ -1458,7 +1472,7 @@ final class Base extends Prefab implements ArrayAccess {
|
||||
$cached=$cache->exists(
|
||||
$hash=$this->hash($this->hive['VERB'].' '.
|
||||
$this->hive['URI']).'.url',$data);
|
||||
if ($cached && $cached[0]+$ttl>$now) {
|
||||
if ($cached) {
|
||||
if (isset($headers['If-Modified-Since']) &&
|
||||
strtotime($headers['If-Modified-Since'])+
|
||||
$ttl>$now) {
|
||||
@@ -1520,10 +1534,13 @@ final class Base extends Prefab implements ArrayAccess {
|
||||
// Unhandled HTTP method
|
||||
header('Allow: '.implode(',',array_unique($allowed)));
|
||||
if ($cors) {
|
||||
header('Access-Control-Allow-Methods: OPTIONS,'.implode(',',$allowed));
|
||||
header('Access-Control-Allow-Methods: OPTIONS,'.
|
||||
implode(',',$allowed));
|
||||
if ($cors['headers'])
|
||||
header('Access-Control-Allow-Headers: '.(is_array($cors['headers'])?
|
||||
implode(',',$cors['headers']):$cors['headers']));
|
||||
header('Access-Control-Allow-Headers: '.
|
||||
(is_array($cors['headers'])?
|
||||
implode(',',$cors['headers']):
|
||||
$cors['headers']));
|
||||
if ($cors['ttl']>0)
|
||||
header('Access-Control-Max-Age: '.$cors['ttl']);
|
||||
}
|
||||
@@ -1546,28 +1563,26 @@ final class Base extends Prefab implements ArrayAccess {
|
||||
$time=time();
|
||||
$limit=max(0,min($timeout,$max=ini_get('max_execution_time')-1));
|
||||
$out='';
|
||||
$flag=FALSE;
|
||||
// Turn output buffering on
|
||||
ob_start();
|
||||
// Not for the weak of heart
|
||||
while (
|
||||
// No error occurred
|
||||
!$this->hive['ERROR'] &&
|
||||
// Still alive?
|
||||
!connection_aborted() &&
|
||||
// Got time left?
|
||||
(time()-$time+1<$limit) &&
|
||||
// Restart session
|
||||
$flag=@session_start() &&
|
||||
@session_start() &&
|
||||
// CAUTION: Callback will kill host if it never becomes truthy!
|
||||
!($out=$this->call($func,$args))) {
|
||||
session_commit();
|
||||
ob_flush();
|
||||
flush();
|
||||
// Hush down
|
||||
sleep(1);
|
||||
}
|
||||
if ($flag) {
|
||||
session_commit();
|
||||
ob_flush();
|
||||
flush();
|
||||
}
|
||||
ob_flush();
|
||||
flush();
|
||||
return $out;
|
||||
}
|
||||
|
||||
@@ -1577,9 +1592,11 @@ final class Base extends Prefab implements ArrayAccess {
|
||||
function abort() {
|
||||
@session_start();
|
||||
session_commit();
|
||||
header('Content-Length: 0');
|
||||
$out='';
|
||||
while (ob_get_level())
|
||||
ob_end_clean();
|
||||
$out=ob_get_clean().$out;
|
||||
header('Content-Length: '.strlen($out));
|
||||
echo $out;
|
||||
flush();
|
||||
if (function_exists('fastcgi_finish_request'))
|
||||
fastcgi_finish_request();
|
||||
@@ -1826,7 +1843,7 @@ final class Base extends Prefab implements ArrayAccess {
|
||||
$out='';
|
||||
$pre=FALSE;
|
||||
$text=trim($text);
|
||||
if (!preg_match('/^<\?php/',$text)) {
|
||||
if ($text && !preg_match('/^<\?php/',$text)) {
|
||||
$text='<?php '.$text;
|
||||
$pre=TRUE;
|
||||
}
|
||||
@@ -2083,9 +2100,9 @@ final class Base extends Prefab implements ArrayAccess {
|
||||
'CONFIG'=>NULL,
|
||||
'CORS'=>array(
|
||||
'headers'=>'',
|
||||
'origin'=>false,
|
||||
'credentials'=>false,
|
||||
'expose'=>false,
|
||||
'origin'=>FALSE,
|
||||
'credentials'=>FALSE,
|
||||
'expose'=>FALSE,
|
||||
'ttl'=>0),
|
||||
'DEBUG'=>0,
|
||||
'DIACRITICS'=>array(),
|
||||
@@ -2131,7 +2148,7 @@ final class Base extends Prefab implements ArrayAccess {
|
||||
'SERIALIZER'=>extension_loaded($ext='igbinary')?$ext:'php',
|
||||
'TEMP'=>'tmp/',
|
||||
'TIME'=>microtime(TRUE),
|
||||
'TZ'=>(@ini_get('date.timezone'))?:'UTC',
|
||||
'TZ'=>@date_default_timezone_get(),
|
||||
'UI'=>'./',
|
||||
'UNLOAD'=>NULL,
|
||||
'UPLOADS'=>'./',
|
||||
@@ -2500,8 +2517,7 @@ class View extends Prefab {
|
||||
function render($file,$mime='text/html',array $hive=NULL,$ttl=0) {
|
||||
$fw=Base::instance();
|
||||
$cache=Cache::instance();
|
||||
$cached=$cache->exists($hash=$fw->hash($file),$data);
|
||||
if ($cached && $cached[0]+$ttl>microtime(TRUE))
|
||||
if ($cache->exists($hash=$fw->hash($file),$data))
|
||||
return $data;
|
||||
foreach ($fw->split($fw->get('UI').';./') as $dir)
|
||||
if (is_file($this->view=$fw->fixslashes($dir.$file))) {
|
||||
@@ -2516,7 +2532,7 @@ class View extends Prefab {
|
||||
foreach($this->trigger['afterrender'] as $func)
|
||||
$data=$fw->call($func,$data);
|
||||
if ($ttl)
|
||||
$cache->set($hash,$data);
|
||||
$cache->set($hash,$data,$ttl);
|
||||
return $data;
|
||||
}
|
||||
user_error(sprintf(Base::E_Open,$file),E_USER_ERROR);
|
||||
@@ -2539,7 +2555,7 @@ class Preview extends View {
|
||||
//! MIME type
|
||||
$mime,
|
||||
//! token filter
|
||||
$filter = array(
|
||||
$filter=array(
|
||||
'esc'=>'$this->esc',
|
||||
'raw'=>'$this->raw',
|
||||
'alias'=>'\Base::instance()->alias',
|
||||
@@ -2552,15 +2568,24 @@ class Preview extends View {
|
||||
* @param $str string
|
||||
**/
|
||||
function token($str) {
|
||||
return trim(preg_replace('/\{\{(.+?)\}\}/s',trim('\1'),
|
||||
$str=trim(preg_replace('/\{\{(.+?)\}\}/s',trim('\1'),
|
||||
Base::instance()->compile($str)));
|
||||
if (preg_match('/^(.+)(?<!\|)\|((?:\h*\w+(?:\h*[,;]?))+)$/s',
|
||||
$str,$parts)) {
|
||||
$str=trim($parts[1]);
|
||||
foreach (Base::instance()->split($parts[2]) as $func)
|
||||
$str=is_string($cmd=$this->filter($func))?$cmd.'('.$str.')':
|
||||
'\Base::instance()->call('.
|
||||
'$this->filter(\''.$func.'\'),array('.$str.'))';
|
||||
}
|
||||
return $str;
|
||||
}
|
||||
|
||||
/**
|
||||
* register token filter
|
||||
* Register or get (a specific one or all) token filters
|
||||
* @param string $key
|
||||
* @param string $func
|
||||
* @return array
|
||||
* @param string|closure $func
|
||||
* @return array|closure|string
|
||||
*/
|
||||
function filter($key=NULL,$func=NULL) {
|
||||
if (!$key)
|
||||
@@ -2578,19 +2603,15 @@ class Preview extends View {
|
||||
protected function build($node) {
|
||||
$self=$this;
|
||||
return preg_replace_callback(
|
||||
'/\{\-(.+?)\-\}|\{\{(.+?)\}\}(\n+)?/s',
|
||||
'/\{\-(.+?)\-\}|\{\{(.+?)\}\}(\n+)?|(\{\*.*?\*\})/s',
|
||||
function($expr) use($self) {
|
||||
if ($expr[1])
|
||||
return $expr[1];
|
||||
$str=trim($self->token($expr[2]));
|
||||
if (preg_match('/^([^|]+?)\h*\|(\h*\w+(?:\h*[,;]\h*\w+)*)/',
|
||||
$str,$parts)) {
|
||||
$str=$parts[1];
|
||||
foreach (Base::instance()->split($parts[2]) as $func)
|
||||
$str=$self->filter($func).'('.$str.')';
|
||||
}
|
||||
return '<?php echo '.$str.'; ?>'.
|
||||
(isset($expr[3])?$expr[3]."\n":'');
|
||||
return empty($expr[4])?
|
||||
('<?php echo '.$str.'; ?>'.
|
||||
(isset($expr[3])?$expr[3]."\n":'')):
|
||||
'';
|
||||
},
|
||||
preg_replace_callback(
|
||||
'/\{~(.+?)~\}/s',
|
||||
@@ -2631,8 +2652,7 @@ class Preview extends View {
|
||||
if (!is_dir($tmp=$fw->get('TEMP')))
|
||||
mkdir($tmp,Base::MODE,TRUE);
|
||||
foreach ($fw->split($fw->get('UI')) as $dir) {
|
||||
$cached=$cache->exists($hash=$fw->hash($dir.$file),$data);
|
||||
if ($cached && $cached[0]+$ttl>microtime(TRUE))
|
||||
if ($cache->exists($hash=$fw->hash($dir.$file),$data))
|
||||
return $data;
|
||||
if (is_file($view=$fw->fixslashes($dir.$file))) {
|
||||
if (!is_file($this->view=($tmp.
|
||||
@@ -2659,7 +2679,7 @@ class Preview extends View {
|
||||
foreach ($this->trigger['afterrender'] as $func)
|
||||
$data = $fw->call($func, $data);
|
||||
if ($ttl)
|
||||
$cache->set($hash,$data);
|
||||
$cache->set($hash,$data,$ttl);
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user