Completed
Push — master ( 1afbdd...1aa3e0 )
by Kenji
02:36
created

CI_Loader::model()   F

Complexity

Conditions 22
Paths 492

Size

Total Lines 122
Code Lines 48

Duplication

Lines 21
Ratio 17.21 %
Metric Value
dl 21
loc 122
rs 3.057
cc 22
eloc 48
nc 492
nop 3

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 - 2016, 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 - 2016, 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
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...
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
	public function __construct()
137
	{
138
		$this->_ci_ob_level = ob_get_level();
139
		$this->_ci_classes =& is_loaded();
140
141
		log_message('info', 'Loader Class Initialized');
142
	}
143
144
	// --------------------------------------------------------------------
145
146
	/**
147
	 * Initializer
148
	 *
149
	 * @todo	Figure out a way to move this to the constructor
150
	 *		without breaking *package_path*() methods.
151
	 * @uses	CI_Loader::_ci_autoloader()
152
	 * @used-by	CI_Controller::__construct()
153
	 * @return	void
154
	 */
155
	public function initialize()
156
	{
157
		$this->_ci_autoloader();
158
	}
159
160
	// --------------------------------------------------------------------
161
162
	/**
163
	 * Is Loaded
164
	 *
165
	 * A utility method to test if a class is in the self::$_ci_classes array.
166
	 *
167
	 * @used-by	Mainly used by Form Helper function _get_validation_object().
168
	 *
169
	 * @param 	string		$class	Class name to check for
170
	 * @return 	string|bool	Class object name if loaded or FALSE
171
	 */
172
	public function is_loaded($class)
173
	{
174
		return array_search(ucfirst($class), $this->_ci_classes, TRUE);
175
	}
176
177
	// --------------------------------------------------------------------
178
179
	/**
180
	 * Library Loader
181
	 *
182
	 * Loads and instantiates libraries.
183
	 * Designed to be called from application controllers.
184
	 *
185
	 * @param	string	$library	Library name
186
	 * @param	array	$params		Optional parameters to pass to the library class constructor
187
	 * @param	string	$object_name	An optional object name to assign to
188
	 * @return	object
189
	 */
190
	public function library($library, $params = NULL, $object_name = NULL)
191
	{
192 View Code Duplication
		if (empty($library))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
193
		{
194
			return $this;
195
		}
196
		elseif (is_array($library))
197
		{
198
			foreach ($library as $key => $value)
199
			{
200
				if (is_int($key))
201
				{
202
					$this->library($value, $params);
203
				}
204
				else
205
				{
206
					$this->library($key, $params, $value);
207
				}
208
			}
209
210
			return $this;
211
		}
212
213
		if ($params !== NULL && ! is_array($params))
214
		{
215
			$params = NULL;
216
		}
217
218
		$this->_ci_load_library($library, $params, $object_name);
219
		return $this;
220
	}
221
222
	// --------------------------------------------------------------------
223
224
	/**
225
	 * Model Loader
226
	 *
227
	 * Loads and instantiates models.
228
	 *
229
	 * @param	string	$model		Model name
230
	 * @param	string	$name		An optional object name to assign to
231
	 * @param	bool	$db_conn	An optional database connection configuration to initialize
232
	 * @return	object
233
	 * 
234
	 * modified by ci-phpunit-test
235
	 */
236
	public function model($model, $name = '', $db_conn = FALSE)
237
	{
238 View Code Duplication
		if (empty($model))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
239
		{
240
			return $this;
241
		}
242
		elseif (is_array($model))
243
		{
244
			foreach ($model as $key => $value)
245
			{
246
				is_int($key) ? $this->model($value, '', $db_conn) : $this->model($key, $value, $db_conn);
247
			}
248
249
			return $this;
250
		}
251
252
		$path = '';
253
254
		// Is the model in a sub-folder? If so, parse out the filename and path.
255 View Code Duplication
		if (($last_slash = strrpos($model, '/')) !== FALSE)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
256
		{
257
			// The path is in front of the last slash
258
			$path = substr($model, 0, ++$last_slash);
259
260
			// And the model name behind it
261
			$model = substr($model, $last_slash);
262
		}
263
264
		if (empty($name))
265
		{
266
			$name = $model;
267
		}
268
269
		if (in_array($name, $this->_ci_models, TRUE))
270
		{
271
			return $this;
272
		}
273
274
		$CI =& get_instance();
275
		if (isset($CI->$name))
276
		{
277
			throw new RuntimeException('The model name you are loading is the name of a resource that is already being used: '.$name);
278
		}
279
280
		if ($db_conn !== FALSE && ! class_exists('CI_DB', FALSE))
281
		{
282
			if ($db_conn === TRUE)
283
			{
284
				$db_conn = '';
285
			}
286
287
			$this->database($db_conn, FALSE, TRUE);
288
		}
289
290
		// Note: All of the code under this condition used to be just:
291
		//
292
		//       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...
293
		//
294
		//       However, load_class() instantiates classes
295
		//       to cache them for later use and that prevents
296
		//       MY_Model from being an abstract class and is
297
		//       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...
298
//		if ( ! class_exists('CI_Model', FALSE))
299
//		{
300
			$app_path = APPPATH.'core'.DIRECTORY_SEPARATOR;
301
			if (file_exists($app_path.'Model.php'))
302
			{
303
				require_once($app_path.'Model.php');
304
				if ( ! class_exists('CI_Model', FALSE))
305
				{
306
					throw new RuntimeException($app_path."Model.php exists, but doesn't declare class CI_Model");
307
				}
308
			}
309
			elseif ( ! class_exists('CI_Model', FALSE))
310
			{
311
				require_once(BASEPATH.'core'.DIRECTORY_SEPARATOR.'Model.php');
312
			}
313
314
			$class = config_item('subclass_prefix').'Model';
315
			if (file_exists($app_path.$class.'.php'))
316
			{
317
				require_once($app_path.$class.'.php');
318
				if ( ! class_exists($class, FALSE))
319
				{
320
					throw new RuntimeException($app_path.$class.".php exists, but doesn't declare class ".$class);
321
				}
322
			}
323
//		}
324
325
		$model = ucfirst($model);
326
		if ( ! class_exists($model, FALSE))
327
		{
328
			foreach ($this->_ci_model_paths as $mod_path)
329
			{
330
				if ( ! file_exists($mod_path.'models/'.$path.$model.'.php'))
331
				{
332
					continue;
333
				}
334
335
				require_once($mod_path.'models/'.$path.$model.'.php');
336
				if ( ! class_exists($model, FALSE))
337
				{
338
					throw new RuntimeException($mod_path."models/".$path.$model.".php exists, but doesn't declare class ".$model);
339
				}
340
341
				break;
342
			}
343
344
			if ( ! class_exists($model, FALSE))
345
			{
346
				throw new RuntimeException('Unable to locate the model you have specified: '.$model);
347
			}
348
		}
349
//		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...
350
//		{
351
//			throw new RuntimeException("Class ".$model." already exists and doesn't extend CI_Model");
352
//		}
353
354
		$this->_ci_models[] = $name;
355
		$CI->$name = new $model();
356
		return $this;
357
	}
