Issues (85)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

src/Inflector.php (9 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * @package    Fuel\Common
4
 * @version    2.0
5
 * @author     Fuel Development Team
6
 * @license    MIT License
7
 * @copyright  2010 - 2015 Fuel Development Team
8
 * @link       http://fuelphp.com
9
 */
10
11
namespace Fuel\Common;
12
13
/**
14
 * Some of this code was written by Flinn Mueller
15
 *
16
 * @package Fuel\Common
17
 *
18
 * @copyright Flinn Mueller
19
 */
20
class Inflector
21
{
22
	/**
23
	 * @var  array  List of uncountable words
24
	 */
25
	protected $uncountableWords = array(
26
		'equipment', 'information', 'rice', 'money',
27
		'species', 'series', 'fish', 'meta'
28
	);
29
30
	/**
31
	 * @var  array  Regex rules for pluralisation
32
	 */
33
	protected $pluralRules = array(
34
		'/^(ox)$/i'                 => '\1\2en',     // ox
35
		'/([m|l])ouse$/i'           => '\1ice',      // mouse, louse
36
		'/(matr|vert|ind)ix|ex$/i'  => '\1ices',     // matrix, vertex, index
37
		'/(x|ch|ss|sh)$/i'          => '\1es',       // search, switch, fix, box, process, address
38
		'/([^aeiouy]|qu)y$/i'       => '\1ies',      // query, ability, agency
39
		'/(hive)$/i'                => '\1s',        // archive, hive
40
		'/(?:([^f])fe|([lr])f)$/i'  => '\1\2ves',    // half, safe, wife
41
		'/sis$/i'                   => 'ses',        // basis, diagnosis
42
		'/([ti])um$/i'              => '\1a',        // datum, medium
43
		'/(p)erson$/i'              => '\1eople',    // person, salesperson
44
		'/(m)an$/i'                 => '\1en',       // man, woman, spokesman
45
		'/(c)hild$/i'               => '\1hildren',  // child
46
		'/(buffal|tomat)o$/i'       => '\1\2oes',    // buffalo, tomato
47
		'/(bu|campu)s$/i'           => '\1\2ses',    // bus, campus
48
		'/(alias|status|virus)$/i'  => '\1es',       // alias
49
		'/(octop)us$/i'             => '\1i',        // octopus
50
		'/(ax|cris|test)is$/i'      => '\1es',       // axis, crisis
51
		'/s$/'                     => 's',          // no change (compatibility)
52
		'/$/'                      => 's',
53
	);
54
55
	/**
56
	 * @var  array  Regex rules for singularisation
57
	 */
58
	protected $singularRules = array(
59
		'/(matr)ices$/i'         => '\1ix',
60
		'/(vert|ind)ices$/i'     => '\1ex',
61
		'/^(ox)en/i'             => '\1',
62
		'/(alias)es$/i'          => '\1',
63
		'/([octop|vir])i$/i'     => '\1us',
64
		'/(cris|ax|test)es$/i'   => '\1is',
65
		'/(shoe)s$/i'            => '\1',
66
		'/(o)es$/i'              => '\1',
67
		'/(bus|campus)es$/i'     => '\1',
68
		'/([m|l])ice$/i'         => '\1ouse',
69
		'/(x|ch|ss|sh)es$/i'     => '\1',
70
		'/(m)ovies$/i'           => '\1\2ovie',
71
		'/(s)eries$/i'           => '\1\2eries',
72
		'/([^aeiouy]|qu)ies$/i'  => '\1y',
73
		'/([lr])ves$/i'          => '\1f',
74
		'/(tive)s$/i'            => '\1',
75
		'/(hive)s$/i'            => '\1',
76
		'/([^f])ves$/i'          => '\1fe',
77
		'/(^analy)ses$/i'        => '\1sis',
78
		'/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i' => '\1\2sis',
79
		'/([ti])a$/i'            => '\1um',
80
		'/(p)eople$/i'           => '\1\2erson',
81
		'/(m)en$/i'              => '\1an',
82
		'/(s)tatuses$/i'         => '\1\2tatus',
83
		'/(c)hildren$/i'         => '\1\2hild',
84
		'/(n)ews$/i'             => '\1\2ews',
85
		'/([^us])s$/i'           => '\1',
86
	);
87
88
	/**
89
	 * @var  Fuel\Config\Config  Instance of a Fuel config container
90
	 */
91
	protected $config;
92
93
	/**
94
	 * @var  Fuel\Security\Manager  Instance of a Fuel security manager
95
	 */
96
	protected $security;
97
98
	/**
99
	 * @var  Fuel\Common\Str  Instance of a Fuel string helper
100
	 */
101
	protected $str;
102
103
	/**
104
	 * Class constructor
105
	 *
106
	 * @param  Fuel\Config\Config     $config    Instance of a Fuel config container
107
	 * @param  Fuel\Security\Manager  $security  Instance of a Fuel security manager
108
	 *
109
	 * @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...
110
	 *
111
	 * @since 2.0.0
112
	 */
113
	public function __construct($config = null, $security = null, $str = null)
114
	{
115
		$this->config = $config;
116
		$this->security = $security;
117
		$this->str = $str;
118
	}
119
120
	/**
121
	 * Add order suffix to numbers ex. 1st 2nd 3rd 4th 5th
122
	 *
123
	 * @param   int     the number to ordinalize
124
	 * @return  string  the ordinalized version of $number
125
	 * @link    http://snipplr.com/view/4627/a-function-to-add-a-prefix-to-numbers-ex-1st-2nd-3rd-4th-5th/
126
	 */
127
	public function ordinalize($number)
128
	{
129
		if ( ! is_numeric($number))
130
		{
131
			return $number;
132
		}
133
134
		if (in_array(($number % 100), range(11, 13)))
135
		{
136
			return $number . 'th';
137
		}
138
		else
139
		{
140
			switch ($number % 10)
141
			{
142
				case 1:
143
					return $number . 'st';
144
					break;
0 ignored issues
show
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
145
				case 2:
146
					return $number . 'nd';
147
					break;
0 ignored issues
show
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
148
				case 3:
149
					return $number . 'rd';
150
					break;
0 ignored issues
show
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
151
				default:
152
					return $number . 'th';
153
					break;
0 ignored issues
show
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
154
			}
155
		}
156
	}
157
158
	/**
159
	 * Gets the plural version of the given word
160
	 *
161
	 * @param   string  the word to pluralize
162
	 * @param   int     number of instances
163
	 * @return  string  the plural version of $word
164
	 */
165
	public function pluralize($word, $count = 0)
166
	{
167
		$result = strval($word);
168
169
		// If a counter is provided, and that equals 1
170
		// return as singular.
171
		if ($count === 1)
172
		{
173
			return $result;
174
		}
175
176
		if ( ! $this->isCountable($result))
177
		{
178
			return $result;
179
		}
180
181 View Code Duplication
		foreach ($this->pluralRules as $rule => $replacement)
0 ignored issues
show
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...
182
		{
183
			if (preg_match($rule, $result))
184
			{
185
				$result = preg_replace($rule, $replacement, $result);
186
				break;
187
			}
188
		}
189
190
		return $result;
191
	}
192
193
	/**
194
	 * Gets the singular version of the given word
195
	 *
196
	 * @param   string  the word to singularize
197
	 * @return  string  the singular version of $word
198
	 */
199
	public function singularize($word)
200
	{
201
		$result = strval($word);
202
203
		if ( ! $this->isCountable($result))
204
		{
205
			return $result;
206
		}
207
208 View Code Duplication
		foreach ($this->singularRules as $rule => $replacement)
0 ignored issues
show
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...
209
		{
210
			if (preg_match($rule, $result))
211
			{
212
				$result = preg_replace($rule, $replacement, $result);
213
				break;
214
			}
215
		}
216
217
		return $result;
218
	}
219
220
	/**
221
	 * Takes a string that has words seperated by underscores and turns it into
222
	 * a CamelCased string.
223
	 *
224
	 * @param   string  the underscored word
225
	 * @return  string  the CamelCased version of $underscored_word
226
	 */
227
	public function camelize($underscored_word)
228
	{
229
		return preg_replace_callback(
230
			'/(^|_)(.)/',
231
			function ($parm)
232
			{
233
				return strtoupper($parm[2]);
234
			},
235
			strval($underscored_word)
236
		);
237
	}
238
239
	/**
240
	 * Takes a CamelCased string and returns an underscore separated version.
241
	 *
242
	 * @param   string  the CamelCased word
243
	 * @return  string  an underscore separated version of $camel_cased_word
244
	 */
245
	public function underscore($camel_cased_word)
246
	{
247
		return $this->str->lower(preg_replace('/([A-Z]+)([A-Z])/', '\1_\2', preg_replace('/([a-z\d])([A-Z])/', '\1_\2', strval($camel_cased_word))));
248
	}
249
250
	/**
251
	 * Translate string to 7-bit ASCII
252
	 * Only works with UTF-8.
253
	 *
254
	 * @param   string  $str              string to translate
255
	 * @param   bool    $allow_non_ascii  wether to remove non ascii
256
	 * @return  string                    translated string
257
	 */
258
	public function ascii($str, $allow_non_ascii = false)
259
	{
260
		// Translate unicode characters to their simpler counterparts
261
		$this->config->load('ascii', true);
262
		$foreign_characters = $this->config->get('ascii');
263
264
		$str = preg_replace(array_keys($foreign_characters), array_values($foreign_characters), $str);
265
266
		if ( ! $allow_non_ascii)
267
		{
268
			return preg_replace('/[^\x09\x0A\x0D\x20-\x7E]/', '', $str);
269
		}
270
271
		return $str;
272
	}
273
274
	/**
275
	 * Converts your text to a URL-friendly title so it can be used in the URL.
276
	 * Only works with UTF8 input and and only outputs 7 bit ASCII characters.
277
	 *
278
	 * @param   string  $str              the text
279
	 * @param   string  $sep              the separator (either - or _)
280
	 * @param   bool    $lowercase        wether to convert to lowercase
281
	 * @param   bool    $allow_non_ascii  wether to allow non ascii
282
	 * @return  string                    the new title
283
	 */
284
	public function friendlyTitle($str, $sep = '-', $lowercase = false, $allow_non_ascii = false)
285
	{
286
		// Allow underscore, otherwise default to dash
287
		$sep = $sep === '_' ? '_' : '-';
288
289
		// Remove tags
290
		$str = $this->security->stripTags($str);
291
292
		// Decode all entities to their simpler forms
293
		$str = html_entity_decode($str, ENT_QUOTES, 'UTF-8');
294
295
		// Replace apostrophes.
296
		$str = preg_replace("#[\’]#", '-', $str);
297
298
		// Remove all quotes.
299
		$str = preg_replace("#[\"\']#", '', $str);
300
301
		// Only allow 7bit characters
302
		$str = $this->ascii($str, $allow_non_ascii);
303
304
		if ($allow_non_ascii)
305
		{
306
			// Strip regular special chars.
307
			$str = preg_replace("#[\.;:'\"\]\}\[\{\+\)\(\*&\^\$\#@\!±`%~']#iu", '', $str);
308
		}
309
		else
310
		{
311
			// Strip unwanted characters
312
			$str = preg_replace("#[^a-z0-9]#i", $sep, $str);
313
		}
314
315
		$str = preg_replace("#[/_|+ -]+#u", $sep, $str);
316
		$str = trim($str, $sep);
317
318
		if ($lowercase === true)
319
		{
320
			$str = $this->str->lower($str);
321
		}
322
323
		return $str;
324
	}
325
326
	/**
327
	 * Turns an underscore or dash separated word and turns it into a human looking string.
328
	 *
329
	 * @param   string  the word
330
	 * @param   string  the separator (either _ or -)
331
	 * @param   bool    lowercare string and upper case first
332
	 * @return  string  the human version of given string
333
	 */
334
	public function humanize($str, $sep = '_', $lowercase = true)
335
	{
336
		// Allow dash, otherwise default to underscore
337
		$sep = $sep != '-' ? '_' : $sep;
338
339
		if ($lowercase === true)
340
		{
341
			$str = $this->str->ucfirst($str);
342
		}
343
344
		return str_replace($sep, " ", strval($str));
345
	}
346
347
	/**
348
	 * Takes the class name out of a modulized string.
349
	 *
350
	 * @param   string  the modulized class
351
	 * @return  string  the string without the class name
352
	 */
353
	public function demodulize($class_name_in_module)
354
	{
355
		return preg_replace('/^.*::/', '', strval($class_name_in_module));
356
	}
357
358
	/**
359
	 * Takes the namespace off the given class name.
360
	 *
361
	 * @param   string  the class name
362
	 * @return  string  the string without the namespace
363
	 */
364
	public function denamespace($class_name)
365
	{
366
		$class_name = trim($class_name, '\\');
367
		if ($last_separator = strrpos($class_name, '\\'))
368
		{
369
			$class_name = substr($class_name, $last_separator + 1);
370
		}
371
		return $class_name;
372
	}
373
374
	/**
375
	 * Returns the namespace of the given class name.
376
	 *
377
	 * @param   string  $class_name  the class name
378
	 * @return  string  the string without the namespace
379
	 */
380
	public function getNamespace($class_name)
381
	{
382
		$class_name = trim($class_name, '\\');
383
		if ($last_separator = strrpos($class_name, '\\'))
384
		{
385
			return substr($class_name, 0, $last_separator + 1);
386
		}
387
		return '';
388
	}
389
390
	/**
391
	 * Takes a class name and determines the table name.  The table name is a
392
	 * pluralized version of the class name.
393
	 *
394
	 * @param   string  the table name
395
	 * @return  string  the table name
396
	 */
397 View Code Duplication
	public function tableize($class_name)
0 ignored issues
show
This method seems to be duplicated in your project.

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

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

Loading history...
398
	{
399
		$class_name = $this->denamespace($class_name);
400
		if (strncasecmp($class_name, 'Model_', 6) === 0)
401
		{
402
			$class_name = substr($class_name, 6);
403
		}
404
		return $this->str->lower($this->pluralize($this->underscore($class_name)));
405
	}
406
407
	/**
408
	 * Takes an underscored classname and uppercases all letters after the underscores.
409
	 *
410
	 * @param   string  classname
411
	 * @param   string  separator
412
	 * @return  string
413
	 */
414
	public function wordsToUpper($class, $sep = '_')
415
	{
416
		return str_replace(' ', $sep, ucwords(str_replace($sep, ' ', $class)));
417
	}
418
419
	/**
420
	 * Takes a table name and creates the class name.
421
	 *
422
	 * @param   string  the table name
423
	 * @param   bool    whether to singularize the table name or not
424
	 * @return  string  the class name
425
	 */
426
	public function classify($name, $force_singular = true)
427
	{
428
		$class = ($force_singular) ? $this->singularize($name) : $name;
429
		return $this->wordsToUpper($class);
430
	}
431
432
	/**
433
	 * Gets the foreign key for a given class.
434
	 *
435
	 * @param   string  the class name
436
	 * @param   bool    $use_underscore	whether to use an underscore or not
437
	 * @return  string  the foreign key
438
	 */
439 View Code Duplication
	public function foreignKey($class_name, $use_underscore = true)
0 ignored issues
show
This method seems to be duplicated in your project.

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

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

Loading history...
440
	{
441
		$class_name = $this->denamespace($this->str->lower($class_name));
442
		if (strncasecmp($class_name, 'Model_', 6) === 0)
443
		{
444
			$class_name = substr($class_name, 6);
445
		}
446
		return $this->underscore($this->demodulize($class_name)).($use_underscore ? "_id" : "id");
447
	}
448
449
	/**
450
	 * Checks if the given word has a plural version.
451
	 *
452
	 * @param   string  the word to check
453
	 * @return  bool    if the word is countable
454
	 */
455
	public function isCountable($word)
456
	{
457
		return ! (\in_array($this->str->lower(\strval($word)), $this->uncountableWords));
458
	}
459
}
460
461