Merging latest develop

This commit is contained in:
Lonnie Ezell 2018-08-24 23:25:35 -05:00
commit 96bf16595b
No known key found for this signature in database
GPG Key ID: 8EB408F8D82F5002
453 changed files with 20703 additions and 10944 deletions

5
.gitignore vendored
View File

@ -63,6 +63,10 @@ writable/uploads/*
writable/debugbar/*
application/Database/Migrations/2*
php_errors.log
#-------------------------
# User Guide Temp Files
#-------------------------
@ -122,3 +126,4 @@ nb-configuration.xml
.vscode/
/results/
/phpunit*.xml

View File

@ -8,7 +8,6 @@ php:
matrix:
fast_finish: true
allow_failures:
- php: 7.2
- php: nightly
global:
@ -44,4 +43,4 @@ before_script:
- composer install --prefer-source
after_success:
- travis_retry php tests/bin/coveralls.phar
- travis_retry php tests/bin/php-coveralls.phar -v

View File

@ -215,7 +215,7 @@ class App extends BaseConfig
| Reverse Proxy IPs
|--------------------------------------------------------------------------
|
| If your getServer is behind a reverse proxy, you must whitelist the proxy
| If your server is behind a reverse proxy, you must whitelist the proxy
| IP addresses from which CodeIgniter should trust headers such as
| HTTP_X_FORWARDED_FOR and HTTP_CLIENT_IP in order to properly identify
| the visitor's IP address.
@ -240,11 +240,13 @@ class App extends BaseConfig
| CSRFCookieName = The cookie name
| CSRFExpire = The number in seconds the token should expire.
| CSRFRegenerate = Regenerate token on every submission
| CSRFRedirect = Redirect to previous page with error on failure
*/
public $CSRFTokenName = 'csrf_test_name';
public $CSRFCookieName = 'csrf_cookie_name';
public $CSRFExpire = 7200;
public $CSRFRegenerate = true;
public $CSRFRedirect = true;
/*
|--------------------------------------------------------------------------
@ -270,6 +272,9 @@ class App extends BaseConfig
| and state of your application during that page display. By default it will
| NOT be displayed under production environments, and will only display if
| CI_DEBUG is true, since if it's not, there's not much to display anyway.
|
| toolbarMaxHistory = Number of history files, 0 for none or -1 for unlimited
|
*/
public $toolbarCollectors = [
'CodeIgniter\Debug\Toolbar\Collectors\Timers',
@ -281,6 +286,7 @@ class App extends BaseConfig
'CodeIgniter\Debug\Toolbar\Collectors\Routes',
'CodeIgniter\Debug\Toolbar\Collectors\Events',
];
public $toolbarMaxHistory = 20;
/*
|--------------------------------------------------------------------------

View File

@ -1,6 +1,6 @@
<?php namespace Config;
require BASEPATH.'Config/AutoloadConfig.php';
require_once BASEPATH.'Config/AutoloadConfig.php';
/**
* -------------------------------------------------------------------

View File

@ -36,7 +36,7 @@ class Cache extends BaseConfig
| system.
|
*/
public $path = WRITEPATH.'cache/';
public $storePath = WRITEPATH.'cache/';
/*
|--------------------------------------------------------------------------

View File

@ -23,7 +23,7 @@ class ContentSecurityPolicy extends BaseConfig
public $imageSrc = 'self';
public $base_uri = null;
public $baseURI = 'none';
public $childSrc = null;
@ -38,6 +38,8 @@ class ContentSecurityPolicy extends BaseConfig
public $mediaSrc = null;
public $objectSrc = null;
public $manifestSrc = null;
public $pluginTypes = null;

View File

@ -8,7 +8,7 @@
class DocTypes
{
static $list =
public $list =
[
'xhtml11' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">',
'xhtml1-strict' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">',

View File

@ -2,6 +2,16 @@
class Email
{
/**
* @var string
*/
public $fromEmail;
/**
* @var string
*/
public $fromName;
/**
* The "user agent"
* @var string

View File

@ -9,15 +9,18 @@ class Filters extends BaseConfig
public $aliases = [
'csrf' => \App\Filters\CSRF::class,
'toolbar' => \App\Filters\DebugToolbar::class,
'honeypot' => \App\Filters\Honeypot::class
];
// Always applied before every request
public $globals = [
'before' => [
// 'csrf'
//'honeypot'
// 'csrf',
],
'after' => [
'toolbar'
'toolbar',
//'honeypot'
]
];

View File

@ -0,0 +1,31 @@
<?php namespace Config;
use CodeIgniter\Config\BaseConfig;
class Honeypot extends BaseConfig
{
/**
* Makes Honeypot visible or not to human
*
* @var boolean
*/
public $hidden = true;
/**
* Honeypot Label Content
* @var String
*/
public $label = 'Fill This Field';
/**
* Honeypot Field Name
* @var String
*/
public $name = 'honeypot';
/**
* Honeypot HTML Template
* @var String
*/
public $template = '<label>{label}</label><input type="text" name="{name}" value=""/>';
}

View File

@ -6,7 +6,7 @@
* Modifying these allows you to re-structure your application,
* share a system folder between multiple applications, and more.
*
* All paths are relative to the application's front controller, index.php
* All paths are relative to the project's root folder.
*/
class Paths
{
@ -19,7 +19,7 @@ class Paths
* Include the path if the folder is not in the same directory
* as this file.
*/
public $systemDirectory = '../system';
public $systemDirectory = 'system';
/*
*---------------------------------------------------------------
@ -34,7 +34,7 @@ class Paths
*
* NO TRAILING SLASH!
*/
public $applicationDirectory = '../application';
public $applicationDirectory = 'application';
/*
* ---------------------------------------------------------------
@ -47,7 +47,7 @@ class Paths
* for maximum security, keeping it out of the application and/or
* system directories.
*/
public $writableDirectory = '../writable';
public $writableDirectory = 'writable';
/*
* ---------------------------------------------------------------
@ -60,7 +60,7 @@ class Paths
* for maximum security, keeping it out of the application and/or
* system directories.
*/
public $testsDirectory = '../tests';
public $testsDirectory = 'tests';
/*
* ---------------------------------------------------------------

View File

@ -1,6 +1,7 @@
<?php namespace Config;
use CodeIgniter\Config\Services as CoreServices;
use CodeIgniter\Config\BaseConfig;
require_once BASEPATH.'Config/Services.php';
@ -30,5 +31,20 @@ class Services extends CoreServices
// return new \CodeIgniter\Example();
// }
public static function honeypot(BaseConfig $config = null, $getShared = true)
{
if ($getShared)
{
return self::getSharedInstance('honeypot', $config);
}
if (is_null($config))
{
$config = new \Config\Honeypot();
}
return new \CodeIgniter\Honeypot\Honeypot($config);
}
}

View File

@ -0,0 +1,219 @@
<?php namespace Config;
use CodeIgniter\Config\BaseConfig;
class UserAgents extends BaseConfig
{
/*
| -------------------------------------------------------------------
| USER AGENT TYPES
| -------------------------------------------------------------------
| This file contains four arrays of user agent data. It is used by the
| User Agent Class to help identify browser, platform, robot, and
| mobile device data. The array keys are used to identify the device
| and the array values are used to set the actual name of the item.
*/
public $platforms = [
'windows nt 10.0' => 'Windows 10',
'windows nt 6.3' => 'Windows 8.1',
'windows nt 6.2' => 'Windows 8',
'windows nt 6.1' => 'Windows 7',
'windows nt 6.0' => 'Windows Vista',
'windows nt 5.2' => 'Windows 2003',
'windows nt 5.1' => 'Windows XP',
'windows nt 5.0' => 'Windows 2000',
'windows nt 4.0' => 'Windows NT 4.0',
'winnt4.0' => 'Windows NT 4.0',
'winnt 4.0' => 'Windows NT',
'winnt' => 'Windows NT',
'windows 98' => 'Windows 98',
'win98' => 'Windows 98',
'windows 95' => 'Windows 95',
'win95' => 'Windows 95',
'windows phone' => 'Windows Phone',
'windows' => 'Unknown Windows OS',
'android' => 'Android',
'blackberry' => 'BlackBerry',
'iphone' => 'iOS',
'ipad' => 'iOS',
'ipod' => 'iOS',
'os x' => 'Mac OS X',
'ppc mac' => 'Power PC Mac',
'freebsd' => 'FreeBSD',
'ppc' => 'Macintosh',
'linux' => 'Linux',
'debian' => 'Debian',
'sunos' => 'Sun Solaris',
'beos' => 'BeOS',
'apachebench' => 'ApacheBench',
'aix' => 'AIX',
'irix' => 'Irix',
'osf' => 'DEC OSF',
'hp-ux' => 'HP-UX',
'netbsd' => 'NetBSD',
'bsdi' => 'BSDi',
'openbsd' => 'OpenBSD',
'gnu' => 'GNU/Linux',
'unix' => 'Unknown Unix OS',
'symbian' => 'Symbian OS',
];
// The order of this array should NOT be changed. Many browsers return
// multiple browser types so we want to identify the sub-type first.
public $browsers = [
'OPR' => 'Opera',
'Flock' => 'Flock',
'Edge' => 'Spartan',
'Chrome' => 'Chrome',
// Opera 10+ always reports Opera/9.80 and appends Version/<real version> to the user agent string
'Opera.*?Version' => 'Opera',
'Opera' => 'Opera',
'MSIE' => 'Internet Explorer',
'Internet Explorer' => 'Internet Explorer',
'Trident.* rv' => 'Internet Explorer',
'Shiira' => 'Shiira',
'Firefox' => 'Firefox',
'Chimera' => 'Chimera',
'Phoenix' => 'Phoenix',
'Firebird' => 'Firebird',
'Camino' => 'Camino',
'Netscape' => 'Netscape',
'OmniWeb' => 'OmniWeb',
'Safari' => 'Safari',
'Mozilla' => 'Mozilla',
'Konqueror' => 'Konqueror',
'icab' => 'iCab',
'Lynx' => 'Lynx',
'Links' => 'Links',
'hotjava' => 'HotJava',
'amaya' => 'Amaya',
'IBrowse' => 'IBrowse',
'Maxthon' => 'Maxthon',
'Ubuntu' => 'Ubuntu Web Browser',
'Vivaldi' => 'Vivaldi',
];
public $mobiles = [
// legacy array, old values commented out
'mobileexplorer' => 'Mobile Explorer',
// 'openwave' => 'Open Wave',
// 'opera mini' => 'Opera Mini',
// 'operamini' => 'Opera Mini',
// 'elaine' => 'Palm',
'palmsource' => 'Palm',
// 'digital paths' => 'Palm',
// 'avantgo' => 'Avantgo',
// 'xiino' => 'Xiino',
'palmscape' => 'Palmscape',
// 'nokia' => 'Nokia',
// 'ericsson' => 'Ericsson',
// 'blackberry' => 'BlackBerry',
// 'motorola' => 'Motorola'
// Phones and Manufacturers
'motorola' => 'Motorola',
'nokia' => 'Nokia',
'palm' => 'Palm',
'iphone' => 'Apple iPhone',
'ipad' => 'iPad',
'ipod' => 'Apple iPod Touch',
'sony' => 'Sony Ericsson',
'ericsson' => 'Sony Ericsson',
'blackberry' => 'BlackBerry',
'cocoon' => 'O2 Cocoon',
'blazer' => 'Treo',
'lg' => 'LG',
'amoi' => 'Amoi',
'xda' => 'XDA',
'mda' => 'MDA',
'vario' => 'Vario',
'htc' => 'HTC',
'samsung' => 'Samsung',
'sharp' => 'Sharp',
'sie-' => 'Siemens',
'alcatel' => 'Alcatel',
'benq' => 'BenQ',
'ipaq' => 'HP iPaq',
'mot-' => 'Motorola',
'playstation portable' => 'PlayStation Portable',
'playstation 3' => 'PlayStation 3',
'playstation vita' => 'PlayStation Vita',
'hiptop' => 'Danger Hiptop',
'nec-' => 'NEC',
'panasonic' => 'Panasonic',
'philips' => 'Philips',
'sagem' => 'Sagem',
'sanyo' => 'Sanyo',
'spv' => 'SPV',
'zte' => 'ZTE',
'sendo' => 'Sendo',
'nintendo dsi' => 'Nintendo DSi',
'nintendo ds' => 'Nintendo DS',
'nintendo 3ds' => 'Nintendo 3DS',
'wii' => 'Nintendo Wii',
'open web' => 'Open Web',
'openweb' => 'OpenWeb',
// Operating Systems
'android' => 'Android',
'symbian' => 'Symbian',
'SymbianOS' => 'SymbianOS',
'elaine' => 'Palm',
'series60' => 'Symbian S60',
'windows ce' => 'Windows CE',
// Browsers
'obigo' => 'Obigo',
'netfront' => 'Netfront Browser',
'openwave' => 'Openwave Browser',
'mobilexplorer' => 'Mobile Explorer',
'operamini' => 'Opera Mini',
'opera mini' => 'Opera Mini',
'opera mobi' => 'Opera Mobile',
'fennec' => 'Firefox Mobile',
// Other
'digital paths' => 'Digital Paths',
'avantgo' => 'AvantGo',
'xiino' => 'Xiino',
'novarra' => 'Novarra Transcoder',
'vodafone' => 'Vodafone',
'docomo' => 'NTT DoCoMo',
'o2' => 'O2',
// Fallback
'mobile' => 'Generic Mobile',
'wireless' => 'Generic Mobile',
'j2me' => 'Generic Mobile',
'midp' => 'Generic Mobile',
'cldc' => 'Generic Mobile',
'up.link' => 'Generic Mobile',
'up.browser' => 'Generic Mobile',
'smartphone' => 'Generic Mobile',
'cellphone' => 'Generic Mobile',
];
// There are hundreds of bots but these are the most common.
public $robots = [
'googlebot' => 'Googlebot',
'msnbot' => 'MSNBot',
'baiduspider' => 'Baiduspider',
'bingbot' => 'Bing',
'slurp' => 'Inktomi Slurp',
'yahoo' => 'Yahoo',
'ask jeeves' => 'Ask Jeeves',
'fastcrawler' => 'FastCrawler',
'infoseek' => 'InfoSeek Robot 1.0',
'lycos' => 'Lycos',
'yandex' => 'YandexBot',
'mediapartners-google' => 'MediaPartners Google',
'CRAZYWEBCRAWLER' => 'Crazy Webcrawler',
'adsbot-google' => 'AdsBot Google',
'feedfetcher-google' => 'Feedfetcher Google',
'curious george' => 'Curious George',
'ia_archiver' => 'Alexa Crawler',
'MJ12bot' => 'Majestic-12',
'Uptimebot' => 'Uptimebot',
];
}

View File

@ -1,516 +0,0 @@
<?php namespace App\Controllers;
use CodeIgniter\API\ResponseTrait;
use CodeIgniter\Config\Services;
use CodeIgniter\Controller;
use CodeIgniter\I18n\Time;
use CodeIgniter\Model;
use Config\Database;
/**
* NOTE: This is not a valid file for actual tests.
* This file came about as a small testbed I was using that
* accidentally got committed. It will be removed prior to release
* If you commit any changes to this file, it should be accompanied
* by actual tests also.
*
* @package App\Controllers
*/
class Checks extends Controller
{
use ResponseTrait;
public function index()
{
session()->start();
}
public function forge()
{
echo '<h1>MySQL</h1>';
log_message('debug', 'MYSQL TEST');
$forge_mysql = \Config\Database::forge();
$forge_mysql->getConnection()->query('SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;');
$forge_mysql->dropTable('users', true);
$forge_mysql->getConnection()->query('SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;');
$forge_mysql->addField([
'id' => [
'type' => 'INTEGER',
'constraint' => 11
],
'name' => [
'type' => 'VARCHAR',
'constraint' => 50,
]
]);
$forge_mysql->addKey('id', true);
$attributes = array('ENGINE' => 'InnoDB');
$forge_mysql->createTable('users', true, $attributes);
$data_insert = array(
'id' => 1,
'name' => 'User 1',
);
$forge_mysql->getConnection()->table('users')->insert($data_insert);
$drop = $forge_mysql->dropTable('invoices', true);
$forge_mysql->addField([
'id' => [
'type' => 'INTEGER',
'constraint' => 11,
],
'users_id' => [
'type' => 'INTEGER',
'constraint' => 11
],
'other_id' => [
'type' => 'INTEGER',
'constraint' => 11
]
]);
$forge_mysql->addKey('id', true);
$forge_mysql->addForeignKey('users_id','users','id','CASCADE','CASCADE');
$forge_mysql->addForeignKey('other_id','users','id','CASCADE','CASCADE');
$attributes = array('ENGINE' => 'InnoDB');
$res = $forge_mysql->createTable('invoices', true,$attributes);
if(!$res){
var_dump($forge_mysql->getConnection()->mysqli);
}else{
echo '<br><br>OK';
var_dump($forge_mysql->getConnection()->getForeignKeyData('invoices'));
}
$res = $forge_mysql->dropForeignKey('invoices','invoices_other_id_foreign');
echo '<h1>PostgreSQL</h1>';
$forge_pgsql = \Config\Database::forge('pgsql');
$forge_pgsql->dropTable('users',true, true);
$forge_pgsql->addField([
'id' => [
'type' => 'INTEGER',
'constraint' => 11,
'auto_increment' => true,
],
'name' => [
'type' => 'VARCHAR',
'constraint' => 50,
]
]);
$forge_pgsql->addKey('id', true);
$forge_pgsql->createTable('users', true);
$data_insert = array(
'id' => 1,
'name' => 'User 1',
);
$forge_pgsql->getConnection()->table('users')->insert($data_insert);
$forge_pgsql->dropTable('invoices',true);
$forge_pgsql->addField([
'id' => [
'type' => 'INTEGER',
'constraint' => 11,
'auto_increment' => true,
],
'users_id' => [
'type' => 'INTEGER',
'constraint' => 11
],
'other_id' => [
'type' => 'INTEGER',
'constraint' => 11
],
'another_id' => [
'type' => 'INTEGER',
'constraint' => 11
]
]);
$forge_pgsql->addKey('id', true);
$forge_pgsql->addForeignKey('users_id','users','id','CASCADE','CASCADE');
$forge_pgsql->addForeignKey('other_id','users','id');
$res = $forge_pgsql->createTable('invoices', true);
if(!$res){
var_dump($forge_pgsql->getConnection()->mysqli);
}else{
echo '<br><br>OK';
var_dump($forge_pgsql->getConnection()->getForeignKeyData('invoices'));
}
//$res = $forge_pgsql->dropForeignKey('invoices','invoices_other_id_foreign');
}
public function sqlite()
{
$forge = \Config\Database::forge();
$forge->dropTable('users', true);
$forge->dropTable('invoices', true);
// Ensure Foreign Keys are on
$forge->getConnection()->simpleQuery("PRAGMA foreign_keys=1");
// Create a table
$forge->addField([
'id' => [
'type' => 'INTEGER',
'constraint' => 11,
'auto_increment' => true,
],
'name' => [
'type' => 'VARCHAR',
'constraint' => 50,
]
]);
$forge->addKey('id', true);
$forge->createTable('users', true);
$data_insert = array(
'id' => 1,
'name' => 'User 1',
);
$forge->getConnection()->table('users')->insert($data_insert);
$forge->addField([
'id' => [
'type' => 'INTEGER',
'constraint' => 11,
'auto_increment' => true,
],
'users_id' => [
'type' => 'INTEGER',
'constraint' => 11
],
'other_id' => [
'type' => 'INTEGER',
'constraint' => 11
],
'another_id' => [
'type' => 'INTEGER',
'constraint' => 11
]
]);
$forge->addKey('id', true);
$forge->addForeignKey('users_id','users','id','CASCADE','CASCADE');
$forge->addForeignKey('other_id','users','id');
$res = $forge->createTable('invoices', true);
dd($forge->getConnection()->getForeignKeyData('invoices'));
}
public function escape()
{
$db = Database::connect();
$db->initialize();
$jobs = $db->table('job')
->whereNotIn('name', ['Politician', 'Accountant'])
->get()
->getResult();
die(var_dump($jobs));
}
public function password()
{
$db = Database::connect();
$db->initialize();
$result = $db->table('misc')
->insert([
'key' => 'password',
'value' => '$2y$10$ErQlCj/Mo10il.FthAm0WOjYdf3chZEGPFqaPzjqOX2aj2uYf5Ihq'
]);
die(var_dump($result));
}
public function forms()
{
helper('form');
var_dump(form_open());
}
public function api()
{
$data = [
"total_users" => 3,
"users" => [
[
"id" => 1,
"name" => "Nitya",
"address" => [
"country" => "India",
"city" => "Kolkata",
"zip" => 700102,
]
],
[
"id" => 2,
"name" => "John",
"address" => [
"country" => "USA",
"city" => "Newyork",
"zip" => "NY1234",
]
],
[
"id" => 3,
"name" => "Viktor",
"address" => [
"country" => "Australia",
"city" => "Sydney",
"zip" => 123456,
]
],
]
];
return $this->respond($data);
}
public function db()
{
$db = Database::connect();
$db->initialize();
$query = $db->prepare(function($db){
return $db->table('user')->insert([
'name' => 'a',
'email' => 'b@example.com',
'country' => 'x'
]);
});
$query->execute('foo', 'foo@example.com', 'US');
}
public function db2()
{
$db = Database::connect();
$db->initialize();
$db->table('user')->insert([
'name' => 'a',
'email' => 'b@example.com',
'country' => 'x'
]);
}
public function format()
{
echo '<pre>';
var_dump($this->response->getHeaderLine('content-type'));
}
public function model()
{
$model = new class() extends Model {
protected $table = 'job';
};
$results = $model->findAll();
$developer = $model->findWhere('name', 'Developer');
$politician = $model->find(3);
dd($politician);
}
public function curl()
{
$client = Services::curlrequest([
'debug' => true,
'follow_redirects' => true,
'json' => ['foo' => 'bar']
]);
echo '<pre>';
$response = $client->request('PUT', 'http://ci4.dev/checks/catch');
echo $response->getBody();
}
// Simply echos back what's given in the body.
public function catch()
{
$body = print_r($this->request->getRawInput(), true);
echo $body;
}
public function redirect()
{
return redirect('/checks/model');
}
public function image()
{
$info = Services::image('imagick')
->withFile("/Users/kilishan/Documents/BobHeader.jpg")
->getFile()
->getProperties(true);
dd(ENVIRONMENT);
$images = Services::image('imagick')
->getVersion();
// ->withFile("/Users/kilishan/Documents/BobHeader.jpg")
// ->resize(500, 100, true)
// ->crop(200, 75, 20, 0, false)
// ->rotate(90)
// ->save('/Users/kilishan/temp.jpg');
// $images = Services::image('imagick')
// ->withFile("/Users/kilishan/Documents/BobHeader.jpg")
// ->fit(500, 100, 'bottom-left')
// ->text('Bob is Back!', [
// 'fontPath' => '/Users/kilishan/Downloads/Calibri.ttf',
// 'fontSize' => 40,
// 'padding' => 0,
// 'opacity' => 0.5,
// 'vAlign' => 'top',
// 'hAlign' => 'right',
// 'withShadow' => true,
// ])
// ->save('/Users/kilishan/temp.jpg', 100);
ddd($images);
}
public function time()
{
$time = new Time();
echo($time);
echo '<br/>';
echo Time::now();
echo '<br/>';
echo Time::parse('First Monday of December');
echo '<br/>';
$time = new Time('Next Monday');
die($time);
}
public function csp()
{
// $this->response->CSP->reportOnly(true);
$this->response->CSP->setDefaultSrc(base_url());
$this->response->CSP->addStyleSrc('unsafe-inline');
$this->response->CSP->addStyleSrc('https://maxcdn.bootstrapcdn.com');
echo <<<EOF
<!doctype html>
<html>
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
</head>
<body>
<style {csp-style-nonce}>
body { background: #efefef; }
</style>
</body>
</html>
EOF;
}
public function upload()
{
if ($this->request->getMethod() == 'post')
{
$this->validate([
'avatar' => 'uploaded[avatar]|ext_in[avatar,png,jpg,jpeg,gif]'
]);
/**
* @var \CodeIgniter\HTTP\Files\UploadedFile
*/
$file = $this->request->getFile('avatar');
echo "Name: {$file->getName()}<br/>";
echo "Temp Name: {$file->getTempName()}<br/>";
echo "Original Name: {$file->getClientName()}<br/>";
echo "Random Name: {$file->getRandomName()}<br/>";
echo "Extension: {$file->getExtension()}<br/>";
echo "Client Extension: {$file->getClientExtension()}<br/>";
echo "Guessed Extension: {$file->guessExtension()}<br/>";
echo "MimeType: {$file->getMimeType()}<br/>";
echo "IsValid: {$file->isValid()}<br/>";
echo "Size (b): {$file->getSize()}<br/>";
echo "Size (kb): {$file->getSize('kb')}<br/>";
echo "Size (mb): {$file->getSize('mb')}<br/>";
echo "Size (mb): {$file->getSize('mb')}<br/>";
echo "Path: {$file->getPath()}<br/>";
echo "RealPath: {$file->getRealPath()}<br/>";
echo "Filename: {$file->getFilename()}<br/>";
echo "Basename: {$file->getBasename()}<br/>";
echo "Pathname: {$file->getPathname()}<br/>";
echo "Permissions: {$file->getPerms()}<br/>";
echo "Inode: {$file->getInode()}<br/>";
echo "Owner: {$file->getOwner()}<br/>";
echo "Group: {$file->getGroup()}<br/>";
echo "ATime: {$file->getATime()}<br/>";
echo "MTime: {$file->getMTime()}<br/>";
echo "CTime: {$file->getCTime()}<br/>";
dd($file);
}
echo <<<EOF
<!doctype html>
<html>
<body>
<form action="" method="post" enctype="multipart/form-data">
<input type="file" name="avatar">
<input type="submit" value="Upload">
</form>
</body>
</html>
EOF;
;
}
public function parser()
{
$this->parser = Services::parser();
}
public function error()
{
throw new \RuntimeException('Oops!', 403);
}
}

View File

@ -3,6 +3,7 @@
use CodeIgniter\Filters\FilterInterface;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use CodeIgniter\Security\Exceptions\SecurityException;
use Config\Services;
class CSRF implements FilterInterface
@ -30,7 +31,19 @@ class CSRF implements FilterInterface
$security = Services::security();
$security->CSRFVerify($request);
try
{
$security->CSRFVerify($request);
}
catch (SecurityException $e)
{
if (config('App')->CSRFRedirect && ! $request->isAJAX())
{
return redirect()->back()->with('error', $e->getMessage());
}
throw $e;
}
}
//--------------------------------------------------------------------