358
359
	// --------------------------------------------------------------------
360
361
	/**
362
	 * Database Loader
363
	 *
364
	 * @param	mixed	$params		Database configuration options
365
	 * @param	bool	$return 	Whether to return the database object
366
	 * @param	bool	$query_builder	Whether to enable Query Builder
367
	 *					(overrides the configuration setting)
368
	 *
369
	 * @return	object|bool	Database object if $return is set to TRUE,
370
	 *					FALSE on failure, CI_Loader instance in any other case
371
	 */
372
	public function database($params = '', $return = FALSE, $query_builder = NULL)
373
	{
374
		// Grab the super object
375
		$CI =& get_instance();
376
377
		// Do we even need to load the database class?
378
		if ($return === FALSE && $query_builder === NULL && isset($CI->db) && is_object($CI->db) && ! empty($CI->db->conn_id))
379
		{
380
			return FALSE;
381
		}
382
383
		require_once(BASEPATH.'database/DB.php');
384
385
		if ($return === TRUE)
386
		{
387
			return DB($params, $query_builder);
388
		}
389
390
		// Initialize the db variable. Needed to prevent
391
		// reference errors with some configurations
392
		$CI->db = '';
393
394
		// Load the DB class
395
		$CI->db =& DB($params, $query_builder);
396
		return $this;
397
	}
398
399
	// --------------------------------------------------------------------
400
401
	/**
402
	 * Load the Database Utilities Class
403
	 *
404
	 * @param	object	$db	Database object
405
	 * @param	bool	$return	Whether to return the DB Utilities class object or not
406
	 * @return	object
407
	 */
408
	public function dbutil($db = NULL, $return = FALSE)
409
	{
410
		$CI =& get_instance();
411
412 View Code Duplication
		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...
Duplication introduced by
This code seems to be duplicated across 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...
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...
413
		{
414
			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...
415
			$db =& $CI->db;
416
		}
417
418
		require_once(BASEPATH.'database/DB_utility.php');
419
		require_once(BASEPATH.'database/drivers/'.$db->dbdriver.'/'.$db->dbdriver.'_utility.php');
420
		$class = 'CI_DB_'.$db->dbdriver.'_utility';
421
422
		if ($return === TRUE)
423
		{
424
			return new $class($db);
425
		}
426
427
		$CI->dbutil = new $class($db);
428
		return $this;
429
	}
430
431
	// --------------------------------------------------------------------
432
433
	/**
434
	 * Load the Database Forge Class
435
	 *
436
	 * @param	object	$db	Database object
437
	 * @param	bool	$return	Whether to return the DB Forge class object or not
438
	 * @return	object
439
	 */
440
	public function dbforge($db = NULL, $return = FALSE)
441
	{
442
		$CI =& get_instance();
443 View Code Duplication
		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...
Duplication introduced by
This code seems to be duplicated across 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...
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...
444
		{
445
			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...
446
			$db =& $CI->db;
447
		}
448
449
		require_once(BASEPATH.'database/DB_forge.php');
450
		require_once(BASEPATH.'database/drivers/'.$db->dbdriver.'/'.$db->dbdriver.'_forge.php');
451
452
		if ( ! empty($db->subdriver))
453
		{
454
			$driver_path = BASEPATH.'database/drivers/'.$db->dbdriver.'/subdrivers/'.$db->dbdriver.'_'.$db->subdriver.'_forge.php';
455
			if (file_exists($driver_path))
456
			{
457
				require_once($driver_path);
458
				$class = 'CI_DB_'.$db->dbdriver.'_'.$db->subdriver.'_forge';
459
			}
460
		}
461
		else
462
		{
463
			$class = 'CI_DB_'.$db->dbdriver.'_forge';
464
		}
465
466
		if ($return === TRUE)
467
		{
468
			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...
469
		}
470
471
		$CI->dbforge = new $class($db);
472
		return $this;
473
	}
