Completed
Push — master ( 6f129c...145541 )
by Kenji
04:28
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))
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
		if (is_array($library))
722
		{
723
			foreach ($library as $driver)
724
			{
725
				$this->driver($driver);
726
			}
727
728
			return $this;
729
		}
730
		elseif (empty($library))
731
		{
732
			return FALSE;
733
		}
734
735
		if ( ! class_exists('CI_Driver_Library', FALSE))
736
		{
737
			// We aren't instantiating an object here, just making the base class available
738
			require BASEPATH.'libraries/Driver.php';
739
		}
740
741
		// We can save the loader some time since Drivers will *always* be in a subfolder,
742
		// and typically identically named to the library
743
		if ( ! strpos($library, '/'))
744
		{
745
			$library = ucfirst($library).'/'.$library;
746
		}
747
748
		return $this->library($library, $params, $object_name);
749
	}
750
751
	// --------------------------------------------------------------------
752
753
	/**
754
	 * Add Package Path
755
	 *
756
	 * Prepends a parent path to the library, model, helper and config
757
	 * path arrays.
758
	 *
759
	 * @see	CI_Loader::$_ci_library_paths
760
	 * @see	CI_Loader::$_ci_model_paths
761
	 * @see CI_Loader::$_ci_helper_paths
762
	 * @see CI_Config::$_config_paths
763
	 *
764
	 * @param	string	$path		Path to add
765
	 * @param 	bool	$view_cascade	(default: TRUE)
766
	 * @return	object
767
	 */
768
	public function add_package_path($path, $view_cascade = TRUE)
769
	{
770
		$path = rtrim($path, '/').'/';
771
772
		array_unshift($this->_ci_library_paths, $path);
773
		array_unshift($this->_ci_model_paths, $path);
774
		array_unshift($this->_ci_helper_paths, $path);
775
776
		$this->_ci_view_paths = array($path.'views/' => $view_cascade) + $this->_ci_view_paths;
777
778
		// Add config file path
779
		$config =& $this->_ci_get_component('config');
780
		$config->_config_paths[] = $path;
781
782
		return $this;
783
	}
784
785
	// --------------------------------------------------------------------
786
787
	/**
788
	 * Get Package Paths
789
	 *
790
	 * Return a list of all package paths.
791
	 *
792
	 * @param	bool	$include_base	Whether to include BASEPATH (default: FALSE)
793
	 * @return	array
794
	 */
795
	public function get_package_paths($include_base = FALSE)
796
	{
797
		return ($include_base === TRUE) ? $this->_ci_library_paths : $this->_ci_model_paths;
798
	}
799
800
	// --------------------------------------------------------------------
801
802
	/**
803
	 * Remove Package Path
804
	 *
805
	 * Remove a path from the library, model, helper and/or config
806
	 * path arrays if it exists. If no path is provided, the most recently
807
	 * added path will be removed removed.
808
	 *
809
	 * @param	string	$path	Path to remove
810
	 * @return	object
811
	 */
812
	public function remove_package_path($path = '')
813
	{
814
		$config =& $this->_ci_get_component('config');
815
816
		if ($path === '')
817
		{
818
			array_shift($this->_ci_library_paths);
819
			array_shift($this->_ci_model_paths);
820
			array_shift($this->_ci_helper_paths);
821
			array_shift($this->_ci_view_paths);
822
			array_pop($config->_config_paths);
823
		}
824
		else
825
		{
826
			$path = rtrim($path, '/').'/';
827
			foreach (array('_ci_library_paths', '_ci_model_paths', '_ci_helper_paths') as $var)
828
			{
829
				if (($key = array_search($path, $this->{$var})) !== FALSE)
830
				{
831
					unset($this->{$var}[$key]);
832
				}
833
			}
834
835
			if (isset($this->_ci_view_paths[$path.'views/']))
836
			{
837
				unset($this->_ci_view_paths[$path.'views/']);
838
			}
839
840
			if (($key = array_search($path, $config->_config_paths)) !== FALSE)
841
			{
842
				unset($config->_config_paths[$key]);
843
			}
844
		}
845
846
		// make sure the application default paths are still in the array
847
		$this->_ci_library_paths = array_unique(array_merge($this->_ci_library_paths, array(APPPATH, BASEPATH)));
848
		$this->_ci_helper_paths = array_unique(array_merge($this->_ci_helper_paths, array(APPPATH, BASEPATH)));
849
		$this->_ci_model_paths = array_unique(array_merge($this->_ci_model_paths, array(APPPATH)));
850
		$this->_ci_view_paths = array_merge($this->_ci_view_paths, array(APPPATH.'views/' => TRUE));
851
		$config->_config_paths = array_unique(array_merge($config->_config_paths, array(APPPATH)));
852
853
		return $this;
854
	}