View File

@ -33,23 +33,20 @@ class DebugToolbar implements FilterInterface
*/
public function after(RequestInterface $request, ResponseInterface $response)
{
$format = $response->getHeaderLine('content-type');
if ( ! is_cli() && CI_DEBUG && strpos($format, 'html') !== false)
if ( ! is_cli() && CI_DEBUG)
{
global $app;
$toolbar = Services::toolbar(new App());
$toolbar = Services::toolbar(config(App::class));
$stats = $app->getPerformanceStats();
$output = $toolbar->run(
$data = $toolbar->run(
$stats['startTime'],
$stats['totalTime'],
$stats['startMemory'],
$request,
$response
);
helper(['filesystem', 'url']);
helper('filesystem');
// Updated to time() so we can get history
$time = time();
@ -59,12 +56,26 @@ class DebugToolbar implements FilterInterface
mkdir(WRITEPATH.'debugbar', 0777);
}
write_file(WRITEPATH .'debugbar/'.'debugbar_' . $time, $output, 'w+');
write_file(WRITEPATH .'debugbar/'.'debugbar_' . $time, $data, 'w+');
$format = $response->getHeaderLine('content-type');
// Non-HTML formats should not include the debugbar
// then we send headers saying where to find the debug data
// for this response
if ($request->isAJAX() || strpos($format, 'html') === false)
{
return $response->setHeader('Debugbar-Time', (string)$time)
->setHeader('Debugbar-Link', site_url("?debugbar_time={$time}"))
->getBody();
}
$script = PHP_EOL
. '<script type="text/javascript" id="debugbar_loader" '
. '<script type="text/javascript" {csp-script-nonce} id="debugbar_loader" '
. 'data-time="' . $time . '" '
. 'src="' . rtrim(site_url(), '/') . '?debugbar"></script>'
. '<script type="text/javascript" {csp-script-nonce} id="debugbar_dynamic_script"></script>'
. '<style type="text/css" {csp-style-nonce} id="debugbar_dynamic_style"></style>'
. PHP_EOL;
if (strpos($response->getBody(), '</body>') !== false)

View File

@ -0,0 +1,51 @@
<?php namespace App\Filters;
use CodeIgniter\Filters\FilterInterface;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use Config\Services;
use CodeIgniter\Honeypot\Exceptions\HoneypotException;
class Honeypot implements FilterInterface
{
/**
* Checks if Honeypot field is empty, if so
* then the requester is a bot,show a blank
* page
*
* @param RequestInterface|\CodeIgniter\HTTP\IncomingRequest $request
*
* @return mixed
*/
public function before (RequestInterface $request)
{
// Checks honeypot field if value was entered then show blank if so.
$honeypot = Services::honeypot(new \Config\Honeypot());
if($honeypot->hasContent($request))
{
throw HoneypotException::isBot();
}
}
/**
* Checks if Honeypot field is empty, if so
* then the requester is a bot,show a blank
* page
*
* @param RequestInterface|\CodeIgniter\HTTP\IncomingRequest $request
* @param ResponseInterface|\CodeIgniter\HTTP\Response $response
* @return mixed
*/
public function after (RequestInterface $request, ResponseInterface $response)
{
$honeypot = Services::honeypot(new \Config\Honeypot());
$honeypot->attachHoneypot($response);
}
}

View File

@ -190,7 +190,7 @@
<!-- Request -->
<div class="content" id="request">
<?php $request = \CodeIgniter\Config\Services::request(null, true); ?>
<?php $request = \Config\Services::request(); ?>
<table>
<tbody>
@ -220,7 +220,7 @@
</tr>
<tr>
<td>User Agent</td>
<td><?= $request->getUserAgent() ?></td>
<td><?= $request->getUserAgent()->getAgentString() ?></td>
</tr>
</tbody>
@ -299,7 +299,7 @@
<!-- Response -->
<?php
$response = \CodeIgniter\Config\Services::response(null, true);
$response = \Config\Services::response();
$response->setStatusCode(http_response_code());
?>
<div class="content" id="response">

View File

@ -12,17 +12,19 @@
},
"autoload": {
"psr-4": {
"CodeIgniter\\": "system/"
"CodeIgniter\\": "system/",
"Psr\\Log\\": "system/ThirdParty/PSR/Log/"
}
},
"require": {
"php": ">=7.1",
"zendframework/zend-escaper": "^2.5",
"paragonie/sodium_compat": "^1.1",
"kint-php/kint": "^2.1"
"kint-php/kint": "^2.1",
"ext-intl": "*"
},
"require-dev": {
"phpunit/phpunit": "^6.0",
"phpunit/phpunit": "^7.0",
"mikey179/vfsStream": "1.6.*",
"codeigniter4/codeigniter4-standard": "^1.0"
},

11
env
View File

@ -20,7 +20,7 @@
# app.sessionDriver = 'CodeIgniter\Session\Handlers\FileHandler'
# app.sessionCookieName = 'ci_session'
# app.sessionSavePath = NULL
# app.sessionMachIP = false
# app.sessionMatchIP = false
# app.sessionTimeToUpdate = 300
# app.sessionRegenerateDestroy = false
@ -76,3 +76,12 @@
# contentsecuritypolicy.reportURI = null
# contentsecuritypolicy.sandbox = false
# contentsecuritypolicy.upgradeInsecureRequests = false
#--------------------------------------------------------------------
# HONEYPOT
#--------------------------------------------------------------------
# honeypot.hidden = 'true'
# honeypot.label = 'Fill This Field'
# honeypot.name = 'honeypot'
# honeypot.template = '<label>{label}</label><input type="text" name="{name}" value=""/>'

View File

@ -1,15 +1,102 @@
<!DOCTYPE html>
<html>
<head>
<title>CodeIgniter 4 ... almost!</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<p>If you see this message, you have not configured your web server properly.</p>
<p>You need to set your "document root" to the <code>public</code> folder
inside your project. This could be your default setting, or that of
a virtual host, depending on how you set up your local development
environment.</p>
</body>
<head>
<title>CodeIgniter 4 ... almost!</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
div.logo {
height: 200px;
width: 155px;
display: inline-block;
opacity: 0.08;
position: absolute;
top: 2rem;
left: 50%;
margin-left: -73px;
}
body {
height: 100%;
background: #fafafa;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
color: #777;
font-weight: 300;
}
h1 {
font-weight: lighter;
letter-spacing: 0.8;
font-size: 3rem;
margin-top: 145px;
margin-bottom: 0;
color: #222;
}
.wrap {
max-width: 1024px;
margin: 5rem auto;
padding: 2rem;
background: #fff;
text-align: center;
border: 1px solid #efefef;
border-radius: 0.5rem;
position: relative;
}
.guide {
margin-top: 3rem;
text-align: left;
}
p {
margin-top: 1.5rem;
}
a:active,
a:link,
a:visited {
color: #dd4814;
}
</style>
</head>
<body>
<div class="wrap">
<h1>CodeIgniter 4 ... Almost!!!</h1>
<div class="logo">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="155.000000px" height="200.000000px" viewBox="0 0 155.000000 200.000000"
preserveAspectRatio="xMidYMid meet">
<g transform="translate(0.000000,200.000000) scale(0.100000,-0.100000)" fill="#000000" stroke="none">
<path d="M737 1963 c22 -79 -7 -185 -78 -290 -18 -26 -107 -122 -197 -213
-239 -240 -336 -371 -403 -544 -79 -206 -78 -408 5 -582 64 -134 212 -264 361
-314 l60 -20 -30 22 c-210 152 -229 387 -48 588 25 27 48 50 51 50 4 0 7 -27
7 -61 0 -57 2 -62 37 -95 30 -27 46 -34 78 -34 56 0 99 24 116 65 29 69 16
120 -50 205 -105 134 -117 233 -43 347 l31 48 7 -47 c13 -82 58 -129 250 -258
209 -141 306 -261 328 -405 11 -72 -1 -161 -31 -218 -27 -53 -112 -143 -165
-174 -24 -14 -43 -26 -43 -28 0 -2 24 4 53 14 241 83 427 271 482 486 19 76
19 202 -1 285 -35 152 -146 305 -299 412 l-70 49 -6 -33 c-8 -48 -26 -76 -59
-93 -45 -23 -103 -19 -138 10 -67 57 -78 146 -37 305 30 116 32 206 5 291 -27
89 -104 206 -162 247 -17 13 -18 12 -11 -15z"/>
</g>
</svg>
</div>
<div class="guide">
<p>If you see this message, you have not configured your web server properly.</p>
<p>You need to set your "document root" to the <code>public</code> folder
inside your project. This could be your default setting, or that of
a virtual host, depending on how you set up your local development
environment.</p>
<p>If you are exploring CodeIgniter for the very first time, you
should start by reading the (in progress)
<a href="https://bcit-ci.github.io/CodeIgniter4">User Guide</a>.</p>
</div>
</div>
</body>
</html>

View File

@ -10,6 +10,10 @@
stopOnIncomplete="false"
stopOnSkipped="false">
<testsuites>
<testsuite name="app">
<directory>./tests</directory>
<exclude>./tests/system</exclude>
</testsuite>
<testsuite name="system">
<directory>./tests/system</directory>
<exclude>./tests/system/Database</exclude>
@ -23,14 +27,14 @@
<whitelist processUncoveredFilesFromWhitelist="true">
<directory suffix=".php">./system</directory>
<exclude>
<file>./system/bootstrap.php</file>
<file>./system/Commands/Sessions/Views/migration.tpl.php</file>
<file>./system/ComposerScripts.php</file>
<file>./system/Config/Routes.php</file>
<directory>./system/Debug/Toolbar/Views</directory>
<directory>./system/Pager/Views</directory>
<directory>./system/ThirdParty</directory>
<directory>./system/Validation/Views</directory>
<file>./system/bootstrap.php</file>
<file>./system/Commands/Sessions/Views/migration.tpl.php</file>
<file>./system/ComposerScripts.php</file>
<file>./system/Config/Routes.php</file>
</exclude>
</whitelist>
</filter>

View File

@ -1,13 +1,12 @@
<?php
// Location to the Paths config file.
// This should be the only line you need to
// edit in this file.
$pathsPath = '../application/Config/Paths.php';
// Path to the front controller (this file)
define('FCPATH', __DIR__.DIRECTORY_SEPARATOR);
// Location of the Paths config file.
// This is the first of two lines that might need to be changed, depending on your folder structure.
$pathsPath = FCPATH . '../application/Config/Paths.php';
/*
*---------------------------------------------------------------
* BOOTSTRAP THE APPLICATION
@ -24,7 +23,9 @@ chdir(__DIR__);
require $pathsPath;
$paths = new Config\Paths();
$app = require rtrim($paths->systemDirectory,'/ ').'/bootstrap.php';
// Location of the framework bootstrap file.
// This is the second of two lines that might need to be changed, depending on your folder structure.
$app = require FCPATH . '../system/bootstrap.php';
/*
*---------------------------------------------------------------

36
serve
View File

@ -1,36 +0,0 @@
<?php
/**
* CodeIgniter PHP-Development Server Launcher
*
* This script launches the built-in PHP development server
* making sure that it knows the webroot is in the public folder,
* and using the rewrite.php file to mimic mod_rewrite functionality.
*
* The script is automatically set to the development environment
* within the rewrite.php file.
*/
$php = PHP_BINARY; // command to call PHP
/*
* Collect any user-supplied options and apply them
*/
$options = getopt(null, ['host:', 'port:']);
$host = $options['host'] ?? 'localhost';
$port = $options['port'] ?? '8080';
/*
* Get the party started
*/
require_once __DIR__.'/system/CLI/CLI.php';
\CodeIgniter\CLI\CLI::write("CodeIgniter development server started on http://{$host}:{$port}", 'green');
\CodeIgniter\CLI\CLI::write("Press Control-C to stop.");
/*
* Call PHP's built-in webserver, making sure to set our
* base path to the public folder, and to use the rewrite file
* to ensure our environment is set and it simulates basic mod_rewrite.
*/
passthru("{$php} -S {$host}:{$port} -t public/ rewrite.php");

View File

@ -344,16 +344,15 @@ trait ResponseTrait
return $data;
}
// Determine correct response type through content negotiation
$config = new Format();
$format = $this->request->negotiate('media', $config->supportedResponseFormats, true);
$this->response->setContentType($format);
// if we don't have a formatter, make one
if ( ! isset($this->formatter))
{
$config = new Format();
// Determine correct response type through content negotiation
$format = $this->request->negotiate('media', $config->supportedResponseFormats, true);
$this->response->setContentType($format);
// if no formatter, use the default
$this->formatter = $config->getFormatter($format);
}

View File