474
475
	// --------------------------------------------------------------------
476
477
	/**
478
	 * View Loader
479
	 *
480
	 * Loads "view" files.
481
	 *
482
	 * @param	string	$view	View name
483
	 * @param	array	$vars	An associative array of data
484
	 *				to be extracted for use in the view
485
	 * @param	bool	$return	Whether to return the view output
486
	 *				or leave it to the Output class
487
	 * @return	object|string
488
	 */
489
	public function view($view, $vars = array(), $return = FALSE)
490
	{
491
		return $this->_ci_load(array('_ci_view' => $view, '_ci_vars' => $this->_ci_object_to_array($vars), '_ci_return' => $return));
0 ignored issues
show
Documentation introduced by
$vars is of type array, but the function expects a object.

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...
492
	}
493
494
	// --------------------------------------------------------------------
495
496
	/**
497
	 * Generic File Loader
498
	 *
499
	 * @param	string	$path	File path
500
	 * @param	bool	$return	Whether to return the file output
501
	 * @return	object|string
502
	 */
503
	public function file($path, $return = FALSE)
504
	{
505
		return $this->_ci_load(array('_ci_path' => $path, '_ci_return' => $return));
506
	}
507
508
	// --------------------------------------------------------------------
509
510
	/**
511
	 * Set Variables
512
	 *
513
	 * Once variables are set they become available within
514
	 * the controller class and its "view" files.
515
	 *
516
	 * @param	array|object|string	$vars
517
	 *					An associative array or object containing values
518
	 *					to be set, or a value's name if string
519
	 * @param 	string	$val	Value to set, only used if $vars is a string
520
	 * @return	object
521
	 */
522
	public function vars($vars, $val = '')
523
	{
524
		if (is_string($vars))
525
		{
526
			$vars = array($vars => $val);
527
		}
528
529
		$vars = $this->_ci_object_to_array($vars);
0 ignored issues
show
Bug introduced by
It seems like $vars defined by $this->_ci_object_to_array($vars) on line 529 can also be of type array; however, CI_Loader::_ci_object_to_array() does only seem to accept object, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
530
531
		if (is_array($vars) && count($vars) > 0)
532
		{
533
			foreach ($vars as $key => $val)
534
			{
535
				$this->_ci_cached_vars[$key] = $val;
536
			}
537
		}
538
539
		return $this;
540
	}
541
542
	// --------------------------------------------------------------------
543
544
	/**
545
	 * Clear Cached Variables
546
	 *
547
	 * Clears the cached variables.
548
	 *
549
	 * @return	CI_Loader
550
	 */
551
	public function clear_vars()
552
	{
553
		$this->_ci_cached_vars = array();
554
		return $this;
555
	}
556
557
	// --------------------------------------------------------------------
558
559
	/**
560
	 * Get Variable
561
	 *
562
	 * Check if a variable is set and retrieve it.
563
	 *
564
	 * @param	string	$key	Variable name
565
	 * @return	mixed	The variable or NULL if not found
566
	 */
567
	public function get_var($key)
568
	{
569
		return isset($this->_ci_cached_vars[$key]) ? $this->_ci_cached_vars[$key] : NULL;
570
	}
571
572
	// --------------------------------------------------------------------
573
574
	/**
575
	 * Get Variables
576
	 *
577
	 * Retrieves all loaded variables.
578
	 *
579
	 * @return	array
580
	 */
581
	public function get_vars()
582
	{
583
		return $this->_ci_cached_vars;
584
	}
585
586
	// --------------------------------------------------------------------
587
588
	/**
589
	 * Helper Loader
590
	 *
591
	 * @param	string|string[]	$helpers	Helper name(s)
592
	 * @return	object
593
	 */
594
	public function helper($helpers = array())
595
	{
596
		foreach ($this->_ci_prep_filename($helpers, '_helper') as $helper)
597
		{
598
			if (isset($this->_ci_helpers[$helper]))
599
			{
600
				continue;
601
			}
602
603
			// Is this a helper extension request?
604
			$ext_helper = config_item('subclass_prefix').$helper;
605
			$ext_loaded = FALSE;
606
			foreach ($this->_ci_helper_paths as $path)
607
			{
608
				if (file_exists($path.'helpers/'.$ext_helper.'.php'))
609
				{
610
					include_once($path.'helpers/'.$ext_helper.'.php');
611
					$ext_loaded = TRUE;
612
				}
613
			}
614
615
			// If we have loaded extensions - check if the base one is here
616
			if ($ext_loaded === TRUE)
617
			{
618
				$base_helper = BASEPATH.'helpers/'.$helper.'.php';
619
				if ( ! file_exists($base_helper))
620
				{
621
					show_error('Unable to load the requested file: helpers/'.$helper.'.php');
622
				}
623
624
				include_once($base_helper);
625
				$this->_ci_helpers[$helper] = TRUE;
626
				log_message('info', 'Helper loaded: '.$helper);
627
				continue;
628
			}
629
630
			// No extensions found ... try loading regular helpers and/or overrides
631
			foreach ($this->_ci_helper_paths as $path)
632
			{
633
				if (file_exists($path.'helpers/'.$helper.'.php'))
634
				{
635
					include_once($path.'helpers/'.$helper.'.php');
636
637
					$this->_ci_helpers[$helper] = TRUE;
638
					log_message('info', 'Helper loaded: '.$helper);
639
					break;
640
				}
641
			}
642
643
			// unable to load the helper
644
			if ( ! isset($this->_ci_helpers[$helper]))
645
			{
646
				show_error('Unable to load the requested file: helpers/'.$helper.'.php');
647
			}
648
		}
649
650
		return $this;
651
	}