855
856
	// --------------------------------------------------------------------
857
858
	/**
859
	 * Internal CI Data Loader
860
	 *
861
	 * Used to load views and files.
862
	 *
863
	 * Variables are prefixed with _ci_ to avoid symbol collision with
864
	 * variables made available to view files.
865
	 *
866
	 * @used-by	CI_Loader::view()
867
	 * @used-by	CI_Loader::file()
868
	 * @param	array	$_ci_data	Data to load
869
	 * @return	object
870
	 */
871
	protected function _ci_load($_ci_data)
872
	{
873
		// Set the default data variables
874
		foreach (array('_ci_view', '_ci_vars', '_ci_path', '_ci_return') as $_ci_val)
875
		{
876
			$$_ci_val = isset($_ci_data[$_ci_val]) ? $_ci_data[$_ci_val] : FALSE;
877
		}
878
879
		$file_exists = FALSE;
880
881
		// Set the path to the requested file
882
		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...
883
		{
884
			$_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...
885
			$_ci_file = end($_ci_x);
886
		}
887
		else
888
		{
889
			$_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...
890
			$_ci_file = ($_ci_ext === '') ? $_ci_view.'.php' : $_ci_view;
891
892
			foreach ($this->_ci_view_paths as $_ci_view_file => $cascade)
893
			{
894
				if (file_exists($_ci_view_file.$_ci_file))
895
				{
896
					$_ci_path = $_ci_view_file.$_ci_file;
897
					$file_exists = TRUE;
898
					break;
899
				}
900
901
				if ( ! $cascade)
902
				{
903
					break;
904
				}
905
			}
906
		}
907
908
		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...
909
		{
910
			show_error('Unable to load the requested file: '.$_ci_file);
911
		}
912
913
		// This allows anything loaded using $this->load (views, files, etc.)
914
		// to become accessible from within the Controller and Model functions.
915
		$_ci_CI =& get_instance();
916
		foreach (get_object_vars($_ci_CI) as $_ci_key => $_ci_var)
917
		{
918
			if ( ! isset($this->$_ci_key))
919
			{
920
				$this->$_ci_key =& $_ci_CI->$_ci_key;
921
			}
922
		}
923
924
		/*
925
		 * Extract and cache variables
926
		 *
927
		 * You can either set variables using the dedicated $this->load->vars()
928
		 * function or via the second parameter of this function. We'll merge
929
		 * the two types and cache them so that views that are embedded within
930
		 * other views can have access to these variables.
931
		 */
932
		if (is_array($_ci_vars))
933
		{
934
			$this->_ci_cached_vars = array_merge($this->_ci_cached_vars, $_ci_vars);
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...
935
		}
936
		extract($this->_ci_cached_vars);
937
938
		/*
939
		 * Buffer the output
940
		 *
941
		 * We buffer the output for two reasons:
942
		 * 1. Speed. You get a significant speed boost.
943
		 * 2. So that the final rendered template can be post-processed by
944
		 *	the output class. Why do we need post processing? For one thing,
945
		 *	in order to show the elapsed page load time. Unless we can
946
		 *	intercept the content right before it's sent to the browser and
947
		 *	then stop the timer it won't be accurate.
948
		 */
949
		ob_start();
950
951
		// If the PHP installation does not support short tags we'll
952
		// do a little string replacement, changing the short tags
953
		// to standard PHP echo statements.
954
		if ( ! is_php('5.4') && ! ini_get('short_open_tag') && config_item('rewrite_short_tags') === TRUE)
955
		{
956
			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...
957
		}
958
		else
959
		{
960
			include($_ci_path); // include() vs include_once() allows for multiple views with the same name
961
		}
962
963
		log_message('info', 'File loaded: '.$_ci_path);
964
965
		// Return the file data if requested
966
		if ($_ci_return === TRUE)
967
		{
968
			$buffer = ob_get_contents();
969
			@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...
970
			return $buffer;
971
		}
972
973
		/*
974
		 * Flush the buffer... or buff the flusher?
975
		 *
976
		 * In order to permit views to be nested within
977
		 * other views, we need to flush the content back out whenever
978
		 * we are beyond the first level of output buffering so that
979
		 * it can be seen and included properly by the first included
980
		 * template and any subsequent ones. Oy!
981
		 */
982
		if (ob_get_level() > $this->_ci_ob_level + 1)
983
		{
984
			ob_end_flush();
985
		}
986
		else
987
		{
988
			$_ci_CI->output->append_output(ob_get_contents());
989
			@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...
990
		}
991
992
		return $this;
993
	}
