Merge pull request #1 from bcit-ci/develop

Update latest version
This commit is contained in:
bangbangda 2018-06-29 16:46:03 +08:00 committed by GitHub
commit a754b930ad
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
414 changed files with 15214 additions and 7011 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:
@ -43,4 +42,4 @@ before_script:
- composer install --prefer-source
after_success:
- travis_retry php tests/bin/coveralls.phar
- travis_retry php tests/bin/coveralls.phar -v

View File

@ -270,6 +270,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 +284,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

@ -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

@ -33,15 +33,13 @@ 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());
$stats = $app->getPerformanceStats();
$output = $toolbar->run(
$data = $toolbar->run(
$stats['startTime'],
$stats['totalTime'],
$stats['startMemory'],
@ -49,7 +47,7 @@ class DebugToolbar implements FilterInterface
$response
);
helper(['filesystem', 'url']);
helper('filesystem');
// Updated to time() so we can get history
$time = time();
@ -59,7 +57,19 @@ 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" '

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,7 +12,8 @@
},
"autoload": {
"psr-4": {
"CodeIgniter\\": "system/"
"CodeIgniter\\": "system/",
"Psr\\Log\\": "system/ThirdParty/PSR/Log/"
}
},
"require": {
@ -22,7 +23,7 @@
"kint-php/kint": "^2.1"
},
"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/Live</exclude> -->
@ -20,14 +24,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

@ -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,10 +45,19 @@
*
* 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.
*
* http://fuelphp.com
* originally made available under. Reference: 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
*/
class CLI
@ -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,7 +213,7 @@ class CLI
if (is_string($options))
{
$extra_output = ' [' . static::color($options, 'white') .']';
$extra_output = ' [' . static::color($options, 'white') . ']';
$default = $options;
}
@ -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
}
}
}
@ -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,15 +648,10 @@ 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 there is a following segment, and it doesn't start with a dash, it's a value.
if (isset($_SERVER['argv'][$i + 1]) && mb_substr($_SERVER['argv'][$i + 1], 0, 1) != '-')
{
$value = $_SERVER['argv'][$i + 1];
@ -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

@ -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

@ -310,7 +310,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,7 @@
* @filesource
*/
use CodeIgniter\HTTP\RedirectResponse;
use CodeIgniter\HTTP\Request;
use Config\Services;
use Config\Cache;
use CodeIgniter\HTTP\URI;
@ -44,6 +45,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
@ -179,8 +181,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();
@ -200,7 +206,7 @@ class CodeIgniter
try
{
$this->handleRequest($routes, $cacheConfig);
return $this->handleRequest($routes, $cacheConfig, $returnResponse);
} catch (Router\RedirectException $e)
{
$logger = Services::logger();
@ -224,8 +230,11 @@ class CodeIgniter
*
* @param \CodeIgniter\Router\RouteCollectionInterface $routes
* @param $cacheConfig
* @param bool $returnResponse
*
* @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);
@ -256,6 +265,11 @@ class CodeIgniter
// Handle any redirects
if ($returned instanceof RedirectResponse)
{
if ($returnResponse)
{
return $returned;
}
$this->callExit(EXIT_SUCCESS);
}
@ -278,12 +292,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 +376,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 +400,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 +427,7 @@ class CodeIgniter
{
$this->response = Services::response($this->config);
if ( ! is_cli())
if ( ! is_cli() || ENVIRONMENT == 'testing')
{
$this->response->setProtocolVersion($this->request->getProtocolVersion());
}
@ -522,7 +564,7 @@ class CodeIgniter
*/
protected function generateCacheName($config): string
{
if (is_cli())
if (is_cli() && ! (ENVIRONMENT == 'testing'))
{
return md5($this->request->getPath());
}
@ -616,7 +658,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 +702,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);
}
}
@ -755,7 +797,7 @@ class CodeIgniter
}
// Display 404 Errors
$this->response->setStatusCode(404);
$this->response->setStatusCode($e->getCode());
if (ENVIRONMENT !== 'testing')
{
@ -773,7 +815,7 @@ class CodeIgniter
}
}
throw new PageNotFoundException(lang('HTTP.pageNotFound'));
throw PageNotFoundException::forPageNotFound();
}
//--------------------------------------------------------------------

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