652
653
	// --------------------------------------------------------------------
654
655
	/**
656
	 * Load Helpers
657
	 *
658
	 * An alias for the helper() method in case the developer has
659
	 * written the plural form of it.
660
	 *
661
	 * @uses	CI_Loader::helper()
662
	 * @param	string|string[]	$helpers	Helper name(s)
663
	 * @return	object
664
	 */
665
	public function helpers($helpers = array())
666
	{
667
		return $this->helper($helpers);
668
	}
669
670
	// --------------------------------------------------------------------
671
672
	/**
673
	 * Language Loader
674
	 *
675
	 * Loads language files.
676
	 *
677
	 * @param	string|string[]	$files	List of language file names to load
678
	 * @param	string		Language name
679
	 * @return	object
680
	 */
681
	public function language($files, $lang = '')
682
	{
683
		get_instance()->lang->load($files, $lang);
684
		return $this;
685
	}
686
687
	// --------------------------------------------------------------------
688
689
	/**
690
	 * Config Loader
691
	 *
692
	 * Loads a config file (an alias for CI_Config::load()).
693
	 *
694
	 * @uses	CI_Config::load()
695
	 * @param	string	$file			Configuration file name
696
	 * @param	bool	$use_sections		Whether configuration values should be loaded into their own section
697
	 * @param	bool	$fail_gracefully	Whether to just return FALSE or display an error message
698
	 * @return	bool	TRUE if the file was loaded correctly or FALSE on failure
699
	 */
700
	public function config($file, $use_sections = FALSE, $fail_gracefully = FALSE)
701
	{
702
		return get_instance()->config->load($file, $use_sections, $fail_gracefully);
703
	}
704
705
	// --------------------------------------------------------------------
706
707
	/**
708
	 * Driver Loader
709
	 *
710
	 * Loads a driver library.
711
	 *
712
	 * @param	string|string[]	$library	Driver name(s)
713
	 * @param	array		$params		Optional parameters to pass to the driver
714
	 * @param	string		$object_name	An optional object name to assign to
715
	 *
716
	 * @return	object|bool	Object or FALSE on failure if $library is a string
717
	 *				and $object_name is set. CI_Loader instance otherwise.
718
	 */
719
	public function driver($library, $params = NULL, $object_name = NULL)
720
	{
721 View Code Duplication
		if (is_array($library))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
722
		{
723
			foreach ($library as $key => $value)
724
			{
725
				if (is_int($key))
726
				{
727
					$this->driver($value, $params);
728
				}
729
				else
730
				{
731
					$this->driver($key, $params, $value);
732
				}
733
			}
734
735
			return $this;
736
		}
737
		elseif (empty($library))
738
		{
739
			return FALSE;
740
		}
741
742
		if ( ! class_exists('CI_Driver_Library', FALSE))
743
		{
744
			// We aren't instantiating an object here, just making the base class available
745
			require BASEPATH.'libraries/Driver.php';
746
		}
747
748
		// We can save the loader some time since Drivers will *always* be in a subfolder,
749
		// and typically identically named to the library
750
		if ( ! strpos($library, '/'))
751
		{
752
			$library = ucfirst($library).'/'.$library;
753
		}
754
755
		return $this->library($library, $params, $object_name);
756
	}
757
758
	// --------------------------------------------------------------------
759
760
	/**
761
	 * Add Package Path
762
	 *
763
	 * Prepends a parent path to the library, model, helper and config
764
	 * path arrays.
765
	 *
766
	 * @see	CI_Loader::$_ci_library_paths
767
	 * @see	CI_Loader::$_ci_model_paths
768
	 * @see CI_Loader::$_ci_helper_paths
769
	 * @see CI_Config::$_config_paths
770
	 *
771
	 * @param	string	$path		Path to add
772
	 * @param 	bool	$view_cascade	(default: TRUE)
773
	 * @return	object
774
	 */
775
	public function add_package_path($path, $view_cascade = TRUE)
776
	{
777
		$path = rtrim($path, '/').'/';
778
779
		array_unshift($this->_ci_library_paths, $path);
780
		array_unshift($this->_ci_model_paths, $path);
781
		array_unshift($this->_ci_helper_paths, $path);
782
783
		$this->_ci_view_paths = array($path.'views/' => $view_cascade) + $this->_ci_view_paths;
784
785
		// Add config file path
786
		$config =& $this->_ci_get_component('config');
787
		$config->_config_paths[] = $path;
788
789
		return $this;
790
	}
791
792
	// --------------------------------------------------------------------
793
794
	/**
795
	 * Get Package Paths
796
	 *
797
	 * Return a list of all package paths.
798
	 *
799
	 * @param	bool	$include_base	Whether to include BASEPATH (default: FALSE)
800
	 * @return	array
801
	 */
802
	public function get_package_paths($include_base = FALSE)
803
	{
804
		return ($include_base === TRUE) ? $this->_ci_library_paths : $this->_ci_model_paths;
805
	}
806
807
	// --------------------------------------------------------------------
808
809
	/**
810
	 * Remove Package Path
811
	 *
812
	 * Remove a path from the library, model, helper and/or config
813
	 * path arrays if it exists. If no path is provided, the most recently
814
	 * added path will be removed removed.
815
	 *
816
	 * @param	string	$path	Path to remove
817
	 * @return	object
818
	 */