994
995
	// --------------------------------------------------------------------
996
997
	/**
998
	 * Internal CI Library Loader
999
	 *
1000
	 * @used-by	CI_Loader::library()
1001
	 * @uses	CI_Loader::_ci_init_library()
1002
	 *
1003
	 * @param	string	$class		Class name to load
1004
	 * @param	mixed	$params		Optional parameters to pass to the class constructor
1005
	 * @param	string	$object_name	Optional object name to assign to
1006
	 * @return	void
1007
	 * 
1008
	 * modified by ci-phpunit-test
1009
	 */
1010
	protected function _ci_load_library($class, $params = NULL, $object_name = NULL)
1011
	{
1012
		// Get the class name, and while we're at it trim any slashes.
1013
		// The directory path can be included as part of the class name,
1014
		// but we don't want a leading slash
1015
		$class = str_replace('.php', '', trim($class, '/'));
1016
1017
		// Was the path included with the class name?
1018
		// We look for a slash to determine this
1019 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...
1020
		{
1021
			// Extract the path
1022
			$subdir = substr($class, 0, ++$last_slash);
1023
1024
			// Get the filename from the path
1025
			$class = substr($class, $last_slash);
1026
		}
1027
		else
1028
		{
1029
			$subdir = '';
1030
		}
1031
1032
		$class = ucfirst($class);
1033
1034
		// Is this a stock library? There are a few special conditions if so ...
1035
		if (file_exists(BASEPATH.'libraries/'.$subdir.$class.'.php'))
1036
		{
1037
			return $this->_ci_load_stock_library($class, $subdir, $params, $object_name);
1038
		}
1039
1040
		// Let's search for the requested library file and load it.
1041
		foreach ($this->_ci_library_paths as $path)
1042
		{
1043
			// BASEPATH has already been checked for
1044
			if ($path === BASEPATH)
1045
			{
1046
				continue;
1047
			}
1048
1049
			$filepath = $path.'libraries/'.$subdir.$class.'.php';
1050
1051
			// Safety: Was the class already loaded by a previous call?
1052 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...
1053
			{
1054
				// Before we deem this to be a duplicate request, let's see
1055
				// if a custom object name is being supplied. If so, we'll
1056
				// return a new instance of the object
1057
				if ($object_name !== NULL)
1058
				{
1059
					$CI =& get_instance();
1060
					if ( ! isset($CI->$object_name))
1061
					{
1062
						return $this->_ci_init_library($class, '', $params, $object_name);
1063
					}
1064
				}
1065
1066
//				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...
1067
//				return;
1068
			}
1069
			// Does the file exist? No? Bummer...
1070
			if ( ! file_exists($filepath))
1071
			{
1072
				continue;
1073
			}
1074
1075
			include_once($filepath);
1076
			return $this->_ci_init_library($class, '', $params, $object_name);
1077
		}
1078
1079
		// One last attempt. Maybe the library is in a subdirectory, but it wasn't specified?
1080
		if ($subdir === '')
1081
		{
1082
			return $this->_ci_load_library($class.'/'.$class, $params, $object_name);
1083
		}
1084
1085
		// If we got this far we were unable to find the requested class.
1086
		log_message('error', 'Unable to load the requested class: '.$class);
1087
		show_error('Unable to load the requested class: '.$class);
1088
	}