@ -121,7 +121,7 @@ class MigrateStatus extends BaseCommand
if (empty($migrations))
{
CLI::error("$namespace: " . lang('Migrations.migNoneFound'));
CLI::error("$namespace: " . lang('Migrations.noneFound'));
continue;
}
@ -129,7 +129,7 @@ class MigrateStatus extends BaseCommand
CLI::newLine(1);
CLI::write(lang('Migrations.migHistoryFor') . "$namespace: ", 'green');
CLI::write(lang('Migrations.historyFor') . "$namespace: ", 'green');
CLI::newLine(1);
@ -142,7 +142,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 + 6) . lang('Migrations.on'), 'yellow');
foreach ($migrations as $version => $migration)

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

@ -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 = realpath(__DIR__ . '/../../../public') . 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,126 @@
<?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\Autoload;
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'))
{
@ -282,14 +300,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 +453,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
}
}
@ -667,6 +688,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 +705,7 @@ if ( ! function_exists('force_https'))
$response = Services::response(null, true);
}
if ($request->isSecure())
if (is_cli() || $request->isSecure())
{
return;
}
@ -716,12 +742,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();
@ -740,7 +767,7 @@ if (! function_exists('old'))
$value = unserialize($value);
}
return $value;
return $escape === false ? $value : esc($value, $escape);
}
}
@ -835,6 +862,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 +890,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;
}
@ -929,6 +958,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 +988,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,219 @@
<?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
*/
use CodeIgniter\Autoloader\FileLocator;
/**
* 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];
}
//--------------------------------------------------------------------
/**
* 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, ['Config\\Services', 'CodeIgniter\\Config\\Services']))
{
static::$services[] = new $classname();
}
}
}
if (! count(static::$services))
{
return;
}
// Try to find the desired service method
foreach (static::$services as $class)
{
if (method_exists($class, $name))
{
return $class::$name(...$arguments);
}
}
}
}

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

@ -0,0 +1,122 @@
<?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);
}
$class = strtolower($class);
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

@ -126,11 +126,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,17 +27,19 @@
* 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 CodeIgniter\Database\ConnectionInterface;
use CodeIgniter\Database\MigrationRunner;
use CodeIgniter\HTTP\URI;
use CodeIgniter\View\RendererInterface;
use Config\App;
/**
* Services Configuration file.
@ -56,26 +58,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 +96,7 @@ class Services
return self::getSharedInstance('cache', $config);
}
if ( ! is_object($config))
if (! is_object($config))
{
$config = new \Config\Cache();
}
@ -138,14 +122,12 @@ class Services
return self::getSharedInstance('clirequest', $config);
}
if ( ! is_object($config))
if (! is_object($config))
{
$config = new \Config\App();
}
return new \CodeIgniter\HTTP\CLIRequest(
$config, new \CodeIgniter\HTTP\URI()
);
return new \CodeIgniter\HTTP\CLIRequest($config);
}
//--------------------------------------------------------------------
@ -161,28 +143,32 @@ 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();
}
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 +206,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 +229,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 +251,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,10 +336,14 @@ 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);
}
@ -453,7 +459,7 @@ class Services
$config = new \Config\Pager();
}
if ( ! $view instanceof RendererInterface)
if (! $view instanceof RendererInterface)
{
$view = self::renderer();
}
@ -467,12 +473,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 +506,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 +538,16 @@ class Services
return self::getSharedInstance('request', $config);
}
if ( ! is_object($config))
if (! is_object($config))
{
$config = new \Config\App();
$config = new App();
}
return new \CodeIgniter\HTTP\IncomingRequest(
$config, new \CodeIgniter\HTTP\URI()
$config,
new \CodeIgniter\HTTP\URI(),
'php://input',
new \CodeIgniter\HTTP\UserAgent()
);
}
@ -559,7 +568,7 @@ class Services
return self::getSharedInstance('response', $config);
}
if ( ! is_object($config))
if (! is_object($config))
{
$config = new \Config\App();
}
@ -584,12 +593,16 @@ class Services
return self::getSharedInstance('redirectResponse', $config);
}
if ( ! is_object($config))
if (! is_object($config))
{
$config = new \Config\App();
}
return new \CodeIgniter\HTTP\RedirectResponse($config);
$response = new \CodeIgniter\HTTP\RedirectResponse($config);
$response->setProtocolVersion(self::request()
->getProtocolVersion());
return $response;
}
//--------------------------------------------------------------------
@ -656,7 +669,7 @@ class Services
return self::getSharedInstance('security', $config);
}
if ( ! is_object($config))
if (! is_object($config))
{
$config = new \Config\App();
}
@ -679,7 +692,7 @@ class Services
return self::getSharedInstance('session', $config);
}
if ( ! is_object($config))
if (! is_object($config))
{
$config = new \Config\App();
}
@ -687,7 +700,7 @@ class Services
$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);
@ -751,7 +764,7 @@ class Services
return self::getSharedInstance('toolbar', $config);
}
if ( ! is_object($config))
if (! is_object($config))
{
$config = new \Config\App();
}
@ -843,86 +856,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,47 @@
* 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',
];
public function __construct()

View File

@ -170,11 +170,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
*/