819
	public function remove_package_path($path = '')
820
	{
821
		$config =& $this->_ci_get_component('config');
822
823
		if ($path === '')
824
		{
825
			array_shift($this->_ci_library_paths);
826
			array_shift($this->_ci_model_paths);
827
			array_shift($this->_ci_helper_paths);
828
			array_shift($this->_ci_view_paths);
829
			array_pop($config->_config_paths);
830
		}
831
		else
832
		{
833
			$path = rtrim($path, '/').'/';
834
			foreach (array('_ci_library_paths', '_ci_model_paths', '_ci_helper_paths') as $var)
835
			{
836
				if (($key = array_search($path, $this->{$var})) !== FALSE)
837
				{
838
					unset($this->{$var}[$key]);
839
				}
840
			}
841
842
			if (isset($this->_ci_view_paths[$path.'views/']))
843
			{
844
				unset($this->_ci_view_paths[$path.'views/']);
845
			}
846
847
			if (($key = array_search($path, $config->_config_paths)) !== FALSE)
848
			{
849
				unset($config->_config_paths[$key]);
850
			}
851
		}
852
853
		// make sure the application default paths are still in the array
854
		$this->_ci_library_paths = array_unique(array_merge($this->_ci_library_paths, array(APPPATH, BASEPATH)));
855
		$this->_ci_helper_paths = array_unique(array_merge($this->_ci_helper_paths, array(APPPATH, BASEPATH)));
856
		$this->_ci_model_paths = array_unique(array_merge($this->_ci_model_paths, array(APPPATH)));
857
		$this->_ci_view_paths = array_merge($this->_ci_view_paths, array(APPPATH.'views/' => TRUE));
858
		$config->_config_paths = array_unique(array_merge($config->_config_paths, array(APPPATH)));
859
860
		return $this;
861
	}
862
863
	// --------------------------------------------------------------------
864
865
	/**
866
	 * Internal CI Data Loader
867
	 *
868
	 * Used to load views and files.
869
	 *
870
	 * Variables are prefixed with _ci_ to avoid symbol collision with
871
	 * variables made available to view files.
872
	 *
873
	 * @used-by	CI_Loader::view()
874
	 * @used-by	CI_Loader::file()
875
	 * @param	array	$_ci_data	Data to load
876
	 * @return	object
877
	 */
878
	protected function _ci_load($_ci_data)
879
	{
880
		// Set the default data variables
881
		foreach (array('_ci_view', '_ci_vars', '_ci_path', '_ci_return') as $_ci_val)
882
		{
883
			$$_ci_val = isset($_ci_data[$_ci_val]) ? $_ci_data[$_ci_val] : FALSE;
884
		}
885
886
		$file_exists = FALSE;
887
888
		// Set the path to the requested file
889
		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...
890
		{
891
			$_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...
892
			$_ci_file = end($_ci_x);
893
		}
894
		else
895
		{
896
			$_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...
897
			$_ci_file = ($_ci_ext === '') ? $_ci_view.'.php' : $_ci_view;
898
899
			foreach ($this->_ci_view_paths as $_ci_view_file => $cascade)
900
			{
901
				if (file_exists($_ci_view_file.$_ci_file))
902
				{
903
					$_ci_path = $_ci_view_file.$_ci_file;
904
					$file_exists = TRUE;
905
					break;
906
				}
907
908
				if ( ! $cascade)
909
				{
910
					break;
911
				}
912
			}
913
		}
914
915
		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...
916
		{
917
			show_error('Unable to load the requested file: '.$_ci_file);
918
		}
919
920
		// This allows anything loaded using $this->load (views, files, etc.)
921
		// to become accessible from within the Controller and Model functions.
922
		$_ci_CI =& get_instance();
923
		foreach (get_object_vars($_ci_CI) as $_ci_key => $_ci_var)
924
		{
925
			if ( ! isset($this->$_ci_key))
926
			{
927
				$this->$_ci_key =& $_ci_CI->$_ci_key;
928
			}
929
		}
930
931
		/*
932
		 * Extract and cache variables
933
		 *
934
		 * You can either set variables using the dedicated $this->load->vars()
935
		 * function or via the second parameter of this function. We'll merge
936
		 * the two types and cache them so that views that are embedded within
937
		 * other views can have access to these variables.
938
		 */
939
		if (is_array($_ci_vars))
940
		{
941
			foreach (array_keys($_ci_vars) as $key)
0 ignored issues
show
Bug introduced by
The variable $_ci_vars 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...
942
			{
943
				if (strncmp($key, '_ci_', 4) === 0)
944
				{
945
					unset($_ci_vars[$key]);
946
				}
947
			}
948
949
			$this->_ci_cached_vars = array_merge($this->_ci_cached_vars, $_ci_vars);
950
		}
951
		extract($this->_ci_cached_vars);
952
953
		/*
954
		 * Buffer the output
955
		 *
956
		 * We buffer the output for two reasons:
957
		 * 1. Speed. You get a significant speed boost.
958
		 * 2. So that the final rendered template can be post-processed by
959
		 *	the output class. Why do we need post processing? For one thing,
960
		 *	in order to show the elapsed page load time. Unless we can
961
		 *	intercept the content right before it's sent to the browser and
962
		 *	then stop the timer it won't be accurate.
963
		 */
964
		ob_start();
965
966
		// If the PHP installation does not support short tags we'll
967
		// do a little string replacement, changing the short tags
968
		// to standard PHP echo statements.
969
		if ( ! is_php('5.4') && ! ini_get('short_open_tag') && config_item('rewrite_short_tags') === TRUE)
970
		{
971
			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...
972
		}
973
		else
974
		{
975
			include($_ci_path); // include() vs include_once() allows for multiple views with the same name
976
		}
977
978
		log_message('info', 'File loaded: '.$_ci_path);
979
980
		// Return the file data if requested
981
		if ($_ci_return === TRUE)
982
		{
983
			$buffer = ob_get_contents();
984
			@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...
985
			return $buffer;
986
		}
987
988
		/*
989
		 * Flush the buffer... or buff the flusher?
990
		 *
991
		 * In order to permit views to be nested within
992
		 * other views, we need to flush the content back out whenever
993
		 * we are beyond the first level of output buffering so that
994
		 * it can be seen and included properly by the first included
995
		 * template and any subsequent ones. Oy!
996
		 */
997
		if (ob_get_level() > $this->_ci_ob_level + 1)
998
		{
999
			ob_end_flush();
1000
		}
1001
		else
1002
		{
1003
			$_ci_CI->output->append_output(ob_get_contents());
1004
			@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...
1005
		}
1006
1007
		return $this;
1008
	}