1089
1090
	// --------------------------------------------------------------------
1091
1092
	/**
1093
	 * Internal CI Stock Library Loader
1094
	 *
1095
	 * @used-by	CI_Loader::_ci_load_library()
1096
	 * @uses	CI_Loader::_ci_init_library()
1097
	 *
1098
	 * @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...
1099
	 * @param	string	$file_path	Path to the library filename, relative to libraries/
1100
	 * @param	mixed	$params		Optional parameters to pass to the class constructor
1101
	 * @param	string	$object_name	Optional object name to assign to
1102
	 * @return	void
1103
	 * 
1104
	 * modified by ci-phpunit-test
1105
	 */
1106
	protected function _ci_load_stock_library($library_name, $file_path, $params, $object_name)
1107
	{
1108
		$prefix = 'CI_';
1109
1110
//		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...
1111
		{
1112
			if (class_exists(config_item('subclass_prefix').$library_name, FALSE))
1113
			{
1114
				$prefix = config_item('subclass_prefix');
1115
			}
1116
1117
			// Before we deem this to be a duplicate request, let's see
1118
			// if a custom object name is being supplied. If so, we'll
1119
			// return a new instance of the object
1120 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...
1121
			{
1122
				$CI =& get_instance();
1123
				if ( ! isset($CI->$object_name))
1124
				{
1125
					return $this->_ci_init_library($library_name, $prefix, $params, $object_name);
1126
				}
1127
			}
1128
1129
//			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...
1130
//			return;
1131
		}
1132
1133
		$paths = $this->_ci_library_paths;
1134
		array_pop($paths); // BASEPATH
1135
		array_pop($paths); // APPPATH (needs to be the first path checked)
1136
		array_unshift($paths, APPPATH);
1137
1138
		foreach ($paths as $path)
1139
		{
1140
			if (file_exists($path = $path.'libraries/'.$file_path.$library_name.'.php'))
1141
			{
1142
				// Override
1143
				include_once($path);
1144
//				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...
1145
				{
1146
					return $this->_ci_init_library($library_name, $prefix, $params, $object_name);
1147
				}
1148
//				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...
1149
//				{
1150
//					log_message('debug', $path.' exists, but does not declare '.$prefix.$library_name);
1151
//				}
1152
			}
1153
		}
1154
1155
		include_once(BASEPATH.'libraries/'.$file_path.$library_name.'.php');
1156
1157
		// Check for extensions
1158
		$subclass = config_item('subclass_prefix').$library_name;
1159
		foreach ($paths as $path)
1160
		{
1161
			if (file_exists($path = $path.'libraries/'.$file_path.$subclass.'.php'))
1162
			{
1163
				include_once($path);
1164
				if (class_exists($subclass, FALSE))
1165
				{
1166
					$prefix = config_item('subclass_prefix');
1167
					break;
1168
				}
1169
				else
1170
				{
1171
					log_message('debug', $path.' exists, but does not declare '.$subclass);
1172
				}
1173
			}
1174
		}
1175
1176
		return $this->_ci_init_library($library_name, $prefix, $params, $object_name);
1177
	}
1178
1179
	// --------------------------------------------------------------------