View File

@ -753,7 +753,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;
}
@ -2474,7 +2474,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) . "'";
}
@ -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

@ -481,7 +481,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))
@ -672,7 +672,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.');
}
@ -715,7 +715,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)
{
@ -786,7 +786,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)
{
@ -1015,7 +1015,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

@ -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

@ -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

@ -73,7 +73,7 @@ class PreparedQuery extends BasePreparedQuery implements PreparedQueryInterface
*/
public function _prepare(string $sql, array $options = [])
{
$this->name = mt_rand(1, 10000000000000000);
$this->name = random_int(1, 10000000000000000);
$sql = $this->parameterize($sql);

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

@ -37,6 +37,7 @@
*/
use CodeIgniter\Config\BaseConfig;
use Config\Services;
use CodeIgniter\Format\XMLFormatter;
/**
* Debug Toolbar
@ -58,9 +59,11 @@ class Toolbar
protected $collectors = [];
/**
* @var float App start time
* Incoming Request
*
* @var \CodeIgniter\HTTP\IncomingRequest
*/
protected $startTime;
protected static $request;
//--------------------------------------------------------------------
@ -86,33 +89,207 @@ 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
* @return string JSON encoded data
*/
public function run($startTime, $totalTime, $startMemory, $request, $response): string
{
$this->startTime = $startTime;
// Data items used within the view.
$collectors = $this->collectors;
$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()-$startMemory)/1048576, 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'] = [];
$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();
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(),
];
}
ob_start();
include(__DIR__.'/Toolbar/Views/toolbar.tpl.php');
$output = ob_get_contents();
ob_end_clean();
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 (isset($_SESSION) && ! 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();
return json_encode($data);
}
//--------------------------------------------------------------------
/**
* Format output
*
* @param string $data JSON encoded Toolbar data
* @param string $format html, json, xml
*
* @return string
*/
protected static function format(string $data, string $format = 'html')
{
$data = json_decode($data, true);
// History must be loaded on the fly
$filenames = glob(WRITEPATH.'debugbar/debugbar_*');
$total = count($filenames);
rsort($filenames);
$files = [];
$current = self::$request->getGet('debugbar_time');
$app = new \Config\App;
for ($i = 0; $i < $total; $i++)
{
// 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[$i] = [
'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'],
];
// Oldest files will be deleted
if ($app->toolbarMaxHistory >= 0 && $i >= $app->toolbarMaxHistory)
{
unlink($filenames[$i]);
continue;
}
}
// 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':
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 'json':
$output = json_encode($data);
case 'xml':
$formatter = new XMLFormatter;
$output = $formatter->format($data);
break;
}
return $output;
}
@ -122,18 +299,18 @@ 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): string
{
$displayTime = $segmentCount*$segmentDuration;
$rows = $this->collectTimelineData();
$output = '';
$rows = self::collectTimelineData($collectors);
$output = '';
foreach ($rows as $row)
{
@ -143,15 +320,12 @@ class Toolbar
$output .= "<td style='text-align: right'>".number_format($row['duration']*1000, 2)." ms</td>";
$output .= "<td colspan='{$segmentCount}' style='overflow: hidden'>";
$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,
2)."%'></span>";
$output .= "</td>";
$output .= "</tr>";
}
@ -165,24 +339,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 +408,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 +432,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