1009
1010
	// --------------------------------------------------------------------
1011
1012
	/**
1013
	 * Internal CI Library Loader
1014
	 *
1015
	 * @used-by	CI_Loader::library()
1016
	 * @uses	CI_Loader::_ci_init_library()
1017
	 *
1018
	 * @param	string	$class		Class name to load
1019
	 * @param	mixed	$params		Optional parameters to pass to the class constructor
1020
	 * @param	string	$object_name	Optional object name to assign to
1021
	 * @return	void
1022
	 * 
1023
	 * modified by ci-phpunit-test
1024
	 */
1025
	protected function _ci_load_library($class, $params = NULL, $object_name = NULL)
1026
	{
1027
		// Get the class name, and while we're at it trim any slashes.
1028
		// The directory path can be included as part of the class name,
1029
		// but we don't want a leading slash
1030
		$class = str_replace('.php', '', trim($class, '/'));
1031
1032
		// Was the path included with the class name?
1033
		// We look for a slash to determine this
1034 View Code Duplication
		if (($last_slash = strrpos($class, '/')) !== FALSE)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
1035
		{
1036
			// Extract the path
1037
			$subdir = substr($class, 0, ++$last_slash);
1038
1039
			// Get the filename from the path
1040
			$class = substr($class, $last_slash);
1041
		}
1042
		else
1043
		{
1044
			$subdir = '';
1045
		}
1046
1047
		$class = ucfirst($class);
1048
1049
		// Is this a stock library? There are a few special conditions if so ...
1050
		if (file_exists(BASEPATH.'libraries/'.$subdir.$class.'.php'))
1051
		{
1052
			return $this->_ci_load_stock_library($class, $subdir, $params, $object_name);
1053
		}
1054
1055
		// Let's search for the requested library file and load it.
1056
		foreach ($this->_ci_library_paths as $path)
1057
		{
1058
			// BASEPATH has already been checked for
1059
			if ($path === BASEPATH)
1060
			{
1061
				continue;
1062
			}
1063
1064
			$filepath = $path.'libraries/'.$subdir.$class.'.php';
1065
1066
			// Safety: Was the class already loaded by a previous call?
1067 View Code Duplication
			if (class_exists($class, FALSE))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
1068
			{
1069
				// Before we deem this to be a duplicate request, let's see
1070
				// if a custom object name is being supplied. If so, we'll
1071
				// return a new instance of the object
1072
				if ($object_name !== NULL)
1073
				{
1074
					$CI =& get_instance();
1075
					if ( ! isset($CI->$object_name))
1076
					{
1077
						return $this->_ci_init_library($class, '', $params, $object_name);
1078
					}
1079
				}
1080
1081
//				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...
1082
//				return;
1083
			}
1084
			// Does the file exist? No? Bummer...
1085
			if ( ! file_exists($filepath))
1086
			{
1087
				continue;
1088
			}
1089
1090
			include_once($filepath);
1091
			return $this->_ci_init_library($class, '', $params, $object_name);
1092
		}
1093
1094
		// One last attempt. Maybe the library is in a subdirectory, but it wasn't specified?
1095
		if ($subdir === '')
1096
		{
1097
			return $this->_ci_load_library($class.'/'.$class, $params, $object_name);
1098
		}
1099
1100
		// If we got this far we were unable to find the requested class.
1101
		log_message('error', 'Unable to load the requested class: '.$class);
1102
		show_error('Unable to load the requested class: '.$class);
1103
	}
1104
1105
	// --------------------------------------------------------------------
1106
1107
	/**
1108
	 * Internal CI Stock Library Loader
1109
	 *
1110
	 * @used-by	CI_Loader::_ci_load_library()
1111
	 * @uses	CI_Loader::_ci_init_library()
1112
	 *
1113
	 * @param	string	$library	Library name to load
0 ignored issues
show
Documentation introduced by
There is no parameter named $library. Did you maybe mean $library_name?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.

Consider the following example. The parameter $ireland is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $ireland
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was changed, but the annotation was not.

Loading history...
1114
	 * @param	string	$file_path	Path to the library filename, relative to libraries/
1115
	 * @param	mixed	$params		Optional parameters to pass to the class constructor
1116
	 * @param	string	$object_name	Optional object name to assign to
1117
	 * @return	void
1118
	 * 
1119
	 * modified by ci-phpunit-test
1120
	 */