1180
1181
	/**
1182
	 * Internal CI Library Instantiator
1183
	 *
1184
	 * @used-by	CI_Loader::_ci_load_stock_library()
1185
	 * @used-by	CI_Loader::_ci_load_library()
1186
	 *
1187
	 * @param	string		$class		Class name
1188
	 * @param	string		$prefix		Class name prefix
1189
	 * @param	array|null|bool	$config		Optional configuration to pass to the class constructor:
1190
	 *						FALSE to skip;
1191
	 *						NULL to search in config paths;
1192
	 *						array containing configuration data
1193
	 * @param	string		$object_name	Optional object name to assign to
1194
	 * @return	void
1195
	 */
1196
	protected function _ci_init_library($class, $prefix, $config = FALSE, $object_name = NULL)
1197
	{
1198
		// Is there an associated config file for this class? Note: these should always be lowercase
1199
		if ($config === NULL)
1200
		{
1201
			// Fetch the config paths containing any package paths
1202
			$config_component = $this->_ci_get_component('config');
1203
1204
			if (is_array($config_component->_config_paths))
1205
			{
1206
				$found = FALSE;
1207
				foreach ($config_component->_config_paths as $path)
1208
				{
1209
					// We test for both uppercase and lowercase, for servers that
1210
					// are case-sensitive with regard to file names. Load global first,
1211
					// override with environment next
1212
					if (file_exists($path.'config/'.strtolower($class).'.php'))
1213
					{
1214
						include($path.'config/'.strtolower($class).'.php');
1215
						$found = TRUE;
1216
					}
1217
					elseif (file_exists($path.'config/'.ucfirst(strtolower($class)).'.php'))
1218
					{
1219
						include($path.'config/'.ucfirst(strtolower($class)).'.php');
1220
						$found = TRUE;
1221
					}
1222
1223
					if (file_exists($path.'config/'.ENVIRONMENT.'/'.strtolower($class).'.php'))
1224
					{
1225
						include($path.'config/'.ENVIRONMENT.'/'.strtolower($class).'.php');
1226
						$found = TRUE;
1227
					}
1228
					elseif (file_exists($path.'config/'.ENVIRONMENT.'/'.ucfirst(strtolower($class)).'.php'))
1229
					{
1230
						include($path.'config/'.ENVIRONMENT.'/'.ucfirst(strtolower($class)).'.php');
1231
						$found = TRUE;
1232
					}
1233
1234
					// Break on the first found configuration, thus package
1235
					// files are not overridden by default paths
1236
					if ($found === TRUE)
1237
					{
1238
						break;
1239
					}
1240
				}
1241
			}
1242
		}
1243
1244
		$class_name = $prefix.$class;
1245
1246
		// Is the class name valid?
1247
		if ( ! class_exists($class_name, FALSE))
1248
		{
1249
			log_message('error', 'Non-existent class: '.$class_name);
1250
			show_error('Non-existent class: '.$class_name);
1251
		}
1252
1253
		// Set the variable name we will assign the class to
1254
		// Was a custom class name supplied? If so we'll use it
1255
		if (empty($object_name))
1256
		{
1257
			$object_name = strtolower($class);
1258
			if (isset($this->_ci_varmap[$object_name]))
1259
			{
1260
				$object_name = $this->_ci_varmap[$object_name];
1261
			}
1262
		}
1263
1264
		// Don't overwrite existing properties
1265
		$CI =& get_instance();
1266
		if (isset($CI->$object_name))
1267
		{
1268
			if ($CI->$object_name instanceof $class_name)
1269
			{
1270
				log_message('debug', $class_name." has already been instantiated as '".$object_name."'. Second attempt aborted.");
1271
				return;
1272
			}
1273
1274
			show_error("Resource '".$object_name."' already exists and is not a ".$class_name." instance.");
1275
		}
1276
1277
		// Save the class name and object name
1278
		$this->_ci_classes[$object_name] = $class;
1279
1280
		// Instantiate the class
1281
		$CI->$object_name = isset($config)
1282
			? new $class_name($config)
1283
			: new $class_name();
1284
	}
1285
1286
	// --------------------------------------------------------------------
1287
1288
	/**
1289
	 * CI Autoloader
1290
	 *
1291
	 * Loads component listed in the config/autoload.php file.
1292
	 *
1293
	 * @used-by	CI_Loader::initialize()
1294
	 * @return	void
1295
	 */