@ -9,24 +9,17 @@ class Config
public static function display()
{
$config = new App();
$parser = \Config\Services::parser(BASEPATH . 'Debug/Toolbar/Views/', null,false);
$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;
}
//--------------------------------------------------------------------
@ -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

@ -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 style="width: 70px">
<button class="ci-history-load" data-time="{time}">Load</button>
</td>
<td style="width: 140px">{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);

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

@ -6,86 +6,86 @@
<?= 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>
<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 -->
@ -96,107 +96,87 @@
<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++) : ?>
<?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) ?>
</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><?= $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,20 @@
<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>

View File

@ -1,24 +1,60 @@
<?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');
toolbar.innerHTML = this.responseText;
document.body.appendChild(toolbar);
} else {
toolbar.innerHTML = this.responseText;
}
eval(document.getElementById("toolbar_js").innerHTML);
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

@ -144,7 +144,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 +267,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];
}

View File

@ -65,7 +65,7 @@ class Events
*
* @var string
*/
protected static $eventsFile;
protected static $eventsFile = '';
/**
* If true, events will not actually be fired.
@ -290,7 +290,7 @@ class Events
*
* @param string $path
*/
public function setFile(string $path)
public static function setFile(string $path)
{
self::$eventsFile = $path;
}

View File

@ -0,0 +1,9 @@
<?php namespace CodeIgniter\Exceptions;
/**
* Error: Action must be taken immediately (system/db down, etc)
*/
class AlertError extends \Error
{
}

View File

@ -0,0 +1,29 @@
<?php namespace CodeIgniter\Exceptions;
/**
* Exception for automatic logging.
*/
class ConfigException extends CriticalError
{
/**
* Error code
* @var int
*/
protected $code = 3;
public static function forMissingMigrationsTable()
{
throw new static(lang('Migrations.missingTable'));
}
public static function forInvalidMigrationType(string $type = null)
{
throw new static(lang('Migrations.invalidType', [$type]));
}
public static function forDisabledMigrations()
{
throw new static(lang('Migrations.disabled'));
}
}

View File

@ -0,0 +1,9 @@
<?php namespace CodeIgniter\Exceptions;
/**
* Error: Critical conditions, like component unavailble, etc.
*/
class CriticalError extends \Error
{
}

View File

@ -0,0 +1,9 @@
<?php namespace CodeIgniter\Exceptions;
/**
* Error: system is unusable
*/
class EmergencyError extends \Error
{
}

View File

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

View File

@ -8,10 +8,32 @@
*
* @package CodeIgniter\Exceptions
*/
class FrameworkException extends \RuntimeException
class FrameworkException extends \RuntimeException implements ExceptionInterface
{
public static function forEmptyBaseURL(): self
{
return new self('You have an empty or invalid base URL. The baseURL value must be set in Config\App.php, or through the .env file.');
return new static('You have an empty or invalid base URL. The baseURL value must be set in Config\App.php, or through the .env file.');
}
public static function forInvalidFile(string $path)
{
return new static(lang('Core.invalidFile', [$path]));
}
public static function forCopyError()
{
return new static(lang('Core.copyError'));
}
public static function forMissingExtension(string $extension)
{
return new static(lang('Core.missingExtension', [$extension]));
}
public static function forNoHandlers(string $class)
{
return new static(lang('Core.noHandlers', [$class]));
}
}