1121
	protected function _ci_load_stock_library($library_name, $file_path, $params, $object_name)
1122
	{
1123
		$prefix = 'CI_';
1124
1125
//		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...
1126
		{
1127
			if (class_exists(config_item('subclass_prefix').$library_name, FALSE))
1128
			{
1129
				$prefix = config_item('subclass_prefix');
1130
			}
1131
1132
			// Before we deem this to be a duplicate request, let's see
1133
			// if a custom object name is being supplied. If so, we'll
1134
			// return a new instance of the object
1135 View Code Duplication
			if ($object_name !== NULL)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
1136
			{
1137
				$CI =& get_instance();
1138
				if ( ! isset($CI->$object_name))
1139
				{
1140
					return $this->_ci_init_library($library_name, $prefix, $params, $object_name);
1141
				}
1142
			}
1143
1144
//			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...
1145
//			return;
1146
		}
1147
1148
		$paths = $this->_ci_library_paths;
1149
		array_pop($paths); // BASEPATH
1150
		array_pop($paths); // APPPATH (needs to be the first path checked)
1151
		array_unshift($paths, APPPATH);
1152
1153
		foreach ($paths as $path)
1154
		{
1155
			if (file_exists($path = $path.'libraries/'.$file_path.$library_name.'.php'))
1156
			{
1157
				// Override
1158
				include_once($path);
1159
//				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...
1160
				{
1161
					return $this->_ci_init_library($library_name, $prefix, $params, $object_name);
1162
				}
1163
//				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...
1164
//				{
1165
//					log_message('debug', $path.' exists, but does not declare '.$prefix.$library_name);
1166
//				}
1167
			}
1168
		}
1169
1170
		include_once(BASEPATH.'libraries/'.$file_path.$library_name.'.php');
1171
1172
		// Check for extensions
1173
		$subclass = config_item('subclass_prefix').$library_name;
1174
		foreach ($paths as $path)
1175
		{
1176
			if (file_exists($path = $path.'libraries/'.$file_path.$subclass.'.php'))
1177
			{
1178
				include_once($path);
1179
				if (class_exists($subclass, FALSE))
1180
				{
1181
					$prefix = config_item('subclass_prefix');
1182
					break;
1183
				}
1184
				else
1185
				{
1186
					log_message('debug', $path.' exists, but does not declare '.$subclass);
1187
				}
1188
			}
1189
		}
1190
1191
		return $this->_ci_init_library($library_name, $prefix, $params, $object_name);
1192
	}
1193
1194
	// --------------------------------------------------------------------
1195
1196
	/**
1197
	 * Internal CI Library Instantiator
1198
	 *
1199
	 * @used-by	CI_Loader::_ci_load_stock_library()
1200
	 * @used-by	CI_Loader::_ci_load_library()
1201
	 *
1202
	 * @param	string		$class		Class name
1203
	 * @param	string		$prefix		Class name prefix
1204
	 * @param	array|null|bool	$config		Optional configuration to pass to the class constructor:
1205
	 *						FALSE to skip;
1206
	 *						NULL to search in config paths;
1207
	 *						array containing configuration data
1208
	 * @param	string		$object_name	Optional object name to assign to
1209
	 * @return	void
1210
	 */
1211
	protected function _ci_init_library($class, $prefix, $config = FALSE, $object_name = NULL)
1212
	{
1213
		// Is there an associated config file for this class? Note: these should always be lowercase
1214
		if ($config === NULL)
1215
		{
1216
			// Fetch the config paths containing any package paths
1217
			$config_component = $this->_ci_get_component('config');
1218
1219
			if (is_array($config_component->_config_paths))
1220
			{
1221
				$found = FALSE;
1222
				foreach ($config_component->_config_paths as $path)
1223
				{
1224
					// We test for both uppercase and lowercase, for servers that
1225
					// are case-sensitive with regard to file names. Load global first,
1226
					// override with environment next
1227
					if (file_exists($path.'config/'.strtolower($class).'.php'))
1228
					{
1229
						include($path.'config/'.strtolower($class).'.php');
1230
						$found = TRUE;
1231
					}
1232
					elseif (file_exists($path.'config/'.ucfirst(strtolower($class)).'.php'))
1233
					{
1234
						include($path.'config/'.ucfirst(strtolower($class)).'.php');
1235
						$found = TRUE;
1236
					}
1237
1238
					if (file_exists($path.'config/'.ENVIRONMENT.'/'.strtolower($class).'.php'))
1239
					{
1240
						include($path.'config/'.ENVIRONMENT.'/'.strtolower($class).'.php');
1241
						$found = TRUE;
1242
					}
1243
					elseif (file_exists($path.'config/'.ENVIRONMENT.'/'.ucfirst(strtolower($class)).'.php'))
1244
					{
1245
						include($path.'config/'.ENVIRONMENT.'/'.ucfirst(strtolower($class)).'.php');
1246
						$found = TRUE;
1247
					}
1248
1249
					// Break on the first found configuration, thus package
1250
					// files are not overridden by default paths
1251
					if ($found === TRUE)
1252
					{
1253
						break;
1254
					}
1255
				}
1256
			}
1257
		}
1258
1259
		$class_name = $prefix.$class;
1260
1261
		// Is the class name valid?
1262
		if ( ! class_exists($class_name, FALSE))
1263
		{
1264
			log_message('error', 'Non-existent class: '.$class_name);
1265
			show_error('Non-existent class: '.$class_name);
1266
		}
1267
1268
		// Set the variable name we will assign the class to
1269
		// Was a custom class name supplied? If so we'll use it
1270
		if (empty($object_name))
1271
		{
1272
			$object_name = strtolower($class);
1273
			if (isset($this->_ci_varmap[$object_name]))
1274
			{
1275
				$object_name = $this->_ci_varmap[$object_name];
1276
			}
1277
		}
1278
1279
		// Don't overwrite existing properties
1280
		$CI =& get_instance();
1281
		if (isset($CI->$object_name))
1282
		{
1283
			if ($CI->$object_name instanceof $class_name)
1284
			{
1285
				log_message('debug', $class_name." has already been instantiated as '".$object_name."'. Second attempt aborted.");
1286
				return;
1287
			}
1288
1289
			show_error("Resource '".$object_name."' already exists and is not a ".$class_name." instance.");
1290
		}
1291
1292
		// Save the class name and object name
1293
		$this->_ci_classes[$object_name] = $class;
1294
1295
		// Instantiate the class
1296
		$CI->$object_name = isset($config)
1297
			? new $class_name($config)
1298
			: new $class_name();
1299
	}