@ -165,7 +165,7 @@ class Autoloader
*
* @return Autoloader
*/
public function addNamespace($namespace, $path)
public function addNamespace(string $namespace, string $path)
{
if (isset($this->prefixes[$namespace]))
{
@ -194,7 +194,7 @@ class Autoloader
*
* @return Autoloader
*/
public function removeNamespace($namespace)
public function removeNamespace(string $namespace)
{
unset($this->prefixes[$namespace]);
@ -211,7 +211,7 @@ class Autoloader
* @return mixed The mapped file on success, or boolean false
* on failure.
*/
public function loadClass($class)
public function loadClass(string $class)
{
$class = trim($class, '\\');
$class = str_ireplace('.php', '', $class);
@ -237,7 +237,7 @@ class Autoloader
*
* @return mixed The mapped file name on success, or boolean false on fail
*/
protected function loadInNamespace($class)
protected function loadInNamespace(string $class)
{
if (strpos($class, '\\') === false)
{
@ -283,7 +283,7 @@ class Autoloader
*
* @return mixed The mapped file name on success, or boolean false on failure
*/
protected function loadLegacy($class)
protected function loadLegacy(string $class)
{
// If there is a namespace on this class, then
// we cannot load it from traditional locations.
@ -323,7 +323,7 @@ class Autoloader
*
* @return bool
*/
protected function requireFile($file)
protected function requireFile(string $file)
{
$file = $this->sanitizeFilename($file);

View File

@ -151,6 +151,56 @@ class FileLocator
//--------------------------------------------------------------------
/**
* Examines a file and returns the fully qualified domain name.
*
* @param string $file
*
* @return string
*/
public function getClassname(string $file) : string
{
$php = file_get_contents($file);
$tokens = token_get_all($php);
$count = count($tokens);
$dlm = false;
$namespace = '';
$class_name = '';
for ($i = 2; $i < $count; $i++)
{
if ((isset($tokens[$i-2][1]) && ($tokens[$i-2][1] == "phpnamespace" || $tokens[$i-2][1] == "namespace")) || ($dlm && $tokens[$i-1][0] == T_NS_SEPARATOR && $tokens[$i][0] == T_STRING))
{
if (! $dlm)
{
$namespace = 0;
}
if (isset($tokens[$i][1]))
{
$namespace = $namespace ? $namespace."\\".$tokens[$i][1] : $tokens[$i][1];
$dlm = true;
}
}
elseif ($dlm && ($tokens[$i][0] != T_NS_SEPARATOR) && ($tokens[$i][0] != T_STRING))
{
$dlm = false;
}
if (($tokens[$i-2][0] == T_CLASS || (isset($tokens[$i-2][1]) && $tokens[$i-2][1] == "phpclass"))
&& $tokens[$i-1][0] == T_WHITESPACE
&& $tokens[$i][0] == T_STRING)
{
$class_name = $tokens[$i][1];
break;
}
}
if( empty( $class_name ) ) return "";
return $namespace .'\\'. $class_name;
}
//--------------------------------------------------------------------
/**
* Searches through all of the defined namespaces looking for a file.
* Returns an array of all found locations for the defined file.

View File

@ -35,6 +35,7 @@
* @since Version 3.0.0
* @filesource
*/
use CodeIgniter\CLI\Exceptions\CLIException;
/**
* Class CLI
@ -44,9 +45,18 @@
*
* Portions of this code were initially from the FuelPHP Framework,
* version 1.7.x, and used here under the MIT license they were
* originally made available under.
* originally made available under. Reference: http://fuelphp.com
*
* http://fuelphp.com
* Some of the code in this class is Windows-specific, and not
* possible to test using travis-ci. It has been phpunit-annotated
* to prevent messing up code coverage.
*
* Some of the methods require keyboard input, and are not unit-testable
* as a result: input() and prompt().
* validate() is internal, and not testable if prompt() isn't.
* The wait() method is mostly testable, as long as you don't give it
* an argument of "0".
* These have been flagged to ignore for code coverage purposes.
*
* @package CodeIgniter\HTTP
*/
@ -118,6 +128,7 @@ class CLI
* @var array
*/
protected static $segments = [];
/**
* @var array
*/
@ -135,6 +146,10 @@ class CLI
// http://www.php.net/manual/en/readline.installation.php
static::$readline_support = extension_loaded('readline');
// clear segments & options to keep testing clean
static::$segments = [];
static::$options = [];
static::parseCommandLine();
static::$initialized = true;
@ -149,8 +164,9 @@ class CLI
* php index.php user -v --v -name=John --name=John
*
* @param string $prefix
*
* @return string
*
* @codeCoverageIgnore
*/
public static function input(string $prefix = null): string
{
@ -188,6 +204,7 @@ class CLI
* @param string $validation Validation rules
*
* @return string The user input
* @codeCoverageIgnore
*/
public static function prompt($field, $options = null, $validation = null): string
{
@ -196,11 +213,11 @@ class CLI
if (is_string($options))
{
$extra_output = ' [' . static::color($options, 'white') .']';
$extra_output = ' [' . static::color($options, 'white') . ']';
$default = $options;
}
if (is_array($options) && count($options))
if (is_array($options) && $options)
{
$opts = $options;
$extra_output_default = static::color($opts[0], 'white');
@ -213,8 +230,8 @@ class CLI
}
else
{
$extra_output = ' [' .$extra_output_default.', '. implode(', ', $opts) . ']';
$validation .= '|in_list['. implode(',', $options) .']';
$extra_output = ' [' . $extra_output_default . ', ' . implode(', ', $opts) . ']';
$validation .= '|in_list[' . implode(',', $options) . ']';
$validation = trim($validation, '|');
}
@ -224,11 +241,11 @@ class CLI
fwrite(STDOUT, $field . $extra_output . ': ');
// Read the input from keyboard.
$input = trim(static::input()) ? : $default;
$input = trim(static::input()) ?: $default;
if (isset($validation))
{
while (! static::validate($field, $input, $validation))
while ( ! static::validate($field, $input, $validation))
{
$input = static::prompt($field, $options, $validation);
}
@ -247,11 +264,12 @@ class CLI
* @param string $rules Validation rules
*
* @return boolean
* @codeCoverageIgnore
*/
protected static function validate($field, $value, $rules)
{
$validation = \Config\Services::validation(null, false);
$validation->setRule($field, $rules);
$validation->setRule($field, null, $rules);
$validation->run([$field => $value]);
if ($validation->hasError($field))
@ -345,8 +363,11 @@ class CLI
}
else
{
// this chunk cannot be tested because of keyboard input
// @codeCoverageIgnoreStart
static::write(static::$wait_msg);
static::input();
// @codeCoverageIgnoreEnd
}
}
}
@ -358,7 +379,7 @@ class CLI
*/
public static function isWindows()
{
return 'win' === strtolower(substr(php_uname("s"), 0, 3));
return stripos(PHP_OS, 'WIN') === 0;
}
//--------------------------------------------------------------------
@ -373,7 +394,7 @@ class CLI
public static function newLine(int $num = 1)
{
// Do it once or more, write with empty string gives us a new line
for ($i = 0; $i < $num; $i ++ )
for ($i = 0; $i < $num; $i ++)
{
static::write('');
}
@ -385,6 +406,7 @@ class CLI
* Clears the screen of output
*
* @return void
* @codeCoverageIgnore
*/
public static function clearScreen()
{
@ -414,17 +436,19 @@ class CLI
{
if (static::isWindows() && ! isset($_SERVER['ANSICON']))
{
// @codeCoverageIgnoreStart
return $text;
// @codeCoverageIgnoreEnd
}
if ( ! array_key_exists($foreground, static::$foreground_colors))
{
throw new \RuntimeException('Invalid CLI foreground color: ' . $foreground);
throw CLIException::forInvalidColor('foreground', $foreground);
}
if ($background !== null && ! array_key_exists($background, static::$background_colors))
{
throw new \RuntimeException('Invalid CLI background color: ' . $background);
throw CLIException::forInvalidColor('background', $background);
}
$string = "\033[" . static::$foreground_colors[$foreground] . "m";
@ -459,7 +483,9 @@ class CLI
{
if (static::isWindows() || (int) shell_exec('tput cols') == 0)
{
// @codeCoverageIgnoreStart
return $default;
// @codeCoverageIgnoreEnd
}
return (int) shell_exec('tput cols');
@ -480,7 +506,9 @@ class CLI
{
if (static::isWindows())
{
// @codeCoverageIgnoreStart
return $default;
// @codeCoverageIgnoreEnd
}
return (int) shell_exec('tput lines');
@ -604,7 +632,8 @@ class CLI
{
$optionsFound = false;
for ($i = 1; $i < $_SERVER['argc']; $i ++ )
// start picking segments off from #1, ignoring the invoking program
for ($i = 1; $i < $_SERVER['argc']; $i ++)
{
// If there's no '-' at the beginning of the argument
// then add it to our segments.
@ -619,16 +648,11 @@ class CLI
// value belonging to this option.
$optionsFound = true;
if (mb_substr($_SERVER['argv'][$i], 0, 1) != '-')
{
continue;
}
$arg = str_replace('-', '', $_SERVER['argv'][$i]);
$value = null;
// if the next item doesn't have a dash it's a value.
if (isset($_SERVER['argv'][$i + 1]) && mb_substr($_SERVER['argv'][$i + 1], 0, 1) != '-')
// if there is a following segment, and it doesn't start with a dash, it's a value.
if (isset($_SERVER['argv'][$i + 1]) && mb_strpos($_SERVER['argv'][$i + 1], '-') !== 0)
{
$value = $_SERVER['argv'][$i + 1];
$i ++;
@ -683,6 +707,18 @@ class CLI
//--------------------------------------------------------------------
/**
* Returns the raw array of segments found.
*
* @return array
*/
public static function getSegments()
{
return static::$segments;
}
//--------------------------------------------------------------------
/**
* Gets a single command-line option. Returns TRUE if the option
* exists, but doesn't have a value, and is simply acting as a flag.
@ -720,7 +756,7 @@ class CLI
//--------------------------------------------------------------------
/**
* Returns the options a string, suitable for passing along on
* Returns the options as a string, suitable for passing along on
* the CLI to other commands.
*
* @return string
@ -765,7 +801,7 @@ class CLI
$table_rows = [];
// We need only indexes and not keys
if (! empty($thead))
if ( ! empty($thead))
{
$table_rows[] = array_values($thead);
}
@ -787,7 +823,7 @@ class CLI
$max_cols_lengths = [];
// Read row by row and define the longest columns
for ($row = 0; $row < $total_rows; $row++)
for ($row = 0; $row < $total_rows; $row ++ )
{
$column = 0; // Current column index
foreach ($table_rows[$row] as $col)
@ -798,19 +834,19 @@ class CLI
// If the current column does not have a value among the larger ones
// or the value of this is greater than the existing one
// then, now, this assumes the maximum length
if (! isset($max_cols_lengths[$column]) || $all_cols_lengths[$row][$column] > $max_cols_lengths[$column])
if ( ! isset($max_cols_lengths[$column]) || $all_cols_lengths[$row][$column] > $max_cols_lengths[$column])
{
$max_cols_lengths[$column] = $all_cols_lengths[$row][$column];
}
// We can go check the size of the next column...
$column++;
$column ++;
}
}
// Read row by row and add spaces at the end of the columns
// to match the exact column length
for ($row = 0; $row < $total_rows; $row++)
for ($row = 0; $row < $total_rows; $row ++ )
{
$column = 0;
foreach ($table_rows[$row] as $col)
@ -820,14 +856,14 @@ class CLI
{
$table_rows[$row][$column] = $table_rows[$row][$column] . str_repeat(' ', $diff);
}
$column++;
$column ++;
}
}
$table = '';
// Joins columns and append the well formatted rows to the table
for ($row = 0; $row < $total_rows; $row++)
for ($row = 0; $row < $total_rows; $row ++ )
{
// Set the table border-top
if ($row === 0)
@ -856,5 +892,7 @@ class CLI
//--------------------------------------------------------------------
}
// Ensure the class is initialized.
// Ensure the class is initialized. Done outside of code coverage
// @codeCoverageIgnoreStart
CLI::init();
// @codeCoverageIgnoreEnd

View File

@ -39,7 +39,6 @@ use CodeIgniter\Controller;
class CommandRunner extends Controller
{
/**
* Stores the info about found Commands.
*
@ -47,6 +46,11 @@ class CommandRunner extends Controller
*/
protected $commands = [];
/**
* @var \CodeIgniter\Log\Logger
*/
protected $logger;
//--------------------------------------------------------------------
/**

View File

@ -63,15 +63,20 @@ class Console
/**
* Runs the current command discovered on the CLI.
*
* @param bool $useSafeOutput
*
* @return \CodeIgniter\HTTP\RequestInterface|\CodeIgniter\HTTP\Response|\CodeIgniter\HTTP\ResponseInterface|mixed
* @throws \CodeIgniter\HTTP\RedirectException
*/
public function run()
public function run(bool $useSafeOutput = false)
{
$path = CLI::getURI() ?: 'list';
// Set the path for the application to route to.
$this->app->setPath("ci{$path}");
return $this->app->run();
return $this->app->useSafeOutput($useSafeOutput)->run();
}
//--------------------------------------------------------------------

View File

@ -0,0 +1,15 @@
<?php namespace CodeIgniter\CLI\Exceptions;
class CLIException extends \RuntimeException
{
/**
* @param string $type
* @param string $color
*
* @return \CodeIgniter\CLI\Exceptions\CLIException
*/
public static function forInvalidColor(string $type, string $color)
{
return new static(lang('CLI.invalidColor', [$type, $color]));
}
}

View File

@ -36,6 +36,8 @@
* @filesource
*/
use CodeIgniter\Cache\Exceptions\CacheException;
/**
* Class Cache
*
@ -45,7 +47,6 @@
*/
class CacheFactory
{
/**
* Attempts to create the desired cache handler, based upon the
*
@ -59,12 +60,12 @@ class CacheFactory
{
if ( ! isset($config->validHandlers) || ! is_array($config->validHandlers))
{
throw new \InvalidArgumentException(lang('Cache.cacheInvalidHandlers'));
throw CacheException::forInvalidHandlers();
}
if ( ! isset($config->handler) || ! isset($config->backupHandler))
{
throw new \InvalidArgumentException(lang('Cache.cacheNoBackup'));
throw CacheException::forNoBackup();
}
$handler = ! empty($handler) ? $handler : $config->handler;
@ -72,7 +73,7 @@ class CacheFactory
if ( ! array_key_exists($handler, $config->validHandlers) || ! array_key_exists($backup, $config->validHandlers))
{
throw new \InvalidArgumentException(lang('Cache.cacheHandlerNotFound'));
throw CacheException::forHandlerNotFound();
}
// Get an instance of our handler.

View File

@ -0,0 +1,28 @@
<?php namespace CodeIgniter\Cache\Exceptions;
class CacheException extends \RuntimeException implements ExceptionInterface
{
/**
* @return \CodeIgniter\Cache\Exceptions\CacheException
*/
public static function forInvalidHandlers()
{
return new static(lang('Cache.invalidHandlers'));
}
/**
* @return \CodeIgniter\Cache\Exceptions\CacheException
*/
public static function forNoBackup()
{
return new static(lang('Cache.noBackup'));
}
/**
* @return \CodeIgniter\Cache\Exceptions\CacheException
*/
public static function forHandlerNotFound()
{
return new static(lang('Cache.handlerNotFound'));
}
}

View File

@ -0,0 +1,11 @@
<?php namespace CodeIgniter\Cache\Exceptions;
/**
* Provides a domain-level interface for broad capture
* of all framework-related exceptions.
*
* catch (\CodeIgniter\Cache\Exceptions\ExceptionInterface) { ... }
*/
interface ExceptionInterface
{
}

View File

@ -59,7 +59,7 @@ class FileHandler implements CacheInterface
public function __construct($config)
{
$this->prefix = $config->prefix ?: '';
$this->path = ! empty($config->path) ? $config->path : WRITEPATH . 'cache';
$this->path = ! empty($config->storePath) ? $config->storePath : WRITEPATH . 'cache';
$this->path = rtrim($this->path, '/') . '/';
}
@ -322,7 +322,14 @@ class FileHandler implements CacheInterface
*/
protected function writeFile($path, $data, $mode = 'wb')
{
if (($fp = @fopen($path, $mode)) === false)
try
{
if (($fp = @fopen($path, $mode)) === false)
{
return false;
}
}
catch (\ErrorException $e)
{
return false;
}

View File

@ -287,7 +287,8 @@ class MemcachedHandler implements CacheInterface
$stored = $this->memcached->get($key);
if (count($stored) !== 3)
// if not an array, don't try to count for PHP7.2
if (! is_array($stored) || count($stored) !== 3)
{
return FALSE;
}
@ -310,7 +311,7 @@ class MemcachedHandler implements CacheInterface
*/
public function isSupported(): bool
{
return (extension_loaded('memcached') OR extension_loaded('memcache'));
return (extension_loaded('memcached') || extension_loaded('memcache'));
}
}

View File

@ -95,7 +95,7 @@ class PredisHandler implements CacheInterface
// Check if the connection is valid by trying to get the time.
$this->redis->time();
} catch (Exception $e)
} catch (\Exception $e)
{
// thrown if can't connect to redis server.
throw new CriticalError('Cache: Predis connection refused (' . $e->getMessage() . ')');
@ -117,7 +117,7 @@ class PredisHandler implements CacheInterface
['__ci_type', '__ci_value'], $this->redis->hmget($key, ['__ci_type', '__ci_value'])
);
if ( ! isset($data['__ci_type'], $data['__ci_value']) OR $data['__ci_value'] === false)
if ( ! isset($data['__ci_type'], $data['__ci_value']) || $data['__ci_value'] === false)
{
return false;
}
@ -263,7 +263,7 @@ class PredisHandler implements CacheInterface
{
$data = array_combine(['__ci_value'], $this->redis->hmget($key, ['__ci_value']));
if (isset($data['__ci_value']) AND $data['__ci_value'] !== false)
if (isset($data['__ci_value']) && $data['__ci_value'] !== false)
{
return [
'expire' => time() + $this->redis->ttl($key),

View File

@ -35,8 +35,8 @@
* @since Version 3.0.0
* @filesource
*/
use CodeIgniter\Exceptions\CriticalError;
use CodeIgniter\Cache\CacheInterface;
use CodeIgniter\CriticalError;
class RedisHandler implements CacheInterface
{
@ -70,13 +70,14 @@ class RedisHandler implements CacheInterface
//--------------------------------------------------------------------
public function __construct(array $config)
public function __construct($config)
{
$config = (array)$config;
$this->prefix = $config['prefix'] ?? '';
if ( ! empty($config))
{
$this->config = array_merge($this->config, $config);
$this->config = array_merge($this->config, $config['redis']);
}
}
@ -116,7 +117,7 @@ class RedisHandler implements CacheInterface
{
// log_message('error', 'Cache: Redis authentication failed.');
}
} catch (RedisException $e)
} catch (\RedisException $e)
{
throw new CriticalError('Cache: Redis connection refused (' . $e->getMessage() . ')');
}
@ -137,7 +138,7 @@ class RedisHandler implements CacheInterface
$data = $this->redis->hMGet($key, ['__ci_type', '__ci_value']);
if ( ! isset($data['__ci_type'], $data['__ci_value']) OR $data['__ci_value'] === false)
if ( ! isset($data['__ci_type'], $data['__ci_value']) || $data['__ci_value'] === false)
{
return false;
}

View File

@ -36,6 +36,8 @@
* @filesource
*/
use CodeIgniter\HTTP\RedirectResponse;
use CodeIgniter\HTTP\Request;
use CodeIgniter\HTTP\ResponseInterface;
use Config\Services;
use Config\Cache;
use CodeIgniter\HTTP\URI;
@ -44,6 +46,7 @@ use CodeIgniter\Events\Events;
use CodeIgniter\HTTP\Response;
use CodeIgniter\HTTP\CLIRequest;
use CodeIgniter\Router\RouteCollectionInterface;
use CodeIgniter\Exceptions\PageNotFoundException;
/**
* This class is the core of the framework, and will analyse the
@ -64,12 +67,6 @@ class CodeIgniter
*/
protected $startTime;
/**
* Amount of memory at app start.
* @var int
*/
protected $startMemory;
/**
* Total app execution time
* @var float
@ -136,12 +133,18 @@ class CodeIgniter
*/
protected $path;
/**
* Should the Response instance "pretend"
* to keep from setting headers/cookies/etc
* @var bool
*/
protected $useSafeOutput = false;
//--------------------------------------------------------------------
public function __construct($config)
{
$this->startTime = microtime(true);
$this->startMemory = memory_get_usage(true);
$this->config = $config;
}
@ -179,8 +182,12 @@ class CodeIgniter
* makes all of the pieces work together.
*
* @param \CodeIgniter\Router\RouteCollectionInterface $routes
* @param bool $returnResponse
*
* @throws \CodeIgniter\HTTP\RedirectException
* @throws \Exception
*/
public function run(RouteCollectionInterface $routes = null)
public function run(RouteCollectionInterface $routes = null, bool $returnResponse = false)
{
$this->startBenchmark();
@ -196,12 +203,23 @@ class CodeIgniter
// Check for a cached page. Execution will stop
// if the page has been cached.
$cacheConfig = new Cache();
$this->displayCache($cacheConfig);
$response = $this->displayCache($cacheConfig);
if ($response instanceof ResponseInterface)
{
if ($returnResponse)
{
return $response;
}
$this->response->pretend($this->useSafeOutput)->send();
$this->callExit(EXIT_SUCCESS);
}
try
{
$this->handleRequest($routes, $cacheConfig);
} catch (Router\RedirectException $e)
return $this->handleRequest($routes, $cacheConfig, $returnResponse);
}
catch (Router\RedirectException $e)
{
$logger = Services::logger();
$logger->info('REDIRECTED ROUTE at ' . $e->getMessage());
@ -219,13 +237,35 @@ class CodeIgniter
//--------------------------------------------------------------------
/**
* Set our Response instance to "pretend" mode so that things like
* cookies and headers are not actually sent, allowing PHP 7.2+ to
* not complain when ini_set() function is used.
*
* @param bool $safe
*
* @return $this
*/
public function useSafeOutput(bool $safe = true)
{
$this->useSafeOutput = $safe;
return $this;
}
//--------------------------------------------------------------------
/**
* Handles the main request logic and fires the controller.
*
* @param \CodeIgniter\Router\RouteCollectionInterface $routes
* @param $cacheConfig
* @param bool $returnResponse
*
* @return \CodeIgniter\HTTP\RequestInterface|\CodeIgniter\HTTP\Response|\CodeIgniter\HTTP\ResponseInterface|mixed
* @throws \CodeIgniter\Filters\Exceptions\FilterException
*/
protected function handleRequest(RouteCollectionInterface $routes = null, $cacheConfig)
protected function handleRequest(RouteCollectionInterface $routes = null, $cacheConfig, bool $returnResponse = false)
{
$this->tryToRouteIt($routes);
@ -233,7 +273,16 @@ class CodeIgniter
$filters = Services::filters();
$uri = $this->request instanceof CLIRequest ? $this->request->getPath() : $this->request->uri->getPath();
$filters->run($uri, 'before');
$possibleRedirect = $filters->run($uri, 'before');
if($possibleRedirect instanceof RedirectResponse)
{
return $possibleRedirect;
}
// If a Response instance is returned, the Response will be sent back to the client and script execution will stop
if($possibleRedirect instanceof ResponseInterface)
{
return $possibleRedirect->send();
}
$returned = $this->startController();
@ -256,6 +305,11 @@ class CodeIgniter
// Handle any redirects
if ($returned instanceof RedirectResponse)
{
if ($returnResponse)
{
return $returned;
}
$this->callExit(EXIT_SUCCESS);
}
@ -278,12 +332,17 @@ class CodeIgniter
unset($uri);
$this->sendResponse();
if (! $returnResponse)
{
$this->sendResponse();
}
//--------------------------------------------------------------------
// Is there a post-system event?
//--------------------------------------------------------------------
Events::trigger('post_system');
return $this->response;
}
//--------------------------------------------------------------------
@ -357,6 +416,23 @@ class CodeIgniter
//--------------------------------------------------------------------
/**
* Sets a Request object to be used for this request.
* Used when running certain tests.
*
* @param \CodeIgniter\HTTP\Request $request
*
* @return \CodeIgniter\CodeIgniter
*/
public function setRequest(Request $request)
{
$this->request = $request;
return $this;
}
//--------------------------------------------------------------------
/**
* Get our Request object, (either IncomingRequest or CLIRequest)
* and set the server protocol based on the information provided
@ -364,14 +440,20 @@ class CodeIgniter
*/
protected function getRequestObject()
{
if (is_cli())
if ($this->request instanceof Request)
{
return;
}
if (is_cli() && ! (ENVIRONMENT == 'testing'))
{
$this->request = Services::clirequest($this->config);
}
else
{
$this->request = Services::request($this->config);
$this->request->setProtocolVersion($_SERVER['SERVER_PROTOCOL']);
// guess at protocol if needed
$this->request->setProtocolVersion($_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.1');
}
}
@ -385,7 +467,7 @@ class CodeIgniter
{
$this->response = Services::response($this->config);
if ( ! is_cli())
if ( ! is_cli() || ENVIRONMENT == 'testing')
{
$this->response->setProtocolVersion($this->request->getProtocolVersion());
}
@ -453,8 +535,9 @@ class CodeIgniter
}
$output = $this->displayPerformanceMetrics($output);
$this->response->setBody($output)->send();
$this->callExit(EXIT_SUCCESS);
$this->response->setBody($output);
return $this->response;
};
}
@ -469,7 +552,7 @@ class CodeIgniter
*/
public static function cache(int $time)
{
self::$cacheTTL = (int) $time;
self::$cacheTTL = $time;
}
//--------------------------------------------------------------------
@ -507,7 +590,6 @@ class CodeIgniter
return [
'startTime' => $this->startTime,
'totalTime' => $this->totalTime,
'startMemory' => $this->startMemory
];
}
@ -522,7 +604,7 @@ class CodeIgniter
*/
protected function generateCacheName($config): string
{
if (is_cli())
if (is_cli() && ! (ENVIRONMENT == 'testing'))
{
return md5($this->request->getPath());
}
@ -616,7 +698,7 @@ class CodeIgniter
return $this->path;
}
return is_cli() ? $this->request->getPath() : $this->request->uri->getPath();
return (is_cli() && ! (ENVIRONMENT == 'testing')) ? $this->request->getPath() : $this->request->uri->getPath();
}
//--------------------------------------------------------------------
@ -660,19 +742,19 @@ class CodeIgniter
// No controller specified - we don't know what to do now.
if (empty($this->controller))
{
throw new PageNotFoundException('Controller is empty.');
throw PageNotFoundException::forEmptyController();
}
// Try to autoload the class
if ( ! class_exists($this->controller, true) || $this->method[0] === '_')
{
throw new PageNotFoundException('Controller or its method is not found.');
throw PageNotFoundException::forControllerNotFound($this->controller, $this->method);
}
else if ( ! method_exists($this->controller, '_remap') &&
! is_callable([$this->controller, $this->method], false)
)
{
throw new PageNotFoundException('Controller method is not found.');
throw PageNotFoundException::forMethodNotFound($this->method);
}
}
@ -685,7 +767,8 @@ class CodeIgniter
*/
protected function createController()
{
$class = new $this->controller($this->request, $this->response);
$class = new $this->controller();
$class->initController($this->request, $this->response, Services::logger());
$this->benchmark->stop('controller_constructor');
@ -755,7 +838,7 @@ class CodeIgniter
}
// Display 404 Errors
$this->response->setStatusCode(404);
$this->response->setStatusCode($e->getCode());
if (ENVIRONMENT !== 'testing')
{
@ -773,7 +856,7 @@ class CodeIgniter
}
}
throw new PageNotFoundException(lang('HTTP.pageNotFound'));
throw PageNotFoundException::forPageNotFound($e->getMessage());
}
//--------------------------------------------------------------------
@ -875,7 +958,7 @@ class CodeIgniter
*/
protected function sendResponse()
{
$this->response->send();
$this->response->pretend($this->useSafeOutput)->send();
}
//--------------------------------------------------------------------

View File

@ -108,15 +108,15 @@ class CreateMigration extends BaseCommand
if (empty($name))
{
$name = CLI::prompt(lang('Migrations.migNameMigration'));
$name = CLI::prompt(lang('Migrations.nameMigration'));
}
if (empty($name))
{
CLI::error(lang('Migrations.migBadCreateName'));
CLI::error(lang('Migrations.badCreateName'));
return;
}
$namespace = CLI::getOption('n');
$ns = CLI::getOption('n');
$homepath = APPPATH;
if ( ! empty($ns))
@ -168,7 +168,7 @@ EOD;
helper('filesystem');
if ( ! write_file($path, $template))
{
CLI::error(lang('Migrations.migWriteError'));
CLI::error(lang('Migrations.writeError'));
return;
}

View File

@ -102,7 +102,7 @@ class MigrateCurrent extends BaseCommand
{
$runner = Services::migrations();
CLI::write(lang('Migrations.migToVersion'), 'yellow');
CLI::write(lang('Migrations.toVersion'), 'yellow');
$group = CLI::getOption('g');
try
@ -115,13 +115,13 @@ class MigrateCurrent extends BaseCommand
}
CLI::write('Done');
} catch (\Exception $e)
{
$this->showError($e);
}
}
}

View File

@ -102,7 +102,7 @@ class MigrateLatest extends BaseCommand
{
$runner = Services::migrations();
CLI::write(lang('Migrations.migToLatest'), 'yellow');
CLI::write(lang('Migrations.toLatest'), 'yellow');
$namespace = CLI::getOption('n');
$group = CLI::getOption('g');
@ -124,13 +124,13 @@ class MigrateLatest extends BaseCommand
}
CLI::write('Done');
} catch (\Exception $e)
{
$this->showError($e);
}
}
}

View File

@ -106,7 +106,7 @@ class MigrateRollback extends BaseCommand
{
$runner = Services::migrations();
CLI::write(lang('Migrations.migRollingBack'), 'yellow');
CLI::write(lang('Migrations.rollingBack'), 'yellow');
$group = CLI::getOption('g');
if ( ! is_null($group))
{
@ -148,7 +148,7 @@ class MigrateRollback extends BaseCommand
$this->showError($e);
}
}
}

View File

@ -93,6 +93,12 @@ class MigrateStatus extends BaseCommand
'-g' => 'Set database group',
];
protected $ignoredNamespaces = [
'CodeIgniter',
'Config',
'Tests\Support'
];
/**
* Displays a list of all migrations and whether they've been run or not.
*
@ -114,25 +120,25 @@ class MigrateStatus extends BaseCommand
// Loop for all $namespaces
foreach ($namespaces as $namespace => $path)
{
if (in_array($namespace, $this->ignoredNamespaces))
{
continue;
}
$runner->setNamespace($namespace);
$migrations = $runner->findMigrations();
$history = $runner->getHistory();
CLI::write($namespace);
if (empty($migrations))
{
CLI::error("$namespace: " . lang('Migrations.migNoneFound'));
CLI::error(lang('Migrations.noneFound'));
continue;
}
ksort($migrations);
CLI::newLine(1);
CLI::write(lang('Migrations.migHistoryFor') . "$namespace: ", 'green');
CLI::newLine(1);
$max = 0;
foreach ($migrations as $version => $migration)
{
@ -142,7 +148,7 @@ class MigrateStatus extends BaseCommand
$max = max($max, strlen($file));
}
CLI::write(str_pad(lang('Migrations.filename'), $max + 6) . lang('Migrations.migOn'), 'yellow');
CLI::write(' '. str_pad(lang('Migrations.filename'), $max + 4) . lang('Migrations.on'), 'yellow');
foreach ($migrations as $version => $migration)
@ -157,7 +163,7 @@ class MigrateStatus extends BaseCommand
$date = date("Y-m-d H:i:s", $row['time']);
}
CLI::write(str_pad($migration->name, $max + 6) . ($date ? $date : '---'));
CLI::write(str_pad(' '.$migration->name, $max + 6) . ($date ? $date : '---'));
}
}
}

View File

@ -118,7 +118,7 @@ class MigrateVersion extends BaseCommand
exit();
}
CLI::write(sprintf(lang('Migrations.migToVersionPH'), $version), 'yellow');
CLI::write(sprintf(lang('Migrations.toVersionPH'), $version), 'yellow');
$namespace = CLI::getOption('n');
$group = CLI::getOption('g');
@ -131,7 +131,7 @@ class MigrateVersion extends BaseCommand
$this->showError($e);
}
}
}

View File

@ -125,77 +125,68 @@ class ListCommands extends BaseCommand
*/
protected function describeCommands(array $commands = [])
{
arsort($commands);
ksort($commands);
$names = array_keys($commands);
$descs = array_column($commands, 'description');
$groups = array_column($commands, 'group');
$lastGroup = '';
// Sort into buckets by group
$sorted = [];
$maxTitleLength = 0;
// Pad each item to the same length
$names = $this->padArray($names, 2, 2);
$countNames = count($names);
for ($i = 0; $i < $countNames; $i ++ )
foreach ($commands as $title => $command)
{
$lastGroup = $this->describeGroup($groups[$i], $lastGroup);
$out = CLI::color($names[$i], 'yellow');
if (isset($descs[$i]))
if (! isset($sorted[$command['group']]))
{
$out .= CLI::wrap($descs[$i], 125, strlen($names[$i]));
$sorted[$command['group']] = [];
}
CLI::write($out);
$sorted[$command['group']][$title] = $command;
$maxTitleLength = max($maxTitleLength, strlen($title));
}
}
//--------------------------------------------------------------------
ksort($sorted);
/**
* Outputs the description, if necessary.
*
* @param string $new
* @param string $old
*
* @return string
*/
protected function describeGroup(string $new, string $old)
{
if ($new == $old)
// Display it all...
foreach ($sorted as $group => $items)
{
return $old;
CLI::newLine();
CLI::write($group);
foreach ($items as $title => $item)
{
$title = $this->padTitle($title, $maxTitleLength, 2, 2);
$out = CLI::color($title, 'yellow');
if (isset($item['description']))
{
$out .= CLI::wrap($item['description'], 125, strlen($title));
}
CLI::write($out);
}
}
CLI::newLine();
CLI::write($new);
return $new;
}
//--------------------------------------------------------------------
/**
* Returns a new array where all of the string elements have
* been padding with trailing spaces to be the same length.
* Pads our string out so that all titles are the same length to nicely line up descriptions.
*
* @param array $array
* @param int $extra // How many extra spaces to add at the end
* @param int $indent
* @param string $item
* @param $max
* @param int $extra // How many extra spaces to add at the end
* @param int $indent
*
* @return array
*/
protected function padArray($array, $extra = 2, $indent = 0)
protected function padTitle(string $item, $max, $extra = 2, $indent = 0)
{
$max = max(array_map('strlen', $array)) + $extra + $indent;
$max += $extra + $indent;
foreach ($array as &$item)
{
$item = str_repeat(' ', $indent) . $item;
$item = str_pad($item, $max);
}
$item = str_repeat(' ', $indent) . $item;
$item = str_pad($item, $max);
return $array;
return $item;
}
//--------------------------------------------------------------------

View File

@ -0,0 +1,85 @@
<?php namespace CodeIgniter\Commands\Server;
/**
* CodeIgniter
*
* An open source application development framework for PHP
*
* This content is released under the MIT License (MIT)
*
* Copyright (c) 2014-2018 British Columbia Institute of Technology
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @package CodeIgniter
* @author CodeIgniter Dev Team
* @copyright 2014-2018 British Columbia Institute of Technology (https://bcit.ca/)
* @license https://opensource.org/licenses/MIT MIT License
* @link https://codeigniter.com
* @since Version 3.0.0
* @filesource
*/
use CodeIgniter\CLI\BaseCommand;
use CodeIgniter\CLI\CLI;
/**
* Launch the PHP development server
*
* Not testable, as it throws phpunit for a loop :-/
* @codeCoverageIgnore
*/
class Serve extends BaseCommand
{
protected $group = 'CodeIgniter';
protected $name = 'serve';
protected $description = 'Launchs the CodeIgniter PHP-Development Server.';
protected $usage = 'serve';
protected $arguments = [];
protected $options = [
'-php' => 'The PHP Binary [default: "PHP_BINARY"]',
'-host' => 'The HTTP Host [default: "localhost"]',
'-port' => 'The HTTP Host Port [default: "8080"]',
];
public function run(array $params)
{
// Collect any user-supplied options and apply them
$php = CLI::getOption('php') ?? PHP_BINARY;
$host = CLI::getOption('host') ?? 'localhost';
$port = CLI::getOption('port') ?? '8080';
// Get the party started
CLI::write("CodeIgniter development server started on http://{$host}:{$port}", 'green');
CLI::write('Press Control-C to stop.');
// Set the Front Controller path as Document Root
$docroot = FCPATH;
// Mimic Apache's mod_rewrite functionality with user settings
$rewrite = __DIR__ . '/rewrite.php';
// Call PHP's built-in webserver, making sure to set our
// base path to the public folder, and to use the rewrite file
// to ensure our environment is set and it simulates basic mod_rewrite.
passthru("{$php} -S {$host}:{$port} -t {$docroot} {$rewrite}");
}
}

View File

@ -2,11 +2,18 @@
/**
* CodeIgniter PHP-Development Server Rewrite Rules
*
* This script works with serve.php to help run a seamless
* This script works with the CLI serve command to help run a seamless
* development server based around PHP's built-in development
* server. This file simply tries to mimic Apache's mod_rewrite
* functionality so the site will operate as normal.
*
*/
// @codeCoverageIgnoreStart
// Avoid this file run when listing commands
if (php_sapi_name() === 'cli')
{
return;
}
// If we're serving the site locally, then we need
// to let the application know that we're in development mode
@ -14,15 +21,20 @@ $_SERVER['CI_ENVIRONMENT'] = 'development';
$uri = urldecode(parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH));
$path = __DIR__.'/public/'.ltrim($uri,'/');
// Front Controller path - expected to be in the default folder
$fcpath = $_SERVER['DOCUMENT_ROOT'] . DIRECTORY_SEPARATOR;
// Full path
$path = $fcpath . ltrim($uri, '/');
// If $path is an existing file or folder within the public folder
// then let the request handle it like normal.
if ($uri !== '/' && (is_file($path) || is_dir($path)))
{
return false;
return false;
}
// Otherwise, we'll load the index file and let
// the framework handle the request from here.
require_once __DIR__.'/public/index.php';
require_once $fcpath . 'index.php';
// @codeCoverageIgnoreEnd

View File

@ -39,6 +39,12 @@ use CodeIgniter\CLI\BaseCommand;
use CodeIgniter\CLI\CLI;
use Config\App;
/**
* Creates a migration file for database sessions.
*
* @package CodeIgniter\Commands
*/
class CreateMigration extends BaseCommand
{
@ -98,7 +104,7 @@ class CreateMigration extends BaseCommand
{
$config = new App();
$tableName = CLI::getOption('t') ?? $config->sessionSavePath ?? 'ci_sessions';
$tableName = CLI::getOption('t') ?? 'ci_sessions';
$path = APPPATH . 'Database/Migrations/' . date('YmdHis_') . 'create_' . $tableName . '_table' . '.php';
@ -109,7 +115,7 @@ class CreateMigration extends BaseCommand
'matchIP' => $config->sessionMatchIP ?? false,
];
$template = view('\CodeIgniter\Commands\Sessions\Views\migration.tpl', $data);
$template = view('\CodeIgniter\Commands\Sessions\Views\migration.tpl', $data, ['debug' => false]);
$template = str_replace('@php', '<?php', $template);
// Write the file out.

View File

@ -1,41 +1,5 @@
@php namespace <?= $namespace ?>\Database\Migrations;
/**
* CodeIgniter
*
* An open source application development framework for PHP
*
* This content is released under the MIT License (MIT)
*
* Copyright (c) 2014-2018 British Columbia Institute of Technology
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @package CodeIgniter
* @author CodeIgniter Dev Team
* @copyright 2014-2018 British Columbia Institute of Technology (https://bcit.ca/)
* @license https://opensource.org/licenses/MIT MIT License
* @link https://codeigniter.com
* @since Version 3.0.0
* @filesource
*/
use CodeIgniter\Database\Migration;
class Migration_create_<?= $tableName ?>_table extends Migration

View File

@ -0,0 +1,123 @@
<?php namespace CodeIgniter\Commands\Utilities;
/**
* CodeIgniter
*
* An open source application development framework for PHP
*
* This content is released under the MIT License (MIT)
*
* Copyright (c) 2014-2018 British Columbia Institute of Technology
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @package CodeIgniter
* @author CodeIgniter Dev Team
* @copyright 2014-2018 British Columbia Institute of Technology (https://bcit.ca/)
* @license https://opensource.org/licenses/MIT MIT License
* @link https://codeigniter.com
* @since Version 3.0.0
* @filesource
*/
use CodeIgniter\CLI\BaseCommand;
use CodeIgniter\CLI\CLI;
use Config\Autoload;
/**
* Lists namespaces set in Config\Autoload with their
* full server path. Helps you to verify that you have
* the namespaces setup correctly.
*
* @package CodeIgniter\Commands
*/
class Namespaces extends BaseCommand
{
/**
* The group the command is lumped under
* when listing commands.
*
* @var string
*/
protected $group = 'CodeIgniter';
/**
* The Command's name
*
* @var string
*/
protected $name = 'namespaces';
/**
* the Command's short description
*
* @var string
*/
protected $description = 'Verifies your namespaces are setup correctly.';
/**
* the Command's usage
*
* @var string
*/
protected $usage = 'namespaces';
/**
* the Command's Arguments
*
* @var array
*/
protected $arguments = [];
/**
* the Command's Options
*
* @var array
*/
protected $options = [];
//--------------------------------------------------------------------
/**
* Displays the help for the spark cli script itself.
*
* @param array $params
*/
public function run(array $params)
{
$config = new Autoload();
$tbody = [];
foreach ($config->psr4 as $ns => $path)
{
$path = realpath($path) ?? $path;
$tbody[] = [
$ns,
realpath($path) ?? $path,
is_dir($path) ? "Yes" : "MISSING"
];
}
$thead = ['Namespace', 'Path', 'Found?'];
CLI::table($tbody, $thead);
}
}

View File

@ -0,0 +1,125 @@
<?php namespace CodeIgniter\Commands\Utilities;
/**
* CodeIgniter
*
* An open source application development framework for PHP
*
* This content is released under the MIT License (MIT)
*
* Copyright (c) 2014-2018 British Columbia Institute of Technology
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*RouRouddfdf
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @package CodeIgniter
* @author CodeIgniter Dev Team
* @copyright 2014-2018 British Columbia Institute of Technology (https://bcit.ca/)
* @license https://opensource.org/licenses/MIT MIT License
* @link https://codeigniter.com
* @since Version 3.0.0
* @filesource
*/
use CodeIgniter\CLI\BaseCommand;
use CodeIgniter\CLI\CLI;
use Config\Services;
/**
* Lists all of the user-defined routes. This will include any Routes files
* that can be discovered, but will NOT include any routes that are not defined
* in a routes file, but are instead discovered through auto-routing.
*
* @package CodeIgniter\Commands
*/
class Routes extends BaseCommand
{
/**
* The group the command is lumped under
* when listing commands.
*
* @var string
*/
protected $group = 'CodeIgniter';
/**
* The Command's name
*
* @var string
*/
protected $name = 'routes';
/**
* the Command's short description
*
* @var string
*/
protected $description = 'Displays all of user-defined routes. Does NOT display auto-detected routes.';
/**
* the Command's usage
*
* @var string
*/
protected $usage = 'routes';
/**
* the Command's Arguments
*
* @var array
*/
protected $arguments = [];
/**
* the Command's Options
*
* @var array
*/
protected $options = [];
//--------------------------------------------------------------------
/**
* Displays the help for the spark cli script itself.
*
* @param array $params
*/
public function run(array $params)
{
$collection = Services::routes(true);
$methods = ['get', 'head', 'post', 'put', 'delete', 'options', 'trace', 'connect', 'cli'];
$tbody = [];
foreach ($methods as $method)
{
$routes = $collection->getRoutes($method);
foreach ($routes as $from => $to)
$tbody[] = [
$from,
$method,
$to
];
}
$thead = ['Route', 'Method', 'Command'];
CLI::table($tbody, $thead);
}
}

View File

@ -85,6 +85,24 @@ if ( ! function_exists('cache'))
//--------------------------------------------------------------------
if ( ! function_exists('config'))
{
/**
* More simple way of getting config instances
*
* @param string $name
* @param bool $getShared
*
* @return mixed
*/
function config(string $name, bool $getShared = true)
{
return \CodeIgniter\Config\Config::get($name, $getShared);
}
}
//--------------------------------------------------------------------
if ( ! function_exists('view'))
{
@ -252,8 +270,16 @@ if ( ! function_exists('esc'))
$method = 'escape' . ucfirst($context);
}
// @todo Optimize this to only load a single instance during page request.
$escaper = new \Zend\Escaper\Escaper($encoding);
static $escaper;
if (! $escaper)
{
$escaper = new \Zend\Escaper\Escaper($encoding);
}
if ($encoding && $escaper->getEncoding() !== $encoding)
{
$escaper = new \Zend\Escaper\Escaper($encoding);
}
$data = $escaper->$method($data);
}
@ -282,14 +308,15 @@ if ( ! function_exists('session'))
*/
function session($val = null)
{
$session = \Config\Services::session();
// Returning a single item?
if (is_string($val))
{
helper('array');
return dot_array_search($val, $_SESSION);
return $session->get($val);
}
return \Config\Services::session();
return $session;
}
}
@ -434,13 +461,15 @@ if ( ! function_exists('log_message'))
// for asserting that logs were called in the test code.
if (ENVIRONMENT == 'testing')
{
$logger = new \CodeIgniter\Log\TestLogger(new \Config\Logger());
$logger = new \Tests\Support\Log\TestLogger(new \Config\Logger());
return $logger->log($level, $message, $context);
}
// @codeCoverageIgnoreStart
return Services::logger(true)
->log($level, $message, $context);
// @codeCoverageIgnoreEnd
}
}
@ -584,7 +613,7 @@ if ( ! function_exists('app_timezone'))
*/
function app_timezone()
{
$config = new \Config\App();
$config = config(\Config\App::class);
return $config->appTimezone;
}
@ -605,7 +634,7 @@ if ( ! function_exists('csrf_token'))
*/
function csrf_token()
{
$config = new \Config\App();
$config = config(\Config\App::class);
return $config->CSRFTokenName;
}
@ -667,6 +696,11 @@ if ( ! function_exists('force_https'))
* Defaults to 1 year.
* @param RequestInterface $request
* @param ResponseInterface $response
*
* Not testable, as it will exit!
*
* @throws \CodeIgniter\HTTP\RedirectException
* @codeCoverageIgnore
*/
function force_https(int $duration = 31536000, RequestInterface $request = null, ResponseInterface $response = null)
{
@ -679,7 +713,7 @@ if ( ! function_exists('force_https'))
$response = Services::response(null, true);
}
if ($request->isSecure())
if (is_cli() || $request->isSecure())
{
return;
}
@ -716,12 +750,13 @@ if (! function_exists('old'))
* Provides access to "old input" that was set in the session
* during a redirect()->withInput().
*
* @param string $key
* @param null $default
* @param string $key
* @param null $default
* @param string|bool $escape
*
* @return mixed|null
*/
function old(string $key, $default=null)
function old(string $key, $default = null, $escape = 'html')
{
$request = Services::request();
@ -735,12 +770,12 @@ if (! function_exists('old'))
}
// If the result was serialized array or string, then unserialize it for use...
if (substr($value, 0, 2) == 'a:' || substr($value, 0, 2) == 's:')
if (strpos($value, 'a:') === 0 || strpos($value, 's:') === 0)
{
$value = unserialize($value);
}
return $value;
return $escape === false ? $value : esc($value, $escape);
}
}
@ -835,6 +870,8 @@ if ( ! function_exists('is_really_writable'))
* @param string $file
*
* @return bool
*
* @codeCoverageIgnore Not practical to test, as travis runs on linux
*/
function is_really_writable($file)
{
@ -861,7 +898,7 @@ if ( ! function_exists('is_really_writable'))
return true;
}
elseif ( ! is_file($file) OR ( $fp = @fopen($file, 'ab')) === false)
elseif ( ! is_file($file) || ( $fp = @fopen($file, 'ab')) === false)
{
return false;
}
@ -890,7 +927,7 @@ if ( ! function_exists('slash_item'))
*/
function slash_item($item)
{
$config = new \Config\App();
$config = config(\Config\App::class);
$configItem = $config->{$item};
if ( ! isset($configItem) || empty(trim($configItem)))
@ -929,6 +966,8 @@ if ( ! function_exists('function_usable'))
* @param string $function_name Function to check for
* @return bool TRUE if the function exists and is safe to call,
* FALSE otherwise.
*
* @codeCoverageIgnore This is too exotic
*/
function function_usable($function_name)
{
@ -957,6 +996,8 @@ if (! function_exists('dd'))
* Prints a Kint debug report and exits.
*
* @param array ...$vars
*
* @codeCoverageIgnore Can't be tested ... exits
*/
function dd(...$vars)
{

View File

@ -91,7 +91,7 @@ class AutoloadConfig
if (isset($_SERVER['CI_ENVIRONMENT']) && $_SERVER['CI_ENVIRONMENT'] === 'testing')
{
$this->psr4['Tests\Support'] = BASEPATH . '../tests/_support/';
$this->psr4['Tests\Support'] = BASEPATH . '../tests/_support';
}
/**
@ -143,10 +143,6 @@ class AutoloadConfig
'CodeIgniter\Debug\Exceptions' => BASEPATH . 'Debug/Exceptions.php',
'CodeIgniter\Debug\Timer' => BASEPATH . 'Debug/Timer.php',
'CodeIgniter\Debug\Iterator' => BASEPATH . 'Debug/Iterator.php',
'CodeIgniter\Encryption\Encryption' => BASEPATH . 'Encryption/Encryption.php',
'CodeIgniter\Encryption\EncrypterInterface' => BASEPATH . 'Encryption/EncrypterInterface.php',
'CodeIgniter\Encryption\Handlers\BaseHandler' => BASEPATH . 'Encryption/Handlers/BaseHandler.php',
'CodeIgniter\Encryption\Handlers\OpenSSLHandler' => BASEPATH . 'Encryption/Handlers/OpenSSLHandler.php',
'CodeIgniter\Events\Events' => BASEPATH . 'Events/Events.php',
'CodeIgniter\HTTP\CLIRequest' => BASEPATH . 'HTTP/CLIRequest.php',
'CodeIgniter\HTTP\ContentSecurityPolicy' => BASEPATH . 'HTTP/ContentSecurityPolicy.php',

View File

@ -59,7 +59,7 @@ class BaseConfig
/**
* Will attempt to get environment variables with names
* that match the properties of the child class.
*
*
* The "shortPrefix" is the lowercase-only config class name.
*/
public function __construct()
@ -78,12 +78,18 @@ class BaseConfig
if ($value = $this->getEnvValue("{$property}.{$key}", $prefix, $shortPrefix))
{
if (is_null($value))
{
continue;
}
if ($value === 'false')
{
$value = false;
}
elseif ($value === 'true')
{
$value = true;
}
$this->$property[$key] = $value;
}
@ -94,14 +100,22 @@ class BaseConfig
if (($value = $this->getEnvValue($property, $prefix, $shortPrefix)) !== false)
{
if (is_null($value))
{
continue;
}
if ($value === 'false')
{
$value = false;
}
elseif ($value === 'true')
{
$value = true;
}
$this->$property = $value;
$this->$property = is_bool($value)
? $value
: trim($value, '\'"');
}
}
}
@ -123,7 +137,8 @@ class BaseConfig
protected function getEnvValue(string $property, string $prefix, string $shortPrefix)
{
$shortPrefix = ltrim( $shortPrefix, '\\' );
switch (true) {
switch (true)
{
case array_key_exists( "{$shortPrefix}.{$property}", $_ENV ):
return $_ENV["{$shortPrefix}.{$property}"];
break;
@ -160,7 +175,9 @@ class BaseConfig
{
// ignore non-applicable registrars
if ( ! method_exists($callable, $shortName))
{
continue;
}
$properties = $callable::$shortName();

View File

@ -0,0 +1,241 @@
<?php namespace CodeIgniter\Config;
/**
* CodeIgniter
*
* An open source application development framework for PHP
*
* This content is released under the MIT License (MIT)
*
* Copyright (c) 2014-2018 British Columbia Institute of Technology
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @package CodeIgniter
* @author CodeIgniter Dev Team
* @copyright 2014-2018 British Columbia Institute of Technology (https://bcit.ca/)
* @license https://opensource.org/licenses/MIT MIT License
* @link https://codeigniter.com
* @since Version 3.0.0
* @filesource
*/
/**
* Services Configuration file.
*
* Services are simply other classes/libraries that the system uses
* to do its job. This is used by CodeIgniter to allow the core of the
* framework to be swapped out easily without affecting the usage within
* the rest of your application.
*
* This is used in place of a Dependency Injection container primarily
* due to its simplicity, which allows a better long-term maintenance
* of the applications built on top of CodeIgniter. A bonus side-effect
* is that IDEs are able to determine what class you are calling
* whereas with DI Containers there usually isn't a way for them to do this.
*
* @see http://blog.ircmaxell.com/2015/11/simple-easy-risk-and-change.html
* @see http://www.infoq.com/presentations/Simple-Made-Easy
*/
class BaseService
{
/**
* Cache for instance of any services that
* have been requested as a "shared" instance.
*
* @var array
*/
static protected $instances = [];
/**
* Mock objects for testing which are returned if exist.
*
* @var array
*/
static protected $mocks = [];
/**
* Have we already discovered other Services?
*
* @var bool
*/
static protected $discovered = false;
/**
* A cache of other service classes we've found.
*
* @var array
*/
static protected $services = [];
//--------------------------------------------------------------------
/**
* Returns a shared instance of any of the class' services.
*
* $key must be a name matching a service.
*
* @param string $key
* @param array ...$params
*
* @return mixed
*/
protected static function getSharedInstance(string $key, ...$params)
{
// Returns mock if exists
if (isset(static::$mocks[$key]))
{
return static::$mocks[$key];
}
if (! isset(static::$instances[$key]))
{
// Make sure $getShared is false
array_push($params, false);
static::$instances[$key] = static::$key(...$params);
}
return static::$instances[$key];
}
//--------------------------------------------------------------------
/**
* The file locator provides utility methods for looking for non-classes
* within namespaced folders, as well as convenience methods for
* loading 'helpers', and 'libraries'.
*
* @param bool $getShared
*
* @return \CodeIgniter\Autoloader\FileLocator
*/
public static function locator($getShared = true)
{
if ($getShared)
{
return self::getSharedInstance('locator');
}
return new \CodeIgniter\Autoloader\FileLocator(new \Config\Autoload());
}
//--------------------------------------------------------------------
/**
* Provides the ability to perform case-insensitive calling of service
* names.
*
* @param string $name
* @param array $arguments
*
* @return mixed
*/
public static function __callStatic(string $name, array $arguments)
{
$name = strtolower($name);
if (method_exists(__CLASS__, $name))
{
return Services::$name(...$arguments);
}
return static::discoverServices($name, $arguments);
}
//--------------------------------------------------------------------
/**
* Reset shared instances and mocks for testing.
*/
public static function reset()
{
static::$mocks = [];
static::$instances = [];
}
//--------------------------------------------------------------------
/**
* Inject mock object for testing.
*
* @param string $name
* @param $mock
*/
public static function injectMock(string $name, $mock)
{
$name = strtolower($name);
static::$mocks[$name] = $mock;
}
//--------------------------------------------------------------------
/**
* Will scan all psr4 namespaces registered with system to look
* for new Config\Services files. Caches a copy of each one, then
* looks for the service method in each, returning an instance of
* the service, if available.
*
* @param string $name
* @param array $arguments
*/
protected static function discoverServices(string $name, array $arguments)
{
if (! static::$discovered)
{
$locator = static::locator();
$files = $locator->search('Config/Services');
if (empty($files))
{
return;
}
// Get instances of all service classes and cache them locally.
foreach ($files as $file)
{
$classname = $locator->getClassname($file);
if (! in_array($classname, ['CodeIgniter\\Config\\Services']))
{
static::$services[] = new $classname();
}
}
static::$discovered = true;
}
if (! static::$services)
{
return;
}
// Try to find the desired service method
foreach (static::$services as $class)
{
if (method_exists(get_class($class), $name))
{
return $class::$name(...$arguments);
}
}
}
}

120
system/Config/Config.php Normal file
View File

@ -0,0 +1,120 @@
<?php namespace CodeIgniter\Config;
/**
* CodeIgniter
*
* An open source application development framework for PHP
*
* This content is released under the MIT License (MIT)
*
* Copyright (c) 2014-2018 British Columbia Institute of Technology
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @package CodeIgniter
* @author CodeIgniter Dev Team
* @copyright 2014-2018 British Columbia Institute of Technology (https://bcit.ca/)
* @license https://opensource.org/licenses/MIT MIT License
* @link https://codeigniter.com
* @since Version 3.0.0
* @filesource
*/
/**
* Class Config
*
* @package CodeIgniter\Config
*/
class Config
{
/**
* Cache for instance of any configurations that
* have been requested as "shared" instance.
*
* @var array
*/
static private $instances = [];
//--------------------------------------------------------------------
/**
* Create new configuration instances or return
* a shared instance
*
* @param string $name Configuration name
* @param boolean $getShared Use shared instance
*
* @return mixed|null
*/
public static function get(string $name, bool $getShared = true)
{
$class = $name;
if (($pos = strrpos($name, '\\')) !== false)
{
$class = substr($name, $pos + 1);
}
if (! $getShared)
{
return self::createClass($name);
}
if (! isset( self::$instances[$class] ))
{
self::$instances[$class] = self::createClass($name);
}
return self::$instances[$class];
}
//--------------------------------------------------------------------
/**
* Find configuration class and create instance
*
* @param string $name Classname
*
* @return mixed|null
*/
private static function createClass(string $name)
{
if (class_exists($name))
{
return new $name();
}
$locator = Services::locator();
$file = $locator->locateFile($name, 'Config');
if (empty($file))
{
return null;
}
$name = $locator->getClassname($file);
if (empty($name))
{
return null;
}
return new $name();
}
//--------------------------------------------------------------------
}

View File

@ -109,6 +109,7 @@ class DotEnv
}
}
return true; // for success
}
//--------------------------------------------------------------------
@ -126,11 +127,17 @@ class DotEnv
list($name, $value) = $this->normaliseVariable($name, $value);
if ( ! getenv($name, true))
{
putenv("$name=$value");
}
if (empty($_ENV[$name]))
{
$_ENV[$name] = $value;
}
if (empty($_SERVER[$name]))
{
$_SERVER[$name] = $value;
}
}
//--------------------------------------------------------------------

View File

@ -27,14 +27,15 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @package CodeIgniter
* @author CodeIgniter Dev Team
* @copyright 2014-2018 British Columbia Institute of Technology (https://bcit.ca/)
* @license https://opensource.org/licenses/MIT MIT License
* @link https://codeigniter.com
* @since Version 3.0.0
* @package CodeIgniter
* @author CodeIgniter Dev Team
* @copyright 2014-2018 British Columbia Institute of Technology (https://bcit.ca/)
* @license https://opensource.org/licenses/MIT MIT License
* @link https://codeigniter.com
* @since Version 3.0.0
* @filesource
*/
use Config\App;
use CodeIgniter\Database\ConnectionInterface;
use CodeIgniter\Database\MigrationRunner;
use CodeIgniter\View\RendererInterface;
@ -56,26 +57,8 @@ use CodeIgniter\View\RendererInterface;
* @see http://blog.ircmaxell.com/2015/11/simple-easy-risk-and-change.html
* @see http://www.infoq.com/presentations/Simple-Made-Easy
*/
class Services
class Services extends BaseService
{
/**
* Cache for instance of any services that
* have been requested as a "shared" instance.
*
* @var array
*/
static protected $instances = [];
/**
* Mock objects for testing which are returned if exist.
*
* @var array
*/
static protected $mocks = [];
//--------------------------------------------------------------------
/**
* The Autoloader class is the central class that handles our
* spl_autoload_register method, and helper methods.
@ -112,7 +95,7 @@ class Services
return self::getSharedInstance('cache', $config);
}
if ( ! is_object($config))
if (! is_object($config))
{
$config = new \Config\Cache();
}
@ -138,14 +121,12 @@ class Services
return self::getSharedInstance('clirequest', $config);
}
if ( ! is_object($config))
if (! is_object($config))
{
$config = new \Config\App();
$config = config(App::class);
}
return new \CodeIgniter\HTTP\CLIRequest(
$config, new \CodeIgniter\HTTP\URI()
);
return new \CodeIgniter\HTTP\CLIRequest($config);
}
//--------------------------------------------------------------------
@ -161,28 +142,27 @@ class Services
*
* @return \CodeIgniter\HTTP\CURLRequest
*/
public static function curlrequest(array $options = [], $response = null, \Config\App $config = null, $getShared = true)
{
public static function curlrequest(array $options = [], $response = null, \Config\App $config = null, $getShared = true) {
if ($getShared === true)
{
return self::getSharedInstance('curlrequest', $options, $response, $config);
}
if ( ! is_object($config))
if (! is_object($config))
{
$config = new \Config\App();
$config = config(App::class);
}
if ( ! is_object($response))
if (! is_object($response))
{
$response = new \CodeIgniter\HTTP\Response($config);
}
return new \CodeIgniter\HTTP\CURLRequest(
$config,
new \CodeIgniter\HTTP\URI(isset($options['base_uri']) ? : null),
$response,
$options
$config,
new \CodeIgniter\HTTP\URI($options['base_uri'] ?? null),
$response,
$options
);
}
@ -220,16 +200,22 @@ class Services
* - set_error_handler
* - register_shutdown_function
*
* @param \Config\Exceptions $config
* @param bool $getShared
* @param \Config\Exceptions $config
* @param \CodeIgniter\HTTP\IncomingRequest $request
* @param \CodeIgniter\HTTP\Response $response
* @param bool $getShared
*
* @return \CodeIgniter\Debug\Exceptions
*/
public static function exceptions(\Config\Exceptions $config = null, $getShared = true)
{
public static function exceptions(
\Config\Exceptions $config = null,
\CodeIgniter\HTTP\IncomingRequest $request = null,
\CodeIgniter\HTTP\Response $response = null,
$getShared = true
) {
if ($getShared)
{
return self::getSharedInstance('exceptions', $config);
return self::getSharedInstance('exceptions', $config, $request, $response);
}
if (empty($config))
@ -237,7 +223,17 @@ class Services
$config = new \Config\Exceptions();
}
return (new \CodeIgniter\Debug\Exceptions($config));
if (empty($request))
{
$request = static::request();
}
if (empty($response))
{
$response = static::response();
}
return (new \CodeIgniter\Debug\Exceptions($config, $request, $response));
}
//--------------------------------------------------------------------
@ -249,7 +245,7 @@ class Services
* act on or modify the response itself before it is sent to the client.
*
* @param mixed $config
* @param bool $getShared
* @param bool $getShared
*
* @return \CodeIgniter\Filters\Filters
*/
@ -334,37 +330,20 @@ class Services
{
if ($getShared)
{
return self::getSharedInstance('language', $locale);
return self::getSharedInstance('language', $locale)
->setLocale($locale);
}
$locale = ! empty($locale) ? $locale : self::request()->getLocale();
$locale = ! empty($locale)
? $locale
: self::request()
->getLocale();
return new \CodeIgniter\Language\Language($locale);
}
//--------------------------------------------------------------------
/**
* The file locator provides utility methods for looking for non-classes
* within namespaced folders, as well as convenience methods for
* loading 'helpers', and 'libraries'.
*
* @param bool $getShared
*
* @return \CodeIgniter\Autoloader\FileLocator
*/
public static function locator($getShared = true)
{
if ($getShared)
{
return self::getSharedInstance('locator');
}
return new \CodeIgniter\Autoloader\FileLocator(new \Config\Autoload());
}
//--------------------------------------------------------------------
/**
* The Logger class is a PSR-3 compatible Logging class that supports
* multiple handlers that process the actual logging.
@ -453,7 +432,7 @@ class Services
$config = new \Config\Pager();
}
if ( ! $view instanceof RendererInterface)
if (! $view instanceof RendererInterface)
{
$view = self::renderer();
}
@ -467,12 +446,12 @@ class Services
* The Parser is a simple template parser.
*
* @param string $viewPath
* @param mixed $config
* @param mixed $config
* @param bool $getShared
*
* @return \CodeIgniter\View\Parser
*/
public static function parser($viewPath = APPPATH . 'Views/', $config = null, $getShared = true)
public static function parser($viewPath = APPPATH.'Views/', $config = null, $getShared = true)
{
if ($getShared)
{
@ -500,7 +479,7 @@ class Services
*
* @return \CodeIgniter\View\View
*/
public static function renderer($viewPath = APPPATH . 'Views/', $config = null, $getShared = true)
public static function renderer($viewPath = APPPATH.'Views/', $config = null, $getShared = true)
{
if ($getShared)
{
@ -532,13 +511,16 @@ class Services
return self::getSharedInstance('request', $config);
}
if ( ! is_object($config))
if (! is_object($config))
{
$config = new \Config\App();
$config = config(App::class);
}
return new \CodeIgniter\HTTP\IncomingRequest(
$config, new \CodeIgniter\HTTP\URI()
$config,
new \CodeIgniter\HTTP\URI(),
'php://input',
new \CodeIgniter\HTTP\UserAgent()
);
}
@ -559,9 +541,9 @@ class Services
return self::getSharedInstance('response', $config);
}
if ( ! is_object($config))
if (! is_object($config))
{
$config = new \Config\App();
$config = config(App::class);
}
return new \CodeIgniter\HTTP\Response($config);
@ -584,12 +566,16 @@ class Services
return self::getSharedInstance('redirectResponse', $config);
}
if ( ! is_object($config))
if (! is_object($config))
{
$config = new \Config\App();
$config = config(App::class);
}
return new \CodeIgniter\HTTP\RedirectResponse($config);
$response = new \CodeIgniter\HTTP\RedirectResponse($config);
$response->setProtocolVersion(self::request()
->getProtocolVersion());
return $response;
}
//--------------------------------------------------------------------
@ -656,9 +642,9 @@ class Services
return self::getSharedInstance('security', $config);
}
if ( ! is_object($config))
if (! is_object($config))
{
$config = new \Config\App();
$config = config(App::class);
}
return new \CodeIgniter\Security\Security($config);
@ -679,20 +665,25 @@ class Services
return self::getSharedInstance('session', $config);
}
if ( ! is_object($config))
if (! is_object($config))
{
$config = new \Config\App();
$config = config(App::class);
}
$logger = self::logger(true);
$driverName = $config->sessionDriver;
$driver = new $driverName($config);
$driver = new $driverName($config);
$driver->setLogger($logger);
$session = new \CodeIgniter\Session\Session($driver, $config);
$session->setLogger($logger);
if (session_status() == PHP_SESSION_NONE)
{
$session->start();
}
return $session;
}
@ -751,9 +742,9 @@ class Services
return self::getSharedInstance('toolbar', $config);
}
if ( ! is_object($config))
if (! is_object($config))
{
$config = new \Config\App();
$config = config(App::class);
}
return new \CodeIgniter\Debug\Toolbar($config);
@ -843,86 +834,6 @@ class Services
return new \CodeIgniter\Typography\Typography();
}
//--------------------------------------------------------------------
//--------------------------------------------------------------------
// Utility Methods - DO NOT EDIT
//--------------------------------------------------------------------
/**
* Returns a shared instance of any of the class' services.
*
* $key must be a name matching a service.
*
* @param string $key
* @param array ...$params
*
* @return mixed
*/
protected static function getSharedInstance(string $key, ...$params)
{
// Returns mock if exists
if (isset(static::$mocks[$key]))
{
return static::$mocks[$key];
}
if ( ! isset(static::$instances[$key]))
{
// Make sure $getShared is false
array_push($params, false);
static::$instances[$key] = static::$key(...$params);
}
return static::$instances[$key];
}
//--------------------------------------------------------------------
/**
* Provides the ability to perform case-insensitive calling of service
* names.
*
* @param string $name
* @param array $arguments
*
* @return mixed
*/
public static function __callStatic(string $name, array $arguments)
{
$name = strtolower($name);
if (method_exists(__CLASS__, $name))
{
return Services::$name(...$arguments);
}
}
//--------------------------------------------------------------------
/**
* Reset shared instances and mocks for testing.
*/
public static function reset()
{
static::$mocks = [];
static::$instances = [];
}
//--------------------------------------------------------------------
/**
* Inject mock object for testing.
*
* @param string $name
* @param $mock
*/
public static function injectMock(string $name, $mock)
{
$name = strtolower($name);
static::$mocks[$name] = $mock;
}
//--------------------------------------------------------------------
}

