Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
1 | <?php |
||
22 | class Inflector |
||
23 | { |
||
24 | /** |
||
25 | * Default inflector locale. |
||
26 | * |
||
27 | * Alias to {@link INFLECTOR_DEFAULT_LOCALE}. |
||
28 | */ |
||
29 | const DEFAULT_LOCALE = INFLECTOR_DEFAULT_LOCALE; |
||
30 | |||
31 | /** |
||
32 | * {@link camelize()} option to downcase the first letter. |
||
33 | */ |
||
34 | const DOWNCASE_FIRST_LETTER = true; |
||
35 | |||
36 | /** |
||
37 | * {@link camelize()} option to keep the first letter as is. |
||
38 | */ |
||
39 | const UPCASE_FIRST_LETTER = false; |
||
40 | |||
41 | /** |
||
42 | * @var Inflector[] |
||
43 | */ |
||
44 | static private $inflectors = array(); |
||
45 | |||
46 | /** |
||
47 | * Returns an inflector for the specified locale. |
||
48 | * |
||
49 | * Note: Inflectors are shared for the same locale. If you need to alter an inflector you |
||
50 | * MUST clone it first. |
||
51 | * |
||
52 | * @param string $locale |
||
53 | * |
||
54 | * @return \ICanBoogie\Inflector |
||
55 | */ |
||
56 | static public function get($locale = self::DEFAULT_LOCALE) |
||
65 | |||
66 | /** |
||
67 | * Inflections used by the inflector. |
||
68 | * |
||
69 | * @var Inflections |
||
70 | */ |
||
71 | protected $inflections; |
||
72 | |||
73 | /** |
||
74 | * Initializes the {@link $inflections} property. |
||
75 | * |
||
76 | * @param Inflections $inflections |
||
77 | */ |
||
78 | protected function __construct(Inflections $inflections = null) |
||
82 | |||
83 | /** |
||
84 | * Returns the {@link $inflections} property. |
||
85 | * |
||
86 | * @param string $property |
||
87 | * |
||
88 | * @throws PropertyNotDefined in attempt to read an inaccessible property. If the {@link PropertyNotDefined} |
||
89 | * class is not available a {@link \InvalidArgumentException} is thrown instead. |
||
90 | */ |
||
91 | public function __get($property) |
||
107 | |||
108 | /** |
||
109 | * Clone inflections. |
||
110 | */ |
||
111 | public function __clone() |
||
115 | |||
116 | /** |
||
117 | * Applies inflection rules for {@link singularize} and {@link pluralize}. |
||
118 | * |
||
119 | * <pre> |
||
120 | * $this->apply_inflections('post', $this->plurals); // "posts" |
||
121 | * $this->apply_inflections('posts', $this->singulars); // "post" |
||
122 | * </pre> |
||
123 | * |
||
124 | * @param string $word |
||
125 | * @param array $rules |
||
126 | * |
||
127 | * @return string |
||
128 | */ |
||
129 | private function apply_inflections($word, array $rules) |
||
155 | |||
156 | /** |
||
157 | * Returns the plural form of the word in the string. |
||
158 | * |
||
159 | * <pre> |
||
160 | * $this->pluralize('post'); // "posts" |
||
161 | * $this->pluralize('children'); // "child" |
||
162 | * $this->pluralize('sheep'); // "sheep" |
||
163 | * $this->pluralize('words'); // "words" |
||
164 | * $this->pluralize('CamelChild'); // "CamelChild" |
||
165 | * </pre> |
||
166 | * |
||
167 | * @param string $word |
||
168 | * |
||
169 | * @return string |
||
170 | */ |
||
171 | public function pluralize($word) |
||
175 | |||
176 | /** |
||
177 | * The reverse of {@link pluralize}, returns the singular form of a word in a string. |
||
178 | * |
||
179 | * <pre> |
||
180 | * $this->singularize('posts'); // "post" |
||
181 | * $this->singularize('childred'); // "child" |
||
182 | * $this->singularize('sheep'); // "sheep" |
||
183 | * $this->singularize('word'); // "word" |
||
184 | * $this->singularize('CamelChildren'); // "CamelChild" |
||
185 | * </pre> |
||
186 | * |
||
187 | * @param string $word |
||
188 | * |
||
189 | * @return string |
||
190 | */ |
||
191 | public function singularize($word) |
||
195 | |||
196 | /** |
||
197 | * By default, {@link camelize} converts strings to UpperCamelCase. |
||
198 | * |
||
199 | * {@link camelize} will also convert "/" to "\" which is useful for converting paths to |
||
200 | * namespaces. |
||
201 | * |
||
202 | * <pre> |
||
203 | * $this->camelize('active_model'); // 'ActiveModel' |
||
204 | * $this->camelize('active_model', true); // 'activeModel' |
||
205 | * $this->camelize('active_model/errors'); // 'ActiveModel\Errors' |
||
206 | * $this->camelize('active_model/errors', true); // 'activeModel\Errors' |
||
207 | * </pre> |
||
208 | * |
||
209 | * As a rule of thumb you can think of {@link camelize} as the inverse of {@link underscore}, |
||
210 | * though there are cases where that does not hold: |
||
211 | * |
||
212 | * <pre> |
||
213 | * $this->camelize($this->underscore('SSLError')); // "SslError" |
||
214 | * </pre> |
||
215 | * |
||
216 | * @param string $term |
||
217 | * @param bool $downcase_first_letter One of {@link UPCASE_FIRST_LETTER}, |
||
218 | * {@link DOWNCASE_FIRST_LETTER}. |
||
219 | * |
||
220 | * @return string |
||
221 | */ |
||
222 | public function camelize($term, $downcase_first_letter = self::UPCASE_FIRST_LETTER) |
||
258 | |||
259 | /** |
||
260 | * Makes an underscored, lowercase form from the expression in the string. |
||
261 | * |
||
262 | * Changes "\" to "/" to convert namespaces to paths. |
||
263 | * |
||
264 | * <pre> |
||
265 | * $this->underscore('ActiveModel'); // 'active_model' |
||
266 | * $this->underscore('ActiveModel\Errors'); // 'active_model/errors' |
||
267 | * </pre> |
||
268 | * |
||
269 | * As a rule of thumb you can think of {@link underscore} as the inverse of {@link camelize()}, |
||
270 | * though there are cases where that does not hold: |
||
271 | * |
||
272 | * <pre> |
||
273 | * $this->camelize($this->underscore('SSLError')); // "SslError" |
||
274 | * </pre> |
||
275 | * |
||
276 | * @param string $camel_cased_word |
||
277 | * |
||
278 | * @return string |
||
279 | */ |
||
280 | public function underscore($camel_cased_word) |
||
299 | |||
300 | /** |
||
301 | * Capitalizes the first word and turns underscores into spaces and strips a trailing "_id", |
||
302 | * if any. Like {@link titleize()}, this is meant for creating pretty output. |
||
303 | * |
||
304 | * <pre> |
||
305 | * $this->humanize('employee_salary'); // "Employee salary" |
||
306 | * $this->humanize('author_id'); // "Author" |
||
307 | * </pre> |
||
308 | * |
||
309 | * @param string $lower_case_and_underscored_word |
||
310 | * |
||
311 | * @return string |
||
312 | */ |
||
313 | public function humanize($lower_case_and_underscored_word) |
||
344 | |||
345 | /** |
||
346 | * Capitalizes all the words and replaces some characters in the string to create a nicer |
||
347 | * looking title. {@link titleize()} is meant for creating pretty output. It is not used in |
||
348 | * the Rails internals. |
||
349 | * |
||
350 | * <pre> |
||
351 | * $this->titleize('man from the boondocks'); // "Man From The Boondocks" |
||
352 | * $this->titleize('x-men: the last stand'); // "X Men: The Last Stand" |
||
353 | * $this->titleize('TheManWithoutAPast'); // "The Man Without A Past" |
||
354 | * $this->titleize('raiders_of_the_lost_ark'); // "Raiders Of The Lost Ark" |
||
355 | * </pre> |
||
356 | * |
||
357 | * @param string $str |
||
358 | * |
||
359 | * @return string |
||
360 | */ |
||
361 | public function titleize($str) |
||
374 | |||
375 | /** |
||
376 | * Replaces underscores with dashes in the string. |
||
377 | * |
||
378 | * <pre> |
||
379 | * $this->dasherize('puni_puni'); // "puni-puni" |
||
380 | * </pre> |
||
381 | * |
||
382 | * @param string $underscored_word |
||
383 | * |
||
384 | * @return string |
||
385 | */ |
||
386 | public function dasherize($underscored_word) |
||
390 | |||
391 | /** |
||
392 | * Makes an hyphenated, lowercase form from the expression in the string. |
||
393 | * |
||
394 | * This is a combination of {@link underscore} and {@link dasherize}. |
||
395 | * |
||
396 | * @param string $str |
||
397 | * |
||
398 | * @return string |
||
399 | */ |
||
400 | public function hyphenate($str) |
||
404 | |||
405 | /** |
||
406 | * Returns the suffix that should be added to a number to denote the position in an ordered |
||
407 | * sequence such as 1st, 2nd, 3rd, 4th. |
||
408 | * |
||
409 | * <pre> |
||
410 | * $this->ordinal(1); // "st" |
||
411 | * $this->ordinal(2); // "nd" |
||
412 | * $this->ordinal(1002); // "nd" |
||
413 | * $this->ordinal(1003); // "rd" |
||
414 | * $this->ordinal(-11); // "th" |
||
415 | * $this->ordinal(-1021); // "st" |
||
416 | * </pre> |
||
417 | * |
||
418 | * @param int $number |
||
419 | * |
||
420 | * @return string |
||
421 | */ |
||
422 | public function ordinal($number) |
||
439 | |||
440 | /** |
||
441 | * Turns a number into an ordinal string used to denote the position in an ordered sequence |
||
442 | * such as 1st, 2nd, 3rd, 4th. |
||
443 | * |
||
444 | * <pre> |
||
445 | * $this->ordinalize(1); // "1st" |
||
446 | * $this->ordinalize(2); // "2nd" |
||
447 | * $this->ordinalize(1002); // "1002nd" |
||
448 | * $this->ordinalize(1003); // "1003rd" |
||
449 | * $this->ordinalize(-11); // "-11th" |
||
450 | * $this->ordinalize(-1021); // "-1021st" |
||
451 | * </pre> |
||
452 | * |
||
453 | * @param int $number |
||
454 | * |
||
455 | * @return string |
||
456 | */ |
||
457 | public function ordinalize($number) |
||
461 | |||
462 | /** |
||
463 | * Multi-byte safe ucfirst |
||
464 | * |
||
465 | * @param $str |
||
466 | * @return string |
||
467 | */ |
||
468 | private static function ucfirst($str) |
||
472 | } |
||
473 |
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.