1300
1301
	// --------------------------------------------------------------------
1302
1303
	/**
1304
	 * CI Autoloader
1305
	 *
1306
	 * Loads component listed in the config/autoload.php file.
1307
	 *
1308
	 * @used-by	CI_Loader::initialize()
1309
	 * @return	void
1310
	 */
1311
	protected function _ci_autoloader()
1312
	{
1313
		if (file_exists(APPPATH.'config/autoload.php'))
1314
		{
1315
			include(APPPATH.'config/autoload.php');
1316
		}
1317
1318 View Code Duplication
		if (file_exists(APPPATH.'config/'.ENVIRONMENT.'/autoload.php'))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
1319
		{
1320
			include(APPPATH.'config/'.ENVIRONMENT.'/autoload.php');
1321
		}
1322
1323
		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...
1324
		{
1325
			return;
1326
		}
1327
1328
		// Autoload packages
1329
		if (isset($autoload['packages']))
1330
		{
1331
			foreach ($autoload['packages'] as $package_path)
1332
			{
1333
				$this->add_package_path($package_path);
1334
			}
1335
		}
1336
1337
		// Load any custom config file
1338
		if (count($autoload['config']) > 0)
1339
		{
1340
			foreach ($autoload['config'] as $val)
1341
			{
1342
				$this->config($val);
1343
			}
1344
		}
1345
1346
		// Autoload helpers and languages
1347
		foreach (array('helper', 'language') as $type)
1348
		{
1349
			if (isset($autoload[$type]) && count($autoload[$type]) > 0)
1350
			{
1351
				$this->$type($autoload[$type]);
1352
			}
1353
		}
1354
1355
		// Autoload drivers
1356
		if (isset($autoload['drivers']))
1357
		{
1358
			$this->driver($autoload['drivers']);
1359
		}
1360
1361
		// Load libraries
1362
		if (isset($autoload['libraries']) && count($autoload['libraries']) > 0)
1363
		{
1364
			// Load the database driver.
1365
			if (in_array('database', $autoload['libraries']))
1366
			{
1367
				$this->database();
1368
				$autoload['libraries'] = array_diff($autoload['libraries'], array('database'));
1369
			}
1370
1371
			// Load all other libraries
1372
			$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...
1373
		}
1374
1375
		// Autoload models
1376
		if (isset($autoload['model']))
1377
		{
1378
			$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...
1379
		}
1380
	}
1381
1382
	// --------------------------------------------------------------------
1383
1384
	/**
1385
	 * CI Object to Array translator
1386
	 *
1387
	 * Takes an object as input and converts the class variables to
1388
	 * an associative array with key/value pairs.
1389
	 *
1390
	 * @param	object	$object	Object data to translate
1391
	 * @return	array
1392
	 */
1393
	protected function _ci_object_to_array($object)
1394
	{
1395
		return is_object($object) ? get_object_vars($object) : $object;
1396
	}
1397
1398
	// --------------------------------------------------------------------
1399
1400
	/**
1401
	 * CI Component getter
1402
	 *
1403
	 * Get a reference to a specific library or model.
1404
	 *
1405
	 * @param 	string	$component	Component name
1406
	 * @return	bool
1407
	 */
1408
	protected function &_ci_get_component($component)
1409
	{
1410
		$CI =& get_instance();
1411
		return $CI->$component;
1412
	}
1413
1414
	// --------------------------------------------------------------------
1415
1416
	/**
1417
	 * Prep filename
1418
	 *
1419
	 * This function prepares filenames of various items to
1420
	 * make their loading more reliable.
1421
	 *
1422
	 * @param	string|string[]	$filename	Filename(s)
1423
	 * @param 	string		$extension	Filename extension
1424
	 * @return	array
1425
	 */
1426
	protected function _ci_prep_filename($filename, $extension)
1427
	{
1428
		if ( ! is_array($filename))
1429
		{
1430
			return array(strtolower(str_replace(array($extension, '.php'), '', $filename).$extension));
1431
		}
1432
		else
1433
		{
1434
			foreach ($filename as $key => $val)
1435
			{
1436
				$filename[$key] = strtolower(str_replace(array($extension, '.php'), '', $val).$extension);
1437
			}
1438
1439
			return $filename;
1440
		}
1441
	}
1442
1443
}
1444