1296
	protected function _ci_autoloader()
1297
	{
1298
		if (file_exists(APPPATH.'config/autoload.php'))
1299
		{
1300
			include(APPPATH.'config/autoload.php');
1301
		}
1302
1303 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...
1304
		{
1305
			include(APPPATH.'config/'.ENVIRONMENT.'/autoload.php');
1306
		}
1307
1308
		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...
1309
		{
1310
			return;
1311
		}
1312
1313
		// Autoload packages
1314
		if (isset($autoload['packages']))
1315
		{
1316
			foreach ($autoload['packages'] as $package_path)
1317
			{
1318
				$this->add_package_path($package_path);
1319
			}
1320
		}
1321
1322
		// Load any custom config file
1323
		if (count($autoload['config']) > 0)
1324
		{
1325
			foreach ($autoload['config'] as $val)
1326
			{
1327
				$this->config($val);
1328
			}
1329
		}
1330
1331
		// Autoload helpers and languages
1332
		foreach (array('helper', 'language') as $type)
1333
		{
1334
			if (isset($autoload[$type]) && count($autoload[$type]) > 0)
1335
			{
1336
				$this->$type($autoload[$type]);
1337
			}
1338
		}
1339
1340
		// Autoload drivers
1341
		if (isset($autoload['drivers']))
1342
		{
1343
			foreach ($autoload['drivers'] as $item)
1344
			{
1345
				$this->driver($item);
1346
			}
1347
		}
1348
1349
		// Load libraries
1350
		if (isset($autoload['libraries']) && count($autoload['libraries']) > 0)
1351
		{
1352
			// Load the database driver.
1353
			if (in_array('database', $autoload['libraries']))
1354
			{
1355
				$this->database();
1356
				$autoload['libraries'] = array_diff($autoload['libraries'], array('database'));
1357
			}
1358
1359
			// Load all other libraries
1360
			$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...
1361
		}
1362
1363
		// Autoload models
1364
		if (isset($autoload['model']))
1365
		{
1366
			$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...
1367
		}
1368
	}
1369
1370
	// --------------------------------------------------------------------
1371
1372
	/**
1373
	 * CI Object to Array translator
1374
	 *
1375
	 * Takes an object as input and converts the class variables to
1376
	 * an associative array with key/value pairs.
1377
	 *
1378
	 * @param	object	$object	Object data to translate
1379
	 * @return	array
1380
	 */
1381
	protected function _ci_object_to_array($object)
1382
	{
1383
		return is_object($object) ? get_object_vars($object) : $object;
1384
	}
1385
1386
	// --------------------------------------------------------------------
1387
1388
	/**
1389
	 * CI Component getter
1390
	 *
1391
	 * Get a reference to a specific library or model.
1392
	 *
1393
	 * @param 	string	$component	Component name
1394
	 * @return	bool
1395
	 */
1396
	protected function &_ci_get_component($component)
1397
	{
1398
		$CI =& get_instance();
1399
		return $CI->$component;
1400
	}
1401
1402
	// --------------------------------------------------------------------
1403
1404
	/**
1405
	 * Prep filename
1406
	 *
1407
	 * This function prepares filenames of various items to
1408
	 * make their loading more reliable.
1409
	 *
1410
	 * @param	string|string[]	$filename	Filename(s)
1411
	 * @param 	string		$extension	Filename extension
1412
	 * @return	array
1413
	 */
1414
	protected function _ci_prep_filename($filename, $extension)
1415
	{
1416
		if ( ! is_array($filename))
1417
		{
1418
			return array(strtolower(str_replace(array($extension, '.php'), '', $filename).$extension));
1419
		}
1420
		else
1421
		{
1422
			foreach ($filename as $key => $val)
1423
			{
1424
				$filename[$key] = strtolower(str_replace(array($extension, '.php'), '', $val).$extension);
1425
			}
1426
1427
			return $filename;
1428
		}
1429
	}
1430
1431
}
1432