diff --git a/.github/workflows/test-phpunit.yml b/.github/workflows/test-phpunit.yml index c660b937e04..d965765bce7 100644 --- a/.github/workflows/test-phpunit.yml +++ b/.github/workflows/test-phpunit.yml @@ -15,10 +15,28 @@ jobs: strategy: fail-fast: false matrix: - php: [ '8.1', '8.0', '7.4', '7.3', '7.2', '7.1', '7.0', '5.6', '5.5', '5.4'] + php: [ '8.2', '8.1', '8.0', '7.4', '7.3', '7.2', '7.1', '7.0', '5.6', '5.5', '5.4'] DB: [ 'pdo/mysql', 'pdo/pgsql', 'pdo/sqlite', 'mysqli', 'pgsql', 'sqlite' ] compiler: [ default ] include: + - php: '8.2' + DB: 'pdo/mysql' + compiler: jit + - php: '8.2' + DB: 'pdo/pgsql' + compiler: jit + - php: '8.2' + DB: 'pdo/sqlite' + compiler: jit + - php: '8.2' + DB: 'mysqli' + compiler: jit + - php: '8.2' + DB: 'pgsql' + compiler: jit + - php: '8.2' + DB: 'sqlite' + compiler: jit - php: '8.1' DB: 'pdo/mysql' compiler: jit diff --git a/composer.json b/composer.json index f5b4e8db43d..e7360a93de7 100644 --- a/composer.json +++ b/composer.json @@ -1,14 +1,11 @@ { "description": "The CodeIgniter framework", - "name": "codeigniter/framework", + "name": "pocketarc/codeigniter", "type": "project", - "homepage": "https://codeigniter.com", + "homepage": "https://github.com/pocketarc/codeigniter", "license": "MIT", "support": { - "forum": "https://forum.codeigniter.com/", - "wiki": "https://github.com/bcit-ci/CodeIgniter/wiki", - "slack": "https://codeigniterchat.slack.com", - "source": "https://github.com/bcit-ci/CodeIgniter" + "source": "https://github.com/pocketarc/codeigniter" }, "require": { "php": ">=5.4.8" diff --git a/index.php b/index.php index 8b095a77a78..81a588c22f5 100644 --- a/index.php +++ b/index.php @@ -73,7 +73,11 @@ case 'testing': case 'production': ini_set('display_errors', 0); - error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED & ~E_STRICT & ~E_USER_NOTICE & ~E_USER_DEPRECATED); + if (version_compare(PHP_VERSION, '8.4', '>=')) { + error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED & ~E_USER_NOTICE & ~E_USER_DEPRECATED); + } else { + error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED & ~E_STRICT & ~E_USER_NOTICE & ~E_USER_DEPRECATED); + } break; default: diff --git a/readme.rst b/readme.rst index 3722ed9023b..e0100b8f32e 100644 --- a/readme.rst +++ b/readme.rst @@ -1,71 +1,31 @@ -################### -What is CodeIgniter -################### +######################## +What is this repository? +######################## -CodeIgniter is an Application Development Framework - a toolkit - for people -who build web sites using PHP. Its goal is to enable you to develop projects -much faster than you could if you were writing code from scratch, by providing -a rich set of libraries for commonly needed tasks, as well as a simple -interface and logical structure to access these libraries. CodeIgniter lets -you creatively focus on your project by minimizing the amount of code needed -for a given task. +This is a fork of CodeIgniter 3, with the goal of keeping it up to date with **PHP 8.4** and beyond. There is no intention to add new features or change the way CI3 works. This is purely a maintenance fork. -******************* -Release Information -******************* +The original CodeIgniter 3.x branch is no longer maintained, and has not been updated to work with PHP 8.2, or any newer version. This fork is intended to fill that gap. -This repo contains in-development code for future releases. To download the -latest stable release please visit the `CodeIgniter Downloads -`_ page. +If the original CodeIgniter 3.x branch is updated to work with PHP 8.2+, and starts to be maintained again, this fork might be retired. -************************** -Changelog and New Features -************************** +**************** +Issues and Pulls +**************** -You can find a list of all changes for each release in the `user -guide change log `_. +Issues and Pull Requests are welcome, but please note that this is a maintenance fork. New features will not be accepted. If you have a new feature you would like to see in CodeIgniter, please submit it to the original CodeIgniter 3.x branch. ******************* Server Requirements ******************* -PHP version 5.6 or newer is recommended. - -It should work on 5.4.8 as well, but we strongly advise you NOT to run -such old versions of PHP, because of potential security and performance -issues, as well as missing features. +PHP version 5.4 or newer, same as the original CI3 requirements. ************ Installation ************ -Please see the `installation section `_ -of the CodeIgniter User Guide. - -******* -License -******* - -Please see the `license -agreement `_. - -********* -Resources -********* - -- `User Guide `_ -- `Contributing Guide `_ -- `Language File Translations `_ -- `Community Forums `_ -- `Community Wiki `_ -- `Community Slack Channel `_ - -Report security issues to our `Security Panel `_ -or via our `page on HackerOne `_, thank you. +Simple: Just use composer. -*************** -Acknowledgement -*************** +.. code-block:: bash -The CodeIgniter team would like to thank EllisLab, all the -contributors to the CodeIgniter project and you, the CodeIgniter user. + composer require pocketarc/codeigniter diff --git a/system/core/Controller.php b/system/core/Controller.php index aeccd60ee4c..3713ae06308 100644 --- a/system/core/Controller.php +++ b/system/core/Controller.php @@ -50,6 +50,7 @@ * @author EllisLab Dev Team * @link https://codeigniter.com/userguide3/general/controllers.html */ +#[AllowDynamicProperties] class CI_Controller { /** diff --git a/system/core/Exceptions.php b/system/core/Exceptions.php index 7244f3f28ea..4c3b63e4e97 100644 --- a/system/core/Exceptions.php +++ b/system/core/Exceptions.php @@ -62,18 +62,25 @@ class CI_Exceptions { * @var array */ public $levels = array( - E_ERROR => 'Error', - E_WARNING => 'Warning', - E_PARSE => 'Parsing Error', - E_NOTICE => 'Notice', - E_CORE_ERROR => 'Core Error', - E_CORE_WARNING => 'Core Warning', - E_COMPILE_ERROR => 'Compile Error', - E_COMPILE_WARNING => 'Compile Warning', - E_USER_ERROR => 'User Error', - E_USER_WARNING => 'User Warning', - E_USER_NOTICE => 'User Notice', - E_STRICT => 'Runtime Notice' + E_ERROR => 'Error', + E_RECOVERABLE_ERROR => 'Recoverable Error', + E_WARNING => 'Warning', + E_PARSE => 'Parsing Error', + E_NOTICE => 'Notice', + E_DEPRECATED => 'Deprecated Notice', + E_CORE_ERROR => 'Core Error', + E_CORE_WARNING => 'Core Warning', + E_COMPILE_ERROR => 'Compile Error', + E_COMPILE_WARNING => 'Compile Warning', + E_USER_ERROR => 'User Error', + E_USER_WARNING => 'User Warning', + E_USER_NOTICE => 'User Notice', + E_USER_DEPRECATED => 'User Deprecated Notice', + + # 2048 is E_STRICT, but it's deprecated in PHP 8.4. + # We're keeping this here for backwards compatibility. + # If we're on older PHP, E_STRICT errors will be labelled correctly, and if we're on PHP 8.4+, this will be ignored. + 2048 => 'Strict Notice', ); /** diff --git a/system/core/Loader.php b/system/core/Loader.php index 648b7cfc7c2..b7380c05098 100644 --- a/system/core/Loader.php +++ b/system/core/Loader.php @@ -49,6 +49,7 @@ * @author EllisLab Dev Team * @link https://codeigniter.com/userguide3/libraries/loader.html */ +#[AllowDynamicProperties] class CI_Loader { // All these are set automatically. Don't mess with them. @@ -498,7 +499,20 @@ class_exists('CI_DB', FALSE) OR $this->database(); */ public function view($view, $vars = array(), $return = FALSE) { - return $this->_ci_load(array('_ci_view' => $view, '_ci_vars' => $this->_ci_prepare_view_vars($vars), '_ci_return' => $return)); + $measure = "View - $view"; + $CI =& get_instance(); + + if (property_exists($CI, "debugbar") && $CI->debugbar) { + $CI->debugbar["time"]->startMeasure($measure); + } + + $result = $this->_ci_load(array('_ci_view' => $view, '_ci_vars' => $this->_ci_prepare_view_vars($vars), '_ci_return' => $return)); + + if (property_exists($CI, "debugbar") && $CI->debugbar && $CI->debugbar["time"]->hasStartedMeasure($measure)) { + $CI->debugbar["time"]->stopMeasure($measure); + } + + return $result; } // -------------------------------------------------------------------- diff --git a/system/core/Model.php b/system/core/Model.php index 1ba10fbb79d..b2bbbd4d484 100644 --- a/system/core/Model.php +++ b/system/core/Model.php @@ -49,6 +49,14 @@ */ class CI_Model { + /** + * Class constructor + * + * @link https://github.com/bcit-ci/CodeIgniter/issues/5332 + * @return void + */ + public function __construct() {} + /** * __get magic * diff --git a/system/core/Output.php b/system/core/Output.php index 02f3933f515..2109774932c 100644 --- a/system/core/Output.php +++ b/system/core/Output.php @@ -456,7 +456,7 @@ public function _display($output = NULL) $elapsed = $BM->elapsed_time('total_execution_time_start', 'total_execution_time_end'); - if ($this->parse_exec_vars === TRUE) + if ($this->parse_exec_vars === TRUE && !empty($output)) { $memory = round(memory_get_usage() / 1024 / 1024, 2).'MB'; $output = str_replace(array('{elapsed_time}', '{memory_usage}'), array($elapsed, $memory), $output); diff --git a/system/core/Router.php b/system/core/Router.php index e0fb922f1a6..6dca57cf3d2 100644 --- a/system/core/Router.php +++ b/system/core/Router.php @@ -58,6 +58,13 @@ class CI_Router { */ public $config; + /** + * CI_URI class object + * + * @var object + */ + public $uri; + /** * List of routes * @@ -439,6 +446,19 @@ public function set_class($class) // -------------------------------------------------------------------- + /** + * Fetch the current class + * + * @deprecated 3.0.0 Read the 'class' property instead + * @return string + */ + public function fetch_class() + { + return $this->class; + } + + // -------------------------------------------------------------------- + /** * Set method name * @@ -452,6 +472,19 @@ public function set_method($method) // -------------------------------------------------------------------- + /** + * Fetch the current method + * + * @deprecated 3.0.0 Read the 'method' property instead + * @return string + */ + public function fetch_method() + { + return $this->method; + } + + // -------------------------------------------------------------------- + /** * Set directory name * @@ -470,4 +503,21 @@ public function set_directory($dir, $append = FALSE) $this->directory .= str_replace('.', '', trim($dir, '/')).'/'; } } + + // -------------------------------------------------------------------- + + /** + * Fetch directory + * + * Feches the sub-directory (if any) that contains the requested + * controller class. + * + * @deprecated 3.0.0 Read the 'directory' property instead + * @return string + */ + public function fetch_directory() + { + return $this->directory; + } + } diff --git a/system/core/URI.php b/system/core/URI.php index 1e948588354..95b9c926c96 100644 --- a/system/core/URI.php +++ b/system/core/URI.php @@ -51,6 +51,13 @@ */ class CI_URI { + /** + * CI_Config instance + * + * @var CI_Config + */ + public $config; + /** * List of cached URI segments * diff --git a/system/database/DB_driver.php b/system/database/DB_driver.php index de03a418567..6cbd7026e91 100644 --- a/system/database/DB_driver.php +++ b/system/database/DB_driver.php @@ -51,6 +51,7 @@ * @author EllisLab Dev Team * @link https://codeigniter.com/userguide3/database/ */ +#[AllowDynamicProperties] abstract class CI_DB_driver { /** diff --git a/system/database/DB_query_builder.php b/system/database/DB_query_builder.php index de6aa04fc08..c8592352818 100644 --- a/system/database/DB_query_builder.php +++ b/system/database/DB_query_builder.php @@ -71,7 +71,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver { * * @var array */ - protected $qb_select = array(); + public $qb_select = array(); /** * QB DISTINCT flag @@ -141,7 +141,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver { * * @var array */ - protected $qb_orderby = array(); + public $qb_orderby = array(); /** * QB data sets diff --git a/system/database/drivers/pdo/pdo_driver.php b/system/database/drivers/pdo/pdo_driver.php index 559e865552c..a806b4427d8 100644 --- a/system/database/drivers/pdo/pdo_driver.php +++ b/system/database/drivers/pdo/pdo_driver.php @@ -36,6 +36,9 @@ * @since Version 2.1.0 * @filesource */ + +use DebugBar\DataCollector\PDO\TraceablePDO; + defined('BASEPATH') OR exit('No direct script access allowed'); /** @@ -65,7 +68,9 @@ class CI_DB_pdo_driver extends CI_DB { * * @var array */ - public $options = array(); + public $options = array( + PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, + ); // -------------------------------------------------------------------- @@ -127,6 +132,8 @@ public function __construct($params) */ public function db_connect($persistent = FALSE) { + global $debugbar; + if ($persistent === TRUE) { $this->options[PDO::ATTR_PERSISTENT] = TRUE; @@ -142,7 +149,13 @@ public function db_connect($persistent = FALSE) try { - return new PDO($this->dsn, $this->username, $this->password, $this->options); + if ($debugbar) { + $pdo = new TraceablePDO(new PDO($this->dsn, $this->username, $this->password, $this->options)); + $debugbar->addCollector(new DebugBar\DataCollector\PDO\PDOCollector($pdo)); + return $pdo; + } else { + return new PDO($this->dsn, $this->username, $this->password, $this->options); + } } catch (PDOException $e) { diff --git a/system/helpers/date_helper.php b/system/helpers/date_helper.php index 6ea9d82bd98..12fa872e321 100644 --- a/system/helpers/date_helper.php +++ b/system/helpers/date_helper.php @@ -501,7 +501,7 @@ function timezone_menu($default = 'UTC', $class = '', $name = 'timezones', $attr * for various other ones in this library * * @param string timezone - * @return string + * @return string|array */ function timezones($tz = '') { diff --git a/system/helpers/file_helper.php b/system/helpers/file_helper.php index a751f771eb9..dc5ee6b5a5c 100644 --- a/system/helpers/file_helper.php +++ b/system/helpers/file_helper.php @@ -50,6 +50,25 @@ // ------------------------------------------------------------------------ +if ( ! function_exists('read_file')) +{ + /** + * Read File + * + * Opens the file specified in the path and returns it as a string. + * + * @deprecated 3.0.0 It is now just an alias for PHP's native file_get_contents(). + * @param string $file Path to file + * @return string File contents + */ + function read_file($file) + { + return @file_get_contents($file); + } +} + +// ------------------------------------------------------------------------ + if ( ! function_exists('write_file')) { /** diff --git a/system/helpers/text_helper.php b/system/helpers/text_helper.php index 506d45aca70..979e1458044 100644 --- a/system/helpers/text_helper.php +++ b/system/helpers/text_helper.php @@ -423,6 +423,8 @@ function convert_accented_characters($str) $array_from = array_keys($foreign_characters); $array_to = array_values($foreign_characters); } + + $str = (gettype($str) === 'NULL') ? '' : $str; return preg_replace($array_from, $array_to, $str); } diff --git a/system/libraries/Cache/drivers/Cache_redis.php b/system/libraries/Cache/drivers/Cache_redis.php index 19fbdc0cae4..27454329e81 100644 --- a/system/libraries/Cache/drivers/Cache_redis.php +++ b/system/libraries/Cache/drivers/Cache_redis.php @@ -163,7 +163,7 @@ public function get($key) { $data = $this->_redis->hMGet($key, array('__ci_type', '__ci_value')); - if ($value !== FALSE && $this->_redis->sIsMember('_ci_redis_serialized', $key)) + if ($data === FALSE || $this->_redis->sIsMember('_ci_redis_serialized', $key)) { return FALSE; } @@ -223,6 +223,7 @@ public function save($id, $data, $ttl = 60, $raw = FALSE) } else { + $this->_redis->expireAt($id, time() + $ttl); $this->_redis->{static::$_sRemove_name}('_ci_redis_serialized', $id); } diff --git a/system/libraries/Driver.php b/system/libraries/Driver.php index 84f0b6c3e76..23f4d23f3d0 100644 --- a/system/libraries/Driver.php +++ b/system/libraries/Driver.php @@ -50,6 +50,7 @@ * @author EllisLab Dev Team * @link */ +#[AllowDynamicProperties] class CI_Driver_Library { /** diff --git a/system/libraries/Encryption.php b/system/libraries/Encryption.php index 572cab3fcb1..a457003fe29 100644 --- a/system/libraries/Encryption.php +++ b/system/libraries/Encryption.php @@ -366,10 +366,10 @@ public function create_key($length) * Encrypt * * @param string $data Input data - * @param array $params Input parameters + * @param array|null $params Input parameters * @return string */ - public function encrypt($data, array $params = NULL) + public function encrypt($data, $params = NULL) { if (($params = $this->_get_params($params)) === FALSE) { @@ -501,10 +501,10 @@ protected function _openssl_encrypt($data, $params) * Decrypt * * @param string $data Encrypted data - * @param array $params Input parameters + * @param array|null $params Input parameters * @return string */ - public function decrypt($data, array $params = NULL) + public function decrypt($data, $params = NULL) { if (($params = $this->_get_params($params)) === FALSE) { diff --git a/system/libraries/Image_lib.php b/system/libraries/Image_lib.php index 4e5fc7be6fc..9067eff692f 100644 --- a/system/libraries/Image_lib.php +++ b/system/libraries/Image_lib.php @@ -85,6 +85,14 @@ class CI_Image_lib { */ public $new_image = ''; + + /** + * Path to destination image + * + * @var string + */ + public $dest_image = ''; + /** * Image width * diff --git a/system/libraries/Profiler.php b/system/libraries/Profiler.php index d423c14811c..4c3537bd25b 100644 --- a/system/libraries/Profiler.php +++ b/system/libraries/Profiler.php @@ -73,6 +73,76 @@ class CI_Profiler { 'config' ); + /** + * Compile benchmarks + * + * @var bool + */ + protected $_compile_benchmarks; + + /** + * Compile GET data + * + * @var bool + */ + protected $_compile_get; + + /** + * Compile memory usage + * + * @var bool + */ + protected $_compile_memory_usage; + + /** + * Compile POST data + * + * @var bool + */ + protected $_compile_post; + + /** + * Compile URI string + * + * @var bool + */ + protected $_compile_uri_string; + + /** + * Compile controller info + * + * @var bool + */ + protected $_compile_controller_info; + + /** + * Compile queries + * + * @var bool + */ + protected $_compile_queries; + + /** + * Compile HTTP headers + * + * @var bool + */ + protected $_compile_http_headers; + + /** + * Compile session data + * + * @var bool + */ + protected $_compile_session_data; + + /** + * Compile config data + * + * @var bool + */ + protected $_compile_config; + /** * Number of queries to show before making the additional queries togglable * diff --git a/system/libraries/Session/Session.php b/system/libraries/Session/Session.php index 2d55f822af9..e6715271254 100644 --- a/system/libraries/Session/Session.php +++ b/system/libraries/Session/Session.php @@ -417,7 +417,7 @@ protected function _configure_sid_length() { $bits_per_character = (int) ini_get('session.sid_bits_per_character'); $sid_length = (int) ini_get('session.sid_length'); - if (($bits = $sid_length * $bits_per_character) < 160) + if (($bits = $sid_length * $bits_per_character) < 160 && version_compare(PHP_VERSION, '8.4', '<')) { // Add as many more characters as necessary to reach at least 160 bits $sid_length += (int) ceil((160 % $bits) / $bits_per_character); diff --git a/system/libraries/Table.php b/system/libraries/Table.php index a033ced212c..60b9fddcf84 100644 --- a/system/libraries/Table.php +++ b/system/libraries/Table.php @@ -490,12 +490,12 @@ protected function _compile_template() return; } - $this->temp = $this->_default_template(); + $temp = $this->_default_template(); foreach (array('table_open', 'thead_open', 'thead_close', 'heading_row_start', 'heading_row_end', 'heading_cell_start', 'heading_cell_end', 'tbody_open', 'tbody_close', 'row_start', 'row_end', 'cell_start', 'cell_end', 'row_alt_start', 'row_alt_end', 'cell_alt_start', 'cell_alt_end', 'table_close') as $val) { if ( ! isset($this->template[$val])) { - $this->template[$val] = $this->temp[$val]; + $this->template[$val] = $temp[$val]; } } } diff --git a/tests/Bootstrap.php b/tests/Bootstrap.php index ada6a5998b7..20fabc85db3 100644 --- a/tests/Bootstrap.php +++ b/tests/Bootstrap.php @@ -1,7 +1,12 @@ =')) { + error_reporting(E_ALL); +} else { + error_reporting(E_ALL | E_STRICT); +} $dir = realpath(dirname(__FILE__)); @@ -80,4 +85,4 @@ class_alias('org\bovigo\vfs\vfsStreamWrapper', 'vfsStreamWrapper'); include_once $dir.'/mocks/autoloader.php'; spl_autoload_register('autoload'); -unset($dir); \ No newline at end of file +unset($dir); diff --git a/tests/codeigniter/core/Loader_test.php b/tests/codeigniter/core/Loader_test.php index df9c9f44b68..b14b7178019 100644 --- a/tests/codeigniter/core/Loader_test.php +++ b/tests/codeigniter/core/Loader_test.php @@ -125,7 +125,7 @@ public function test_library_config() // Create library in VFS $lib = 'unit_test_config_lib'; $class = 'CI_'.ucfirst($lib); - $content = 'config = $params; } }'; + $content = "config = $params; } }'; $this->ci_vfs_create(ucfirst($lib), $content, $this->ci_base_root, 'libraries'); // Create config file diff --git a/tests/codeigniter/libraries/Upload_test.php b/tests/codeigniter/libraries/Upload_test.php index 74a7d2c22df..b660d0ec85f 100644 --- a/tests/codeigniter/libraries/Upload_test.php +++ b/tests/codeigniter/libraries/Upload_test.php @@ -59,9 +59,6 @@ function test_data() $data = array( 'file_name' => 'hello.txt', 'file_type' => 'text/plain', - 'file_path' => '/tmp/', - 'full_path' => '/tmp/hello.txt', - 'raw_name' => 'hello', 'orig_name' => 'hello.txt', 'client_name' => '', 'file_ext' => '.txt', @@ -80,6 +77,10 @@ function test_data() $this->upload->{$k} = $v; } + $data['file_path'] = '/tmp/'; + $data['full_path'] = '/tmp/hello.txt'; + $data['raw_name'] = 'hello'; + $this->assertEquals('hello.txt', $this->upload->data('file_name')); $this->assertEquals($data, $this->upload->data()); } diff --git a/tests/mocks/ci_testcase.php b/tests/mocks/ci_testcase.php index 3ebb6b822e9..e755bd0be5b 100644 --- a/tests/mocks/ci_testcase.php +++ b/tests/mocks/ci_testcase.php @@ -1,5 +1,6 @@