View File

@ -27,45 +27,49 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @package CodeIgniter
* @author CodeIgniter Dev Team
* @copyright 2014-2018 British Columbia Institute of Technology (https://bcit.ca/)
* @license https://opensource.org/licenses/MIT MIT License
* @link https://codeigniter.com
* @since Version 3.0.0
* @package CodeIgniter
* @author CodeIgniter Dev Team
* @copyright 2014-2018 British Columbia Institute of Technology (https://bcit.ca/)
* @license https://opensource.org/licenses/MIT MIT License
* @link https://codeigniter.com
* @since Version 4.0.0
* @filesource
*/
class View extends BaseConfig
{
protected $coreFilters = [
'abs' => '\abs',
'capitalize' => '\CodeIgniter\View\Filters::capitalize',
'date' => '\CodeIgniter\View\Filters::date',
'date_modify' => '\CodeIgniter\View\Filters::date_modify',
'default' => '\CodeIgniter\View\Filters::default',
'esc' => '\CodeIgniter\View\Filters::esc',
'excerpt' => '\CodeIgniter\View\Filters::excerpt',
'highlight' => '\CodeIgniter\View\Filters::highlight',
'abs' => '\abs',
'capitalize' => '\CodeIgniter\View\Filters::capitalize',
'date' => '\CodeIgniter\View\Filters::date',
'date_modify' => '\CodeIgniter\View\Filters::date_modify',
'default' => '\CodeIgniter\View\Filters::default',
'esc' => '\CodeIgniter\View\Filters::esc',
'excerpt' => '\CodeIgniter\View\Filters::excerpt',
'highlight' => '\CodeIgniter\View\Filters::highlight',
'highlight_code' => '\CodeIgniter\View\Filters::highlight_code',
'limit_words' => '\CodeIgniter\View\Filters::limit_words',
'limit_chars' => '\CodeIgniter\View\Filters::limit_chars',
'lower' => '\strtolower',
'nl2br' => '\CodeIgniter\View\Filters::nl2br',
'number_format' => '\number_format',
'prose' => '\CodeIgniter\View\Filters::prose',
'round' => '\CodeIgniter\View\Filters::round',
'strip_tags' => '\strip_tags',
'title' => '\CodeIgniter\View\Filters::title',
'upper' => '\strtoupper',
'limit_words' => '\CodeIgniter\View\Filters::limit_words',
'limit_chars' => '\CodeIgniter\View\Filters::limit_chars',
'local_currency' => '\CodeIgniter\View\Filters::local_currency',
'local_number' => '\CodeIgniter\View\Filters::local_number',
'lower' => '\strtolower',
'nl2br' => '\CodeIgniter\View\Filters::nl2br',
'number_format' => '\number_format',
'prose' => '\CodeIgniter\View\Filters::prose',
'round' => '\CodeIgniter\View\Filters::round',
'strip_tags' => '\strip_tags',
'title' => '\CodeIgniter\View\Filters::title',
'upper' => '\strtoupper',
];
protected $corePlugins = [
'current_url' => '\CodeIgniter\View\Plugins::currentURL',
'previous_url' => '\CodeIgniter\View\Plugins::previousURL',
'mailto' => '\CodeIgniter\View\Plugins::mailto',
'safe_mailto' => '\CodeIgniter\View\Plugins::safeMailto',
'lang' => '\CodeIgniter\View\Plugins::lang',
'validation_errors' => '\CodeIgniter\View\Plugins::validationErrors',
'current_url' => '\CodeIgniter\View\Plugins::currentURL',
'previous_url' => '\CodeIgniter\View\Plugins::previousURL',
'mailto' => '\CodeIgniter\View\Plugins::mailto',
'safe_mailto' => '\CodeIgniter\View\Plugins::safeMailto',
'lang' => '\CodeIgniter\View\Plugins::lang',
'validation_errors' => '\CodeIgniter\View\Plugins::validationErrors',
'route' => '\CodeIgniter\View\Plugins::route',
'siteURL' => '\CodeIgniter\View\Plugins::siteURL',
];
public function __construct()

View File

@ -39,6 +39,7 @@ use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use CodeIgniter\Log\Logger;
use CodeIgniter\Validation\Validation;
use Psr\Log\LoggerInterface;
/**
* Class Controller
@ -99,18 +100,17 @@ class Controller
/**
* Constructor.
*
* @param RequestInterface $request
* @param ResponseInterface $response
* @param Logger $logger
* @param RequestInterface $request
* @param ResponseInterface $response
* @param \Psr\Log\LoggerInterface $logger
*
* @throws \CodeIgniter\HTTP\RedirectException
*/
public function __construct(RequestInterface $request, ResponseInterface $response, Logger $logger = null)
public function initController(RequestInterface $request, ResponseInterface $response, LoggerInterface $logger)
{
$this->request = $request;
$this->response = $response;
$this->logger = is_null($logger) ? Services::logger(true) : $logger;
$this->logger = $logger;
$this->logger->info('Controller "' . get_class($this) . '" loaded.');
if ($this->forceHTTPS > 0)
@ -132,6 +132,8 @@ class Controller
* @param int $duration The number of seconds this link should be
* considered secure for. Only with HSTS header.
* Default value is 1 year.
*
* @throws \CodeIgniter\HTTP\RedirectException
*/
public function forceHTTPS(int $duration = 31536000)
{
@ -170,11 +172,11 @@ class Controller
//--------------------------------------------------------------------
/**
* A shortcut to performing validation on $_POST input. If validation
* A shortcut to performing validation on input data. If validation
* is not successful, a $errors property will be set on this class.
*
* @param $rules
* @param array|null $messages
* @param array $rules
* @param array $messages An array of custom error messages
*
* @return bool
*/
@ -182,9 +184,10 @@ class Controller
{
$this->validator = Services::validation();
$success = $this->validator->withRequest($this->request)
->setRules($rules, $messages)
->run();
$success = $this->validator
->withRequest($this->request)
->setRules($rules, $messages)
->run();
return $success;
}

View File

@ -275,6 +275,19 @@ class BaseBuilder
if ($val !== '')
{
$this->QBSelect[] = $val;
/*
* When doing 'SELECT NULL as field_alias FROM table'
* null gets taken as a field, and therefore escaped
* with backticks.
* This prevents NULL being escaped
* @see https://github.com/bcit-ci/CodeIgniter4/issues/1169
*/
if ( strtoupper(mb_substr(trim($val), 0, 4)) == 'NULL')
{
$escape = false;
}
$this->QBNoEscape[] = $escape;
}
}
@ -768,7 +781,7 @@ class BaseBuilder
*/
protected function _whereIn($key = null, $values = null, $not = false, $type = 'AND ', $escape = null)
{
if ($key === null OR $values === null)
if ($key === null || $values === null)
{
return $this;
}
@ -1320,6 +1333,28 @@ class BaseBuilder
//--------------------------------------------------------------------
/**
* Returns the previously set() data, alternatively resetting it
* if needed.
*
* @param bool $clean
*
* @return array
*/
public function getSetData(bool $clean = false)
{
$data = $this->QBSet;
if ($clean)
{
$this->QBSet = [];
}
return $data;
}
//--------------------------------------------------------------------
/**
* Get SELECT query string
*
@ -1501,13 +1536,13 @@ class BaseBuilder
* @param array $set An associative array of insert values
* @param bool $escape Whether to escape values and identifiers
*
* @param int $batch_size
* @param int $batchSize
* @param bool $testing
*
* @return int Number of rows inserted or FALSE on failure
* @throws DatabaseException
*/
public function insertBatch($set = null, $escape = null, $batch_size = 100, $testing = false)
public function insertBatch($set = null, $escape = null, $batchSize = 100, $testing = false)
{
if ($set === null)
{
@ -1540,9 +1575,9 @@ class BaseBuilder
// Batch this baby
$affected_rows = 0;
for ($i = 0, $total = count($this->QBSet); $i < $total; $i += $batch_size)
for ($i = 0, $total = count($this->QBSet); $i < $total; $i += $batchSize)
{
$sql = $this->_insertBatch($this->db->protectIdentifiers($table, true, $escape, false), $this->QBKeys, array_slice($this->QBSet, $i, $batch_size));
$sql = $this->_insertBatch($this->db->protectIdentifiers($table, true, $escape, false), $this->QBKeys, array_slice($this->QBSet, $i, $batchSize));
if ($testing)
{
@ -1973,15 +2008,15 @@ class BaseBuilder
*
* Compiles an update string and runs the query
*
* @param array $set An associative array of update values
* @param string $index The where key
* @param int $batch_size The size of the batch to run
* @param bool $returnSQL True means SQL is returned, false will execute the query
* @param array $set An associative array of update values
* @param string $index The where key
* @param int $batchSize The size of the batch to run
* @param bool $returnSQL True means SQL is returned, false will execute the query
*
* @return mixed Number of rows affected or FALSE on failure
* @throws \CodeIgniter\Database\Exceptions\DatabaseException
*/
public function updateBatch($set = null, $index = null, $batch_size = 100, $returnSQL = false)
public function updateBatch($set = null, $index = null, $batchSize = 100, $returnSQL = false)
{
if ($index === null)
{
@ -2023,9 +2058,9 @@ class BaseBuilder
// Batch this baby
$affected_rows = 0;
$savedSQL = [];
for ($i = 0, $total = count($this->QBSet); $i < $total; $i += $batch_size)
for ($i = 0, $total = count($this->QBSet); $i < $total; $i += $batchSize)
{
$sql = $this->_updateBatch($table, array_slice($this->QBSet, $i, $batch_size), $this->db->protectIdentifiers($index)
$sql = $this->_updateBatch($table, array_slice($this->QBSet, $i, $batchSize), $this->db->protectIdentifiers($index)
);
if ($returnSQL)
@ -2499,7 +2534,7 @@ class BaseBuilder
for ($ci = 0, $cc = count($conditions); $ci < $cc; $ci ++ )
{
if (($op = $this->getOperator($conditions[$ci])) === false
OR ! preg_match('/^(\(?)(.*)(' . preg_quote($op, '/') . ')\s*(.*(?<!\)))?(\)?)$/i', $conditions[$ci], $matches)
|| ! preg_match('/^(\(?)(.*)(' . preg_quote($op, '/') . ')\s*(.*(?<!\)))?(\)?)$/i', $conditions[$ci], $matches)
)
{
continue;

View File

@ -49,49 +49,49 @@ abstract class BaseConnection implements ConnectionInterface
*
* @var string
*/
public $DSN;
protected $DSN;
/**
* Database port
*
* @var int
*/
public $port = '';
protected $port = '';
/**
* Hostname
*
* @var string
*/
public $hostname;
protected $hostname;
/**
* Username
*
* @var string
*/
public $username;
protected $username;
/**
* Password
*
* @var string
*/
public $password;
protected $password;
/**
* Database name
*
* @var string
*/
public $database;
protected $database;
/**
* Database driver
*
* @var string
*/
public $DBDriver = 'MySQLi';
protected $DBDriver = 'MySQLi';
/**
* Sub-driver
@ -99,21 +99,21 @@ abstract class BaseConnection implements ConnectionInterface
* @used-by CI_DB_pdo_driver
* @var string
*/
public $subdriver;
protected $subdriver;
/**
* Table prefix
*
* @var string
*/
public $DBPrefix = '';
protected $DBPrefix = '';
/**
* Persistent connection flag
*
* @var bool
*/
public $pConnect = false;
protected $pConnect = false;
/**
* Debug flag
@ -122,56 +122,56 @@ abstract class BaseConnection implements ConnectionInterface
*
* @var bool
*/
public $DBDebug = false;
protected $DBDebug = false;
/**
* Should we cache results?
*
* @var bool
*/
public $cacheOn = false;
protected $cacheOn = false;
/**
* Path to store cache files.
*
* @var string
*/
public $cacheDir;
protected $cacheDir;
/**
* Character set
*
* @var string
*/
public $charset = 'utf8';
protected $charset = 'utf8';
/**
* Collation
*
* @var string
*/
public $DBCollat = 'utf8_general_ci';
protected $DBCollat = 'utf8_general_ci';
/**
* Swap Prefix
*
* @var string
*/
public $swapPre = '';
protected $swapPre = '';
/**
* Encryption flag/data
*
* @var mixed
*/
public $encrypt = false;
protected $encrypt = false;
/**
* Compression flag
*
* @var bool
*/
public $compress = false;
protected $compress = false;
/**
* Strict ON flag
@ -180,14 +180,14 @@ abstract class BaseConnection implements ConnectionInterface
*
* @var bool
*/
public $strictOn;
protected $strictOn;
/**
* Settings for a failover connection.
*
* @var array
*/
public $failover = [];
protected $failover = [];
//--------------------------------------------------------------------
@ -772,7 +772,7 @@ abstract class BaseConnection implements ConnectionInterface
}
// The query() function will set this flag to FALSE in the event that a query failed
if ($this->transStatus === false OR $this->transFailure === true)
if ($this->transStatus === false || $this->transFailure === true)
{
$this->transRollback();
@ -875,12 +875,12 @@ abstract class BaseConnection implements ConnectionInterface
*/
public function transRollback(): bool
{
if (! $this->transEnabled OR $this->transDepth === 0)
if (! $this->transEnabled || $this->transDepth === 0)
{
return false;
}
// When transactions are nested we only begin/commit/rollback the outermost ones
elseif ($this->transDepth > 1 OR $this->_transRollback())
elseif ($this->transDepth > 1 || $this->_transRollback())
{
$this->transDepth --;
return true;
@ -1241,7 +1241,7 @@ abstract class BaseConnection implements ConnectionInterface
*/
public function escapeIdentifiers($item)
{
if ($this->escapeChar === '' OR empty($item) OR in_array($item, $this->reservedIdentifiers))
if ($this->escapeChar === '' || empty($item) || in_array($item, $this->reservedIdentifiers))
{
return $item;
}
@ -1255,7 +1255,7 @@ abstract class BaseConnection implements ConnectionInterface
return $item;
}
// Avoid breaking functions and literal values inside queries
elseif (ctype_digit($item) OR $item[0] === "'" OR ( $this->escapeChar !== '"' && $item[0] === '"') OR
elseif (ctype_digit($item) || $item[0] === "'" OR ( $this->escapeChar !== '"' && $item[0] === '"') OR
strpos($item, '(') !== false
)
{
@ -1360,7 +1360,7 @@ abstract class BaseConnection implements ConnectionInterface
return $str;
}
else if (is_string($str) OR ( is_object($str) && method_exists($str, '__toString')))
else if (is_string($str) || ( is_object($str) && method_exists($str, '__toString')))
{
return "'" . $this->escapeString($str) . "'";
}
@ -1495,7 +1495,7 @@ abstract class BaseConnection implements ConnectionInterface
public function listTables($constrain_by_prefix = FALSE)
{
// Is there a cached result?
if (isset($this->dataCache['table_names']) && count($this->dataCache['table_names']))
if (isset($this->dataCache['table_names']) && $this->dataCache['table_names'])
{
return $this->dataCache['table_names'];
}
@ -1662,7 +1662,7 @@ abstract class BaseConnection implements ConnectionInterface
}
//--------------------------------------------------------------------
/**
* Returns an object with foreign key data
*
@ -1740,4 +1740,15 @@ abstract class BaseConnection implements ConnectionInterface
abstract protected function _listColumns(string $table = ''): string;
//--------------------------------------------------------------------
public function __get($key)
{
if (property_exists($this, $key))
{
return $this->$key;
}
}
//--------------------------------------------------------------------
}

View File

@ -152,7 +152,7 @@ abstract class BaseResult implements ResultInterface
{
return $this->customResultObject[$className];
}
elseif ( ! $this->resultID OR $this->numRows === 0)
elseif ( ! $this->resultID || $this->numRows === 0)
{
return [];
}
@ -183,7 +183,7 @@ abstract class BaseResult implements ResultInterface
return $this->customResultObject[$className];
}
is_null($this->rowData) OR $this->dataSeek(0);
is_null($this->rowData) || $this->dataSeek(0);
$this->customResultObject[$className] = [];
while ($row = $this->fetchObject($className))
@ -213,7 +213,7 @@ abstract class BaseResult implements ResultInterface
// In the event that query caching is on, the result_id variable
// will not be a valid resource so we'll simply return an empty
// array.
if ( ! $this->resultID OR $this->numRows === 0)
if ( ! $this->resultID || $this->numRows === 0)
{
return [];
}
@ -228,7 +228,7 @@ abstract class BaseResult implements ResultInterface
return $this->resultArray;
}
is_null($this->rowData) OR $this->dataSeek(0);
is_null($this->rowData) || $this->dataSeek(0);
while ($row = $this->fetchAssoc())
{
$this->resultArray[] = $row;
@ -256,7 +256,7 @@ abstract class BaseResult implements ResultInterface
// In the event that query caching is on, the result_id variable
// will not be a valid resource so we'll simply return an empty
// array.
if ( ! $this->resultID OR $this->numRows === 0)
if ( ! $this->resultID || $this->numRows === 0)
{
return [];
}
@ -271,7 +271,7 @@ abstract class BaseResult implements ResultInterface
return $this->resultObject;
}
is_null($this->rowData) OR $this->dataSeek(0);
is_null($this->rowData) || $this->dataSeek(0);
while ($row = $this->fetchObject())
{
$this->resultObject[] = $row;
@ -298,10 +298,10 @@ abstract class BaseResult implements ResultInterface
if ( ! is_numeric($n))
{
// We cache the row data for subsequent uses
is_array($this->rowData) OR $this->row_data = $this->getRowArray(0);
is_array($this->rowData) || $this->row_data = $this->getRowArray(0);
// array_key_exists() instead of isset() to allow for NULL values
if (empty($this->rowData) OR ! array_key_exists($n, $this->rowData))
if (empty($this->rowData) || ! array_key_exists($n, $this->rowData))
{
return null;
}
@ -335,7 +335,7 @@ abstract class BaseResult implements ResultInterface
*/
public function getCustomRowObject($n, string $className)
{
isset($this->customResultObject[$className]) OR $this->customResultObject($className);
isset($this->customResultObject[$className]) || $this->getCustomResultObject($className);
if (empty($this->customResultObject[$className]))
{

View File

@ -76,7 +76,9 @@ class Database
throw new \InvalidArgumentException('You have not selected a database type to connect to.');
}
$className = strpos($params['DBDriver'], '\\') === false ? '\CodeIgniter\Database\\' . $params['DBDriver'] . '\\Connection' : $params['DBDriver'] . '\\Connection';
$className = strpos($params['DBDriver'], '\\') === false
? '\CodeIgniter\Database\\' . $params['DBDriver'] . '\\Connection'
: $params['DBDriver'] . '\\Connection';
$class = new $className($params);

View File

@ -0,0 +1,48 @@
<?php namespace CodeIgniter\Database\Exceptions;
class DataException extends \RuntimeException implements ExceptionInterface
{
/**
* Used by the Model's trigger() method when the callback cannot be found.
*
* @param string $method
*
* @return \CodeIgniter\Database\Exceptions\DataException
*/
public static function forInvalidMethodTriggered(string $method)
{
return new static(lang('Database.invalidEvent', [$method]));
}
/**
* Used by Model's insert/update methods when there isn't
* any data to actually work with.
*
* @param string $mode
*
* @return \CodeIgniter\Database\Exceptions\DataException
*/
public static function forEmptyDataset(string $mode)
{
return new static(lang('Database.emptyDataset', [$mode]));
}
/**
* Thrown when an argument for one of the Model's methods
* were empty or otherwise invalid, and they could not be
* to work correctly for that method.
*
* @param string $argument
*
* @return \CodeIgniter\Database\Exceptions\DataException
*/
public static function forInvalidArgument(string $argument)
{
return new static(lang('Database.invalidArgument', [$argument]));
}
public static function forInvalidAllowedFields(string $model)
{
return new static(lang('Database.invalidAllowedFields', [$model]));
}
}

View File

@ -1,5 +1,7 @@
<?php namespace CodeIgniter\Database\Exceptions;
use CodeIgniter\Exceptions\ExceptionInterface;
/**
* CodeIgniter
*
@ -36,13 +38,11 @@
* @filesource
*/
class DatabaseException extends \Error
class DatabaseException extends \Error implements ExceptionInterface
{
/**
* Exit status code
* @var int
*/
protected $code = 8;
}

View File

@ -0,0 +1,12 @@
<?php namespace CodeIgniter\Database\Exceptions;
/**
* Provides a domain-level interface for broad capture
* of all database-related exceptions.
*
* catch (\CodeIgniter\Database\Exceptions\ExceptionInterface) { ... }
*/
interface ExceptionInterface extends \CodeIgniter\Exceptions\ExceptionInterface
{
}

View File

@ -482,7 +482,7 @@ class Forge
if (($result = $this->db->query($sql)) !== false)
{
empty($this->db->dataCache['table_names']) OR $this->db->dataCache['table_names'][] = $table;
empty($this->db->dataCache['table_names']) || $this->db->dataCache['table_names'][] = $table;
// Most databases don't support creating indexes from within the CREATE TABLE statement
if (! empty($this->keys))
@ -568,7 +568,7 @@ class Forge
{
if (is_string($key))
{
$sql .= ' '.strtoupper($key).' '.$attributes[$key];
$sql .= ' ' . strtoupper($key) . ' ' . $this->db->escape($attributes[$key]);
}
}
@ -677,7 +677,7 @@ class Forge
*/
public function renameTable($table_name, $new_table_name)
{
if ($table_name === '' OR $new_table_name === '')
if ($table_name === '' || $new_table_name === '')
{
throw new \InvalidArgumentException('A table name is required for that operation.');
}
@ -723,7 +723,7 @@ class Forge
public function addColumn($table, $field)
{
// Work-around for literal column definitions
is_array($field) OR $field = [$field];
is_array($field) || $field = [$field];
foreach (array_keys($field) as $k)
{
@ -794,7 +794,7 @@ class Forge
public function modifyColumn($table, $field)
{
// Work-around for literal column definitions
is_array($field) OR $field = [$field];
is_array($field) || $field = [$field];
foreach (array_keys($field) as $k)
{
@ -1025,7 +1025,7 @@ class Forge
*/
protected function _attributeUnsigned(&$attributes, &$field)
{
if (empty($attributes['UNSIGNED']) OR $attributes['UNSIGNED'] !== true)
if (empty($attributes['UNSIGNED']) || $attributes['UNSIGNED'] !== true)
{
return;
}

View File

@ -35,10 +35,10 @@
* @since Version 3.0.0
* @filesource
*/
use CodeIgniter\Config\BaseConfig;
use CodeIgniter\ConfigException;
use Config\Autoload;
use CodeIgniter\CLI\CLI;
use CodeIgniter\Config\BaseConfig;
use CodeIgniter\Exceptions\ConfigException;
/**
* Class MigrationRunner
@ -152,12 +152,12 @@ class MigrationRunner
if (empty($this->table))
{
throw new ConfigException(lang('Migrations.migMissingTable'));
throw ConfigException::forMissingMigrationsTable();
}
if ( ! in_array($this->type, ['sequential', 'timestamp']))
{
throw new ConfigException(lang('Migrations.migInvalidType') . $this->type);
throw ConfigException::forInvalidMigrationType($this->type);
}
// Migration basename regex
@ -189,7 +189,7 @@ class MigrationRunner
{
if ( ! $this->enabled)
{
throw new ConfigException(lang('Migrations.migDisabled'));
throw ConfigException::forDisabledMigrations();
}
// Set Namespace if not null
if ( ! is_null($namespace))
@ -234,7 +234,7 @@ class MigrationRunner
{
// Only include migrations within the scoop
if (($method === 'up' && $version > $currentVersion && $version <= $targetVersion) OR ( $method === 'down' && $version <= $currentVersion && $version > $targetVersion)
if (($method === 'up' && $version > $currentVersion && $version <= $targetVersion) || ( $method === 'down' && $version <= $currentVersion && $version > $targetVersion)
)
{
@ -247,7 +247,7 @@ class MigrationRunner
// Validate the migration file structure
if ( ! class_exists($class, false))
{
throw new \RuntimeException(sprintf(lang('Migrations.migClassNotFound'), $class));
throw new \RuntimeException(sprintf(lang('Migrations.classNotFound'), $class));
}
// Forcing migration to selected database group
@ -255,7 +255,7 @@ class MigrationRunner
if ( ! is_callable([$instance, $method]))
{
throw new \RuntimeException(sprintf(lang('Migrations.migMissingMethod'), $method));
throw new \RuntimeException(sprintf(lang('Migrations.missingMethod'), $method));
}
$instance->{$method}();
@ -389,7 +389,7 @@ class MigrationRunner
$location = $config->psr4[$this->namespace];
// Setting migration directories.
$dir = rtrim($location, '/') . '/Database/Migrations/';
$dir = rtrim($location, DIRECTORY_SEPARATOR) . '/Database/Migrations/';
// Load all *_*.php files in the migrations path
foreach (glob($dir . '*_*.php') as $file)
@ -435,7 +435,7 @@ class MigrationRunner
{
return false;
}
throw new \RuntimeException(lang('Migrations.migEmpty'));
throw new \RuntimeException(lang('Migrations.empty'));
}
// Check if $targetversion file is found
@ -445,7 +445,7 @@ class MigrationRunner
{
return false;
}
throw new \RuntimeException(lang('Migrations.migNotFound') . $targetversion);
throw new \RuntimeException(lang('Migrations.notFound') . $targetversion);
}
ksort($migrations);
@ -461,14 +461,14 @@ class MigrationRunner
{
if ($this->type === 'sequential' && abs($migration->version - $loop) > 1)
{
throw new \RuntimeException(lang('Migration.migGap') . " " . $migration->version);
throw new \RuntimeException(lang('Migration.gap') . " " . $migration->version);
}
// Check if all old migration files are all available to do downgrading
if ($method === 'down')
{
if ($loop <= $history_size && $history_migrations[$loop]['version'] != $migration->version)
{
throw new \RuntimeException(lang('Migration.migGap') . " " . $migration->version);
throw new \RuntimeException(lang('Migration.gap') . " " . $migration->version);
}
}
$loop ++;
@ -650,7 +650,7 @@ class MigrationRunner
]);
if (is_cli())
{
$this->cliMessages[] = "\t" . CLI::color(lang('Migrations.migAdded'), 'yellow') . "($this->namespace) " . $version . '_' . $this->name;
$this->cliMessages[] = "\t" . CLI::color(lang('Migrations.added'), 'yellow') . "($this->namespace) " . $version . '_' . $this->name;
}
}
@ -670,7 +670,7 @@ class MigrationRunner
->delete();
if (is_cli())
{
$this->cliMessages[] = "\t" . CLI::color(lang('Migrations.migRemoved'), 'yellow') . "($this->namespace) " . $version . '_' . $this->name;
$this->cliMessages[] = "\t" . CLI::color(lang('Migrations.removed'), 'yellow') . "($this->namespace) " . $version . '_' . $this->name;
}
}

View File

@ -140,11 +140,11 @@ class Connection extends BaseConnection implements ConnectionInterface
if (is_array($this->encrypt))
{
$ssl = [];
empty($this->encrypt['ssl_key']) OR $ssl['key'] = $this->encrypt['ssl_key'];
empty($this->encrypt['ssl_cert']) OR $ssl['cert'] = $this->encrypt['ssl_cert'];
empty($this->encrypt['ssl_ca']) OR $ssl['ca'] = $this->encrypt['ssl_ca'];
empty($this->encrypt['ssl_capath']) OR $ssl['capath'] = $this->encrypt['ssl_capath'];
empty($this->encrypt['ssl_cipher']) OR $ssl['cipher'] = $this->encrypt['ssl_cipher'];
empty($this->encrypt['ssl_key']) || $ssl['key'] = $this->encrypt['ssl_key'];
empty($this->encrypt['ssl_cert']) || $ssl['cert'] = $this->encrypt['ssl_cert'];
empty($this->encrypt['ssl_ca']) || $ssl['ca'] = $this->encrypt['ssl_ca'];
empty($this->encrypt['ssl_capath']) || $ssl['capath'] = $this->encrypt['ssl_capath'];
empty($this->encrypt['ssl_cipher']) || $ssl['cipher'] = $this->encrypt['ssl_cipher'];
if ( ! empty($ssl))
{
@ -305,7 +305,7 @@ class Connection extends BaseConnection implements ConnectionInterface
$this->connID->next_result();
if($res = $this->connID->store_result())
{
$res->free();
$res->free();
}
}

View File

@ -109,18 +109,18 @@ class Forge extends \CodeIgniter\Database\Forge
{
if (is_string($key))
{
$sql .= ' ' . strtoupper($key) . ' = ' . $attributes[$key];
$sql .= ' ' . strtoupper($key) . ' = ' . $this->db->escape($attributes[$key]);
}
}
if ( ! empty($this->db->charset) && ! strpos($sql, 'CHARACTER SET') && ! strpos($sql, 'CHARSET'))
{
$sql .= ' DEFAULT CHARACTER SET = ' . $this->db->charset;
$sql .= ' DEFAULT CHARACTER SET = ' . $this->db->escape($this->db->charset);
}
if ( ! empty($this->db->DBCollat) && ! strpos($sql, 'COLLATE'))
{
$sql .= ' COLLATE = ' . $this->db->DBCollat;
$sql .= ' COLLATE = ' . $this->db->escape($this->db->DBCollat);
}
return $sql;
@ -228,7 +228,7 @@ class Forge extends \CodeIgniter\Database\Forge
continue;
}
is_array($this->keys[$i]) OR $this->keys[$i] = [$this->keys[$i]];
is_array($this->keys[$i]) || $this->keys[$i] = [$this->keys[$i]];
$unique = in_array($i, $this->uniqueKeys) ? 'UNIQUE ' : '';

View File

@ -148,7 +148,7 @@ class Builder extends BaseBuilder
$this->set($set);
}
if (count($this->QBSet) === 0)
if (! $this->QBSet)
{
if (CI_DEBUG)
{

View File

@ -101,7 +101,7 @@ class Connection extends BaseConnection implements ConnectionInterface
return false;
}
empty($this->schema) or $this->simpleQuery("SET search_path TO {$this->schema},public");
empty($this->schema) || $this->simpleQuery("SET search_path TO {$this->schema},public");
if ($this->setClientEncoding($this->charset) === false)
{
@ -217,7 +217,7 @@ class Connection extends BaseConnection implements ConnectionInterface
$this->initialize();
}
if (is_string($str) OR ( is_object($str) && method_exists($str, '__toString')))
if (is_string($str) || ( is_object($str) && method_exists($str, '__toString')))
{
return pg_escape_literal($this->connID, $str);
}
@ -483,7 +483,7 @@ class Connection extends BaseConnection implements ConnectionInterface
*/
protected function buildDSN()
{
$this->DSN === '' or $this->DSN = '';
$this->DSN === '' || $this->DSN = '';
// If UNIX sockets are used, we shouldn't set a port
if (strpos($this->hostname, '/') !== false)
@ -491,7 +491,7 @@ class Connection extends BaseConnection implements ConnectionInterface
$this->port = '';
}
$this->hostname === '' or $this->DSN = "host={$this->hostname} ";
$this->hostname === '' || $this->DSN = "host={$this->hostname} ";
if ( ! empty($this->port) && ctype_digit($this->port))
{
@ -505,10 +505,10 @@ class Connection extends BaseConnection implements ConnectionInterface
// An empty password is valid!
// password must be set to null to ignore it.
$this->password === null or $this->DSN .= "password='{$this->password}' ";
$this->password === null || $this->DSN .= "password='{$this->password}' ";
}
$this->database === '' or $this->DSN .= "dbname={$this->database} ";
$this->database === '' || $this->DSN .= "dbname={$this->database} ";
// We don't have these options as elements in our standard configuration
// array, but they might be set by parse_url() if the configuration was

View File

@ -76,6 +76,19 @@ class Forge extends \CodeIgniter\Database\Forge
//--------------------------------------------------------------------
/**
* CREATE TABLE attributes
*
* @param array $attributes Associative array of table attributes
* @return string
*/
protected function _createTableAttributes($attributes)
{
return '';
}
//--------------------------------------------------------------------
/**
* ALTER TABLE
*

View File

@ -149,7 +149,7 @@ class Seeder
if ( ! class_exists($class, false))
{
require $path;
require_once $path;
}
$seeder = new $class($this->config);

View File

@ -1,165 +0,0 @@
<?php namespace CodeIgniter;
/**
* CodeIgniter
*
* An open source application development framework for PHP
*
* This content is released under the MIT License (MIT)
*
* Copyright (c) 2014-2018 British Columbia Institute of Technology
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @package CodeIgniter
* @author CodeIgniter Dev Team
* @copyright 2014-2018 British Columbia Institute of Technology (https://bcit.ca/)
* @license https://opensource.org/licenses/MIT MIT License
* @link https://codeigniter.com
* @since Version 3.0.0
* @filesource
*/
/**
* Custom Exceptions
*
* These exceptions are provided for your use, and work to provide a consistent
* experience across the application. The default error codes are already set,
* and will be used to provide both HTTP status codes and CLI exit codes.
*
* The Error Exceptions below are primarily to provide a way to have
* information logged automatically by the application's log system.
*
* @package CodeIgniter
*/
/**
* Error: system is unusable
*/
class EmergencyError extends \Error
{
}
/**
* Error: Action must be taken immediately (system/db down, etc)
*/
class AlertError extends \Error
{
}
/**
* Error: Critical conditions, like component unavailble, etc.
*/
class CriticalError extends \Error
{
}
/**
* Error: Runtime errors that do not require immediate action
*/
class Error extends \Error
{
}
/**
* Exception for automatic logging.
*/
class PageNotFoundException extends \OutOfBoundsException
{
/**
* Error code
* @var int
*/
protected $code = 404;
}
/**
* Exception for automatic logging.
*/
class ConfigException extends CriticalError
{
/**
* Error code
* @var int
*/
protected $code = 3;
}
/**
* Exception for automatic logging.
*/
class UnknownFileException extends CriticalError
{
/**
* Error code
* @var int
*/
protected $code = 4;
}
/**
* Exception for automatic logging.
*/
class UnknownClassException extends CriticalError
{
/**
* Error code
* @var int
*/
protected $code = 5;
}
/**
* Exception for automatic logging.
*/
class UnknownMethodException extends CriticalError
{
/**
* Error code
* @var int
*/
protected $code = 6;
}
/**
* Exception for automatic logging.
*/
class UserInputException extends \OutOfBoundsException
{
/**
* Error code
* @var int
*/
protected $code = 7;
}

View File

@ -35,15 +35,14 @@
* @since Version 3.0.0
* @filesource
*/
use Config\Services;
require __DIR__.'/CustomExceptions.php';
/**
* Exceptions manager
*/
class Exceptions
{
use \CodeIgniter\API\ResponseTrait;
/**
* Nesting level of the output buffering mechanism
*
@ -64,20 +63,35 @@ class Exceptions
*/
protected $config;
/**
* @var \CodeIgniter\HTTP\IncomingRequest
*/
protected $request;
/**
* @var \CodeIgniter\HTTP\Response
*/
protected $response;
//--------------------------------------------------------------------
/**
* Constructor.
*
* @param \Config\Exceptions $config
* @param \Config\Exceptions $config
* @param \CodeIgniter\HTTP\IncomingRequest $request
* @param \CodeIgniter\HTTP\Response $response
*/
public function __construct(\Config\Exceptions $config)
public function __construct(\Config\Exceptions $config, \CodeIgniter\HTTP\IncomingRequest $request, \CodeIgniter\HTTP\Response $response)
{
$this->ob_level = ob_get_level();
$this->viewPath = rtrim($config->errorViewPath, '/ ') . '/';
$this->config = $config;
$this->request = $request;
$this->response = $response;
}
//--------------------------------------------------------------------
@ -124,9 +138,16 @@ class Exceptions
if (! is_cli())
{
$response = Services::response()->setStatusCode($statusCode);
$header = "HTTP/1.1 {$response->getStatusCode()} {$response->getReason()}";
$this->response->setStatusCode($statusCode);
$header = "HTTP/{$this->request->getProtocolVersion()} {$this->response->getStatusCode()} {$this->response->getReason()}";
header($header, true, $statusCode);
if (strpos($this->request->getHeaderLine('accept'), 'text/html') === false)
{
$this->respond(ENVIRONMENT === 'development' ? $this->collectVars($exception, $statusCode) : '', $statusCode)->send();
exit($exitCode);
}
}
$this->render($exception, $statusCode);
@ -203,7 +224,7 @@ class Exceptions
}
// 404 Errors
if ($exception instanceof \CodeIgniter\PageNotFoundException)
if ($exception instanceof \CodeIgniter\Exceptions\PageNotFoundException)
{
return 'error_404.php';
}
@ -271,13 +292,13 @@ class Exceptions
protected function collectVars(\Throwable $exception, int $statusCode)
{
return [
'type' => get_class($exception),
'code' => $statusCode,
'title' => get_class($exception),
'type' => get_class($exception),
'code' => $statusCode,
'message' => $exception->getMessage() ?? '(null)',
'file' => $exception->getFile(),
'line' => $exception->getLine(),
'trace' => $exception->getTrace(),
'title' => get_class($exception)
'file' => $exception->getFile(),
'line' => $exception->getLine(),
'trace' => $exception->getTrace(),
];
}

View File

@ -35,8 +35,10 @@
* @since Version 3.0.0
* @filesource
*/
use CodeIgniter\Config\BaseConfig;
use Config\App;
use Config\Services;
use CodeIgniter\Config\BaseConfig;
use CodeIgniter\Format\XMLFormatter;
/**
* Debug Toolbar
@ -58,9 +60,11 @@ class Toolbar
protected $collectors = [];
/**
* @var float App start time
* Incoming Request
*
* @var \CodeIgniter\HTTP\IncomingRequest
*/
protected $startTime;
protected static $request;
//--------------------------------------------------------------------
@ -86,33 +90,210 @@ class Toolbar
//--------------------------------------------------------------------
/**
* Run
* Returns all the data required by Debug Bar
*
* @param float $startTime
* @param float $startTime App start time
* @param float $totalTime
* @param float $startMemory
* @param \CodeIgniter\HTTP\RequestInterface $request
* @param \CodeIgniter\HTTP\ResponseInterface $response
*
* @return string JSON encoded data
*/
public function run($startTime, $totalTime, $request, $response): string
{
// Data items used within the view.
$data['url'] = current_url();
$data['method'] = $request->getMethod(true);
$data['isAJAX'] = $request->isAJAX();
$data['startTime'] = $startTime;
$data['totalTime'] = $totalTime*1000;
$data['totalMemory'] = number_format((memory_get_peak_usage())/1024/1024, 3);
$data['segmentDuration'] = $this->roundTo($data['totalTime']/7, 5);
$data['segmentCount'] = (int)ceil($data['totalTime']/$data['segmentDuration']);
$data['CI_VERSION'] = \CodeIgniter\CodeIgniter::CI_VERSION;
$data['collectors'] = [];
foreach($this->collectors as $collector)
{
$data['collectors'][] = [
'title' => $collector->getTitle(),
'titleSafe' => $collector->getTitle(true),
'titleDetails' => $collector->getTitleDetails(),
'display' => $collector->display(),
'badgeValue' => $collector->getBadgeValue(),
'isEmpty' => $collector->isEmpty(),
'hasTabContent' => $collector->hasTabContent(),
'hasLabel' => $collector->hasLabel(),
'icon' => $collector->icon(),
'hasTimelineData' => $collector->hasTimelineData(),
'timelineData' => $collector->timelineData(),
];
}
foreach ($this->collectVarData() as $heading => $items)
{
$vardata = [];
if (is_array($items))
{
foreach ($items as $key => $value)
{
$vardata[esc($key)] = is_string($value) ? esc($value) : print_r($value, true);
}
}
$data['vars']['varData'][esc($heading)] = $vardata;
}
if (! empty($_SESSION))
{
foreach ($_SESSION as $key => $value)
{
$data['vars']['session'][esc($key)] = is_string($value) ? esc($value) : print_r($value, true);
}
}
foreach ($request->getGet() as $name => $value)
{
$data['vars']['get'][esc($name)] = is_array($value) ? esc(print_r($value, true)) : esc($value);
}
foreach ($request->getPost() as $name => $value)
{
$data['vars']['post'][esc($name)] = is_array($value) ? esc(print_r($value, true)) : esc($value);
}
foreach ($request->getHeaders() as $header => $value)
{
if (empty($value))
{
continue;
}
if (! is_array($value))
{
$value = [$value];
}
foreach ($value as $h)
{
$data['vars']['headers'][esc($h->getName())] = esc($h->getValueLine());
}
}
foreach ($request->getCookie() as $name => $value)
{
$data['vars']['cookies'][esc($name)] = esc($value);
}
$data['vars']['request'] = ($request->isSecure() ? 'HTTPS' : 'HTTP').'/'.$request->getProtocolVersion();
$data['vars']['response'] = [
'statusCode' => $response->getStatusCode(),
'reason' => esc($response->getReason()),
'contentType' => esc($response->getHeaderLine('content-type')),
];
$data['config'] = \CodeIgniter\Debug\Toolbar\Collectors\Config::display();
if( $response->CSP !== null )
{
$response->CSP->addImageSrc( 'data:' );
}
return json_encode($data);
}
//--------------------------------------------------------------------
/**
* Format output
*
* @param string $data JSON encoded Toolbar data
* @param string $format html, json, xml
*
* @return string
*/
public function run($startTime, $totalTime, $startMemory, $request, $response): string
protected static function format(string $data, string $format = 'html')
{
$this->startTime = $startTime;
$data = json_decode($data, true);
// Data items used within the view.
$collectors = $this->collectors;
// History must be loaded on the fly
$filenames = glob(WRITEPATH.'debugbar/debugbar_*');
$total = count($filenames);
rsort($filenames);
$totalTime = $totalTime*1000;
$totalMemory = number_format((memory_get_peak_usage()-$startMemory)/1048576, 3);
$segmentDuration = $this->roundTo($totalTime/7, 5);
$segmentCount = (int)ceil($totalTime/$segmentDuration);
$varData = $this->collectVarData();
$files = [];
ob_start();
include(__DIR__.'/Toolbar/Views/toolbar.tpl.php');
$output = ob_get_contents();
ob_end_clean();
$current = self::$request->getGet('debugbar_time');
$app = config(App::class);
for ($i = 0; $i < $total; $i++)
{
// Oldest files will be deleted
if ($app->toolbarMaxHistory >= 0 && $i+1 > $app->toolbarMaxHistory)
{
unlink($filenames[$i]);
continue;
}
// Get the contents of this specific history request
ob_start();
include($filenames[$i]);
$contents = ob_get_contents();
ob_end_clean();
$file = json_decode($contents, true);
// Debugbar files shown in History Collector
$files[] = [
'time' => (int)$time = substr($filenames[$i], -10),
'datetime' => date('Y-m-d H:i:s', $time),
'active' => (int)($time == $current),
'status' => $file['vars']['response']['statusCode'],
'method' => $file['method'],
'url' => $file['url'],
'isAJAX' => $file['isAJAX'] ? 'Yes' : 'No',
'contentType' => $file['vars']['response']['contentType'],
];
}
// Set the History here. Class is not necessary
$data['collectors'][] = [
'title' => 'History',
'titleSafe' => 'history',
'titleDetails' => '',
'display' => ['files' => $files],
'badgeValue' => $count = count($files),
'isEmpty' => ! (bool)$count,
'hasTabContent' => true,
'hasLabel' => true,
'icon' => 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAJySURBVEhL3ZU7aJNhGIVTpV6i4qCIgkIHxcXLErS4FBwUFNwiCKGhuTYJGaIgnRoo4qRu6iCiiIuIXXTTIkIpuqoFwaGgonUQlC5KafU5ycmNP0lTdPLA4fu+8573/a4/f6hXpFKpwUwmc9fDfweKbk+n07fgEv33TLSbtt/hvwNFT1PsG/zdTE0Gp+GFfD6/2fbVIxqNrqPIRbjg4t/hY8aztcngfDabHXbKyiiXy2vcrcPH8oDCry2FKDrA+Ar6L01E/ypyXzXaARjDGGcoeNxSDZXE0dHRA5VRE5LJ5CFy5jzJuOX2wHRHRnjbklZ6isQ3tIctBaAd4vlK3jLtkOVWqABBXd47jGHLmjTmSScttQV5J+SjfcUweFQEbsjAas5aqoCLXutJl7vtQsAzpRowYqkBinyCC8Vicb2lOih8zoldd0F8RD7qTFiqAnGrAy8stUAvi/hbqDM+YzkAFrLPdR5ZqoLXsd+Bh5YCIH7JniVdquUWxOPxDfboHhrI5XJ7HHhiqQXox+APe/Qk64+gGYVCYZs8cMpSFQj9JOoFzVqqo7k4HIvFYpscCoAjOmLffUsNUGRaQUwDlmofUa34ecsdgXdcXo4wbakBgiUFafXJV8A4DJ/2UrxUKm3E95H8RbjLcgOJRGILhnmCP+FBy5XvwN2uIPcy1AJvWgqC4xm2aU4Xb3lF4I+Tpyf8hRe5w3J7YLymSeA8Z3nSclv4WLRyFdfOjzrUFX0klJUEtZtntCNc+F69cz/FiDzEPtjzmcUMOr83kDQEX6pAJxJfpL3OX22n01YN7SZCoQnaSdoZ+Jz+PZihH3wt/xlCoT9M6nEtmRSPCQAAAABJRU5ErkJggg==',
'hasTimelineData' => false,
'timelineData' => [],
];
$output = '';
switch ($format)
{
case 'html':
$data['styles'] = [];
extract($data);
$parser = Services::parser(BASEPATH . 'Debug/Toolbar/Views/', null,false);
ob_start();
include(__DIR__.'/Toolbar/Views/toolbar.tpl.php');
$output = ob_get_contents();
ob_end_clean();
break;
case 'json':
$output = json_encode($data);
break;
case 'xml':
$formatter = new XMLFormatter;
$output = $formatter->format($data);
break;
}
return $output;
}
@ -122,37 +303,38 @@ class Toolbar
/**
* Called within the view to display the timeline itself.
*
* @param int $segmentCount
* @param int $segmentDuration
* @param array $collectors
* @param float $startTime
* @param int $segmentCount
* @param int $segmentDuration
*
* @return string
*/
protected function renderTimeline(int $segmentCount, int $segmentDuration): string
protected static function renderTimeline(array $collectors, $startTime, int $segmentCount, int $segmentDuration, array& $styles ): string
{
$displayTime = $segmentCount*$segmentDuration;
$rows = $this->collectTimelineData();
$output = '';
$rows = self::collectTimelineData($collectors);
$output = '';
$styleCount = 0;
foreach ($rows as $row)
{
$output .= "<tr>";
$output .= "<td>{$row['name']}</td>";
$output .= "<td>{$row['component']}</td>";
$output .= "<td style='text-align: right'>".number_format($row['duration']*1000, 2)." ms</td>";
$output .= "<td colspan='{$segmentCount}' style='overflow: hidden'>";
$output .= "<td class='debug-bar-alignRight'>".number_format($row['duration']*1000, 2)." ms</td>";
$output .= "<td class='debug-bar-noverflow' colspan='{$segmentCount}'>";
$offset = ((($row['start']-$this->startTime)*1000)/
$displayTime)*100;
$offset = ((($row['start']-$startTime)*1000)/$displayTime)*100;
$length = (($row['duration']*1000)/$displayTime)*100;
$output .= "<span class='timer' style='left: {$offset}%; width: {$length}%;' title='".number_format($length,
$styles['debug-bar-timeline-'.$styleCount] = "left: {$offset}%; width: {$length}%;";
$output .= "<span class='timer debug-bar-timeline-{$styleCount}' title='".number_format($length,
2)."%'></span>";
$output .= "</td>";
$output .= "</tr>";
$styleCount++;
}
return $output;
@ -165,24 +347,23 @@ class Toolbar
*
* @return array
*/
protected function collectTimelineData(): array
protected static function collectTimelineData($collectors): array
{
$data = [];
// Collect it
foreach ($this->collectors as $collector)
foreach ($collectors as $collector)
{
if (! $collector->hasTimelineData())
if (! $collector['hasTimelineData'])
{
continue;
}
$data = array_merge($data, $collector->timelineData());
$data = array_merge($data, $collector['timelineData']);
}
// Sort it
return $data;
}
@ -235,11 +416,16 @@ class Toolbar
*/
public static function eventHandler()
{
$request = Services::request();
self::$request = Services::request();
if(ENVIRONMENT == 'testing')
{
return;
}
// If the request contains '?debugbar then we're
// simply returning the loading script
if ($request->getGet('debugbar') !== null)
if (self::$request->getGet('debugbar') !== null)
{
// Let the browser know that we are sending javascript
header('Content-Type: application/javascript');
@ -254,23 +440,31 @@ class Toolbar
// Otherwise, if it includes ?debugbar_time, then
// we should return the entire debugbar.
if ($request->getGet('debugbar_time'))
if (self::$request->getGet('debugbar_time'))
{
helper('security');
$file = sanitize_filename('debugbar_'.$request->getGet('debugbar_time'));
// Negotiate the content-type to format the output
$format = self::$request->negotiate('media', [
'text/html',
'application/json',
'application/xml'
]);
$format = explode('/', $format)[1];
$file = sanitize_filename('debugbar_'.self::$request->getGet('debugbar_time'));
$filename = WRITEPATH.'debugbar/'.$file;
// Show the toolbar
if (file_exists($filename))
{
$contents = file_get_contents($filename);
unlink($filename);
$contents = self::format(file_get_contents($filename), $format);
exit($contents);
}
// File was not written or do not exists
exit('<script id="toolbar_js">console.log(\'CI DebugBar: File "WRITEPATH/'.$file.'" not found.\')</script>');
http_response_code(404);
exit(); // Exit here is needed to avoid load the index page
}
}
}

View File

@ -229,14 +229,13 @@ class BaseCollector
//--------------------------------------------------------------------
/**
* Builds and returns the HTML needed to fill a tab to display
* within the Debug Bar
* Returns the data of this collector to be formatted in the toolbar
*
* @return string
* @return array
*/
public function display(): string
public function display(): array
{
return '';
return [];
}
//--------------------------------------------------------------------

View File

@ -1,32 +1,25 @@
<?php namespace CodeIgniter\Debug\Toolbar\Collectors;
use CodeIgniter\CodeIgniter;
use Config\App;
use Config\Services;
use CodeIgniter\CodeIgniter;
class Config
{
public static function display()
{
$config = new App();
$parser = \Config\Services::parser(BASEPATH . 'Debug/Toolbar/Views/', null,false);
$config = config(App::class);
$data = [
'ciVersion' => CodeIgniter::CI_VERSION,
'phpVersion' => phpversion(),
'phpSAPI' => php_sapi_name(),
return [
'ciVersion' => CodeIgniter::CI_VERSION,
'phpVersion' => phpversion(),
'phpSAPI' => php_sapi_name(),
'environment' => ENVIRONMENT,
'baseURL' => $config->baseURL,
'timezone' => app_timezone(),
'locale' => Services::request()->getLocale(),
'cspEnabled' => $config->CSPEnabled,
'salt' => $config->salt,
'baseURL' => $config->baseURL,
'timezone' => app_timezone(),
'locale' => Services::request()->getLocale(),
'cspEnabled' => $config->CSPEnabled,
'salt' => $config->salt,
];
$output = $parser->setData($data)
->render('_config.tpl');
return $output;
}
}

View File

@ -149,11 +149,11 @@ class Database extends BaseCollector
//--------------------------------------------------------------------
/**
* Returns the HTML to fill the Database tab in the toolbar.
* Returns the data of this collector to be formatted in the toolbar
*
* @return string The data formatted for the toolbar.
* @return array
*/
public function display(): string
public function display(): array
{
// Key words we want bolded
$highlight = ['SELECT', 'DISTINCT', 'FROM', 'WHERE', 'AND', 'LEFT&nbsp;JOIN', 'ORDER&nbsp;BY', 'GROUP&nbsp;BY',
@ -161,8 +161,6 @@ class Database extends BaseCollector
'IN', 'LIKE', 'NOT&nbsp;LIKE', 'COUNT', 'MAX', 'MIN', 'ON', 'AS', 'AVG', 'SUM', '(', ')'
];
$parser = \Config\Services::parser(BASEPATH . 'Debug/Toolbar/Views/', null,false);
$data = [
'queries' => []
];
@ -182,10 +180,7 @@ class Database extends BaseCollector
];
}
$output = $parser->setData($data)
->render('_database.tpl');
return $output;
return $data;
}
//--------------------------------------------------------------------
@ -209,8 +204,8 @@ class Database extends BaseCollector
*/
public function getTitleDetails(): string
{
return '(' . count(static::$queries) . ' Queries across ' . count($this->connections) . ' Connection' .
(count($this->connections) > 1 ? 's' : '') . ')';
return '(' . count(static::$queries) . ' Queries across ' . ($countConnection = count($this->connections)) . ' Connection' .
($countConnection > 1 ? 's' : '') . ')';
}
//--------------------------------------------------------------------
@ -236,9 +231,7 @@ class Database extends BaseCollector
*/
public function icon(): string
{
return <<<EOD
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADMSURBVEhLY6A3YExLSwsA4nIycQDIDIhRWEBqamo/UNF/SjDQjF6ocZgAKPkRiFeEhoYyQ4WIBiA9QAuWAPEHqBAmgLqgHcolGQD1V4DMgHIxwbCxYD+QBqcKINseKo6eWrBioPrtQBq/BcgY5ht0cUIYbBg2AJKkRxCNWkDQgtFUNJwtABr+F6igE8olGQD114HMgHIxAVDyAhA/AlpSA8RYUwoeXAPVex5qHCbIyMgwBCkAuQJIY00huDBUz/mUlBQDqHGjgBjAwAAACexpph6oHSQAAAAASUVORK5CYII=">
EOD;
return 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADMSURBVEhLY6A3YExLSwsA4nIycQDIDIhRWEBqamo/UNF/SjDQjF6ocZgAKPkRiFeEhoYyQ4WIBiA9QAuWAPEHqBAmgLqgHcolGQD1V4DMgHIxwbCxYD+QBqcKINseKo6eWrBioPrtQBq/BcgY5ht0cUIYbBg2AJKkRxCNWkDQgtFUNJwtABr+F6igE8olGQD114HMgHIxAVDyAhA/AlpSA8RYUwoeXAPVex5qHCbIyMgwBCkAuQJIY00huDBUz/mUlBQDqHGjgBjAwAAACexpph6oHSQAAAAASUVORK5CYII=';
}

View File

@ -122,14 +122,12 @@ class Events extends BaseCollector
//--------------------------------------------------------------------
/**
* Returns the HTML to fill the Events tab in the toolbar.
* Returns the data of this collector to be formatted in the toolbar
*
* @return string The data formatted for the toolbar.
* @return array
*/
public function display(): string
public function display(): array
{
$parser = \Config\Services::parser(BASEPATH . 'Debug/Toolbar/Views/', null,false);
$data = [
'events' => []
];
@ -153,10 +151,7 @@ class Events extends BaseCollector
$data['events'][$key]['count']++;
}
$output = $parser->setData($data)
->render('_events.tpl');
return $output;
return $data;
}
//--------------------------------------------------------------------
@ -180,9 +175,7 @@ class Events extends BaseCollector
*/
public function icon(): string
{
return <<<EOD
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAEASURBVEhL7ZXNDcIwDIVTsRBH1uDQDdquUA6IM1xgCA6MwJUN2hk6AQzAz0vl0ETUxC5VT3zSU5w81/mRMGZysixbFEVR0jSKNt8geQU9aRpFmp/keX6AbjZ5oB74vsaN5lSzA4tLSjpBFxsjeSuRy4d2mDdQTWU7YLbXTNN05mKyovj5KL6B7q3hoy3KwdZxBlT+Ipz+jPHrBqOIynZgcZonoukb/0ckiTHqNvDXtXEAaygRbaB9FvUTjRUHsIYS0QaSp+Dw6wT4hiTmYHOcYZsdLQ2CbXa4ftuuYR4x9vYZgdb4vsFYUdmABMYeukK9/SUme3KMFQ77+Yfzh8eYF8+orDuDWU5LAAAAAElFTkSuQmCC">
EOD;
return 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAEASURBVEhL7ZXNDcIwDIVTsRBH1uDQDdquUA6IM1xgCA6MwJUN2hk6AQzAz0vl0ETUxC5VT3zSU5w81/mRMGZysixbFEVR0jSKNt8geQU9aRpFmp/keX6AbjZ5oB74vsaN5lSzA4tLSjpBFxsjeSuRy4d2mDdQTWU7YLbXTNN05mKyovj5KL6B7q3hoy3KwdZxBlT+Ipz+jPHrBqOIynZgcZonoukb/0ckiTHqNvDXtXEAaygRbaB9FvUTjRUHsIYS0QaSp+Dw6wT4hiTmYHOcYZsdLQ2CbXa4ftuuYR4x9vYZgdb4vsFYUdmABMYeukK9/SUme3KMFQ77+Yfzh8eYF8+orDuDWU5LAAAAAElFTkSuQmCC';
}
}

View File

@ -81,15 +81,12 @@ class Files extends BaseCollector
//--------------------------------------------------------------------
/**
* Builds and returns the HTML needed to fill a tab to display
* within the Debug Bar
* Returns the data of this collector to be formatted in the toolbar
*
* @return string
* @return array
*/
public function display(): string
public function display(): array
{
$parser = \Config\Services::parser(BASEPATH . 'Debug/Toolbar/Views/', null, false);
$rawFiles = get_included_files();
$coreFiles = [];
$userFiles = [];
@ -117,11 +114,10 @@ class Files extends BaseCollector
sort($userFiles);
sort($coreFiles);
return $parser->setData([
'coreFiles' => $coreFiles,
'userFiles' => $userFiles,
])
->render('_files.tpl');
return [
'coreFiles' => $coreFiles,
'userFiles' => $userFiles,
];
}
//--------------------------------------------------------------------
@ -147,9 +143,7 @@ class Files extends BaseCollector
*/
public function icon(): string
{
return <<<EOD
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGBSURBVEhL7ZQ9S8NQGIVTBQUncfMfCO4uLgoKbuKQOWg+OkXERRE1IAXrIHbVDrqIDuLiJgj+gro7S3dnpfq88b1FMTE3VZx64HBzzvvZWxKnj15QCcPwCD5HUfSWR+JtzgmtsUcQBEva5IIm9SwSu+95CAWbUuy67qBa32ByZEDpIaZYZSZMjjQuPcQUq8yEyYEb8FSerYeQVGbAFzJkX1PyQWLhgCz0BxTCekC1Wp0hsa6yokzhed4oje6Iz6rlJEkyIKfUEFtITVtQdAibn5rMyaYsMS+a5wTv8qeXMhcU16QZbKgl3hbs+L4/pnpdc87MElZgq10p5DxGdq8I7xrvUWUKvG3NbSK7ubngYzdJwSsF7TiOh9VOgfcEz1UayNe3JUPM1RWC5GXYgTfc75B4NBmXJnAtTfpABX0iPvEd9ezALwkplCFXcr9styiNOKc1RRZpaPM9tcqBwlWzGY1qPL9wjqRBgF5BH6j8HWh2S7MHlX8PrmbK+k/8PzjOOzx1D3i1pKTTAAAAAElFTkSuQmCC">
EOD;
return 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGBSURBVEhL7ZQ9S8NQGIVTBQUncfMfCO4uLgoKbuKQOWg+OkXERRE1IAXrIHbVDrqIDuLiJgj+gro7S3dnpfq88b1FMTE3VZx64HBzzvvZWxKnj15QCcPwCD5HUfSWR+JtzgmtsUcQBEva5IIm9SwSu+95CAWbUuy67qBa32ByZEDpIaZYZSZMjjQuPcQUq8yEyYEb8FSerYeQVGbAFzJkX1PyQWLhgCz0BxTCekC1Wp0hsa6yokzhed4oje6Iz6rlJEkyIKfUEFtITVtQdAibn5rMyaYsMS+a5wTv8qeXMhcU16QZbKgl3hbs+L4/pnpdc87MElZgq10p5DxGdq8I7xrvUWUKvG3NbSK7ubngYzdJwSsF7TiOh9VOgfcEz1UayNe3JUPM1RWC5GXYgTfc75B4NBmXJnAtTfpABX0iPvEd9ezALwkplCFXcr9styiNOKc1RRZpaPM9tcqBwlWzGY1qPL9wjqRBgF5BH6j8HWh2S7MHlX8PrmbK+k/8PzjOOzx1D3i1pKTTAAAAAElFTkSuQmCC';
}
}

View File

@ -77,26 +77,22 @@ class Logs extends BaseCollector
//--------------------------------------------------------------------
/**
* Builds and returns the HTML needed to fill a tab to display
* within the Debug Bar
* Returns the data of this collector to be formatted in the toolbar
*
* @return string
* @return array
*/
public function display(): string
public function display(): array
{
$this->collectLogs();
$parser = \Config\Services::parser(BASEPATH . 'Debug/Toolbar/Views/', null, false);
$logs = $this->collectLogs();
if (empty($logs) || ! is_array($logs))
{
return '<p>Nothing was logged. If you were expecting logged items, ensure that LoggerConfig file has the correct threshold set.</p>';
$logs = [];
}
return $parser->setData([
'logs' => $logs
])
->render('_logs.tpl');
return [
'logs' => $logs
];
}
//--------------------------------------------------------------------
@ -122,9 +118,7 @@ class Logs extends BaseCollector
*/
public function icon(): string
{
return <<<EOD
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAACYSURBVEhLYxgFJIHU1FSjtLS0i0D8AYj7gEKMEBkqAaAFF4D4ERCvAFrwH4gDoFIMKSkpFkB+OTEYqgUTACXfA/GqjIwMQyD9H2hRHlQKJFcBEiMGQ7VgAqCBvUgK32dmZspCpagGGNPT0/1BLqeF4bQHQJePpiIwhmrBBEADR1MRfgB0+WgqAmOoFkwANHA0FY0CUgEDAwCQ0PUpNB3kqwAAAABJRU5ErkJggg==">
EOD;
return 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAACYSURBVEhLYxgFJIHU1FSjtLS0i0D8AYj7gEKMEBkqAaAFF4D4ERCvAFrwH4gDoFIMKSkpFkB+OTEYqgUTACXfA/GqjIwMQyD9H2hRHlQKJFcBEiMGQ7VgAqCBvUgK32dmZspCpagGGNPT0/1BLqeF4bQHQJePpiIwhmrBBEADR1MRfgB0+WgqAmOoFkwANHA0FY0CUgEDAwCQ0PUpNB3kqwAAAABJRU5ErkJggg==';
}

View File

@ -70,15 +70,12 @@ class Routes extends BaseCollector
//--------------------------------------------------------------------
/**
* Builds and returns the HTML needed to fill a tab to display
* within the Debug Bar
* Returns the data of this collector to be formatted in the toolbar
*
* @return string
* @return array
*/
public function display(): string
public function display(): array
{
$parser = \Config\Services::parser();
$rawRoutes = Services::routes(true);
$router = Services::router(null, true);
@ -126,11 +123,10 @@ class Routes extends BaseCollector
];
}
return $parser->setData([
'matchedRoute' => $matchedRoute,
'routes' => $routes
])
->render('CodeIgniter\Debug\Toolbar\Views\_routes.tpl');
return [
'matchedRoute' => $matchedRoute,
'routes' => $routes
];
}
//--------------------------------------------------------------------
@ -158,9 +154,7 @@ class Routes extends BaseCollector
*/
public function icon(): string
{
return <<<EOD
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAFDSURBVEhL7ZRNSsNQFIUjVXSiOFEcuQIHDpzpxC0IGYeE/BEInbWlCHEDLsSiuANdhKDjgm6ggtSJ+l25ldrmmTwIgtgDh/t37r1J+16cX0dRFMtpmu5pWAkrvYjjOB7AETzStBFW+inxu3KUJMmhludQpoflS1zXban4LYqiO224h6VLTHr8Z+z8EpIHFF9gG78nDVmW7UgTHKjsCyY98QP+pcq+g8Ku2s8G8X3f3/I8b038WZTp+bO38zxfFd+I6YY6sNUvFlSDk9CRhiAI1jX1I9Cfw7GG1UB8LAuwbU0ZwQnbRDeEN5qqBxZMLtE1ti9LtbREnMIuOXnyIf5rGIb7Wq8HmlZgwYBH7ORTcKH5E4mpjeGt9fBZcHE2GCQ3Vt7oTNPNg+FXLHnSsHkw/FR+Gg2bB8Ptzrst/v6C/wrH+QB+duli6MYJdQAAAABJRU5ErkJggg==">
EOD;
return 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAFDSURBVEhL7ZRNSsNQFIUjVXSiOFEcuQIHDpzpxC0IGYeE/BEInbWlCHEDLsSiuANdhKDjgm6ggtSJ+l25ldrmmTwIgtgDh/t37r1J+16cX0dRFMtpmu5pWAkrvYjjOB7AETzStBFW+inxu3KUJMmhludQpoflS1zXban4LYqiO224h6VLTHr8Z+z8EpIHFF9gG78nDVmW7UgTHKjsCyY98QP+pcq+g8Ku2s8G8X3f3/I8b038WZTp+bO38zxfFd+I6YY6sNUvFlSDk9CRhiAI1jX1I9Cfw7GG1UB8LAuwbU0ZwQnbRDeEN5qqBxZMLtE1ti9LtbREnMIuOXnyIf5rGIb7Wq8HmlZgwYBH7ORTcKH5E4mpjeGt9fBZcHE2GCQ3Vt7oTNPNg+FXLHnSsHkw/FR+Gg2bB8Ptzrst/v6C/wrH+QB+duli6MYJdQAAAABJRU5ErkJggg==';
}
}

View File

@ -98,5 +98,4 @@ class Timers extends BaseCollector
return $data;
}
//--------------------------------------------------------------------
}

View File

@ -182,9 +182,7 @@ class Views extends BaseCollector
*/
public function icon(): string
{
return <<<EOD
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADeSURBVEhL7ZSxDcIwEEWNYA0YgGmgyAaJLTcUaaBzQQEVjMEabBQxAdw53zTHiThEovGTfnE/9rsoRUxhKLOmaa6Uh7X2+UvguLCzVxN1XW9x4EYHzik033Hp3X0LO+DaQG8MDQcuq6qao4qkHuMgQggLvkPLjqh00ZgFDBacMJYFkuwFlH1mshdkZ5JPJERA9JpI6xNCBESvibQ+IURA9JpI6xNCBESvibQ+IURA9DTsuHTOrVFFxixgB/eUFlU8uKJ0eDBFOu/9EvoeKnlJS2/08Tc8NOwQ8sIfMeYFjqKDjdU2sp4AAAAASUVORK5CYII=">
EOD;
return 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADeSURBVEhL7ZSxDcIwEEWNYA0YgGmgyAaJLTcUaaBzQQEVjMEabBQxAdw53zTHiThEovGTfnE/9rsoRUxhKLOmaa6Uh7X2+UvguLCzVxN1XW9x4EYHzik033Hp3X0LO+DaQG8MDQcuq6qao4qkHuMgQggLvkPLjqh00ZgFDBacMJYFkuwFlH1mshdkZ5JPJERA9JpI6xNCBESvibQ+IURA9JpI6xNCBESvibQ+IURA9DTsuHTOrVFFxixgB/eUFlU8uKJ0eDBFOu/9EvoeKnlJS2/08Tc8NOwQ8sIfMeYFjqKDjdU2sp4AAAAASUVORK5CYII=';
}
}

View File

@ -1,4 +1,4 @@
<p style="text-align: right">
<p class="debug-bar-alignRight">
<a href="https://bcit-ci.github.io/CodeIgniter4/index.html" target="_blank" >Read the CodeIgniter docs...</a>
</p>
@ -23,7 +23,7 @@
<tr>
<td>Base URL:</td>
<td>
{ if baseURL == '' }
{ if $baseURL == '' }
<div class="warning">
The $baseURL should always be set manually to prevent possible URL personification from external parties.
</div>
@ -42,12 +42,12 @@
</tr>
<tr>
<td>Content Security Policy Enabled:</td>
<td>{ if cspEnabled } Yes { else } No { endif }</td>
<td>{ if $cspEnabled } Yes { else } No { endif }</td>
</tr>
<tr>
<td>Salt Set?:</td>
<td>
{ if salt == '' }
{ if $salt == '' }
<div class="warning">
You have not defined an application-wide $salt. This could lead to a less secure site.
</div>

View File

@ -1,7 +1,7 @@
<table>
<thead>
<tr>
<th style="width: 6rem;">Time</th>
<th class="debug-bar-width6r">Time</th>
<th>Query String</th>
</tr>
</thead>

View File

@ -1,7 +1,7 @@
<table>
<thead>
<tr>
<th style="width: 6rem;">Time</th>
<th class="debug-bar-width6r">Time</th>
<th>Event Name</th>
<th>Times Called</th>
</tr>

View File

@ -8,7 +8,7 @@
{/userFiles}
{coreFiles}
<tr class="muted">
<td style="width: 20em;">{name}</td>
<td class="debug-bar-width20e">{name}</td>
<td>{path}</td>
</tr>
{/coreFiles}

View File

@ -0,0 +1,28 @@
<table>
<thead>
<tr>
<th>Action</th>
<th>Datetime</th>
<th>Status</th>
<th>Method</th>
<th>URL</th>
<th>Content-Type</th>
<th>Is AJAX?</th>
</tr>
</thead>
<tbody>
{files}
<tr data-active="{active}">
<td class="debug-bar-width70p">
<button class="ci-history-load" data-time="{time}">Load</button>
</td>
<td class="debug-bar-width140p">{datetime}</td>
<td>{status}</td>
<td>{method}</td>
<td>{url}</td>
<td>{contentType}</td>
<td>{isAJAX}</td>
</tr>
{/files}
</tbody>
</table>

View File

@ -1,3 +1,6 @@
{ if $logs == [] }
<p>Nothing was logged. If you were expecting logged items, ensure that LoggerConfig file has the correct threshold set.</p>
{ else }
<table>
<thead>
<tr>
@ -14,3 +17,4 @@
{/logs}
</tbody>
</table>
{ endif }

View File

@ -163,6 +163,38 @@
margin-left: 0.5em;
}
#debug-bar span.ci-label .badge.active {
background-color: red;
}
#debug-bar button {
border: 1px solid #ddd;
background-color: #fff;
cursor: pointer;
border-radius: 4px;
color: #333;
}
#debug-bar button:hover {
background-color: #eaeaea;
}
#debug-bar tr[data-active="1"] {
background-color: #dff0d8;
}
#debug-bar tr[data-active="1"]:hover {
background-color: #a7d499;
}
#debug-bar tr.current {
background-color: #FDC894;
}
#debug-bar tr.current:hover {
background-color: #DD4814;
}
#debug-bar table strong {
font-weight: 500;
color: rgba(0, 0, 0, 0.3);
@ -324,3 +356,46 @@
display: none !important;
}
}
/**
simple styles to replace inline styles
*/
.debug-bar-width30 {
width: 30%;
}
.debug-bar-width10 {
width: 10%;
}
.debug-bar-width70p {
width: 70px;
}
.debug-bar-width140p {
width: 140px;
}
.debug-bar-width20e {
width: 20em;
}
.debug-bar-width6r {
width: 6rem;
}
.debug-bar-ndisplay {
display: none;
}
.debug-bar-alignRight {
text-align: right;
}
.debug-bar-alignLeft {
text-align: left;
}
.debug-bar-noverflow {
overflow: hidden;
}

View File

@ -17,11 +17,36 @@ var ciDebugBar = {
ciDebugBar.createListeners();
ciDebugBar.setToolbarState();
ciDebugBar.setToolbarPosition();
ciDebugBar.toogleViewsHints();
document.getElementById('debug-bar-link').addEventListener('click', ciDebugBar.toggleToolbar, true);
document.getElementById('debug-icon-link').addEventListener('click', ciDebugBar.toggleToolbar, true);
ciDebugBar.toggleViewsHints();
document.getElementById('debug-bar-link').addEventListener('click', ciDebugBar.toggleToolbar, true);
document.getElementById('debug-icon-link').addEventListener('click', ciDebugBar.toggleToolbar, true);
// Allows to highlight the row of the current history request
var btn = document.querySelector('button[data-time="'+localStorage.getItem('debugbar-time')+'"]');
ciDebugBar.addClass(btn.parentNode.parentNode, 'current');
historyLoad = document.getElementsByClassName('ci-history-load');
for (var i = 0; i < historyLoad.length; i++)
{
historyLoad[i].addEventListener('click', function() {
loadDoc(this.getAttribute('data-time'));
}, true);
}
// Display the active Tab on page load
var tab = ciDebugBar.readCookie('debug-bar-tab');
if (document.getElementById(tab)) {
var el = document.getElementById(tab);
el.style.display = 'block';
ciDebugBar.addClass(el, 'active');
tab = document.querySelector('[data-tab='+tab+']');
if (tab) {
ciDebugBar.addClass(tab.parentNode, 'active');
}
}
},
//--------------------------------------------------------------------
@ -48,6 +73,9 @@ var ciDebugBar = {
return;
}
// Remove debug-bar-tab cookie
ciDebugBar.createCookie('debug-bar-tab', '', -1);
// Check our current state.
var state = tab.style.display;
@ -72,6 +100,8 @@ var ciDebugBar = {
{
tab.style.display = 'block';
ciDebugBar.addClass(this.parentNode, 'active');
// Create debug-bar-tab cookie to persistent state
ciDebugBar.createCookie('debug-bar-tab', this.getAttribute('data-tab'), 365);
}
},
@ -156,8 +186,16 @@ var ciDebugBar = {
//--------------------------------------------------------------------
toogleViewsHints: function()
toggleViewsHints: function()
{
// Avoid toggle hints on history requests that are not the initial
if (localStorage.getItem('debugbar-time') != localStorage.getItem('debugbar-time-new'))
{
var a = document.querySelector('a[data-tab="ci-views"]');
a.href = '#';
return;
}
var nodeList = []; // [ Element, NewElement( 1 )/OldElement( 0 ) ]
var sortedComments = [];
var comments = [];
@ -399,15 +437,7 @@ var ciDebugBar = {
return;
}
btn = btn.parentNode;
// Determine Hints state on page load
if (ciDebugBar.readCookie('debug-view'))
{
showHints();
}
btn.onclick = function() {
btn.parentNode.onclick = function() {
if (ciDebugBar.readCookie('debug-view'))
{
hideHints();
@ -417,6 +447,12 @@ var ciDebugBar = {
showHints();
}
};
// Determine Hints state on page load
if (ciDebugBar.readCookie('debug-view'))
{
showHints();
}
},
//--------------------------------------------------------------------

View File

@ -5,87 +5,87 @@
<script id="toolbar_js" type="text/javascript">
<?= file_get_contents(__DIR__.'/toolbar.js') ?>
</script>
<div id="debug-icon" style="display:none">
<a id="debug-icon-link" href="javascript:void(0)">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="155.000000px" height="200.000000px" viewBox="0 0 155.000000 200.000000"
preserveAspectRatio="xMidYMid meet">
<g transform="translate(0.000000,200.000000) scale(0.100000,-0.100000)" fill="#dd4814" stroke="none">
<path d="M737 1963 c22 -79 -7 -185 -78 -290 -18 -26 -107 -122 -197 -213
-239 -240 -336 -371 -403 -544 -79 -206 -78 -408 5 -582 64 -134 212 -264 361
-314 l60 -20 -30 22 c-210 152 -229 387 -48 588 25 27 48 50 51 50 4 0 7 -27
7 -61 0 -57 2 -62 37 -95 30 -27 46 -34 78 -34 56 0 99 24 116 65 29 69 16
120 -50 205 -105 134 -117 233 -43 347 l31 48 7 -47 c13 -82 58 -129 250 -258
209 -141 306 -261 328 -405 11 -72 -1 -161 -31 -218 -27 -53 -112 -143 -165
-174 -24 -14 -43 -26 -43 -28 0 -2 24 4 53 14 241 83 427 271 482 486 19 76
19 202 -1 285 -35 152 -146 305 -299 412 l-70 49 -6 -33 c-8 -48 -26 -76 -59
-93 -45 -23 -103 -19 -138 10 -67 57 -78 146 -37 305 30 116 32 206 5 291 -27
89 -104 206 -162 247 -17 13 -18 12 -11 -15z"/>
</g>
</svg>
</a>
<div id="debug-icon" class="debug-bar-ndisplay">
<a id="debug-icon-link" href="javascript:void(0)">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="155.000000px" height="200.000000px" viewBox="0 0 155.000000 200.000000"
preserveAspectRatio="xMidYMid meet">
<g transform="translate(0.000000,200.000000) scale(0.100000,-0.100000)" fill="#dd4814" stroke="none">
<path d="M737 1963 c22 -79 -7 -185 -78 -290 -18 -26 -107 -122 -197 -213
-239 -240 -336 -371 -403 -544 -79 -206 -78 -408 5 -582 64 -134 212 -264 361
-314 l60 -20 -30 22 c-210 152 -229 387 -48 588 25 27 48 50 51 50 4 0 7 -27
7 -61 0 -57 2 -62 37 -95 30 -27 46 -34 78 -34 56 0 99 24 116 65 29 69 16
120 -50 205 -105 134 -117 233 -43 347 l31 48 7 -47 c13 -82 58 -129 250 -258
209 -141 306 -261 328 -405 11 -72 -1 -161 -31 -218 -27 -53 -112 -143 -165
-174 -24 -14 -43 -26 -43 -28 0 -2 24 4 53 14 241 83 427 271 482 486 19 76
19 202 -1 285 -35 152 -146 305 -299 412 l-70 49 -6 -33 c-8 -48 -26 -76 -59
-93 -45 -23 -103 -19 -138 10 -67 57 -78 146 -37 305 30 116 32 206 5 291 -27
89 -104 206 -162 247 -17 13 -18 12 -11 -15z"/>
</g>
</svg>
</a>
</div>
<div id="debug-bar">
<div class="toolbar">
<span id="toolbar-position"><a href="javascript: void(0)">&#8597;</a></span>
<span id="toolbar-position"><a href="javascript: void(0)">&#8597;</a></span>
<span class="ci-label">
<a href="javascript: void(0)" data-tab="ci-timeline">
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAD7SURBVEhLY6ArSEtLK09NTbWHcvGC9PR0BaDaQiAdUl9fzwQVxg+AFvwHamqHcnGCpKQkeaDa9yD1UD09UCn8AKaBWJySkmIApFehi0ONwwRQBceBLurAh4FqFoHUAtkrgPgREN+ByYEw1DhMANVEMIhAYQ5U1wtU/wmILwLZRlAp/IBYC8gGw88CaFj3A/FnIL4ETDXGUCnyANSC/UC6HIpnQMXAqQXIvo0khxNDjcMEQEmU9AzDuNI7Lgw1DhOAJIEuhQcRKMcC+e+QNHdDpcgD6BaAANSSQqBcENFlDi6AzQKqgkFlwWhxjVI8o2OgmkFaXI8CTMDAAAAxd1O4FzLMaAAAAABJRU5ErkJggg==">
<span class="hide-sm"><?= $totalTime ?> ms &nbsp; <?= $totalMemory ?> MB</span>
</a>
</span>
<?php foreach ($this->collectors as $c) : ?>
<?php if (! $c->isEmpty()) : ?>
<?php if ($c->hasTabContent() || $c->hasLabel()) : ?>
<span class="ci-label">
<a href="javascript: void(0)" data-tab="ci-<?= esc($c->getTitle(true)) ?>" >
<?= $c->icon() ?>
<span class="hide-sm">
<?= esc($c->getTitle()) ?>
<?php if (! is_null($c->getBadgeValue())) : ?>
<span class="badge"><?= $c->getBadgeValue() ?></span>
<?php endif ?>
</span>
</a>
</span>
<?php endif ?>
<?php endif ?>
<?php endforeach; ?>
<a href="javascript: void(0)" data-tab="ci-timeline">
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAD7SURBVEhLY6ArSEtLK09NTbWHcvGC9PR0BaDaQiAdUl9fzwQVxg+AFvwHamqHcnGCpKQkeaDa9yD1UD09UCn8AKaBWJySkmIApFehi0ONwwRQBceBLurAh4FqFoHUAtkrgPgREN+ByYEw1DhMANVEMIhAYQ5U1wtU/wmILwLZRlAp/IBYC8gGw88CaFj3A/FnIL4ETDXGUCnyANSC/UC6HIpnQMXAqQXIvo0khxNDjcMEQEmU9AzDuNI7Lgw1DhOAJIEuhQcRKMcC+e+QNHdDpcgD6BaAANSSQqBcENFlDi6AzQKqgkFlwWhxjVI8o2OgmkFaXI8CTMDAAAAxd1O4FzLMaAAAAABJRU5ErkJggg==">
<span class="hide-sm"><?= $totalTime ?> ms &nbsp; <?= $totalMemory ?> MB</span>
</a>
</span>
<?php foreach ($collectors as $c) : ?>
<?php if (! $c['isEmpty'] && ($c['hasTabContent'] || $c['hasLabel'])) : ?>
<span class="ci-label">
<a href="javascript: void(0)" data-tab="ci-<?= $c['titleSafe'] ?>" >
<img src="<?= $c['icon'] ?>">
<span class="hide-sm">
<?= $c['title'] ?>
<?php if (! is_null($c['badgeValue'])) : ?>
<span class="badge"><?= $c['badgeValue'] ?></span>
<?php endif ?>
</span>
</a>
</span>
<?php endif ?>
<?php endforeach ?>
<span class="ci-label">
<a href="javascript: void(0)" data-tab="ci-vars">
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAACLSURBVEhLYxgFJIHU1NSraWlp/6H4T0pKSjRUijoAyXAwBlrYDpViAFpmARQrJwZDtWACoCROC4D8CnR5XBiqBRMADfyNprgRKkUdAApzoCUdUNwE5MtApYYIALp6NBWBMVQLJgAaOJqK8AOgq+mSio6DggjEBtLUT0UwQ5HZIADkj6aiUTAggIEBANAEDa/lkCRlAAAAAElFTkSuQmCC">
<span class="hide-sm">Vars</span>
</a>
</span>
<a href="javascript: void(0)" data-tab="ci-vars">
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAACLSURBVEhLYxgFJIHU1NSraWlp/6H4T0pKSjRUijoAyXAwBlrYDpViAFpmARQrJwZDtWACoCROC4D8CnR5XBiqBRMADfyNprgRKkUdAApzoCUdUNwE5MtApYYIALp6NBWBMVQLJgAaOJqK8AOgq+mSio6DggjEBtLUT0UwQ5HZIADkj6aiUTAggIEBANAEDa/lkCRlAAAAAElFTkSuQmCC">
<span class="hide-sm">Vars</span>
</a>
</span>
<h1>
<span class="ci-label">
<a href="javascript: void(0)" data-tab="ci-config" >
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="18.60px" height="24.0px" viewBox="0 0 18.60 28.000000"
preserveAspectRatio="xMidYMid meet">
<g transform="translate(0.000000,28.000000) scale(0.010000,-0.010000)" fill="#dd4814" stroke="none">
<path d="M737 1963 c22 -79 -7 -185 -78 -290 -18 -26 -107 -122 -197 -213
-239 -240 -336 -371 -403 -544 -79 -206 -78 -408 5 -582 64 -134 212 -264 361
-314 l60 -20 -30 22 c-210 152 -229 387 -48 588 25 27 48 50 51 50 4 0 7 -27
7 -61 0 -57 2 -62 37 -95 30 -27 46 -34 78 -34 56 0 99 24 116 65 29 69 16
120 -50 205 -105 134 -117 233 -43 347 l31 48 7 -47 c13 -82 58 -129 250 -258
209 -141 306 -261 328 -405 11 -72 -1 -161 -31 -218 -27 -53 -112 -143 -165
-174 -24 -14 -43 -26 -43 -28 0 -2 24 4 53 14 241 83 427 271 482 486 19 76
19 202 -1 285 -35 152 -146 305 -299 412 l-70 49 -6 -33 c-8 -48 -26 -76 -59
-93 -45 -23 -103 -19 -138 10 -67 57 -78 146 -37 305 30 116 32 206 5 291 -27
89 -104 206 -162 247 -17 13 -18 12 -11 -15z"/>
</g>
</svg>
<?= \CodeIgniter\CodeIgniter::CI_VERSION ?>
</a>
</span>
</h1>
<h1>
<span class="ci-label">
<a href="javascript: void(0)" data-tab="ci-config" >
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="18.60px" height="24.0px" viewBox="0 0 18.60 28.000000"
preserveAspectRatio="xMidYMid meet">
<g transform="translate(0.000000,28.000000) scale(0.010000,-0.010000)" fill="#dd4814" stroke="none">
<path d="M737 1963 c22 -79 -7 -185 -78 -290 -18 -26 -107 -122 -197 -213
-239 -240 -336 -371 -403 -544 -79 -206 -78 -408 5 -582 64 -134 212 -264 361
-314 l60 -20 -30 22 c-210 152 -229 387 -48 588 25 27 48 50 51 50 4 0 7 -27
7 -61 0 -57 2 -62 37 -95 30 -27 46 -34 78 -34 56 0 99 24 116 65 29 69 16
120 -50 205 -105 134 -117 233 -43 347 l31 48 7 -47 c13 -82 58 -129 250 -258
209 -141 306 -261 328 -405 11 -72 -1 -161 -31 -218 -27 -53 -112 -143 -165
-174 -24 -14 -43 -26 -43 -28 0 -2 24 4 53 14 241 83 427 271 482 486 19 76
19 202 -1 285 -35 152 -146 305 -299 412 l-70 49 -6 -33 c-8 -48 -26 -76 -59
-93 -45 -23 -103 -19 -138 10 -67 57 -78 146 -37 305 30 116 32 206 5 291 -27
89 -104 206 -162 247 -17 13 -18 12 -11 -15z"/>
</g>
</svg>
<?= $CI_VERSION ?>
</a>
</span>
</h1>
<!-- Open/Close Toggle -->
<a id="debug-bar-link" href="javascript:void(0)">
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAEPSURBVEhL7ZVLDoJAEEThRuoGDwSEG+jCuFU34s3AK3APP1VDDSGMqI1xx0s6M/2rnlHEaMZElmWrPM+vsDvsYbQ7+us0TReSC2EBrEHxCevRYuppYLXkQpC8sVCuGfTvqSE3hFdFwUGuGfRvqSE35NUAfKZrbQNQm2jrMA+gOK+M+FmhDsRL5voHMA8gFGecq0JOXLWlQg7E7AMIxZnjOiZOEJ82gFCcedUE4gS56QP8yf8ywItz7e+RituKlkkDBoIOH4Nd4HZD4NsGYJ/Abn1xEVOcuZ8f0zc/tHiYmzTAwscBvDIK/veyQ9K/rnewjdF26q0kF1IUxZIFPAVW98x/a+qp8L2M/+HMhETRE6S8TxpZ7KGXAAAAAElFTkSuQmCC">
</a>
<!-- Open/Close Toggle -->
<a id="debug-bar-link" href="javascript:void(0)" title="Open/Close">
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAEPSURBVEhL7ZVLDoJAEEThRuoGDwSEG+jCuFU34s3AK3APP1VDDSGMqI1xx0s6M/2rnlHEaMZElmWrPM+vsDvsYbQ7+us0TReSC2EBrEHxCevRYuppYLXkQpC8sVCuGfTvqSE3hFdFwUGuGfRvqSE35NUAfKZrbQNQm2jrMA+gOK+M+FmhDsRL5voHMA8gFGecq0JOXLWlQg7E7AMIxZnjOiZOEJ82gFCcedUE4gS56QP8yf8ywItz7e+RituKlkkDBoIOH4Nd4HZD4NsGYJ/Abn1xEVOcuZ8f0zc/tHiYmzTAwscBvDIK/veyQ9K/rnewjdF26q0kF1IUxZIFPAVW98x/a+qp8L2M/+HMhETRE6S8TxpZ7KGXAAAAAElFTkSuQmCC">
</a>
</div>
<!-- Timeline -->
@ -93,110 +93,90 @@
<table class="timeline">
<thead>
<tr>
<th style="width: 30%">NAME</th>
<th style="width: 10%">COMPONENT</th>
<th style="width: 10%;">DURATION</th>
<?php for ($i=0; $i < $segmentCount; $i++) : ?>
<th class="debug-bar-width30">NAME</th>
<th class="debug-bar-width10">COMPONENT</th>
<th class="debug-bar-width10">DURATION</th>
<?php for ($i = 0; $i < $segmentCount; $i++) : ?>
<th><?= $i * $segmentDuration ?> ms</th>
<?php endfor; ?>
<?php endfor ?>
</tr>
</thead>
<tbody>
<?= $this->renderTimeline($segmentCount, $segmentDuration, $totalTime) ?>
<?= self::renderTimeline($collectors, $startTime, $segmentCount, $segmentDuration, $styles) ?>
</tbody>
</table>
</div>
<!-- Collector-provided Tabs -->
<?php foreach ($this->collectors as $c) : ?>
<?php if (! $c->isEmpty()) : ?>
<?php if ($c->hasTabContent()) : ?>
<div id="ci-<?= esc($c->getTitle(true)) ?>" class="tab">
<h2><?= esc($c->getTitle()) ?> <span><?= esc($c->getTitleDetails()) ?></span></h2>
<?php foreach ($collectors as $c) : ?>
<?php if (! $c['isEmpty']) : ?>
<?php if ($c['hasTabContent']) : ?>
<div id="ci-<?= $c['titleSafe'] ?>" class="tab">
<h2><?= $c['title'] ?> <span><?= $c['titleDetails'] ?></span></h2>
<?= $c->display() ?>
</div>
<?php endif ?>
<?php endif ?>
<?= $parser->setData($c['display'])->render("_{$c['titleSafe']}.tpl") ?>
</div>
<?php endif ?>
<?php endif ?>
<?php endforeach ?>
<!-- In & Out -->
<div id="ci-vars" class="tab">
<!-- VarData from Collectors -->
<?php foreach ($varData as $heading => $items) : ?>
<?php if(isset($vars['varData'])) : ?>
<?php foreach ($vars['varData'] as $heading => $items) : ?>
<a href="javascript:void(0)" onclick="ciDebugBar.toggleDataTable('<?= strtolower(str_replace(' ', '-', $heading)) ?>'); return false;">
<h2><?= esc($heading) ?></h2>
</a>
<a href="javascript:void(0)" onclick="ciDebugBar.toggleDataTable('<?= strtolower(str_replace(' ', '-', $heading)) ?>'); return false;">
<h2><?= $heading ?></h2>
</a>
<?php if (is_array($items)) : ?>
<?php if (is_array($items)) : ?>
<table id="<?= strtolower(str_replace(' ', '-', $heading.'_table')) ?>">
<tbody>
<?php foreach ($items as $key => $value) : ?>
<tr>
<td><?= esc($key) ?></td>
<td>
<?php
if (is_string($value))
{
echo esc($value);
}
else
{
echo print_r($value, true);
}
?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<table id="<?= strtolower(str_replace(' ', '-', $heading.'_table')) ?>">
<tbody>
<?php foreach ($items as $key => $value) : ?>
<tr>
<td><?= $key ?></td>
<td><?= $value ?></td>
</tr>
<?php endforeach ?>
</tbody>
</table>
<?php else: ?>
<p class="muted">No data to display.</p>
<?php endif; ?>
<?php endforeach; ?>
<?php else: ?>
<p class="muted">No data to display.</p>
<?php endif ?>
<?php endforeach ?>
<?php endif ?>
<!-- Session -->
<a href="javascript:void(0)" onclick="ciDebugBar.toggleDataTable('session'); return false;">
<h2>Session User Data</h2>
</a>
<?php if (isset($_SESSION)) : ?>
<?php if (! empty($_SESSION)) : ?>
<?php if (isset($vars['session'])) : ?>
<?php if (! empty($vars['session'])) : ?>
<table id="session_table">
<tbody>
<?php foreach ($_SESSION as $key => $value) : ?>
<?php foreach ($vars['session'] as $key => $value) : ?>
<tr>
<td><?= esc($key) ?></td>
<td>
<?php
if (is_string($value))
{
echo esc($value);
}
else
{
echo print_r($value, true);
}
?>
</td>
<td><?= $key ?></td>
<td><?= $value ?></td>
</tr>
<?php endforeach; ?>
<?php endforeach ?>
</tbody>
</table>
<?php else : ?>
<p class="muted">No data to display.</p>
<?php endif; ?>
<?php endif ?>
<?php else : ?>
<p class="muted">Session doesn't seem to be active.</p>
<?php endif; ?>
<?php endif ?>
<h2>Request <span>( <?= ($request->isSecure() ? 'HTTPS' : 'HTTP').'/'.$request->getProtocolVersion() ?> )</span></h2>
<h2>Request <span>( <?= $vars['request'] ?> )</span></h2>
<?php if ($get = $request->getGet()) : ?>
<?php if (isset($vars['get']) && $get = $vars['get']) : ?>
<a href="javascript:void(0)" onclick="ciDebugBar.toggleDataTable('get'); return false;">
<h3>$_GET</h3>
</a>
@ -205,15 +185,15 @@
<tbody>
<?php foreach ($get as $name => $value) : ?>
<tr>
<td><?= esc($name) ?></td>
<td><?= esc($value) ?></td>
<td><?= $name ?></td>
<td><?= $value ?></td>
</tr>
<?php endforeach; ?>
<?php endforeach ?>
</tbody>
</table>
<?php endif ?>
<?php if ($post = $request->getPost()) : ?>
<?php if (isset($vars['post']) && $post = $vars['post']) : ?>
<a href="javascript:void(0)" onclick="ciDebugBar.toggleDataTable('post'); return false;">
<h3>$_POST</h3>
</a>
@ -222,56 +202,51 @@
<tbody>
<?php foreach ($post as $name => $value) : ?>
<tr>
<td><?= esc($name) ?></td>
<td><?= is_array($value) ? esc(print_r($value, true)) : esc($value) ?></td>
<td><?= $name ?></td>
<td><?= $value ?></td>
</tr>
<?php endforeach; ?>
<?php endforeach ?>
</tbody>
</table>
<?php endif ?>
<?php if ($headers = $request->getHeaders()) : ?>
<?php if (isset($vars['headers']) && $headers = $vars['headers']) : ?>
<a href="javascript:void(0)" onclick="ciDebugBar.toggleDataTable('request_headers'); return false;">
<h3>Headers</h3>
</a>
<table id="request_headers_table">
<tbody>
<?php foreach ($headers as $header => $value) : ?>
<?php if (empty($value)) continue; ?>
<?php if (! is_array($value)) { $value = [$value]; } ?>
<?php foreach ($value as $h) : ?>
<tr>
<td><?= esc($h->getName()) ?></td>
<td><?= esc($h->getValueLine()) ?></td>
<td><?= $header ?></td>
<td><?= $value ?></td>
</tr>
<?php endforeach; ?>
<?php endforeach; ?>
<?php endforeach ?>
</tbody>
</table>
<?php endif ?>
<?php if ($get = $request->getCookie()) : ?>
<?php if (isset($vars['cookies']) && $cookies = $vars['cookies']) : ?>
<a href="javascript:void(0)" onclick="ciDebugBar.toggleDataTable('cookie'); return false;">
<h3>Cookies</h3>
</a>
<table id="cookie_table">
<tbody>
<?php foreach ($get as $name => $value) : ?>
<?php foreach ($cookies as $name => $value) : ?>
<tr>
<td><?= esc($name) ?></td>
<td><?= esc($value) ?></td>
<td><?= $name ?></td>
<td><?= is_array($value) ? var_dump($value) : $value ?></td>
</tr>
<?php endforeach; ?>
<?php endforeach ?>
</tbody>
</table>
<?php endif ?>
<h2>Response <span>( <?= $response->getStatusCode().' - '. esc($response->getReason()) ?> )</span></h2>
<h2>Response <span>( <?= $vars['response']['statusCode'].' - '. $vars['response']['reason'] ?> )</span></h2>
<?php if ($headers = $response->getHeaders()) : ?>
<?php if (isset($vars['headers']) && $headers = $vars['headers']) : ?>
<a href="javascript:void(0)" onclick="ciDebugBar.toggleDataTable('response_headers'); return false;">
<h3>Headers</h3>
</a>
@ -280,18 +255,26 @@
<tbody>
<?php foreach ($headers as $header => $value) : ?>
<tr>
<td><?= esc($header) ?></td>
<td><?= esc($response->getHeaderLine($header)) ?></td>
<td><?= $header ?></td>
<td><?= $value ?></td>
</tr>
<?php endforeach; ?>
<?php endforeach ?>
</tbody>
</table>
<?php endif; ?>
<?php endif ?>
</div>
<!-- Config Values -->
<div id="ci-config" class="tab">
<h2>System Configuration</h2>
<!-- Config Values -->
<div id="ci-config" class="tab">
<h2>System Configuration</h2>
<?= \CodeIgniter\Debug\Toolbar\Collectors\Config::display() ?>
</div>
<?= $parser->setData($config)->render('_config.tpl') ?>
</div>
</div>
<style type="text/css">
<?php foreach( $styles as $name => $style ) : ?>
.<?= $name ?> {
<?= $style ?>
}
<?php endforeach ?>
</style>

View File

@ -1,24 +1,84 @@
<?php if (ENVIRONMENT != 'testing') : ?>
document.addEventListener('DOMContentLoaded', loadDoc, false);
document.addEventListener('DOMContentLoaded', loadDoc, false );
function loadDoc(time) {
if (isNaN(time)) {
time = document.getElementById("debugbar_loader").getAttribute("data-time");
localStorage.setItem('debugbar-time', time);
}
function loadDoc() {
var time = document.getElementById("debugbar_loader").getAttribute("data-time");
var url = "<?php echo rtrim(site_url(), '/') ?>";
localStorage.setItem('debugbar-time-new', time);
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
var toolbar = document.createElement( 'div' );
toolbar.setAttribute( 'id', 'toolbarContainer' );
toolbar.innerHTML = this.responseText;
document.body.appendChild( toolbar );
eval(document.getElementById("toolbar_js").innerHTML);
if (typeof ciDebugBar === 'object') {
ciDebugBar.init();
}
}
};
var url = "<?= rtrim(site_url(), '/') ?>";
xhttp.open("GET", url + "?debugbar_time=" + time, true);
xhttp.send();
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState === 4 && this.status === 200) {
var toolbar = document.getElementById("toolbarContainer");
if (!toolbar) {
toolbar = document.createElement('div');
toolbar.setAttribute('id', 'toolbarContainer');
document.body.appendChild(toolbar);
}
// copy for easier manipulation
let responseText = this.responseText;
// get csp blocked parts
// the style block is the first and starts at 0
{
let PosBeg = responseText.indexOf( '>', responseText.indexOf( '<style' ) ) + 1;
let PosEnd = responseText.indexOf( '</style>', PosBeg );
document.getElementById( 'debugbar_dynamic_style' ).innerHTML = responseText.substr( PosBeg, PosEnd )
responseText = responseText.substr( PosEnd + 8 );
}
// the script block starts right after style blocks ended
{
let PosBeg = responseText.indexOf( '>', responseText.indexOf( '<script' ) ) + 1;
let PosEnd = responseText.indexOf( '</script>' );
document.getElementById( 'debugbar_dynamic_script' ).innerHTML = responseText.substr( PosBeg, PosEnd - PosBeg );
responseText = responseText.substr( PosEnd + 9 );
}
// check for last style block
{
let PosBeg = responseText.indexOf( '>', responseText.lastIndexOf( '<style' ) ) + 1;
let PosEnd = responseText.indexOf( '</style>', PosBeg );
document.getElementById( 'debugbar_dynamic_style' ).innerHTML += responseText.substr( PosBeg, PosEnd - PosBeg );
responseText = responseText.substr( 0, PosBeg );
}
toolbar.innerHTML = responseText;
if (typeof ciDebugBar === 'object') {
ciDebugBar.init();
}
} else if (this.readyState === 4 && this.status === 404) {
console.log('CodeIgniter DebugBar: File "WRITEPATH/debugbar/debugbar_' + time + '" not found.');
}
};
xhttp.open("GET", url + "?debugbar_time=" + time, true);
xhttp.send();
}
// Track all AJAX requests
var oldXHR = window.XMLHttpRequest;
function newXHR() {
var realXHR = new oldXHR();
realXHR.addEventListener("readystatechange", function() {
// Only success responses and URLs that do not contains "debugbar_time" are tracked
if (realXHR.readyState === 4 && realXHR.status.toString()[0] === '2' && realXHR.responseURL.indexOf('debugbar_time') === -1) {
var debugbarTime = realXHR.getResponseHeader('Debugbar-Time');
if (debugbarTime) {
var h2 = document.querySelector('#ci-history > h2');
h2.innerHTML = 'History <small>You have new debug data.</small> <button onclick="loadDoc(' + debugbarTime + ')">Update</button>';
var badge = document.querySelector('a[data-tab="ci-history"] > span > .badge');
badge.className += ' active';
}
}
}, false);
return realXHR;
}
window.XMLHttpRequest = newXHR;
<?php endif; ?>

File diff suppressed because it is too large Load Diff

View File

@ -103,6 +103,41 @@ class Entity
//--------------------------------------------------------------------
/**
* General method that will return all public and protected
* values of this entity as an array. All values are accessed
* through the __get() magic method so will have any casts, etc
* applied to them.
*/
public function toArray(): array
{
$return = [];
// we need to loop over our properties so that we
// allow our magic methods a chance to do their thing.
$properties = get_object_vars($this);
foreach ($properties as $key => $value)
{
if ($key == '_options') continue;
$return[$key] = $this->__get($key);
}
// Loop over our mapped properties and add them to the list...
if (is_array($this->_options['datamap']))
{
foreach ($this->_options['datamap'] as $from => $to)
{
$return[$from] = $this->__get($to);
}
}
return $return;
}
//--------------------------------------------------------------------
/**
* Magic method to allow retrieval of protected and private
* class properties either by their name, or through a `getCamelCasedProperty()`
@ -144,7 +179,7 @@ class Entity
$result = $this->mutateDate($result);
}
// Or cast it as something?
else if (array_key_exists($key, $this->_options['casts']))
else if (isset($this->_options['casts'][$key]) && ! empty($this->_options['casts'][$key]))
{
$result = $this->castAs($result, $this->_options['casts'][$key]);
}
@ -267,7 +302,12 @@ class Entity
*/
protected function mapProperty(string $key)
{
if (array_key_exists($key, $this->_options['datamap']))
if (empty($this->_options['datamap']))
{
return $key;
}
if (isset($this->_options['datamap'][$key]) && ! empty($this->_options['datamap'][$key]))
{
return $this->_options['datamap'][$key];
}
@ -343,7 +383,7 @@ class Entity
$value = (object)$value;
break;
case 'array':
if (is_string($value) && (substr($value, 0, 2) === 'a:' || substr($value, 0, 2) === 's:'))
if (is_string($value) && (strpos($value,'a:') === 0 || strpos($value, 's:') === 0))
{
$value = unserialize($value);
}

Some files were not shown because too many files have changed in this diff Show More