- PHP7.1 fixes, closed #410

This commit is contained in:
Exodus4D
2017-02-23 20:22:36 +01:00
parent 1e928eab1e
commit bb0a61ad77
37 changed files with 2865 additions and 2706 deletions

View File

@@ -2,7 +2,7 @@
/*
Copyright (c) 2009-2016 F3::Factory/Bong Cosca, All rights reserved.
Copyright (c) 2009-2017 F3::Factory/Bong Cosca, All rights reserved.
This file is part of the Fat-Free Framework (http://fatfreeframework.com).

View File

@@ -2,7 +2,7 @@
/*
Copyright (c) 2009-2016 F3::Factory/Bong Cosca, All rights reserved.
Copyright (c) 2009-2017 F3::Factory/Bong Cosca, All rights reserved.
This file is part of the Fat-Free Framework (http://fatfreeframework.com).

View File

@@ -2,7 +2,7 @@
/*
Copyright (c) 2009-2016 F3::Factory/Bong Cosca, All rights reserved.
Copyright (c) 2009-2017 F3::Factory/Bong Cosca, All rights reserved.
This file is part of the Fat-Free Framework (http://fatfreeframework.com).
@@ -45,7 +45,7 @@ final class Base extends Prefab implements ArrayAccess {
//@{ Framework details
const
PACKAGE='Fat-Free Framework',
VERSION='3.6.0-Release';
VERSION='3.6.1-Dev';
//@}
//@{ HTTP status codes (RFC 2616)
@@ -96,7 +96,7 @@ final class Base extends Prefab implements ArrayAccess {
//! Mapped PHP globals
GLOBALS='GET|POST|COOKIE|REQUEST|SESSION|FILES|SERVER|ENV',
//! HTTP verbs
VERBS='GET|HEAD|POST|PUT|PATCH|DELETE|CONNECT',
VERBS='GET|HEAD|POST|PUT|PATCH|DELETE|CONNECT|OPTIONS',
//! Default directory permissions
MODE=0755,
//! Syntax highlighting stylesheet
@@ -128,6 +128,8 @@ final class Base extends Prefab implements ArrayAccess {
$init,
//! Language lookup sequence
$languages,
//! Mutex locks
$locks=[],
//! Default fallback language
$fallback='en';
@@ -1009,10 +1011,11 @@ final class Base extends Prefab implements ArrayAccess {
$country=@constant('ISO::CC_'.strtolower($parts[1])))
$locale.='-'.$country;
}
$locales[]=$locale;
$locale=str_replace('-','_',$locale);
$locales[]=$locale.'.'.ini_get('default_charset');
$locales[]=$locale;
}
setlocale(LC_ALL,str_replace('-','_',$locales));
setlocale(LC_ALL,$locales);
return implode(',',$this->languages);
}
@@ -1116,7 +1119,7 @@ final class Base extends Prefab implements ArrayAccess {
$time=microtime(TRUE);
header_remove('Pragma');
header('Cache-Control: max-age='.(int)$secs);
header('Expires: '.gmdate('r',$time+$secs));
header('Expires: '.gmdate('r',$time+(int)$secs));
header('Last-Modified: '.gmdate('r'));
}
else {
@@ -1160,7 +1163,7 @@ final class Base extends Prefab implements ArrayAccess {
return isset($headers['Client-IP'])?
$headers['Client-IP']:
(isset($headers['X-Forwarded-For'])?
$headers['X-Forwarded-For']:
explode(',',$headers['X-Forwarded-For'])[0]:
(isset($_SERVER['REMOTE_ADDR'])?
$_SERVER['REMOTE_ADDR']:''));
}
@@ -1182,7 +1185,7 @@ final class Base extends Prefab implements ArrayAccess {
$trace=array_filter(
$trace,
function($frame) use($debug) {
return $debug && isset($frame['file']) &&
return isset($frame['file']) &&
($frame['file']!=__FILE__ || $debug>1) &&
(empty($frame['function']) ||
!preg_match('/^(?:(?:trigger|user)_error|'.
@@ -1372,7 +1375,7 @@ final class Base extends Prefab implements ArrayAccess {
if (($handler=$this->hive['ONREROUTE']) &&
$this->call($handler,[$url,$permanent])!==FALSE)
return;
if ($url[0]=='/') {
if ($url[0]=='/' && (empty($url[1]) || $url[1]!='/')) {
$port=$this->hive['PORT'];
$port=in_array($port,[80,443])?'':':'.$port;
$url=$this->hive['SCHEME'].'://'.
@@ -1383,7 +1386,7 @@ final class Base extends Prefab implements ArrayAccess {
$this->status($permanent?301:302);
die;
}
$this->mock('GET '.$url);
$this->mock('GET '.$url.' [cli]');
}
/**
@@ -1470,7 +1473,7 @@ final class Base extends Prefab implements ArrayAccess {
'(?P<\3>[^\/\?]+)',
$wild).'\/?$/'.$case.'um',$url,$args);
foreach (array_keys($args) as $key) {
if (preg_match('/_\d+/',$key)) {
if (preg_match('/^_\d+$/',$key)) {
if (empty($args['*']))
$args['*']=$args[$key];
else {
@@ -1509,7 +1512,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(urldecode($this->hive['PATH']));
$req=urldecode($this->hive['PATH']);
if ($cors=(isset($this->hive['HEADERS']['Origin']) &&
$this->hive['CORS']['origin'])) {
$cors=$this->hive['CORS'];
@@ -1529,8 +1532,7 @@ final class Base extends Prefab implements ArrayAccess {
$route=$routes[$ptr];
if (!$route)
continue;
if ($this->hive['VERB']!='OPTIONS' &&
isset($route[$this->hive['VERB']])) {
if (isset($route[$this->hive['VERB']])) {
if ($this->hive['VERB']=='GET' &&
preg_match('/.+\/$/',$this->hive['PATH']))
$this->reroute(substr($this->hive['PATH'],0,-1).
@@ -1622,7 +1624,8 @@ final class Base extends Prefab implements ArrayAccess {
else
echo $body;
}
return $result;
if ($result || $this->hive['VERB']!='OPTIONS')
return $result;
}
$allowed=array_merge($allowed,array_keys($route));
}
@@ -1923,9 +1926,11 @@ final class Base extends Prefab implements ArrayAccess {
@unlink($lock);
while (!($handle=@fopen($lock,'x')) && !connection_aborted())
usleep(mt_rand(0,100));
$this->locks[$id]=$lock;
$out=$this->call($func,$args);
fclose($handle);
@unlink($lock);
unset($this->locks[$id]);
return $out;
}
@@ -2025,6 +2030,8 @@ final class Base extends Prefab implements ArrayAccess {
if (!($error=error_get_last()) &&
session_status()==PHP_SESSION_ACTIVE)
session_commit();
foreach ($this->locks as $lock)
@unlink($lock);
$handler=$this->hive['UNLOAD'];
if ((!$handler || $this->call($handler,$this)===FALSE) &&
$error && in_array($error['type'],
@@ -2236,8 +2243,10 @@ final class Base extends Prefab implements ArrayAccess {
'httponly'=>TRUE
]
);
$port=0;
if (isset($_SERVER['SERVER_PORT']))
$port=80;
if (isset($headers['X-Forwarded-Port']))
$port=$headers['X-Forwarded-Port'];
elseif (isset($_SERVER['SERVER_PORT']))
$port=$_SERVER['SERVER_PORT'];
// Default configuration
$this->hive+=[
@@ -2295,8 +2304,8 @@ final class Base extends Prefab implements ArrayAccess {
'QUIET'=>FALSE,
'RAW'=>FALSE,
'REALM'=>$scheme.'://'.$_SERVER['SERVER_NAME'].
($port && $port!=80 && $port!=443?
(':'.$port):'').$_SERVER['REQUEST_URI'],
($port && !in_array($port,[80,443])?(':'.$port):'').
$_SERVER['REQUEST_URI'],
'RESPONSE'=>'',
'ROOT'=>$_SERVER['DOCUMENT_ROOT'],
'ROUTES'=>[],
@@ -2375,6 +2384,9 @@ class Cache extends Prefab {
case 'memcache':
$raw=memcache_get($this->ref,$ndx);
break;
case 'memcached':
$raw=$this->ref->get($ndx);
break;
case 'wincache':
$raw=wincache_ucache_get($ndx);
break;
@@ -2420,6 +2432,8 @@ class Cache extends Prefab {
return $this->ref->set($ndx,$data, $ttl ? ['ex'=>$ttl] : []);
case 'memcache':
return memcache_set($this->ref,$ndx,$data,0,$ttl);
case 'memcached':
return $this->ref->set($ndx,$data,$ttl);
case 'wincache':
return wincache_ucache_set($ndx,$data,$ttl);
case 'xcache':
@@ -2457,6 +2471,8 @@ class Cache extends Prefab {
return $this->ref->del($ndx);
case 'memcache':
return memcache_delete($this->ref,$ndx);
case 'memcached':
return $this->ref->delete($ndx);
case 'wincache':
return wincache_ucache_delete($ndx);
case 'xcache':
@@ -2471,12 +2487,11 @@ class Cache extends Prefab {
* Clear contents of cache backend
* @return bool
* @param $suffix string
* @param $lifetime int
**/
function reset($suffix=NULL,$lifetime=0) {
function reset($suffix=NULL) {
if (!$this->dsn)
return TRUE;
$regex='/'.preg_quote($this->prefix.'.','/').'.+?'.
$regex='/'.preg_quote($this->prefix.'.','/').'.+'.
preg_quote($suffix,'/').'/';
$parts=explode('=',$this->dsn,2);
switch ($parts[0]) {
@@ -2489,19 +2504,15 @@ class Cache extends Prefab {
$mtkey=array_key_exists('mtime',$info['cache_list'][0])?
'mtime':'modification_time';
foreach ($info['cache_list'] as $item)
if (preg_match($regex,$item[$key]) &&
$item[$mtkey]+$lifetime<time())
if (preg_match($regex,$item[$key]))
apc_delete($item[$key]);
}
return TRUE;
case 'redis':
$fw=Base::instance();
$keys=$this->ref->keys($this->prefix.'.*'.$suffix);
foreach($keys as $key) {
$val=$fw->unserialize($this->ref->get($key));
if ($val[1]+$lifetime<time())
$this->ref->del($key);
}
foreach($keys as $key)
$this->ref->del($key);
return TRUE;
case 'memcache':
$fw=Base::instance();
@@ -2513,17 +2524,20 @@ class Cache extends Prefab {
$this->ref,'cachedump',$id) as $data)
if (is_array($data))
foreach (array_keys($data) as $key)
if (preg_match($regex,$key) &&
($val=$fw->unserialize(memcache_get($this->ref,$key))) &&
$val[1]+$lifetime<time())
if (preg_match($regex,$key))
memcache_delete($this->ref,$key);
return TRUE;
case 'memcached':
$fw=Base::instance();
foreach ($this->ref->getallkeys() as $key)
if (preg_match($regex,$key))
$this->ref->delete($key);
return TRUE;
case 'wincache':
$info=wincache_ucache_info();
foreach ($info['ucache_entries'] as $item)
if (preg_match($regex,$item['key_name']) &&
$item['use_time']+$lifetime<time())
wincache_ucache_delete($item['key_name']);
if (preg_match($regex,$item['key_name']))
wincache_ucache_delete($item['key_name']);
return TRUE;
case 'xcache':
xcache_unset_by_prefix($this->prefix.'.');
@@ -2531,8 +2545,7 @@ class Cache extends Prefab {
case 'folder':
if ($glob=@glob($parts[1].'*'))
foreach ($glob as $file)
if (preg_match($regex,basename($file)) &&
filemtime($file)+$lifetime<time())
if (preg_match($regex,basename($file)))
@unlink($file);
return TRUE;
}
@@ -2565,6 +2578,14 @@ class Cache extends Prefab {
else
memcache_add_server($this->ref,$host,$port);
}
elseif (preg_match('/^memcached=(.+)/',$dsn,$parts) &&
extension_loaded('memcached'))
foreach ($fw->split($parts[1]) as $server) {
list($host,$port)=explode(':',$server)+[1=>11211];
if (empty($this->ref))
$this->ref=new Memcached();
$this->ref->addServer($host,$port);
}
if (empty($this->ref) && !preg_match('/^folder\h*=/',$dsn))
$dsn=($grep=preg_grep('/^(apc|wincache|xcache)/',
array_map('strtolower',get_loaded_extensions())))?
@@ -2631,28 +2652,50 @@ class View extends Prefab {
);
}
/**
* Send resource to browser using HTTP/2 server push
* @return string
* @param $file string
**/
function push($file) {
$fw=Base::instance();
$hive=$fw->hive();
if ($hive['SCHEME']=='https') {
$base='';
if (!preg_match('/^[.\/]/',$file))
$base=$hive['BASE'].'/';
if (preg_match('/'.$key.'$/',$file))
header('Link: '.'<'.$base.$file.'>; '.'rel=preload',FALSE);
}
return $file;
}
/**
* Create sandbox for template execution
* @return string
* @param $hive array
* @param $mime string
**/
protected function sandbox(array $hive=NULL) {
$this->level++;
protected function sandbox(array $hive=NULL,$mime=NULL) {
$fw=Base::instance();
$implicit=FALSE;
if (is_null($hive)) {
$implicit=TRUE;
$hive=$fw->hive();
}
if ($this->level<2 || $implicit) {
if ($this->level<1 || $implicit) {
if (!$hive['CLI'] && !headers_sent() &&
!preg_grep ('/^Content-Type:/',headers_list()))
header('Content-Type: '.($mime?:'text/html').'; '.
'charset='.$fw->get('ENCODING'));
if ($fw->get('ESCAPE'))
$hive=$this->esc($hive);
if (isset($hive['ALIASES']))
$hive['ALIASES']=$fw->build($hive['ALIASES']);
}
unset($fw,$implicit);
extract($hive);
unset($hive);
unset($fw,$hive,$implicit,$mime);
$this->level++;
ob_start();
require($this->view);
$this->level--;
@@ -2667,21 +2710,18 @@ class View extends Prefab {
* @param $hive array
* @param $ttl int
**/
function render($file,$mime='text/html',array $hive=NULL,$ttl=0) {
function render($file,$mime=NULL,array $hive=NULL,$ttl=0) {
$fw=Base::instance();
$cache=Cache::instance();
if ($cache->exists($hash=$fw->hash($file),$data))
return $data;
foreach ($fw->split($fw->get('UI').';./') as $dir)
foreach ($fw->split($fw->get('UI')) as $dir)
if (is_file($this->view=$fw->fixslashes($dir.$file))) {
if (isset($_COOKIE[session_name()]) &&
!headers_sent() && session_status()!=PHP_SESSION_ACTIVE)
session_start();
$fw->sync('SESSION');
if ($mime && !$fw->get('CLI') && !headers_sent())
header('Content-Type: '.$mime.'; '.
'charset='.$fw->get('ENCODING'));
$data=$this->sandbox($hive);
$data=$this->sandbox($hive,$mime);
if(isset($this->trigger['afterrender']))
foreach($this->trigger['afterrender'] as $func)
$data=$fw->call($func,$data);
@@ -2706,12 +2746,11 @@ class View extends Prefab {
class Preview extends View {
protected
//! MIME type
$mime,
//! token filter
$filter=[
'esc'=>'$this->esc',
'raw'=>'$this->raw',
'push'=>'$this->push',
'alias'=>'\Base::instance()->alias',
'format'=>'\Base::instance()->format'
];
@@ -2804,10 +2843,6 @@ class Preview extends View {
function render($file,$mime=NULL,array $hive=NULL,$ttl=0) {
$fw=Base::instance();
$cache=Cache::instance();
if ($mime)
$this->mime=$mime;
elseif (!$this->mime)
$this->mime='text/html';
if (!is_dir($tmp=$fw->get('TEMP')))
mkdir($tmp,Base::MODE,TRUE);
foreach ($fw->split($fw->get('UI')) as $dir) {
@@ -2830,10 +2865,7 @@ class Preview extends View {
!headers_sent() && session_status()!=PHP_SESSION_ACTIVE)
session_start();
$fw->sync('SESSION');
if (!$fw->get('CLI') && !headers_sent())
header('Content-Type: '.$this->mime.'; '.
'charset='.$fw->get('ENCODING'));
$data=$this->sandbox($hive);
$data=$this->sandbox($hive,$mime);
if(isset($this->trigger['afterrender']))
foreach ($this->trigger['afterrender'] as $func)
$data = $fw->call($func, $data);

View File

@@ -2,7 +2,7 @@
/*
Copyright (c) 2009-2016 F3::Factory/Bong Cosca, All rights reserved.
Copyright (c) 2009-2017 F3::Factory/Bong Cosca, All rights reserved.
This file is part of the Fat-Free Framework (http://fatfreeframework.com).

View File

@@ -1,9 +1,7 @@
<?php
/**
* Lightweight password hashing library
*
* Copyright (c) 2009-2016 F3::Factory/Bong Cosca, All rights reserved.
* Copyright (c) 2009-2017 F3::Factory/Bong Cosca, All rights reserved.
*
* This file is part of the Fat-Free Framework (http://fatfreeframework.com).
*
@@ -19,9 +17,12 @@
* You should have received a copy of the GNU General Public License along
* with Fat-Free Framework. If not, see <http://www.gnu.org/licenses/>.
*
* @deprecated use http://php.net/manual/en/ref.password.php instead (PHP 5.5+ only)
**/
/**
* Lightweight password hashing library (PHP 5.5+ only)
* @deprecated Use http://php.net/manual/en/ref.password.php instead
**/
class Bcrypt extends Prefab {
//@{ Error messages
@@ -52,8 +53,6 @@ class Bcrypt extends Prefab {
else {
$raw=16;
$iv='';
if (extension_loaded('mcrypt'))
$iv=mcrypt_create_iv($raw,MCRYPT_DEV_URANDOM);
if (!$iv && extension_loaded('openssl'))
$iv=openssl_random_pseudo_bytes($raw);
if (!$iv)

View File

@@ -2,7 +2,7 @@
/*
Copyright (c) 2009-2016 F3::Factory/Bong Cosca, All rights reserved.
Copyright (c) 2009-2017 F3::Factory/Bong Cosca, All rights reserved.
This file is part of the Fat-Free Framework (http://fatfreeframework.com).

12
app/lib/composer.json Normal file
View File

@@ -0,0 +1,12 @@
{
"name": "bcosca/fatfree-core",
"description": "A powerful yet easy-to-use PHP micro-framework designed to help you build dynamic and robust Web applications - fast!",
"homepage": "http://fatfreeframework.com/",
"license": "GPL-3.0",
"require": {
"php": ">=5.4"
},
"autoload": {
"classmap": ["."]
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -2,7 +2,7 @@
/*
Copyright (c) 2009-2016 F3::Factory/Bong Cosca, All rights reserved.
Copyright (c) 2009-2017 F3::Factory/Bong Cosca, All rights reserved.
This file is part of the Fat-Free Framework (http://fatfreeframework.com).
@@ -70,9 +70,10 @@ abstract class Cursor extends \Magic implements \IteratorAggregate {
* Count records that match criteria
* @return int
* @param $filter array
* @param $options array
* @param $ttl int
**/
abstract function count($filter=NULL,$ttl=0);
abstract function count($filter=NULL,array $options=NULL,$ttl=0);
/**
* Insert new record
@@ -145,7 +146,7 @@ abstract class Cursor extends \Magic implements \IteratorAggregate {
**/
function paginate(
$pos=0,$size=10,$filter=NULL,array $options=NULL,$ttl=0) {
$total=$this->count($filter,$ttl);
$total=$this->count($filter,$options,$ttl);
$count=ceil($total/$size);
$pos=max(0,min($pos,$count-1));
return [

View File

@@ -2,7 +2,7 @@
/*
Copyright (c) 2009-2016 F3::Factory/Bong Cosca, All rights reserved.
Copyright (c) 2009-2017 F3::Factory/Bong Cosca, All rights reserved.
This file is part of the Fat-Free Framework (http://fatfreeframework.com).

View File

@@ -2,7 +2,7 @@
/*
Copyright (c) 2009-2016 F3::Factory/Bong Cosca, All rights reserved.
Copyright (c) 2009-2017 F3::Factory/Bong Cosca, All rights reserved.
This file is part of the Fat-Free Framework (http://fatfreeframework.com).
@@ -286,11 +286,12 @@ class Mapper extends \DB\Cursor {
* Count records that match criteria
* @return int
* @param $filter array
* @param $options array
* @param $ttl int
**/
function count($filter=NULL,$ttl=0) {
function count($filter=NULL,array $options=NULL,$ttl=0) {
$now=microtime(TRUE);
$out=count($this->find($filter,NULL,$ttl,FALSE));
$out=count($this->find($filter,$options,$ttl,FALSE));
$this->db->jot('('.sprintf('%.1f',1e3*(microtime(TRUE)-$now)).'ms) '.
$this->file.' [count] '.($filter?json_encode($filter):''));
return $out;

View File

@@ -2,7 +2,7 @@
/*
Copyright (c) 2009-2016 F3::Factory/Bong Cosca, All rights reserved.
Copyright (c) 2009-2017 F3::Factory/Bong Cosca, All rights reserved.
This file is part of the Fat-Free Framework (http://fatfreeframework.com).
@@ -59,13 +59,13 @@ class Session extends Mapper {
/**
* Return session data in serialized format
* @return string|FALSE
* @return string
* @param $id string
**/
function read($id) {
$this->load(['@session_id=?',$this->sid=$id]);
if ($this->dry())
return FALSE;
return '';
if ($this->get('ip')!=$this->_ip || $this->get('agent')!=$this->_agent) {
$fw=\Base::instance();
if (!isset($this->onsuspect) ||

View File

@@ -2,7 +2,7 @@
/*
Copyright (c) 2009-2016 F3::Factory/Bong Cosca, All rights reserved.
Copyright (c) 2009-2017 F3::Factory/Bong Cosca, All rights reserved.
This file is part of the Fat-Free Framework (http://fatfreeframework.com).
@@ -37,6 +37,8 @@ class Mongo {
$dsn,
//! MongoDB object
$db,
//! Legacy flag
$legacy,
//! MongoDB log
$log;
@@ -63,7 +65,7 @@ class Mongo {
**/
function log($flag=TRUE) {
if ($flag) {
$cursor=$this->selectcollection('system.profile')->find();
$cursor=$this->db->selectcollection('system.profile')->find();
foreach (iterator_to_array($cursor) as $frame)
if (!preg_match('/\.system\..+$/',$frame['ns']))
$this->log.=date('r',$frame['ts']->sec).' ('.
@@ -76,7 +78,10 @@ class Mongo {
PHP_EOL;
} else {
$this->log=FALSE;
$this->setprofilinglevel(-1);
if ($this->legacy)
$this->db->setprofilinglevel(-1);
else
$this->db->command(['profile'=>-1]);
}
return $this->log;
}
@@ -87,8 +92,12 @@ class Mongo {
**/
function drop() {
$out=$this->db->drop();
if ($this->log!==FALSE)
$this->setprofilinglevel(2);
if ($this->log!==FALSE) {
if ($this->legacy)
$this->db->setprofilinglevel(2);
else
$this->db->command(['profile'=>2]);
}
return $out;
}
@@ -102,6 +111,14 @@ class Mongo {
return call_user_func_array([$this->db,$func],$args);
}
/**
* Return TRUE if legacy driver is loaded
* @return bool
**/
function legacy() {
return $this->legacy;
}
//! Prohibit cloning
private function __clone() {
}
@@ -114,9 +131,14 @@ class Mongo {
**/
function __construct($dsn,$dbname,array $options=NULL) {
$this->uuid=\Base::instance()->hash($this->dsn=$dsn);
$class=class_exists('\MongoClient')?'\MongoClient':'\Mongo';
$this->db=new \MongoDB(new $class($dsn,$options?:[]),$dbname);
$this->setprofilinglevel(2);
if ($this->legacy=class_exists('\MongoClient')) {
$this->db=new \MongoDB(new \MongoClient($dsn,$options?:[]),$dbname);
$this->db->setprofilinglevel(2);
}
else {
$this->db=(new \MongoDB\Client($dsn,$options?:[]))->$dbname;
$this->db->command(['profile'=>2]);
}
}
}

View File

@@ -2,7 +2,7 @@
/*
Copyright (c) 2009-2016 F3::Factory/Bong Cosca, All rights reserved.
Copyright (c) 2009-2017 F3::Factory/Bong Cosca, All rights reserved.
This file is part of the Fat-Free Framework (http://fatfreeframework.com).
@@ -28,6 +28,8 @@ class Mapper extends \DB\Cursor {
protected
//! MongoDB wrapper
$db,
//! Legacy flag
$legacy,
//! Mongo collection
$collection,
//! Mongo document
@@ -155,16 +157,26 @@ class Mapper extends \DB\Cursor {
$filter=$filter?:[];
$collection=$this->collection;
}
$this->cursor=$collection->find($filter,$fields?:[]);
if ($options['order'])
$this->cursor=$this->cursor->sort($options['order']);
if ($options['limit'])
$this->cursor=$this->cursor->limit($options['limit']);
if ($options['offset'])
$this->cursor=$this->cursor->skip($options['offset']);
$result=[];
while ($this->cursor->hasnext())
$result[]=$this->cursor->getnext();
if ($this->legacy) {
$this->cursor=$collection->find($filter,$fields?:[]);
if ($options['order'])
$this->cursor=$this->cursor->sort($options['order']);
if ($options['limit'])
$this->cursor=$this->cursor->limit($options['limit']);
if ($options['offset'])
$this->cursor=$this->cursor->skip($options['offset']);
$result=[];
while ($this->cursor->hasnext())
$result[]=$this->cursor->getnext();
}
else {
$this->cursor=$collection->find($filter,[
'sort'=>$options['order'],
'limit'=>$options['limit'],
'skip'=>$options['offset']
]);
$result=$this->cursor->toarray();
}
if ($options['group'])
$tmp->drop();
if ($fw->get('CACHE') && $ttl)
@@ -200,9 +212,10 @@ class Mapper extends \DB\Cursor {
* Count records that match criteria
* @return int
* @param $filter array
* @param $options array
* @param $ttl int
**/
function count($filter=NULL,$ttl=0) {
function count($filter=NULL,array $options=NULL,$ttl=0) {
$fw=\Base::instance();
$cache=\Cache::instance();
if (!($cached=$cache->exists($hash=$fw->hash($fw->stringify(
@@ -240,8 +253,14 @@ class Mapper extends \DB\Cursor {
\Base::instance()->call($this->trigger['beforeinsert'],
[$this,['_id'=>$this->document['_id']]])===FALSE)
return $this->document;
$this->collection->insert($this->document);
$pkey=['_id'=>$this->document['_id']];
if ($this->legacy) {
$this->collection->insert($this->document);
$pkey=['_id'=>$this->document['_id']];
}
else {
$result=$this->collection->insertone($this->document);
$pkey=['_id'=>$result->getinsertedid()];
}
if (isset($this->trigger['afterinsert']))
\Base::instance()->call($this->trigger['afterinsert'],
[$this,$pkey]);
@@ -259,8 +278,11 @@ class Mapper extends \DB\Cursor {
\Base::instance()->call($this->trigger['beforeupdate'],
[$this,$pkey])===FALSE)
return $this->document;
$this->collection->update(
$pkey,$this->document,['upsert'=>TRUE]);
$upsert=['upsert'=>TRUE];
if ($this->legacy)
$this->collection->update($pkey,$this->document,$upsert);
else
$this->collection->replaceone($pkey,$this->document,$upsert);
if (isset($this->trigger['afterupdate']))
\Base::instance()->call($this->trigger['afterupdate'],
[$this,$pkey]);
@@ -273,15 +295,19 @@ class Mapper extends \DB\Cursor {
* @param $filter array
**/
function erase($filter=NULL) {
if ($filter)
return $this->collection->remove($filter);
if ($filter) {
return $this->legacy?
$this->collection->remove($filter):
$this->collection->deletemany($filter);
}
$pkey=['_id'=>$this->document['_id']];
if (isset($this->trigger['beforeerase']) &&
\Base::instance()->call($this->trigger['beforeerase'],
[$this,$pkey])===FALSE)
return FALSE;
$result=$this->collection->
remove(['_id'=>$this->document['_id']]);
$result=$this->legacy?
$this->collection->remove(['_id'=>$this->document['_id']]):
$this->collection->deleteone(['_id'=>$this->document['_id']]);
parent::erase();
if (isset($this->trigger['aftererase']))
\Base::instance()->call($this->trigger['aftererase'],
@@ -357,6 +383,7 @@ class Mapper extends \DB\Cursor {
**/
function __construct(\DB\Mongo $db,$collection,$fields=NULL) {
$this->db=$db;
$this->legacy=$db->legacy();
$this->collection=$db->selectcollection($collection);
$this->fields=$fields;
$this->reset();

View File

@@ -2,7 +2,7 @@
/*
Copyright (c) 2009-2016 F3::Factory/Bong Cosca, All rights reserved.
Copyright (c) 2009-2017 F3::Factory/Bong Cosca, All rights reserved.
This file is part of the Fat-Free Framework (http://fatfreeframework.com).
@@ -59,13 +59,13 @@ class Session extends Mapper {
/**
* Return session data in serialized format
* @return string|FALSE
* @return string
* @param $id string
**/
function read($id) {
$this->load(['session_id'=>$this->sid=$id]);
if ($this->dry())
return FALSE;
return '';
if ($this->get('ip')!=$this->_ip || $this->get('agent')!=$this->_agent) {
$fw=\Base::instance();
if (!isset($this->onsuspect) ||

View File

@@ -2,7 +2,7 @@
/*
Copyright (c) 2009-2016 F3::Factory/Bong Cosca, All rights reserved.
Copyright (c) 2009-2017 F3::Factory/Bong Cosca, All rights reserved.
This file is part of the Fat-Free Framework (http://fatfreeframework.com).
@@ -113,16 +113,16 @@ class SQL {
/**
* Cast value to PHP type
* @return scalar
* @return mixed
* @param $type string
* @param $val scalar
* @param $val mixed
**/
function value($type,$val) {
switch ($type) {
case self::PARAM_FLOAT:
return (float)(is_string($val)
? str_replace(',','.',preg_replace('/([.,])(?!\d+$)/','',$val))
: $val);
if (!is_string($val))
$val=str_replace(',','.',$val);
return $val;
case \PDO::PARAM_NULL:
return (unset)$val;
case \PDO::PARAM_INT:

View File

@@ -2,7 +2,7 @@
/*
Copyright (c) 2009-2016 F3::Factory/Bong Cosca, All rights reserved.
Copyright (c) 2009-2017 F3::Factory/Bong Cosca, All rights reserved.
This file is part of the Fat-Free Framework (http://fatfreeframework.com).
@@ -226,7 +226,8 @@ class Mapper extends \DB\Cursor {
return preg_replace_callback(
'/\b(\w+)\h*(HAVING.+|$)/i',
function($parts) use($db) {
return $db->quotekey($parts[1]).(isset($parts[2])?(' '.$parts[2]):'');
return $db->quotekey($parts[1]).
(isset($parts[2])?(' '.$parts[2]):'');
},
$str
);
@@ -324,24 +325,18 @@ class Mapper extends \DB\Cursor {
* Count records that match criteria
* @return int
* @param $filter string|array
* @param $options array
* @param $ttl int|array
**/
function count($filter=NULL,$ttl=0) {
$sql='SELECT COUNT(*) AS '.
$this->db->quotekey('rows').' FROM '.$this->table;
$args=[];
if ($filter) {
if (is_array($filter)) {
$args=isset($filter[1]) && is_array($filter[1])?
$filter[1]:
array_slice($filter,1,NULL,TRUE);
$args=is_array($args)?$args:[1=>$args];
list($filter)=$filter;
}
$sql.=' WHERE '.$filter;
}
$result=$this->db->exec($sql,$args,$ttl);
return $result[0]['rows'];
function count($filter=NULL,array $options=NULL,$ttl=0) {
$expr='COUNT(*)';
$field='rows';
$this->adhoc[$field]=['expr'=>$expr,'value'=>NULL];
$result=$this->select($expr.' AS '.$this->db->quotekey($field),
$filter,$options,$ttl);
$out=$result[0]->adhoc[$field]['value'];
unset($this->adhoc[$field]);
return $out;
}
/**
@@ -473,10 +468,10 @@ class Mapper extends \DB\Cursor {
if ($pairs) {
$sql='UPDATE '.$this->table.' SET '.$pairs.$filter;
$this->db->exec($sql,$args);
if (isset($this->trigger['afterupdate']))
\Base::instance()->call($this->trigger['afterupdate'],
[$this,$pkeys]);
}
if (isset($this->trigger['afterupdate']))
\Base::instance()->call($this->trigger['afterupdate'],
[$this,$pkeys]);
// reset changed flag after calling afterupdate
foreach ($this->fields as $key=>&$field) {
$field['changed']=FALSE;
@@ -492,7 +487,7 @@ class Mapper extends \DB\Cursor {
* @param $filter string|array
**/
function erase($filter=NULL) {
if ($filter) {
if (isset($filter)) {
$args=[];
if (is_array($filter)) {
$args=isset($filter[1]) && is_array($filter[1])?
@@ -502,7 +497,7 @@ class Mapper extends \DB\Cursor {
list($filter)=$filter;
}
return $this->db->
exec('DELETE FROM '.$this->table.' WHERE '.$filter.';',$args);
exec('DELETE FROM '.$this->table.($filter?' WHERE '.$filter:'').';',$args);
}
$args=[];
$ctr=0;

View File

@@ -2,7 +2,7 @@
/*
Copyright (c) 2009-2016 F3::Factory/Bong Cosca, All rights reserved.
Copyright (c) 2009-2017 F3::Factory/Bong Cosca, All rights reserved.
This file is part of the Fat-Free Framework (http://fatfreeframework.com).
@@ -59,13 +59,13 @@ class Session extends Mapper {
/**
* Return session data in serialized format
* @return string|FALSE
* @return string
* @param $id string
**/
function read($id) {
$this->load(['session_id=?',$this->sid=$id]);
if ($this->dry())
return FALSE;
return '';
if ($this->get('ip')!=$this->_ip || $this->get('agent')!=$this->_agent) {
$fw=\Base::instance();
if (!isset($this->onsuspect) ||

View File

@@ -2,7 +2,7 @@
/*
Copyright (c) 2009-2016 F3::Factory/Bong Cosca, All rights reserved.
Copyright (c) 2009-2017 F3::Factory/Bong Cosca, All rights reserved.
This file is part of the Fat-Free Framework (http://fatfreeframework.com).

View File

@@ -2,7 +2,7 @@
/*
Copyright (c) 2009-2016 F3::Factory/Bong Cosca, All rights reserved.
Copyright (c) 2009-2017 F3::Factory/Bong Cosca, All rights reserved.
This file is part of the Fat-Free Framework (http://fatfreeframework.com).

View File

@@ -2,7 +2,7 @@
/*
Copyright (c) 2009-2016 F3::Factory/Bong Cosca, All rights reserved.
Copyright (c) 2009-2017 F3::Factory/Bong Cosca, All rights reserved.
This file is part of the Fat-Free Framework (http://fatfreeframework.com).

View File

@@ -2,7 +2,7 @@
/*
Copyright (c) 2009-2016 F3::Factory/Bong Cosca, All rights reserved.
Copyright (c) 2009-2017 F3::Factory/Bong Cosca, All rights reserved.
This file is part of the Fat-Free Framework (http://fatfreeframework.com).

View File

@@ -2,7 +2,7 @@
/*
Copyright (c) 2009-2016 F3::Factory/Bong Cosca, All rights reserved.
Copyright (c) 2009-2017 F3::Factory/Bong Cosca, All rights reserved.
This file is part of the Fat-Free Framework (http://fatfreeframework.com).

View File

@@ -2,7 +2,7 @@
/*
Copyright (c) 2009-2016 F3::Factory/Bong Cosca, All rights reserved.
Copyright (c) 2009-2017 F3::Factory/Bong Cosca, All rights reserved.
This file is part of the Fat-Free Framework (http://fatfreeframework.com).

View File

@@ -2,7 +2,7 @@
/*
Copyright (c) 2009-2016 F3::Factory/Bong Cosca, All rights reserved.
Copyright (c) 2009-2017 F3::Factory/Bong Cosca, All rights reserved.
This file is part of the Fat-Free Framework (http://fatfreeframework.com).
@@ -58,13 +58,13 @@ class Session {
/**
* Return session data in serialized format
* @return string|FALSE
* @return string
* @param $id string
**/
function read($id) {
$this->sid=$id;
if (!$data=$this->_cache->get($id.'.@'))
return FALSE;
return '';
if ($data['ip']!=$this->_ip || $data['agent']!=$this->_agent) {
$fw=Base::instance();
if (!isset($this->onsuspect) ||

View File

@@ -2,7 +2,7 @@
/*
Copyright (c) 2009-2016 F3::Factory/Bong Cosca, All rights reserved.
Copyright (c) 2009-2017 F3::Factory/Bong Cosca, All rights reserved.
This file is part of the Fat-Free Framework (http://fatfreeframework.com).
@@ -45,6 +45,8 @@ class SMTP extends Magic {
$user,
//! Password
$pw,
//! TLS/SSL stream context
$context,
//! TCP/IP socket
$socket,
//! Server-client conversation
@@ -117,7 +119,7 @@ class SMTP extends Magic {
* Send SMTP command and record server response
* @return string
* @param $cmd string
* @param $log bool
* @param $log bool|string
* @param $mock bool
**/
protected function dialog($cmd=NULL,$log=TRUE,$mock=FALSE) {
@@ -177,7 +179,7 @@ class SMTP extends Magic {
* Transmit message
* @return bool
* @param $message string
* @param $log bool
* @param $log bool|string
* @param $mock bool
**/
function send($message,$log=TRUE,$mock=FALSE) {
@@ -192,7 +194,9 @@ class SMTP extends Magic {
// Connect to the server
if (!$mock) {
$socket=&$this->socket;
$socket=@fsockopen($this->host,$this->port,$errno,$errstr);
$socket=@stream_socket_client($this->host.':'.$this->port,
$errno,$errstr,ini_get('default_socket_timeout'),
STREAM_CLIENT_CONNECT,$this->context);
if (!$socket) {
$fw->error(500,$errstr);
return FALSE;
@@ -221,16 +225,16 @@ class SMTP extends Magic {
// Authenticate
$this->dialog('AUTH LOGIN',$log,$mock);
$this->dialog(base64_encode($this->user),$log,$mock);
$auth_rply=$this->dialog(base64_encode($this->pw),$log,$mock);
if (!preg_match('/^235\s.*/',$auth_rply)) {
$reply=$this->dialog(base64_encode($this->pw),$log,$mock);
if (!preg_match('/^235\s.*/',$reply)) {
$this->dialog('QUIT',$log,$mock);
if (!$mock && $socket)
fclose($socket);
return FALSE;
}
}
if (empty($headers['Message-ID']))
$headers['Message-ID']='<'.uniqid('',TRUE).'@'.$this->host.'>';
if (empty($headers['Message-Id']))
$headers['Message-Id']='<'.uniqid('',TRUE).'@'.$this->host.'>';
if (empty($headers['Date']))
$headers['Date']=date('r');
// Required headers
@@ -297,7 +301,7 @@ class SMTP extends Magic {
$out.='Content-Type: application/octet-stream'.$eol;
$out.='Content-Transfer-Encoding: base64'.$eol;
if ($attachment['cid'])
$out.='Content-ID: '.$attachment['cid'].$eol;
$out.='Content-Id: '.$attachment['cid'].$eol;
$out.='Content-Disposition: attachment; '.
'filename="'.$alias.'"'.$eol;
$out.=$eol;
@@ -307,7 +311,7 @@ class SMTP extends Magic {
$out.=$eol;
$out.='--'.$hash.'--'.$eol;
$out.='.';
$this->dialog($out,TRUE,$mock);
$this->dialog($out,preg_match('/verbose/i',$log),$mock);
}
else {
// Send mail headers
@@ -319,7 +323,7 @@ class SMTP extends Magic {
$out.=$message.$eol;
$out.='.';
// Send message
$this->dialog($out,TRUE,$mock);
$this->dialog($out,preg_match('/verbose/i',$log),$mock);
}
$this->dialog('QUIT',$log,$mock);
if (!$mock && $socket)
@@ -336,18 +340,18 @@ class SMTP extends Magic {
* @param $pw string
**/
function __construct(
$host='localhost',$port=25,$scheme=NULL,$user=NULL,$pw=NULL) {
$host='localhost',$port=25,$scheme=NULL,$user=NULL,$pw=NULL,$ctx=NULL) {
$this->headers=[
'MIME-Version'=>'1.0',
'Content-Type'=>'text/plain; '.
'charset='.Base::instance()->get('ENCODING')
];
$this->host=$host;
if (strtolower($this->scheme=strtolower($scheme))=='ssl')
$this->host='ssl://'.$host;
$this->host=(strtolower($this->scheme=strtolower($scheme))=='ssl'?
'ssl':'tcp').'://'.$host;
$this->port=$port;
$this->user=$user;
$this->pw=$pw;
$this->context=$ctx;
}
}

View File

@@ -2,7 +2,7 @@
/*
Copyright (c) 2009-2016 F3::Factory/Bong Cosca, All rights reserved.
Copyright (c) 2009-2017 F3::Factory/Bong Cosca, All rights reserved.
This file is part of the Fat-Free Framework (http://fatfreeframework.com).

View File

@@ -2,7 +2,7 @@
/*
Copyright (c) 2009-2016 F3::Factory/Bong Cosca, All rights reserved.
Copyright (c) 2009-2017 F3::Factory/Bong Cosca, All rights reserved.
This file is part of the Fat-Free Framework (http://fatfreeframework.com).

View File

@@ -2,7 +2,7 @@
/*
Copyright (c) 2009-2016 F3::Factory/Bong Cosca, All rights reserved.
Copyright (c) 2009-2017 F3::Factory/Bong Cosca, All rights reserved.
This file is part of the Fat-Free Framework (http://fatfreeframework.com).

View File

@@ -2,7 +2,7 @@
/*
Copyright (c) 2009-2016 F3::Factory/Bong Cosca, All rights reserved.
Copyright (c) 2009-2017 F3::Factory/Bong Cosca, All rights reserved.
This file is part of the Fat-Free Framework (http://fatfreeframework.com).
@@ -140,26 +140,33 @@ class Web extends Prefab {
header('Content-Length: '.$size);
header('X-Powered-By: '.Base::instance()->get('PACKAGE'));
}
$ctr=0;
$handle=fopen($file,'rb');
$start=microtime(TRUE);
while (!feof($handle) &&
($info=stream_get_meta_data($handle)) &&
!$info['timed_out'] && !connection_aborted()) {
if ($kbps) {
// Throttle output
$ctr++;
if ($ctr/$kbps>$elapsed=microtime(TRUE)-$start)
usleep(1e6*($ctr/$kbps-$elapsed));
}
// Send 1KiB and reset timer
echo fread($handle,1024);
if ($flush) {
ob_flush();
flush();
}
if (!$kbps && $flush) {
while (ob_get_level())
ob_end_clean();
readfile($file);
}
else {
$ctr=0;
$handle=fopen($file,'rb');
$start=microtime(TRUE);
while (!feof($handle) &&
($info=stream_get_meta_data($handle)) &&
!$info['timed_out'] && !connection_aborted()) {
if ($kbps) {
// Throttle output
$ctr++;
if ($ctr/$kbps>$elapsed=microtime(TRUE)-$start)
usleep(1e6*($ctr/$kbps-$elapsed));
}
// Send 1KiB and reset timer
echo fread($handle,1024);
if ($flush) {
ob_flush();
flush();
}
}
fclose($handle);
}
fclose($handle);
return $size;
}

View File

@@ -2,7 +2,7 @@
/*
Copyright (c) 2009-2016 F3::Factory/Bong Cosca, All rights reserved.
Copyright (c) 2009-2017 F3::Factory/Bong Cosca, All rights reserved.
This file is part of the Fat-Free Framework (http://fatfreeframework.com).

View File

@@ -2,7 +2,7 @@
/*
Copyright (c) 2009-2016 F3::Factory/Bong Cosca, All rights reserved.
Copyright (c) 2009-2017 F3::Factory/Bong Cosca, All rights reserved.
This file is part of the Fat-Free Framework (http://fatfreeframework.com).

View File

@@ -2,7 +2,7 @@
/*
Copyright (c) 2009-2016 F3::Factory/Bong Cosca, All rights reserved.
Copyright (c) 2009-2017 F3::Factory/Bong Cosca, All rights reserved.
This file is part of the Fat-Free Framework (http://fatfreeframework.com).
@@ -62,6 +62,8 @@ class OAuth2 extends \Magic {
)
);
$response=$web->request($uri,$options);
if ($response['error'])
user_error($response['error']);
return $response['body'] &&
preg_grep('/HTTP\/1\.\d 200/',$response['headers'])?
json_decode($response['body'],TRUE):
@@ -121,7 +123,7 @@ class OAuth2 extends \Magic {
/**
* Remove scope/claim
* @return NULL
* @param $key
* @param $key string
**/
function clear($key=NULL) {
if ($key)

View File

@@ -2,7 +2,7 @@
/*
Copyright (c) 2009-2016 F3::Factory/Bong Cosca, All rights reserved.
Copyright (c) 2009-2017 F3::Factory/Bong Cosca, All rights reserved.
This file is part of the Fat-Free Framework (http://fatfreeframework.com).

View File

@@ -2,7 +2,7 @@
/*
Copyright (c) 2009-2016 F3::Factory/Bong Cosca, All rights reserved.
Copyright (c) 2009-2017 F3::Factory/Bong Cosca, All rights reserved.
This file is part of the Fat-Free Framework (http://fatfreeframework.com).

View File

@@ -423,7 +423,7 @@ class Setup extends Controller {
],
'php' => [
'label' => 'PHP',
'required' => $f3->get('REQUIREMENTS.PHP.VERSION'),
'required' => number_format((float)$f3->get('REQUIREMENTS.PHP.VERSION'), 1, '.', ''),
'version' => phpversion(),
'check' => version_compare( phpversion(), $f3->get('REQUIREMENTS.PHP.VERSION'), '>=')
],

View File

@@ -10,7 +10,7 @@ NGINX.VERSION = 1.9
[REQUIREMENTS.PHP]
; recommended is >= 5.6
VERSION = 5.6
VERSION = 7.0
; "Perl-Compatible Regular Expressions"
; usually shipped with PHP package,