Completed
Push — master ( 761b56...cfe3b8 )
by Kenji
02:53
created

CI_Loader::model()   F

Complexity

Conditions 22
Paths 492

Size

Total Lines 122
Code Lines 48

Duplication

Lines 122
Ratio 100 %

Importance

Changes 0
Metric Value
cc 22
eloc 48
nc 492
nop 3
dl 122
loc 122
rs 3.057
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 51 and the first side effect is on line 38.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
/**
3
 * CodeIgniter
4
 *
5
 * An open source application development framework for PHP
6
 *
7
 * This content is released under the MIT License (MIT)
8
 *
9
 * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
10
 *
11
 * Permission is hereby granted, free of charge, to any person obtaining a copy
12
 * of this software and associated documentation files (the "Software"), to deal
13
 * in the Software without restriction, including without limitation the rights
14
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15
 * copies of the Software, and to permit persons to whom the Software is
16
 * furnished to do so, subject to the following conditions:
17
 *
18
 * The above copyright notice and this permission notice shall be included in
19
 * all copies or substantial portions of the Software.
20
 *
21
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27
 * THE SOFTWARE.
28
 *
29
 * @package	CodeIgniter
30
 * @author	EllisLab Dev Team
31
 * @copyright	Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
32
 * @copyright	Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
33
 * @license	http://opensource.org/licenses/MIT	MIT License
34
 * @link	https://codeigniter.com
35
 * @since	Version 1.0.0
36
 * @filesource
37
 */
38
defined('BASEPATH') OR exit('No direct script access allowed');
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as or instead of || is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
39
40
/**
41
 * Loader Class (Modified by ci-phpunit-test)
42
 *
43
 * Loads framework components.
44
 *
45
 * @package		CodeIgniter
46
 * @subpackage	Libraries
47
 * @category	Loader
48
 * @author		EllisLab Dev Team
49
 * @link		https://codeigniter.com/user_guide/libraries/loader.html
50
 */