View File

@ -0,0 +1,30 @@
<?php namespace CodeIgniter\Exceptions;
class PageNotFoundException extends \OutOfBoundsException implements ExceptionInterface
{
/**
* Error code
* @var int
*/
protected $code = 404;
public static function forPageNotFound()
{
return new static(lang('HTTP.pageNotFound'));
}
public static function forEmptyController()
{
return new static(lang('HTTP.emptyController'));
}
public static function forControllerNotFound(string $controller, string $method)
{
return new static(lang('HTTP.controllerNotFound', [$controller, $method]));
}
public static function forMethodNotFound(string $method)
{
return new static(lang('HTTP.methodNotFound', [$method]));
}
}

View File

@ -0,0 +1,23 @@
<?php namespace CodeIgniter\Files\Exceptions;
use CodeIgniter\Exceptions\ExceptionInterface;
class FileException extends \RuntimeException implements ExceptionInterface
{
public static function forUnableToMove(string $from = null, string $to = null, string $error = null)
{
return new static(lang('Files.cannotMove', [$from, $to, $error]));
}
public static function forInvalidFilename(string $to = null)
{
return new self(lang('Files.invalidFilename', [$to]));
}
public static function forCopyError(string $to = null)
{
return new self(lang('Files.cannotCopy', [$to]));
}
}

View File

@ -0,0 +1,11 @@
<?php namespace CodeIgniter\Files\Exceptions;
use CodeIgniter\Exceptions\ExceptionInterface;
class FileNotFoundException extends \RuntimeException implements ExceptionInterface
{
public static function forFileNotFound(string $path)
{
return new static(lang('Files.fileNotFound', [$path]));
}
}

View File

@ -36,8 +36,8 @@
* @filesource
*/
use SPLFileInfo;
require_once __DIR__ . '/Exceptions.php';
use CodeIgniter\Files\Exceptions\FileException;
use CodeIgniter\Files\Exceptions\FileNotFoundException;
class File extends SplFileInfo
{
@ -62,7 +62,7 @@ class File extends SplFileInfo
{
if ($checkFile && ! is_file($path))
{
throw new FileNotFoundException();
throw FileNotFoundException::forFileNotFound($path);
}
parent::__construct($path);
@ -95,13 +95,11 @@ class File extends SplFileInfo
{
case 'kb':
return number_format($this->size / 1024, 3);
break;
case 'mb':
return number_format(($this->size / 1024) / 1024, 3);
break;
}
return $this->size;
return (int) $this->size;
}
//--------------------------------------------------------------------
@ -175,7 +173,7 @@ class File extends SplFileInfo
if ( ! @rename($this->getPath(), $destination))
{
$error = error_get_last();
throw new \RuntimeException(sprintf('Could not move file %s to %s (%s)', $this->getBasename(), $targetPath, strip_tags($error['message'])));
throw FileException::forUnableToMove($this->getBasename(), $targetPath, strip_tags($error['message']));
}
@chmod($targetPath, 0777 & ~umask());

View File

@ -0,0 +1,17 @@
<?php namespace CodeIgniter\Filters\Exceptions;
use CodeIgniter\Exceptions\ConfigException;
use CodeIgniter\Exceptions\ExceptionInterface;
class FilterException extends ConfigException implements ExceptionInterface
{
public static function forNoAlias(string $alias)
{
return new static(lang('Filters.noFilter', [$alias]));
}
public static function forIncorrectInterface(string $class)
{
return new static(lang('Filters.incorrectInterface', [$class]));
}
}

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