51 View Code Duplication
class CI_Loader {
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
Duplication introduced by
This class seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
52
53
	// All these are set automatically. Don't mess with them.
54
	/**
55
	 * Nesting level of the output buffering mechanism
56
	 *
57
	 * @var	int
58
	 */
59
	protected $_ci_ob_level;
60
61
	/**
62
	 * List of paths to load views from
63
	 *
64
	 * @var	array
65
	 */
66
	protected $_ci_view_paths =	array(VIEWPATH	=> TRUE);
67
68
	/**
69
	 * List of paths to load libraries from
70
	 *
71
	 * @var	array
72
	 */
73
	protected $_ci_library_paths =	array(APPPATH, BASEPATH);
74
75
	/**
76
	 * List of paths to load models from
77
	 *
78
	 * @var	array
79
	 */
80
	protected $_ci_model_paths =	array(APPPATH);
81
82
	/**
83
	 * List of paths to load helpers from
84
	 *
85
	 * @var	array
86
	 */
87
	protected $_ci_helper_paths =	array(APPPATH, BASEPATH);
88
89
	/**
90
	 * List of cached variables
91
	 *
92
	 * @var	array
93
	 */
94
	protected $_ci_cached_vars =	array();
95
96
	/**
97
	 * List of loaded classes
98
	 *
99
	 * @var	array
100
	 */
101
	protected $_ci_classes =	array();
102
103
	/**
104
	 * List of loaded models
105
	 *
106
	 * @var	array
107
	 */
108
	protected $_ci_models =	array();
109
110
	/**
111
	 * List of loaded helpers
112
	 *
113
	 * @var	array
114
	 */
115
	protected $_ci_helpers =	array();
116
117
	/**
118
	 * List of class name mappings
119
	 *
120
	 * @var	array
121
	 */
122
	protected $_ci_varmap =	array(
123
		'unit_test' => 'unit',
124
		'user_agent' => 'agent'
125
	);
126
127
	// --------------------------------------------------------------------
128
129
	/**
130
	 * Class constructor
131
	 *
132
	 * Sets component load paths, gets the initial output buffering level.
133
	 *
134
	 * @return	void
0 ignored issues
show
Comprehensibility Best Practice introduced by
Adding a @return annotation to constructors is generally not recommended as a constructor does not have a meaningful return value.

Adding a @return annotation to a constructor is not recommended, since a constructor does not have a meaningful return value.

Please refer to the PHP core documentation on constructors.

Loading history...
135
	 *
136
	 * @codeCoverageIgnore
137
	 */
138
	public function __construct()
139
	{
140
		$this->_ci_ob_level = ob_get_level();
141
		$this->_ci_classes =& is_loaded();
142
143
		log_message('info', 'Loader Class Initialized');
144
	}
145
146
	// --------------------------------------------------------------------
147
148
	/**
149
	 * Initializer
150
	 *
151
	 * @todo	Figure out a way to move this to the constructor
152
	 *		without breaking *package_path*() methods.
153
	 * @uses	CI_Loader::_ci_autoloader()
154
	 * @used-by	CI_Controller::__construct()
155
	 * @return	void
156
	 *
157
	 * @codeCoverageIgnore
158
	 */
159
	public function initialize()
160
	{
161
		$this->_ci_autoloader();
162
	}
163
164
	// --------------------------------------------------------------------
165
166
	/**
167
	 * Is Loaded
168
	 *
169
	 * A utility method to test if a class is in the self::$_ci_classes array.
170
	 *
171
	 * @used-by	Mainly used by Form Helper function _get_validation_object().
172
	 *
173
	 * @param 	string		$class	Class name to check for
174
	 * @return 	string|bool	Class object name if loaded or FALSE
175
	 *
176
	 * @codeCoverageIgnore
177
	 */
178
	public function is_loaded($class)
179
	{
180
		return array_search(ucfirst($class), $this->_ci_classes, TRUE);
181
	}
182
183
	// --------------------------------------------------------------------
184
185
	/**
186
	 * Library Loader
187
	 *
188
	 * Loads and instantiates libraries.
189
	 * Designed to be called from application controllers.
190
	 *
191
	 * @param	string	$library	Library name
192
	 * @param	array	$params		Optional parameters to pass to the library class constructor
193
	 * @param	string	$object_name	An optional object name to assign to
194
	 * @return	object
195
	 *
196
	 * @codeCoverageIgnore
197
	 */
198
	public function library($library, $params = NULL, $object_name = NULL)
199
	{
200
		if (empty($library))
201
		{
202
			return $this;
203
		}
204
		elseif (is_array($library))
205
		{
206
			foreach ($library as $key => $value)
207
			{
208
				if (is_int($key))
209
				{
210
					$this->library($value, $params);
211
				}
212
				else
213
				{
214
					$this->library($key, $params, $value);
215
				}
216
			}
217
218
			return $this;
219
		}
220
221
		if ($params !== NULL && ! is_array($params))
222
		{
223
			$params = NULL;
224
		}
225
226
		$this->_ci_load_library($library, $params, $object_name);
227
		return $this;
228
	}
229
230
	// --------------------------------------------------------------------
231
232
	/**
233
	 * Model Loader
234
	 *
235
	 * Loads and instantiates models.
236
	 *
237
	 * @param	string	$model		Model name
238
	 * @param	string	$name		An optional object name to assign to
239
	 * @param	bool	$db_conn	An optional database connection configuration to initialize
240
	 * @return	object
241
	 * 
242
	 * modified by ci-phpunit-test
243
	 */
244
	public function model($model, $name = '', $db_conn = FALSE)
245
	{
246
		if (empty($model))
247
		{
248
			return $this;
249
		}
250
		elseif (is_array($model))
251
		{
252
			foreach ($model as $key => $value)
253
			{
254
				is_int($key) ? $this->model($value, '', $db_conn) : $this->model($key, $value, $db_conn);
255
			}
256
257
			return $this;
258
		}
259
260
		$path = '';
261
262
		// Is the model in a sub-folder? If so, parse out the filename and path.
263
		if (($last_slash = strrpos($model, '/')) !== FALSE)
264
		{
265
			// The path is in front of the last slash
266
			$path = substr($model, 0, ++$last_slash);
267
268
			// And the model name behind it
269
			$model = substr($model, $last_slash);
270
		}
271
272
		if (empty($name))
273
		{
274
			$name = $model;
275
		}
276
277
		if (in_array($name, $this->_ci_models, TRUE))
278
		{
279
			return $this;
280
		}
281
282
		$CI =& get_instance();
283
		if (isset($CI->$name))
284
		{
285
			throw new RuntimeException('The model name you are loading is the name of a resource that is already being used: '.$name);
286
		}
287
288
		if ($db_conn !== FALSE && ! class_exists('CI_DB', FALSE))
289
		{
290
			if ($db_conn === TRUE)
291
			{
292
				$db_conn = '';
293
			}
294
295
			$this->database($db_conn, FALSE, TRUE);
296
		}
297
298
		// Note: All of the code under this condition used to be just:
299
		//
300
		//       load_class('Model', 'core');
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
301
		//
302
		//       However, load_class() instantiates classes
303
		//       to cache them for later use and that prevents
304
		//       MY_Model from being an abstract class and is
305
		//       sub-optimal otherwise anyway.
0 ignored issues
show
Unused Code Comprehensibility introduced by
36% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
306
//		if ( ! class_exists('CI_Model', FALSE))
307
//		{
308
			$app_path = APPPATH.'core'.DIRECTORY_SEPARATOR;
309
			if (file_exists($app_path.'Model.php'))
310
			{
311
				require_once($app_path.'Model.php');
312
				if ( ! class_exists('CI_Model', FALSE))
313
				{
314
					throw new RuntimeException($app_path."Model.php exists, but doesn't declare class CI_Model");
315
				}
316
			}
317
			elseif ( ! class_exists('CI_Model', FALSE))
318
			{
319
				require_once(BASEPATH.'core'.DIRECTORY_SEPARATOR.'Model.php');
320
			}
321
322
			$class = config_item('subclass_prefix').'Model';
323
			if (file_exists($app_path.$class.'.php'))
324
			{
325
				require_once($app_path.$class.'.php');
326
				if ( ! class_exists($class, FALSE))
327
				{
328
					throw new RuntimeException($app_path.$class.".php exists, but doesn't declare class ".$class);
329
				}
330
			}
331
//		}
332
333
		$model = ucfirst($model);
334
		if ( ! class_exists($model, FALSE))
335
		{
336
			foreach ($this->_ci_model_paths as $mod_path)
337
			{
338
				if ( ! file_exists($mod_path.'models/'.$path.$model.'.php'))
339
				{
340
					continue;
341
				}
342
343
				require_once($mod_path.'models/'.$path.$model.'.php');
344
				if ( ! class_exists($model, FALSE))
345
				{
346
					throw new RuntimeException($mod_path."models/".$path.$model.".php exists, but doesn't declare class ".$model);
347
				}
348
349
				break;
350
			}
351
352
			if ( ! class_exists($model, FALSE))
353
			{
354
				throw new RuntimeException('Unable to locate the model you have specified: '.$model);
355
			}
356
		}
357
//		elseif ( ! is_subclass_of($model, 'CI_Model'))
0 ignored issues
show
Unused Code Comprehensibility introduced by
53% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
358
//		{
359
//			throw new RuntimeException("Class ".$model." already exists and doesn't extend CI_Model");
360
//		}
361
362
		$this->_ci_models[] = $name;
363
		$CI->$name = new $model();
364
		return $this;
365
	}
366
367
	// --------------------------------------------------------------------
368
369
	/**
370
	 * Database Loader
371
	 *
372
	 * @param	mixed	$params		Database configuration options
373
	 * @param	bool	$return 	Whether to return the database object
374
	 * @param	bool	$query_builder	Whether to enable Query Builder
375
	 *					(overrides the configuration setting)
376
	 *
377
	 * @return	object|bool	Database object if $return is set to TRUE,
378
	 *					FALSE on failure, CI_Loader instance in any other case
379
	 *
380
	 * @codeCoverageIgnore
381
	 */
382
	public function database($params = '', $return = FALSE, $query_builder = NULL)
383
	{
384
		// Grab the super object
385
		$CI =& get_instance();
386
387
		// Do we even need to load the database class?
388
		if ($return === FALSE && $query_builder === NULL && isset($CI->db) && is_object($CI->db) && ! empty($CI->db->conn_id))
389
		{
390
			return FALSE;
391
		}
392
393
		require_once(BASEPATH.'database/DB.php');
394
395
		if ($return === TRUE)
396
		{
397
			return DB($params, $query_builder);
398
		}
399
400
		// Initialize the db variable. Needed to prevent
401
		// reference errors with some configurations
402
		$CI->db = '';
403
404
		// Load the DB class
405
		$CI->db =& DB($params, $query_builder);
406
		return $this;
407
	}
408
409
	// --------------------------------------------------------------------
410
411
	/**
412
	 * Load the Database Utilities Class
413
	 *
414
	 * @param	object	$db	Database object
415
	 * @param	bool	$return	Whether to return the DB Utilities class object or not
416
	 * @return	object
417
	 *
418
	 * @codeCoverageIgnore
419
	 */
420
	public function dbutil($db = NULL, $return = FALSE)
421
	{
422
		$CI =& get_instance();
423
424
		if ( ! is_object($db) OR ! ($db instanceof CI_DB))
0 ignored issues
show
Bug introduced by
The class CI_DB does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
Comprehensibility Best Practice introduced by
Using logical operators such as or instead of || is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
425
		{
426
			class_exists('CI_DB', FALSE) OR $this->database();
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as or instead of || is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
427
			$db =& $CI->db;
428
		}
429
430
		require_once(BASEPATH.'database/DB_utility.php');
431
		require_once(BASEPATH.'database/drivers/'.$db->dbdriver.'/'.$db->dbdriver.'_utility.php');
432
		$class = 'CI_DB_'.$db->dbdriver.'_utility';
433
434
		if ($return === TRUE)
435
		{
436
			return new $class($db);
437
		}
438
439
		$CI->dbutil = new $class($db);
440
		return $this;
441
	}
442
443
	// --------------------------------------------------------------------
444
445
	/**
446
	 * Load the Database Forge Class
447
	 *
448
	 * @param	object	$db	Database object
449
	 * @param	bool	$return	Whether to return the DB Forge class object or not
450
	 * @return	object
451
	 *
452
	 * @codeCoverageIgnore
453
	 */
454
	public function dbforge($db = NULL, $return = FALSE)
455
	{
456
		$CI =& get_instance();
457
		if ( ! is_object($db) OR ! ($db instanceof CI_DB))
0 ignored issues
show
Bug introduced by
The class CI_DB does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
Comprehensibility Best Practice introduced by
Using logical operators such as or instead of || is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
458
		{
459
			class_exists('CI_DB', FALSE) OR $this->database();
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as or instead of || is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
460
			$db =& $CI->db;
461
		}
462
463
		require_once(BASEPATH.'database/DB_forge.php');
464
		require_once(BASEPATH.'database/drivers/'.$db->dbdriver.'/'.$db->dbdriver.'_forge.php');
465
466
		if ( ! empty($db->subdriver))
467
		{
468
			$driver_path = BASEPATH.'database/drivers/'.$db->dbdriver.'/subdrivers/'.$db->dbdriver.'_'.$db->subdriver.'_forge.php';
469
			if (file_exists($driver_path))
470
			{
471
				require_once($driver_path);
472
				$class = 'CI_DB_'.$db->dbdriver.'_'.$db->subdriver.'_forge';
473
			}
474
		}
475
		else
476
		{
477
			$class = 'CI_DB_'.$db->dbdriver.'_forge';
478
		}
479
480
		if ($return === TRUE)
481
		{
482
			return new $class($db);
0 ignored issues
show
Bug introduced by
The variable $class does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
483
		}
484
485
		$CI->dbforge = new $class($db);
486
		return $this;
487
	}
488
489
	// --------------------------------------------------------------------
490
491
	/**
492
	 * View Loader
493
	 *
494
	 * Loads "view" files.
495
	 *
496
	 * @param	string	$view	View name
497
	 * @param	array	$vars	An associative array of data
498
	 *				to be extracted for use in the view
499
	 * @param	bool	$return	Whether to return the view output
500
	 *				or leave it to the Output class
501
	 * @return	object|string
502
	 *
503
	 * @codeCoverageIgnore
504
	 */
505
	public function view($view, $vars = array(), $return = FALSE)
506
	{
507
		return $this->_ci_load(array('_ci_view' => $view, '_ci_vars' => $this->_ci_prepare_view_vars($vars), '_ci_return' => $return));
508
	}
509
510
	// --------------------------------------------------------------------
511
512
	/**
513
	 * Generic File Loader
514
	 *
515
	 * @param	string	$path	File path
516
	 * @param	bool	$return	Whether to return the file output
517
	 * @return	object|string
518
	 *
519
	 * @codeCoverageIgnore
520
	 */
521
	public function file($path, $return = FALSE)
522
	{
523
		return $this->_ci_load(array('_ci_path' => $path, '_ci_return' => $return));
524
	}
525
526
	// --------------------------------------------------------------------
527
528
	/**
529
	 * Set Variables
530
	 *
531
	 * Once variables are set they become available within
532
	 * the controller class and its "view" files.
533
	 *
534
	 * @param	array|object|string	$vars
535
	 *					An associative array or object containing values
536
	 *					to be set, or a value's name if string
537
	 * @param 	string	$val	Value to set, only used if $vars is a string
538
	 * @return	object
539
	 *
540
	 * @codeCoverageIgnore
541
	 */
542
	public function vars($vars, $val = '')
543
	{
544
		$vars = is_string($vars)
545
			? array($vars => $val)
546
			: $this->_ci_prepare_view_vars($vars);
547
548
		foreach ($vars as $key => $val)
549
		{
550
			$this->_ci_cached_vars[$key] = $val;
551
		}
552
553
		return $this;
554
	}
555
556
	// --------------------------------------------------------------------
557
558
	/**
559
	 * Clear Cached Variables
560
	 *
561
	 * Clears the cached variables.
562
	 *
563
	 * @return	CI_Loader
564
	 *
565
	 * @codeCoverageIgnore
566
	 */
567
	public function clear_vars()
568
	{
569
		$this->_ci_cached_vars = array();
570
		return $this;
571
	}
572
573
	// --------------------------------------------------------------------
574
575
	/**
576
	 * Get Variable
577
	 *
578
	 * Check if a variable is set and retrieve it.
579
	 *
580
	 * @param	string	$key	Variable name
581
	 * @return	mixed	The variable or NULL if not found
582
	 *
583
	 * @codeCoverageIgnore
584
	 */
585
	public function get_var($key)
586
	{
587
		return isset($this->_ci_cached_vars[$key]) ? $this->_ci_cached_vars[$key] : NULL;
588
	}
589
590
	// --------------------------------------------------------------------
591
592
	/**
593
	 * Get Variables
594
	 *
595
	 * Retrieves all loaded variables.
596
	 *
597
	 * @return	array
598
	 *
599
	 * @codeCoverageIgnore
600
	 */
601
	public function get_vars()
602
	{
603
		return $this->_ci_cached_vars;
604
	}
605
606
	// --------------------------------------------------------------------
607
608
	/**
609
	 * Helper Loader
610
	 *
611
	 * @param	string|string[]	$helpers	Helper name(s)
612
	 * @return	object
613
	 *
614
	 * @codeCoverageIgnore
615
	 */
616
	public function helper($helpers = array())
617
	{
618
		is_array($helpers) OR $helpers = array($helpers);
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as or instead of || is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
619
		foreach ($helpers as &$helper)
0 ignored issues
show
Bug introduced by
The expression $helpers of type string|array<integer,string> is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
620
		{
621
			$filename = basename($helper);
622
			$filepath = ($filename === $helper) ? '' : substr($helper, 0, strlen($helper) - strlen($filename));
623
			$filename = strtolower(preg_replace('#(_helper)?(\.php)?$#i', '', $filename)).'_helper';
624
			$helper   = $filepath.$filename;
625
626
			if (isset($this->_ci_helpers[$helper]))
627
			{
628
				continue;
629
			}
630
631
			// Is this a helper extension request?
632
			$ext_helper = config_item('subclass_prefix').$filename;
633
			$ext_loaded = FALSE;
634
			foreach ($this->_ci_helper_paths as $path)
635
			{
636
				if (file_exists($path.'helpers/'.$ext_helper.'.php'))
637
				{
638
					include_once($path.'helpers/'.$ext_helper.'.php');
639
					$ext_loaded = TRUE;
640
				}
641
			}
642
643
			// If we have loaded extensions - check if the base one is here
644
			if ($ext_loaded === TRUE)
645
			{
646
				$base_helper = BASEPATH.'helpers/'.$helper.'.php';
647
				if ( ! file_exists($base_helper))
648
				{
649
					show_error('Unable to load the requested file: helpers/'.$helper.'.php');
650
				}
651
652
				include_once($base_helper);
653
				$this->_ci_helpers[$helper] = TRUE;
654
				log_message('info', 'Helper loaded: '.$helper);
655
				continue;
656
			}
657
658
			// No extensions found ... try loading regular helpers and/or overrides
659
			foreach ($this->_ci_helper_paths as $path)
660
			{
661
				if (file_exists($path.'helpers/'.$helper.'.php'))
662
				{
663
					include_once($path.'helpers/'.$helper.'.php');
664
665
					$this->_ci_helpers[$helper] = TRUE;
666
					log_message('info', 'Helper loaded: '.$helper);
667
					break;
668
				}
669
			}
670
671
			// unable to load the helper
672
			if ( ! isset($this->_ci_helpers[$helper]))
673
			{
674
				show_error('Unable to load the requested file: helpers/'.$helper.'.php');
675
			}
676
		}
677
678
		return $this;
679
	}
680
681
	// --------------------------------------------------------------------
682
683
	/**
684
	 * Load Helpers
685
	 *
686
	 * An alias for the helper() method in case the developer has
687
	 * written the plural form of it.
688
	 *
689
	 * @uses	CI_Loader::helper()
690
	 * @param	string|string[]	$helpers	Helper name(s)
691
	 * @return	object
692
	 *
693
	 * @codeCoverageIgnore
694
	 */
695
	public function helpers($helpers = array())
696
	{
697
		return $this->helper($helpers);
698
	}
699
700
	// --------------------------------------------------------------------
701
702
	/**
703
	 * Language Loader
704
	 *
705
	 * Loads language files.
706
	 *
707
	 * @param	string|string[]	$files	List of language file names to load
708
	 * @param	string		Language name
709
	 * @return	object
710
	 *
711
	 * @codeCoverageIgnore
712
	 */
713
	public function language($files, $lang = '')
714
	{
715
		get_instance()->lang->load($files, $lang);
716
		return $this;
717
	}
718
719
	// --------------------------------------------------------------------
720
721
	/**
722
	 * Config Loader
723
	 *
724
	 * Loads a config file (an alias for CI_Config::load()).
725
	 *
726
	 * @uses	CI_Config::load()
727
	 * @param	string	$file			Configuration file name
728
	 * @param	bool	$use_sections		Whether configuration values should be loaded into their own section
729
	 * @param	bool	$fail_gracefully	Whether to just return FALSE or display an error message
730
	 * @return	bool	TRUE if the file was loaded correctly or FALSE on failure
731
	 *
732
	 * @codeCoverageIgnore
733
	 */
734
	public function config($file, $use_sections = FALSE, $fail_gracefully = FALSE)
735
	{
736
		return get_instance()->config->load($file, $use_sections, $fail_gracefully);
737
	}
738
739
	// --------------------------------------------------------------------
740
741
	/**
742
	 * Driver Loader
743
	 *
744
	 * Loads a driver library.
745
	 *
746
	 * @param	string|string[]	$library	Driver name(s)
747
	 * @param	array		$params		Optional parameters to pass to the driver
748
	 * @param	string		$object_name	An optional object name to assign to
749
	 *
750
	 * @return	object|bool	Object or FALSE on failure if $library is a string
751
	 *				and $object_name is set. CI_Loader instance otherwise.
752
	 *
753
	 * @codeCoverageIgnore
754
	 */
755
	public function driver($library, $params = NULL, $object_name = NULL)
756
	{
757
		if (is_array($library))
758
		{
759
			foreach ($library as $key => $value)
760
			{
761
				if (is_int($key))
762
				{
763
					$this->driver($value, $params);
764
				}
765
				else
766
				{
767
					$this->driver($key, $params, $value);
768
				}
769
			}
770
771
			return $this;
772
		}
773
		elseif (empty($library))
774
		{
775
			return FALSE;
776
		}
777
778
		if ( ! class_exists('CI_Driver_Library', FALSE))
779
		{
780
			// We aren't instantiating an object here, just making the base class available
781
			require BASEPATH.'libraries/Driver.php';
782
		}
783
784
		// We can save the loader some time since Drivers will *always* be in a subfolder,
785
		// and typically identically named to the library
786
		if ( ! strpos($library, '/'))
787
		{
788
			$library = ucfirst($library).'/'.$library;
789
		}
790
791
		return $this->library($library, $params, $object_name);
792
	}
793
794
	// --------------------------------------------------------------------
795
796
	/**
797
	 * Add Package Path
798
	 *
799
	 * Prepends a parent path to the library, model, helper and config
800
	 * path arrays.
801
	 *
802
	 * @see	CI_Loader::$_ci_library_paths
803
	 * @see	CI_Loader::$_ci_model_paths
804
	 * @see CI_Loader::$_ci_helper_paths
805
	 * @see CI_Config::$_config_paths
806
	 *
807
	 * @param	string	$path		Path to add
808
	 * @param 	bool	$view_cascade	(default: TRUE)
809
	 * @return	object
810
	 *
811
	 * @codeCoverageIgnore
812
	 */
813
	public function add_package_path($path, $view_cascade = TRUE)
814
	{
815
		$path = rtrim($path, '/').'/';
816
817
		array_unshift($this->_ci_library_paths, $path);
818
		array_unshift($this->_ci_model_paths, $path);
819
		array_unshift($this->_ci_helper_paths, $path);
820
821
		$this->_ci_view_paths = array($path.'views/' => $view_cascade) + $this->_ci_view_paths;
822
823
		// Add config file path
824
		$config =& $this->_ci_get_component('config');
825
		$config->_config_paths[] = $path;
826
827
		return $this;
828
	}
829
830
	// --------------------------------------------------------------------
831
832
	/**
833
	 * Get Package Paths
834
	 *
835
	 * Return a list of all package paths.
836
	 *
837
	 * @param	bool	$include_base	Whether to include BASEPATH (default: FALSE)
838
	 * @return	array
839
	 *
840
	 * @codeCoverageIgnore
841
	 */
842
	public function get_package_paths($include_base = FALSE)
843
	{
844
		return ($include_base === TRUE) ? $this->_ci_library_paths : $this->_ci_model_paths;
845
	}
846
847
	// --------------------------------------------------------------------
848
849
	/**
850
	 * Remove Package Path
851
	 *
852
	 * Remove a path from the library, model, helper and/or config
853
	 * path arrays if it exists. If no path is provided, the most recently
854
	 * added path will be removed removed.
855
	 *
856
	 * @param	string	$path	Path to remove
857
	 * @return	object
858
	 *
859
	 * @codeCoverageIgnore
860
	 */
861
	public function remove_package_path($path = '')
862
	{
863
		$config =& $this->_ci_get_component('config');
864
865
		if ($path === '')
866
		{
867
			array_shift($this->_ci_library_paths);
868
			array_shift($this->_ci_model_paths);
869
			array_shift($this->_ci_helper_paths);
870
			array_shift($this->_ci_view_paths);
871
			array_pop($config->_config_paths);
872
		}
873
		else
874
		{
875
			$path = rtrim($path, '/').'/';
876
			foreach (array('_ci_library_paths', '_ci_model_paths', '_ci_helper_paths') as $var)
877
			{
878
				if (($key = array_search($path, $this->{$var})) !== FALSE)
879
				{
880
					unset($this->{$var}[$key]);
881
				}
882
			}
883
884
			if (isset($this->_ci_view_paths[$path.'views/']))
885
			{
886
				unset($this->_ci_view_paths[$path.'views/']);
887
			}
888
889
			if (($key = array_search($path, $config->_config_paths)) !== FALSE)
890
			{
891
				unset($config->_config_paths[$key]);
892
			}
893
		}
894
895
		// make sure the application default paths are still in the array
896
		$this->_ci_library_paths = array_unique(array_merge($this->_ci_library_paths, array(APPPATH, BASEPATH)));
897
		$this->_ci_helper_paths = array_unique(array_merge($this->_ci_helper_paths, array(APPPATH, BASEPATH)));
898
		$this->_ci_model_paths = array_unique(array_merge($this->_ci_model_paths, array(APPPATH)));
899
		$this->_ci_view_paths = array_merge($this->_ci_view_paths, array(APPPATH.'views/' => TRUE));
900
		$config->_config_paths = array_unique(array_merge($config->_config_paths, array(APPPATH)));
901
902
		return $this;
903
	}
904
905
	// --------------------------------------------------------------------
906
907
	/**
908
	 * Internal CI Data Loader
909
	 *
910
	 * Used to load views and files.
911
	 *
912
	 * Variables are prefixed with _ci_ to avoid symbol collision with
913
	 * variables made available to view files.
914
	 *
915
	 * @used-by	CI_Loader::view()
916
	 * @used-by	CI_Loader::file()
917
	 * @param	array	$_ci_data	Data to load
918
	 * @return	object
919
	 *
920
	 * @codeCoverageIgnore
921
	 */
922
	protected function _ci_load($_ci_data)
923
	{
924
		// Set the default data variables
925
		foreach (array('_ci_view', '_ci_vars', '_ci_path', '_ci_return') as $_ci_val)
926
		{
927
			$$_ci_val = isset($_ci_data[$_ci_val]) ? $_ci_data[$_ci_val] : FALSE;
928
		}
929
930
		$file_exists = FALSE;
931
932
		// Set the path to the requested file
933
		if (is_string($_ci_path) && $_ci_path !== '')
0 ignored issues
show
Bug introduced by
The variable $_ci_path seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
934
		{
935
			$_ci_x = explode('/', $_ci_path);
0 ignored issues
show
Bug introduced by
The variable $_ci_path seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
936
			$_ci_file = end($_ci_x);
937
		}
938
		else
939
		{
940
			$_ci_ext = pathinfo($_ci_view, PATHINFO_EXTENSION);
0 ignored issues
show
Bug introduced by
The variable $_ci_view does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
941
			$_ci_file = ($_ci_ext === '') ? $_ci_view.'.php' : $_ci_view;
942
943
			foreach ($this->_ci_view_paths as $_ci_view_file => $cascade)
944
			{
945
				if (file_exists($_ci_view_file.$_ci_file))
946
				{
947
					$_ci_path = $_ci_view_file.$_ci_file;
948
					$file_exists = TRUE;
949
					break;
950
				}
951
952
				if ( ! $cascade)
953
				{
954
					break;
955
				}
956
			}
957
		}
958
959
		if ( ! $file_exists && ! file_exists($_ci_path))
0 ignored issues
show
Bug introduced by
The variable $_ci_path does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
960
		{
961
			show_error('Unable to load the requested file: '.$_ci_file);
962
		}
963
964
		// This allows anything loaded using $this->load (views, files, etc.)
965
		// to become accessible from within the Controller and Model functions.
966
		$_ci_CI =& get_instance();
967
		foreach (get_object_vars($_ci_CI) as $_ci_key => $_ci_var)
968
		{
969
			if ( ! isset($this->$_ci_key))
970
			{
971
				$this->$_ci_key =& $_ci_CI->$_ci_key;
972
			}
973
		}
974
975
		/*
976
		 * Extract and cache variables
977
		 *
978
		 * You can either set variables using the dedicated $this->load->vars()
979
		 * function or via the second parameter of this function. We'll merge
980
		 * the two types and cache them so that views that are embedded within
981
		 * other views can have access to these variables.
982
		 */
983
		empty($_ci_vars) OR $this->_ci_cached_vars = array_merge($this->_ci_cached_vars, $_ci_vars);
0 ignored issues
show
Bug introduced by
The variable $_ci_vars seems to never exist, and therefore empty should always return true. Did you maybe rename this variable?

This check looks for calls to isset(...) or empty() on variables that are yet undefined. These calls will always produce the same result and can be removed.

This is most likely caused by the renaming of a variable or the removal of a function/method parameter.

Loading history...
Comprehensibility Best Practice introduced by
Using logical operators such as or instead of || is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
984
		extract($this->_ci_cached_vars);
985
986
		/*
987
		 * Buffer the output
988
		 *
989
		 * We buffer the output for two reasons:
990
		 * 1. Speed. You get a significant speed boost.
991
		 * 2. So that the final rendered template can be post-processed by
992
		 *	the output class. Why do we need post processing? For one thing,
993
		 *	in order to show the elapsed page load time. Unless we can
994
		 *	intercept the content right before it's sent to the browser and
995
		 *	then stop the timer it won't be accurate.
996
		 */
997
		ob_start();
998
999
		// If the PHP installation does not support short tags we'll
1000
		// do a little string replacement, changing the short tags
1001
		// to standard PHP echo statements.
1002
		if ( ! is_php('5.4') && ! ini_get('short_open_tag') && config_item('rewrite_short_tags') === TRUE)
1003
		{
1004
			echo eval('?>'.preg_replace('/;*\s*\?>/', '; ?>', str_replace('<?=', '<?php echo ', file_get_contents($_ci_path))));
0 ignored issues
show
Coding Style introduced by
It is generally not recommended to use eval unless absolutely required.

On one hand, eval might be exploited by malicious users if they somehow manage to inject dynamic content. On the other hand, with the emergence of faster PHP runtimes like the HHVM, eval prevents some optimization that they perform.

Loading history...
1005
		}
1006
		else
1007
		{
1008
			include($_ci_path); // include() vs include_once() allows for multiple views with the same name
1009
		}
1010
1011
		log_message('info', 'File loaded: '.$_ci_path);
1012
1013
		// Return the file data if requested
1014
		if ($_ci_return === TRUE)
1015
		{
1016
			$buffer = ob_get_contents();
1017
			@ob_end_clean();
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
1018
			return $buffer;
1019
		}
1020
1021
		/*
1022
		 * Flush the buffer... or buff the flusher?
1023
		 *
1024
		 * In order to permit views to be nested within
1025
		 * other views, we need to flush the content back out whenever
1026
		 * we are beyond the first level of output buffering so that
1027
		 * it can be seen and included properly by the first included
1028
		 * template and any subsequent ones. Oy!
1029
		 */
1030
		if (ob_get_level() > $this->_ci_ob_level + 1)
1031
		{
1032
			ob_end_flush();
1033
		}
1034
		else
1035
		{
1036
			$_ci_CI->output->append_output(ob_get_contents());
1037
			@ob_end_clean();
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
1038
		}
1039
1040
		return $this;
1041
	}
1042
1043
	// --------------------------------------------------------------------
1044
1045
	/**
1046
	 * Internal CI Library Loader
1047
	 *
1048
	 * @used-by	CI_Loader::library()
1049
	 * @uses	CI_Loader::_ci_init_library()
1050
	 *
1051
	 * @param	string	$class		Class name to load
1052
	 * @param	mixed	$params		Optional parameters to pass to the class constructor
1053
	 * @param	string	$object_name	Optional object name to assign to
1054
	 * @return	void
1055
	 * 
1056
	 * modified by ci-phpunit-test
1057
	 */
1058
	protected function _ci_load_library($class, $params = NULL, $object_name = NULL)
1059
	{
1060
		// Get the class name, and while we're at it trim any slashes.
1061
		// The directory path can be included as part of the class name,
1062
		// but we don't want a leading slash
1063
		$class = str_replace('.php', '', trim($class, '/'));
1064
1065
		// Was the path included with the class name?
1066
		// We look for a slash to determine this
1067
		if (($last_slash = strrpos($class, '/')) !== FALSE)
1068
		{
1069
			// Extract the path
1070
			$subdir = substr($class, 0, ++$last_slash);
1071
1072
			// Get the filename from the path
1073
			$class = substr($class, $last_slash);
1074
		}
1075
		else
1076
		{
1077
			$subdir = '';
1078
		}
1079
1080
		$class = ucfirst($class);
1081
1082
		// Replace library in ci-phpuni-test
1083
		if (file_exists(APPPATH.'tests/_ci_phpunit_test/replacing/libraries/'.$subdir.$class.'.php'))
1084
		{
1085
			return $this->_ci_load_stock_library($class, $subdir, $params, $object_name);
1086
		}
1087
1088
		// Is this a stock library? There are a few special conditions if so ...
1089
		if (file_exists(BASEPATH.'libraries/'.$subdir.$class.'.php'))
1090
		{
1091
			return $this->_ci_load_stock_library($class, $subdir, $params, $object_name);
1092
		}
1093
1094
		// Let's search for the requested library file and load it.
1095
		foreach ($this->_ci_library_paths as $path)
1096
		{
1097
			// BASEPATH has already been checked for
1098
			if ($path === BASEPATH)
1099
			{
1100
				continue;
1101
			}
1102
1103
			$filepath = $path.'libraries/'.$subdir.$class.'.php';
1104
1105
			// Safety: Was the class already loaded by a previous call?
1106
			if (class_exists($class, FALSE))
1107
			{
1108
				// Before we deem this to be a duplicate request, let's see
1109
				// if a custom object name is being supplied. If so, we'll
1110
				// return a new instance of the object
1111
				if ($object_name !== NULL)
1112
				{
1113
					$CI =& get_instance();
1114
					if ( ! isset($CI->$object_name))
1115
					{
1116
						return $this->_ci_init_library($class, '', $params, $object_name);
1117
					}
1118
				}
1119
1120
//				log_message('debug', $class.' class already loaded. Second attempt ignored.');
0 ignored issues
show
Unused Code Comprehensibility introduced by
60% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1121
//				return;
1122
			}
1123
			// Does the file exist? No? Bummer...
1124
			if ( ! file_exists($filepath))
1125
			{
1126
				continue;
1127
			}
1128
1129
			include_once($filepath);
1130
			return $this->_ci_init_library($class, '', $params, $object_name);
1131
		}
1132
1133
		// One last attempt. Maybe the library is in a subdirectory, but it wasn't specified?
1134
		if ($subdir === '')
1135
		{
1136
			return $this->_ci_load_library($class.'/'.$class, $params, $object_name);
1137
		}
1138
1139
		// If we got this far we were unable to find the requested class.
1140
		log_message('error', 'Unable to load the requested class: '.$class);
1141
		show_error('Unable to load the requested class: '.$class);
1142
	}
1143
1144
	// --------------------------------------------------------------------
1145
1146
	/**
1147
	 * Internal CI Stock Library Loader
1148
	 *
1149
	 * @used-by	CI_Loader::_ci_load_library()
1150
	 * @uses	CI_Loader::_ci_init_library()
1151
	 *
1152
	 * @param	string	$library_name	Library name to load
1153
	 * @param	string	$file_path	Path to the library filename, relative to libraries/
1154
	 * @param	mixed	$params		Optional parameters to pass to the class constructor
1155
	 * @param	string	$object_name	Optional object name to assign to
1156
	 * @return	void
1157
	 * 
1158
	 * modified by ci-phpunit-test
1159
	 */
1160
	protected function _ci_load_stock_library($library_name, $file_path, $params, $object_name)
1161
	{
1162
		$prefix = 'CI_';
1163
1164
//		if (class_exists($prefix.$library_name, FALSE))
0 ignored issues
show
Unused Code Comprehensibility introduced by
65% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1165
		{
1166
			if (class_exists(config_item('subclass_prefix').$library_name, FALSE))
1167
			{
1168
				$prefix = config_item('subclass_prefix');
1169
			}
1170
1171
			// Before we deem this to be a duplicate request, let's see
1172
			// if a custom object name is being supplied. If so, we'll
1173
			// return a new instance of the object
1174
			if ($object_name !== NULL)
1175
			{
1176
				$CI =& get_instance();
1177
				if ( ! isset($CI->$object_name))
1178
				{
1179
					return $this->_ci_init_library($library_name, $prefix, $params, $object_name);
1180
				}
1181
			}
1182
1183
//			log_message('debug', $library_name.' class already loaded. Second attempt ignored.');
0 ignored issues
show
Unused Code Comprehensibility introduced by
60% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1184
//			return;
1185
		}
1186
1187
		$paths = $this->_ci_library_paths;
1188
		array_pop($paths); // BASEPATH
1189
		array_pop($paths); // APPPATH (needs to be the first path checked)
1190
		array_unshift($paths, APPPATH);
1191
1192
		foreach ($paths as $path)
1193
		{
1194
			if (file_exists($path = $path.'libraries/'.$file_path.$library_name.'.php'))
1195
			{
1196
				// Override
1197
				include_once($path);
1198
//				if (class_exists($prefix.$library_name, FALSE))
0 ignored issues
show
Unused Code Comprehensibility introduced by
65% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1199
				{
1200
					return $this->_ci_init_library($library_name, $prefix, $params, $object_name);
1201
				}
1202
//				else
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1203
//				{
1204
//					log_message('debug', $path.' exists, but does not declare '.$prefix.$library_name);
1205
//				}
1206
			}
1207
		}
1208
1209
		// Replace library in ci-phpuni-test
1210
		if (file_exists(APPPATH.'tests/_ci_phpunit_test/replacing/libraries/'.$file_path.$library_name.'.php'))
1211
		{
1212
			include_once(APPPATH.'tests/_ci_phpunit_test/replacing/libraries/'.$file_path.$library_name.'.php');
1213
		}
1214
		else
1215
		{
1216
			include_once(BASEPATH.'libraries/'.$file_path.$library_name.'.php');
1217
		}
1218
1219
		// Check for extensions
1220
		$subclass = config_item('subclass_prefix').$library_name;
1221
		foreach ($paths as $path)
1222
		{
1223
			if (file_exists($path = $path.'libraries/'.$file_path.$subclass.'.php'))
1224
			{
1225
				include_once($path);
1226
				if (class_exists($subclass, FALSE))
1227
				{
1228
					$prefix = config_item('subclass_prefix');
1229
					break;
1230
				}
1231
				else
1232
				{
1233
					log_message('debug', $path.' exists, but does not declare '.$subclass);
1234
				}
1235
			}
1236
		}
1237
1238
		return $this->_ci_init_library($library_name, $prefix, $params, $object_name);
1239
	}
1240
1241
	// --------------------------------------------------------------------
1242
1243
	/**
1244
	 * Internal CI Library Instantiator
1245
	 *
1246
	 * @used-by	CI_Loader::_ci_load_stock_library()
1247
	 * @used-by	CI_Loader::_ci_load_library()
1248
	 *
1249
	 * @param	string		$class		Class name
1250
	 * @param	string		$prefix		Class name prefix
1251
	 * @param	array|null|bool	$config		Optional configuration to pass to the class constructor:
1252
	 *						FALSE to skip;
1253
	 *						NULL to search in config paths;
1254
	 *						array containing configuration data
1255
	 * @param	string		$object_name	Optional object name to assign to
1256
	 * @return	void
1257
	 *
1258
	 * @codeCoverageIgnore
1259
	 */
1260
	protected function _ci_init_library($class, $prefix, $config = FALSE, $object_name = NULL)
1261
	{
1262
		// Is there an associated config file for this class? Note: these should always be lowercase
1263
		if ($config === NULL)
1264
		{
1265
			// Fetch the config paths containing any package paths
1266
			$config_component = $this->_ci_get_component('config');
1267
1268
			if (is_array($config_component->_config_paths))
1269
			{
1270
				$found = FALSE;
1271
				foreach ($config_component->_config_paths as $path)
1272
				{
1273
					// We test for both uppercase and lowercase, for servers that
1274
					// are case-sensitive with regard to file names. Load global first,
1275
					// override with environment next
1276
					if (file_exists($path.'config/'.strtolower($class).'.php'))
1277
					{
1278
						include($path.'config/'.strtolower($class).'.php');
1279
						$found = TRUE;
1280
					}
1281
					elseif (file_exists($path.'config/'.ucfirst(strtolower($class)).'.php'))
1282
					{
1283
						include($path.'config/'.ucfirst(strtolower($class)).'.php');
1284
						$found = TRUE;
1285
					}
1286
1287
					if (file_exists($path.'config/'.ENVIRONMENT.'/'.strtolower($class).'.php'))
1288
					{
1289
						include($path.'config/'.ENVIRONMENT.'/'.strtolower($class).'.php');
1290
						$found = TRUE;
1291
					}
1292
					elseif (file_exists($path.'config/'.ENVIRONMENT.'/'.ucfirst(strtolower($class)).'.php'))
1293
					{
1294
						include($path.'config/'.ENVIRONMENT.'/'.ucfirst(strtolower($class)).'.php');
1295
						$found = TRUE;
1296
					}
1297
1298
					// Break on the first found configuration, thus package
1299
					// files are not overridden by default paths
1300
					if ($found === TRUE)
1301
					{
1302
						break;
1303
					}
1304
				}
1305
			}
1306
		}
1307
1308
		$class_name = $prefix.$class;
1309
1310
		// Is the class name valid?
1311
		if ( ! class_exists($class_name, FALSE))
1312
		{
1313
			log_message('error', 'Non-existent class: '.$class_name);
1314
			show_error('Non-existent class: '.$class_name);
1315
		}
1316
1317
		// Set the variable name we will assign the class to
1318
		// Was a custom class name supplied? If so we'll use it
1319
		if (empty($object_name))
1320
		{
1321
			$object_name = strtolower($class);
1322
			if (isset($this->_ci_varmap[$object_name]))
1323
			{
1324
				$object_name = $this->_ci_varmap[$object_name];
1325
			}
1326
		}
1327
1328
		// Don't overwrite existing properties
1329
		$CI =& get_instance();
1330
		if (isset($CI->$object_name))
1331
		{
1332
			if ($CI->$object_name instanceof $class_name)
1333
			{
1334
				log_message('debug', $class_name." has already been instantiated as '".$object_name."'. Second attempt aborted.");
1335
				return;
1336
			}
1337
1338
			show_error("Resource '".$object_name."' already exists and is not a ".$class_name." instance.");
1339
		}
1340
1341
		// Save the class name and object name
1342
		$this->_ci_classes[$object_name] = $class;
1343
1344
		// Instantiate the class
1345
		$CI->$object_name = isset($config)
1346
			? new $class_name($config)
1347
			: new $class_name();
1348
	}
1349
1350
	// --------------------------------------------------------------------
1351
1352
	/**
1353
	 * CI Autoloader
1354
	 *
1355
	 * Loads component listed in the config/autoload.php file.
1356
	 *
1357
	 * @used-by	CI_Loader::initialize()
1358
	 * @return	void
1359
	 *
1360
	 * @codeCoverageIgnore
1361
	 */
1362
	protected function _ci_autoloader()
1363
	{
1364
		if (file_exists(APPPATH.'config/autoload.php'))
1365
		{
1366
			include(APPPATH.'config/autoload.php');
1367
		}
1368
1369
		if (file_exists(APPPATH.'config/'.ENVIRONMENT.'/autoload.php'))
1370
		{
1371
			include(APPPATH.'config/'.ENVIRONMENT.'/autoload.php');
1372
		}
1373
1374
		if ( ! isset($autoload))
0 ignored issues
show
Bug introduced by
The variable $autoload seems only to be defined at a later point. As such the call to isset() seems to always evaluate to false.

This check marks calls to isset(...) or empty(...) that are found before the variable itself is defined. These will always have the same result.

This is likely the result of code being shifted around. Consider removing these calls.

Loading history...
1375
		{
1376
			return;
1377
		}
1378
1379
		// Autoload packages
1380
		if (isset($autoload['packages']))
1381
		{
1382
			foreach ($autoload['packages'] as $package_path)
1383
			{
1384
				$this->add_package_path($package_path);
1385
			}
1386
		}
1387
1388
		// Load any custom config file
1389
		if (count($autoload['config']) > 0)
1390
		{
1391
			foreach ($autoload['config'] as $val)
1392
			{
1393
				$this->config($val);
1394
			}
1395
		}
1396
1397
		// Autoload helpers and languages
1398
		foreach (array('helper', 'language') as $type)
1399
		{
1400
			if (isset($autoload[$type]) && count($autoload[$type]) > 0)
1401
			{
1402
				$this->$type($autoload[$type]);
1403
			}
1404
		}
1405
1406
		// Autoload drivers
1407
		if (isset($autoload['drivers']))
1408
		{
1409
			$this->driver($autoload['drivers']);
1410
		}
1411
1412
		// Load libraries
1413
		if (isset($autoload['libraries']) && count($autoload['libraries']) > 0)
1414
		{
1415
			// Load the database driver.
1416
			if (in_array('database', $autoload['libraries']))
1417
			{
1418
				$this->database();
1419
				$autoload['libraries'] = array_diff($autoload['libraries'], array('database'));
1420
			}
1421
1422
			// Load all other libraries
1423
			$this->library($autoload['libraries']);
0 ignored issues
show
Documentation introduced by
$autoload['libraries'] is of type array, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1424
		}
1425
1426
		// Autoload models
1427
		if (isset($autoload['model']))
1428
		{
1429
			$this->model($autoload['model']);
0 ignored issues
show
Documentation introduced by
$autoload['model'] is of type array, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
1430
		}
1431
	}
1432
1433
	// --------------------------------------------------------------------
1434
1435
	/**
1436
	 * Prepare variables for _ci_vars, to be later extract()-ed inside views
1437
	 *
1438
	 * Converts objects to associative arrays and filters-out internal
1439
	 * variable names (i.e. keys prefixed with '_ci_').
1440
	 *
1441
	 * @param	mixed	$vars
1442
	 * @return	array
1443
	 *
1444
	 * @codeCoverageIgnore
1445
	 */
1446
	protected function _ci_prepare_view_vars($vars)
1447
	{
1448
		if ( ! is_array($vars))
1449
		{
1450
			$vars = is_object($vars)
1451
				? get_object_vars($vars)
1452
				: array();
1453
		}
1454
1455
		foreach (array_keys($vars) as $key)
1456
		{
1457
			if (strncmp($key, '_ci_', 4) === 0)
1458
			{
1459
				unset($vars[$key]);
1460
			}
1461
		}
1462
1463
		return $vars;
1464
	}
1465
1466
	// --------------------------------------------------------------------
1467
1468
	/**
1469
	 * CI Component getter
1470
	 *
1471
	 * Get a reference to a specific library or model.
1472
	 *
1473
	 * @param 	string	$component	Component name
1474
	 * @return	bool
1475
	 *
1476
	 * @codeCoverageIgnore
1477
	 */
1478
	protected function &_ci_get_component($component)
1479
	{
1480
		$CI =& get_instance();
1481
		return $CI->$component;
1482
	}
1483
1484
}
1485