Completed
Push — develop ( c314ec...310a97 )
by Greg
13:42
created

Functions   F

Complexity

Total Complexity 770

Size/Duplication

Total Lines 2209
Duplicated Lines 38.3 %

Coupling/Cohesion

Components 1
Dependencies 11

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 770
c 1
b 0
f 0
lcom 1
cbo 11
dl 846
loc 2209
rs 3.9999

16 Methods

Rating   Name   Duplication   Size   Complexity  
A fetchLatestVersion() 0 19 4
A getCont() 0 16 4
A isFileExternal() 0 3 1
C getSubRecord() 0 30 7
A eventSort() 0 11 3
A eventSortName() 0 7 2
C sortFacts() 0 46 7
A getCloseRelationshipName() 9 9 2
A getAssociateRelationshipName() 9 9 2
D getRelationship() 70 124 24
B getRelationshipName() 0 29 2
C cousinName2() 45 49 18
C getQueryUrl() 0 29 8
D fileUploadErrorText() 0 27 9
D cousinName() 121 125 48
F getRelationshipNameFromPath() 592 1507 629

How to fix   Duplicated Code    Complexity   

Duplicated Code

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:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like Functions often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Functions, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * webtrees: online genealogy
4
 * Copyright (C) 2015 webtrees development team
5
 * This program is free software: you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation, either version 3 of the License, or
8
 * (at your option) any later version.
9
 * This program is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
 * GNU General Public License for more details.
13
 * You should have received a copy of the GNU General Public License
14
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15
 */
16
namespace Fisharebest\Webtrees\Functions;
17
18
use Fisharebest\Webtrees\Auth;
19
use Fisharebest\Webtrees\Database;
20
use Fisharebest\Webtrees\Fact;
21
use Fisharebest\Webtrees\File;
22
use Fisharebest\Webtrees\GedcomRecord;
23
use Fisharebest\Webtrees\I18N;
24
use Fisharebest\Webtrees\Individual;
25
use Fisharebest\Webtrees\Site;
26
27
/**
28
 * Class Functions - common functions
29
 */
30
class Functions {
31
	/**
32
	 * Check with the webtrees.net server for the latest version of webtrees.
33
	 * Fetching the remote file can be slow, so check infrequently, and cache the result.
34
	 * Pass the current versions of webtrees, PHP and MySQL, as the response
35
	 * may be different for each. The server logs are used to generate
36
	 * installation statistics which can be found at http://svn.webtrees.net/statistics.html
37
	 *
38
	 * @return null|string
39
	 */
40
	public static function fetchLatestVersion() {
41
		$last_update_timestamp = Site::getPreference('LATEST_WT_VERSION_TIMESTAMP');
42
		if ($last_update_timestamp < WT_TIMESTAMP - 24 * 60 * 60) {
43
			$row                = Database::prepare("SHOW VARIABLES LIKE 'version'")->fetchOneRow();
44
			$params             = '?w=' . WT_VERSION . '&p=' . PHP_VERSION . '&m=' . $row->value . '&o=' . (DIRECTORY_SEPARATOR === '/' ? 'u' : 'w');
45
			$latest_version_txt = File::fetchUrl('https://dev.webtrees.net/build/latest-version.txt' . $params);
46
			if ($latest_version_txt) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $latest_version_txt of type null|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
47
				Site::setPreference('LATEST_WT_VERSION', $latest_version_txt);
48
				Site::setPreference('LATEST_WT_VERSION_TIMESTAMP', WT_TIMESTAMP);
49
50
				return $latest_version_txt;
51
			} else {
52
				// Cannot connect to server - use cached version (if we have one)
53
				return Site::getPreference('LATEST_WT_VERSION');
54
			}
55
		} else {
56
			return Site::getPreference('LATEST_WT_VERSION');
57
		}
58
	}
59
60
	/**
61
	 * Convert a file upload PHP error code into user-friendly text.
62
	 *
63
	 * @param int $error_code
64
	 *
65
	 * @return string
66
	 */
67
	public static function fileUploadErrorText($error_code) {
68
		switch ($error_code) {
69
			case UPLOAD_ERR_OK:
70
				return I18N::translate('File successfully uploaded');
71
			case UPLOAD_ERR_INI_SIZE:
72
			case UPLOAD_ERR_FORM_SIZE:
73
				// I18N: PHP internal error message - php.net/manual/en/features.file-upload.errors.php
74
				return I18N::translate('The uploaded file exceeds the allowed size.');
75
			case UPLOAD_ERR_PARTIAL:
76
				// I18N: PHP internal error message - php.net/manual/en/features.file-upload.errors.php
77
				return I18N::translate('The file was only partially uploaded. Please try again.');
78
			case UPLOAD_ERR_NO_FILE:
79
				// I18N: PHP internal error message - php.net/manual/en/features.file-upload.errors.php
80
				return I18N::translate('No file was received. Please try again.');
81
			case UPLOAD_ERR_NO_TMP_DIR:
82
				// I18N: PHP internal error message - php.net/manual/en/features.file-upload.errors.php
83
				return I18N::translate('The PHP temporary folder is missing.');
84
			case UPLOAD_ERR_CANT_WRITE:
85
				// I18N: PHP internal error message - php.net/manual/en/features.file-upload.errors.php
86
				return I18N::translate('PHP failed to write to disk.');
87
			case UPLOAD_ERR_EXTENSION:
88
				// I18N: PHP internal error message - php.net/manual/en/features.file-upload.errors.php
89
				return I18N::translate('PHP blocked the file because of its extension.');
90
			default:
91
				return 'Error: ' . $error_code;
92
		}
93
	}
94
95
	/**
96
	 * get a gedcom subrecord
97
	 *
98
	 * searches a gedcom record and returns a subrecord of it. A subrecord is defined starting at a
99
	 * line with level N and all subsequent lines greater than N until the next N level is reached.
100
	 * For example, the following is a BIRT subrecord:
101
	 * <code>1 BIRT
102
	 * 2 DATE 1 JAN 1900
103
	 * 2 PLAC Phoenix, Maricopa, Arizona</code>
104
	 * The following example is the DATE subrecord of the above BIRT subrecord:
105
	 * <code>2 DATE 1 JAN 1900</code>
106
	 *
107
	 * @param int $level the N level of the subrecord to get
108
	 * @param string $tag a gedcom tag or string to search for in the record (ie 1 BIRT or 2 DATE)
109
	 * @param string $gedrec the parent gedcom record to search in
110
	 * @param int $num this allows you to specify which matching <var>$tag</var> to get. Oftentimes a
111
	 *                        gedcom record will have more that 1 of the same type of subrecord. An individual may have
112
	 *                        multiple events for example. Passing $num=1 would get the first 1. Passing $num=2 would get the
113
	 *                        second one, etc.
114
	 *
115
	 * @return string the subrecord that was found or an empty string "" if not found.
116
	 */
117
	public static function getSubRecord($level, $tag, $gedrec, $num = 1) {
118
		if (empty($gedrec)) {
119
			return '';
120
		}
121
		// -- adding \n before and after gedrec
122
		$gedrec       = "\n" . $gedrec . "\n";
123
		$tag          = trim($tag);
124
		$searchTarget = "~[\n]" . $tag . "[\s]~";
125
		$ct           = preg_match_all($searchTarget, $gedrec, $match, PREG_SET_ORDER | PREG_OFFSET_CAPTURE);
126
		if ($ct == 0) {
127
			return '';
128
		}
129
		if ($ct < $num) {
130
			return '';
131
		}
132
		$pos1 = $match[$num - 1][0][1];
133
		$pos2 = strpos($gedrec, "\n$level", $pos1 + 1);
0 ignored issues
show
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $level instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
134
		if (!$pos2) {
135
			$pos2 = strpos($gedrec, "\n1", $pos1 + 1);
136
		}
137
		if (!$pos2) {
138
			$pos2 = strpos($gedrec, "\nWT_", $pos1 + 1); // WT_SPOUSE, WT_FAMILY_ID ...
139
		}
140
		if (!$pos2) {
141
			return ltrim(substr($gedrec, $pos1));
142
		}
143
		$subrec = substr($gedrec, $pos1, $pos2 - $pos1);
144
145
		return ltrim($subrec);
146
	}
147
148
	/**
149
	 * get CONT lines
150
	 *
151
	 * get the N+1 CONT or CONC lines of a gedcom subrecord
152
	 *
153
	 * @param int $nlevel the level of the CONT lines to get
154
	 * @param string $nrec the gedcom subrecord to search in
155
	 *
156
	 * @return string a string with all CONT lines merged
157
	 */
158
	public static function getCont($nlevel, $nrec) {
159
		$text = '';
160
161
		$subrecords = explode("\n", $nrec);
162
		foreach ($subrecords as $thisSubrecord) {
163
			if (substr($thisSubrecord, 0, 2) !== $nlevel . ' ') {
164
				continue;
165
			}
166
			$subrecordType = substr($thisSubrecord, 2, 4);
167
			if ($subrecordType === 'CONT') {
168
				$text .= "\n" . substr($thisSubrecord, 7);
169
			}
170
		}
171
172
		return $text;
173
	}
174
175
	/**
176
	 * Sort a list events for the today/upcoming blocks
177
	 *
178
	 * @param array $a
179
	 * @param array $b
180
	 *
181
	 * @return int
0 ignored issues
show
Documentation introduced by
Should the return type not be integer|double?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
182
	 */
183
	public static function eventSort($a, $b) {
184
		if ($a['jd'] == $b['jd']) {
185
			if ($a['anniv'] == $b['anniv']) {
186
				return I18N::strcasecmp($a['fact'], $b['fact']);
187
			} else {
188
				return $a['anniv'] - $b['anniv'];
189
			}
190
		} else {
191
			return $a['jd'] - $b['jd'];
192
		}
193
	}
194
195
	/**
196
	 * Sort a list events for the today/upcoming blocks
197
	 *
198
	 * @param array $a
199
	 * @param array $b
200
	 *
201
	 * @return int
0 ignored issues
show
Documentation introduced by
Should the return type not be integer|double?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
202
	 */
203
	public static function eventSortName($a, $b) {
204
		if ($a['jd'] == $b['jd']) {
205
			return GedcomRecord::compare($a['record'], $b['record']);
206
		} else {
207
			return $a['jd'] - $b['jd'];
208
		}
209
	}
210
211
	/**
212
	 * A multi-key sort
213
	 * 1. First divide the facts into two arrays one set with dates and one set without dates
214
	 * 2. Sort each of the two new arrays, the date using the compare date function, the non-dated
215
	 * using the compare type function
216
	 * 3. Then merge the arrays back into the original array using the compare type function
217
	 *
218
	 * @param Fact[] $arr
219
	 */
220
	public static function sortFacts(&$arr) {
221
		$dated    = array();
222
		$nondated = array();
223
		//-- split the array into dated and non-dated arrays
224
		$order = 0;
225
		foreach ($arr as $event) {
226
			$event->sortOrder = $order;
227
			$order++;
228
			if ($event->getDate()->isOk()) {
229
				$dated[] = $event;
230
			} else {
231
				$nondated[] = $event;
232
			}
233
		}
234
235
		//-- sort each type of array
236
		usort($dated, '\Fisharebest\Webtrees\Fact::compareDate');
237
		usort($nondated, '\Fisharebest\Webtrees\Fact::compareType');
238
239
		//-- merge the arrays back together comparing by Facts
240
		$dc = count($dated);
241
		$nc = count($nondated);
242
		$i  = 0;
243
		$j  = 0;
244
		$k  = 0;
245
		// while there is anything in the dated array continue merging
246
		while ($i < $dc) {
247
			// compare each fact by type to merge them in order
248
			if ($j < $nc && Fact::compareType($dated[$i], $nondated[$j]) > 0) {
249
				$arr[$k] = $nondated[$j];
250
				$j++;
251
			} else {
252
				$arr[$k] = $dated[$i];
253
				$i++;
254
			}
255
			$k++;
256
		}
257
258
		// get anything that might be left in the nondated array
259
		while ($j < $nc) {
260
			$arr[$k] = $nondated[$j];
261
			$j++;
262
			$k++;
263
		}
264
265
	}
266
267
	/**
268
	 * For close family relationships, such as the families tab and the family navigator
269
	 * Display a tick if both individuals are the same.
270
	 *
271
	 * @param Individual $person1
272
	 * @param Individual $person2
273
	 *
274
	 * @return string
0 ignored issues
show
Documentation introduced by
Should the return type not be string|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
275
	 */
276 View Code Duplication
	public static function getCloseRelationshipName(Individual $person1, Individual $person2) {
0 ignored issues
show
Duplication introduced by
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...
277
		if ($person1 === $person2) {
278
			$label = '<i class="icon-selected" title="' . I18N::translate('self') . '"></i>';
279
		} else {
280
			$label = self::getRelationshipName(self::getRelationship($person1, $person2));
0 ignored issues
show
Documentation introduced by
self::getRelationship($person1, $person2) is of type false|array<string,array...ebtrees\\Individual>"}>, but the function expects a array<integer,array<integer,*>>.

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...
281
		}
282
283
		return $label;
284
	}
285
286
	/**
287
	 * For facts on the individual/family pages.
288
	 *
289
	 * @param Individual $person1
290
	 * @param Individual $person2
291
	 *
292
	 * @return string
0 ignored issues
show
Documentation introduced by
Should the return type not be string|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
293
	 */
294 View Code Duplication
	public static function getAssociateRelationshipName(Individual $person1, Individual $person2) {
0 ignored issues
show
Duplication introduced by
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...
295
		if ($person1 === $person2) {
296
			$label = I18N::translate('self');
297
		} else {
298
			$label = self::getRelationshipName(self::getRelationship($person1, $person2));
0 ignored issues
show
Documentation introduced by
self::getRelationship($person1, $person2) is of type false|array<string,array...ebtrees\\Individual>"}>, but the function expects a array<integer,array<integer,*>>.

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...
299
		}
300
301
		return $label;
302
	}
303
304
	/**
305
	 * Get relationship between two individuals in the gedcom
306
	 *
307
	 * @param Individual $person1 The person to compute the relationship from
308
	 * @param Individual $person2 The person to compute the relatiohip to
309
	 * @param int $maxlength The maximum length of path
310
	 *
311
	 * @return array|bool An array of nodes on the relationship path, or false if no path found
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use false|array<string,Indiv...er|Individual|string[]>.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
312
	 */
313
	public static function getRelationship(Individual $person1, Individual $person2, $maxlength = 4) {
314
		if ($person1 === $person2) {
315
			return false;
316
		}
317
318
		$spouse_codes  = array('M' => 'hus', 'F' => 'wif', 'U' => 'spo');
319
		$parent_codes  = array('M' => 'fat', 'F' => 'mot', 'U' => 'par');
320
		$child_codes   = array('M' => 'son', 'F' => 'dau', 'U' => 'chi');
321
		$sibling_codes = array('M' => 'bro', 'F' => 'sis', 'U' => 'sib');
322
323
		//-- current path nodes
324
		$p1nodes = array();
325
		//-- ids visited
326
		$visited = array();
327
328
		//-- set up first node for person1
329
		$node1 = array(
330
			'path'      => array($person1),
331
			'length'    => 0,
332
			'indi'      => $person1,
333
			'relations' => array('self'),
334
		);
335
		$p1nodes[] = $node1;
336
337
		$visited[$person1->getXref()] = true;
338
339
		$found = false;
340
		while (!$found) {
341
			//-- search the node list for the shortest path length
342
			$shortest = -1;
343
			foreach ($p1nodes as $index => $node) {
344
				if ($shortest == -1) {
345
					$shortest = $index;
346
				} else {
347
					$node1 = $p1nodes[$shortest];
348
					if ($node1['length'] > $node['length']) {
349
						$shortest = $index;
350
					}
351
				}
352
			}
353
			if ($shortest === -1) {
354
				return false;
355
			}
356
			$node = $p1nodes[$shortest];
357
			if ($maxlength == 0 || count($node['path']) <= $maxlength) {
358
				$indi = $node['indi'];
359
				//-- check all parents and siblings of this node
360 View Code Duplication
				foreach ($indi->getChildFamilies(Auth::PRIV_HIDE) as $family) {
361
					$visited[$family->getXref()] = true;
362
					foreach ($family->getSpouses(Auth::PRIV_HIDE) as $spouse) {
363
						if (!isset($visited[$spouse->getXref()])) {
364
							$node1 = $node;
365
							$node1['length']++;
366
							$node1['path'][]      = $spouse;
367
							$node1['indi']        = $spouse;
368
							$node1['relations'][] = $parent_codes[$spouse->getSex()];
369
							$p1nodes[]            = $node1;
370
							if ($spouse === $person2) {
371
								$found   = true;
372
								$resnode = $node1;
373
							} else {
374
								$visited[$spouse->getXref()] = true;
375
							}
376
						}
377
					}
378
					foreach ($family->getChildren(Auth::PRIV_HIDE) as $child) {
379
						if (!isset($visited[$child->getXref()])) {
380
							$node1 = $node;
381
							$node1['length']++;
382
							$node1['path'][]      = $child;
383
							$node1['indi']        = $child;
384
							$node1['relations'][] = $sibling_codes[$child->getSex()];
385
							$p1nodes[]            = $node1;
386
							if ($child === $person2) {
387
								$found   = true;
388
								$resnode = $node1;
389
							} else {
390
								$visited[$child->getXref()] = true;
391
							}
392
						}
393
					}
394
				}
395
				//-- check all spouses and children of this node
396 View Code Duplication
				foreach ($indi->getSpouseFamilies(Auth::PRIV_HIDE) as $family) {
397
					$visited[$family->getXref()] = true;
398
					foreach ($family->getSpouses(Auth::PRIV_HIDE) as $spouse) {
399
						if (!in_array($spouse->getXref(), $node1) || !isset($visited[$spouse->getXref()])) {
400
							$node1 = $node;
401
							$node1['length']++;
402
							$node1['path'][]      = $spouse;
403
							$node1['indi']        = $spouse;
404
							$node1['relations'][] = $spouse_codes[$spouse->getSex()];
405
							$p1nodes[]            = $node1;
406
							if ($spouse === $person2) {
407
								$found   = true;
408
								$resnode = $node1;
409
							} else {
410
								$visited[$spouse->getXref()] = true;
411
							}
412
						}
413
					}
414
					foreach ($family->getChildren(Auth::PRIV_HIDE) as $child) {
415
						if (!isset($visited[$child->getXref()])) {
416
							$node1 = $node;
417
							$node1['length']++;
418
							$node1['path'][]      = $child;
419
							$node1['indi']        = $child;
420
							$node1['relations'][] = $child_codes[$child->getSex()];
421
							$p1nodes[]            = $node1;
422
							if ($child === $person2) {
423
								$found   = true;
424
								$resnode = $node1;
425
							} else {
426
								$visited[$child->getXref()] = true;
427
							}
428
						}
429
					}
430
				}
431
			}
432
			unset($p1nodes[$shortest]);
433
		}
434
435
		return $resnode;
0 ignored issues
show
Bug introduced by
The variable $resnode 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...
436
	}
437
438
	/**
439
	 * Convert the result of get_relationship() into a relationship name.
440
	 *
441
	 * @param mixed[][] $nodes
442
	 *
443
	 * @return string
0 ignored issues
show
Documentation introduced by
Should the return type not be string|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
444
	 */
445
	public static function getRelationshipName($nodes) {
446
		if (!is_array($nodes)) {
447
			return '';
448
		}
449
		$person1 = $nodes['path'][0];
0 ignored issues
show
Unused Code introduced by
$person1 is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
450
		$person2 = $nodes['path'][count($nodes['path']) - 1];
0 ignored issues
show
Unused Code introduced by
$person2 is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
451
		$path    = array_slice($nodes['relations'], 1);
0 ignored issues
show
Unused Code introduced by
$path is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
452
		// Look for paths with *specific* names first.
453
		// Note that every combination must be listed separately, as the same English
454
		// name can be used for many different relationships. e.g.
455
		// brother’s wife & husband’s sister = sister-in-law.
456
		//
457
		// $path is an array of the 12 possible gedcom family relationships:
458
		// mother/father/parent
459
		// brother/sister/sibling
460
		// husband/wife/spouse
461
		// son/daughter/child
462
		//
463
		// This is always the shortest path, so “father, daughter” is “half-sister”, not “sister”.
464
		//
465
		// This is very repetitive in English, but necessary in order to handle the
466
		// complexities of other languages.
467
468
		return self::getRelationshipNameFromPath(
469
			implode('', array_slice($nodes['relations'], 1)),
470
			$nodes['path'][0],
471
			$nodes['path'][count($nodes['path']) - 1]
472
		);
473
	}
474
475
	/**
476
	 * Calculate the name of a cousin.
477
	 *
478
	 * @param int $n
479
	 * @param string $sex
480
	 *
481
	 * @return string
482
	 */
483
	public static function cousinName($n, $sex) {
484
		switch ($sex) {
485 View Code Duplication
			case 'M':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
486
				switch ($n) {
487
					case  1:
0 ignored issues
show
Coding Style introduced by
As per coding-style, case should be followed by a single space.

As per the PSR-2 coding standard, there must be a space after the case keyword, instead of the test immediately following it.

switch (true) {
    case!isset($a):  //wrong
        doSomething();
        break;
    case !isset($b):  //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
488
						/* I18N: Note that for Italian and Polish, “N’th cousins” are different from English “N’th cousins”, and the software has already generated the correct “N” for your language. You only need to translate - you do not need to convert. For other languages, if your cousin rules are different from English, please contact the developers. */
489
						return I18N::translateContext('MALE', 'first cousin');
490
					case  2:
0 ignored issues
show
Coding Style introduced by
As per coding-style, case should be followed by a single space.

As per the PSR-2 coding standard, there must be a space after the case keyword, instead of the test immediately following it.

switch (true) {
    case!isset($a):  //wrong
        doSomething();
        break;
    case !isset($b):  //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
491
						/* I18N: Note that for Italian and Polish, “N’th cousins” are different from English “N’th cousins”, and the software has already generated the correct “N” for your language. You only need to translate - you do not need to convert. For other languages, if your cousin rules are different from English, please contact the developers. */
492
						return I18N::translateContext('MALE', 'second cousin');
493
					case  3:
0 ignored issues
show
Coding Style introduced by
As per coding-style, case should be followed by a single space.

As per the PSR-2 coding standard, there must be a space after the case keyword, instead of the test immediately following it.

switch (true) {
    case!isset($a):  //wrong
        doSomething();
        break;
    case !isset($b):  //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
494
						/* I18N: Note that for Italian and Polish, “N’th cousins” are different from English “N’th cousins”, and the software has already generated the correct “N” for your language. You only need to translate - you do not need to convert. For other languages, if your cousin rules are different from English, please contact the developers. */
495
						return I18N::translateContext('MALE', 'third cousin');
496
					case  4:
0 ignored issues
show
Coding Style introduced by
As per coding-style, case should be followed by a single space.

As per the PSR-2 coding standard, there must be a space after the case keyword, instead of the test immediately following it.

switch (true) {
    case!isset($a):  //wrong
        doSomething();
        break;
    case !isset($b):  //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
497
						/* I18N: Note that for Italian and Polish, “N’th cousins” are different from English “N’th cousins”, and the software has already generated the correct “N” for your language. You only need to translate - you do not need to convert. For other languages, if your cousin rules are different from English, please contact the developers. */
498
						return I18N::translateContext('MALE', 'fourth cousin');
499
					case  5:
0 ignored issues
show
Coding Style introduced by
As per coding-style, case should be followed by a single space.

As per the PSR-2 coding standard, there must be a space after the case keyword, instead of the test immediately following it.

switch (true) {
    case!isset($a):  //wrong
        doSomething();
        break;
    case !isset($b):  //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
500
						/* I18N: Note that for Italian and Polish, “N’th cousins” are different from English “N’th cousins”, and the software has already generated the correct “N” for your language. You only need to translate - you do not need to convert. For other languages, if your cousin rules are different from English, please contact the developers. */
501
						return I18N::translateContext('MALE', 'fifth cousin');
502
					case  6:
0 ignored issues
show
Coding Style introduced by
As per coding-style, case should be followed by a single space.

As per the PSR-2 coding standard, there must be a space after the case keyword, instead of the test immediately following it.

switch (true) {
    case!isset($a):  //wrong
        doSomething();
        break;
    case !isset($b):  //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
503
						/* I18N: Note that for Italian and Polish, “N’th cousins” are different from English “N’th cousins”, and the software has already generated the correct “N” for your language. You only need to translate - you do not need to convert. For other languages, if your cousin rules are different from English, please contact the developers. */
504
						return I18N::translateContext('MALE', 'sixth cousin');
505
					case  7:
0 ignored issues
show
Coding Style introduced by
As per coding-style, case should be followed by a single space.

As per the PSR-2 coding standard, there must be a space after the case keyword, instead of the test immediately following it.

switch (true) {
    case!isset($a):  //wrong
        doSomething();
        break;
    case !isset($b):  //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
506
						/* I18N: Note that for Italian and Polish, “N’th cousins” are different from English “N’th cousins”, and the software has already generated the correct “N” for your language. You only need to translate - you do not need to convert. For other languages, if your cousin rules are different from English, please contact the developers. */
507
						return I18N::translateContext('MALE', 'seventh cousin');
508
					case  8:
0 ignored issues
show
Coding Style introduced by
As per coding-style, case should be followed by a single space.

As per the PSR-2 coding standard, there must be a space after the case keyword, instead of the test immediately following it.

switch (true) {
    case!isset($a):  //wrong
        doSomething();
        break;
    case !isset($b):  //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
509
						/* I18N: Note that for Italian and Polish, “N’th cousins” are different from English “N’th cousins”, and the software has already generated the correct “N” for your language. You only need to translate - you do not need to convert. For other languages, if your cousin rules are different from English, please contact the developers. */
510
						return I18N::translateContext('MALE', 'eighth cousin');
511
					case  9:
0 ignored issues
show
Coding Style introduced by
As per coding-style, case should be followed by a single space.

As per the PSR-2 coding standard, there must be a space after the case keyword, instead of the test immediately following it.

switch (true) {
    case!isset($a):  //wrong
        doSomething();
        break;
    case !isset($b):  //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
512
						/* I18N: Note that for Italian and Polish, “N’th cousins” are different from English “N’th cousins”, and the software has already generated the correct “N” for your language. You only need to translate - you do not need to convert. For other languages, if your cousin rules are different from English, please contact the developers. */
513
						return I18N::translateContext('MALE', 'ninth cousin');
514
					case 10:
515
						/* I18N: Note that for Italian and Polish, “N’th cousins” are different from English “N’th cousins”, and the software has already generated the correct “N” for your language. You only need to translate - you do not need to convert. For other languages, if your cousin rules are different from English, please contact the developers. */
516
						return I18N::translateContext('MALE', 'tenth cousin');
517
					case 11:
518
						/* I18N: Note that for Italian and Polish, “N’th cousins” are different from English “N’th cousins”, and the software has already generated the correct “N” for your language. You only need to translate - you do not need to convert. For other languages, if your cousin rules are different from English, please contact the developers. */
519
						return I18N::translateContext('MALE', 'eleventh cousin');
520
					case 12:
521
						/* I18N: Note that for Italian and Polish, “N’th cousins” are different from English “N’th cousins”, and the software has already generated the correct “N” for your language. You only need to translate - you do not need to convert. For other languages, if your cousin rules are different from English, please contact the developers. */
522
						return I18N::translateContext('MALE', 'twelfth cousin');
523
					case 13:
524
						/* I18N: Note that for Italian and Polish, “N’th cousins” are different from English “N’th cousins”, and the software has already generated the correct “N” for your language. You only need to translate - you do not need to convert. For other languages, if your cousin rules are different from English, please contact the developers. */
525
						return I18N::translateContext('MALE', 'thirteenth cousin');
526
					case 14:
527
						/* I18N: Note that for Italian and Polish, “N’th cousins” are different from English “N’th cousins”, and the software has already generated the correct “N” for your language. You only need to translate - you do not need to convert. For other languages, if your cousin rules are different from English, please contact the developers. */
528
						return I18N::translateContext('MALE', 'fourteenth cousin');
529
					case 15:
530
						/* I18N: Note that for Italian and Polish, “N’th cousins” are different from English “N’th cousins”, and the software has already generated the correct “N” for your language. You only need to translate - you do not need to convert. For other languages, if your cousin rules are different from English, please contact the developers. */
531
						return I18N::translateContext('MALE', 'fifteenth cousin');
532
					default:
533
						/* I18N: Note that for Italian and Polish, “N’th cousins” are different from English “N’th cousins”, and the software has already generated the correct “N” for your language. You only need to translate - you do not need to convert. For other languages, if your cousin rules are different from English, please contact the developers. */
534
						return I18N::translateContext('MALE', '%s × cousin', I18N::number($n));
535
				}
536 View Code Duplication
			case 'F':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
537
				switch ($n) {
538
					case  1:
0 ignored issues
show
Coding Style introduced by
As per coding-style, case should be followed by a single space.

As per the PSR-2 coding standard, there must be a space after the case keyword, instead of the test immediately following it.

switch (true) {
    case!isset($a):  //wrong
        doSomething();
        break;
    case !isset($b):  //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
539
						return I18N::translateContext('FEMALE', 'first cousin');
540
					case  2:
0 ignored issues
show
Coding Style introduced by
As per coding-style, case should be followed by a single space.

As per the PSR-2 coding standard, there must be a space after the case keyword, instead of the test immediately following it.

switch (true) {
    case!isset($a):  //wrong
        doSomething();
        break;
    case !isset($b):  //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
541
						return I18N::translateContext('FEMALE', 'second cousin');
542
					case  3:
0 ignored issues
show
Coding Style introduced by
As per coding-style, case should be followed by a single space.

As per the PSR-2 coding standard, there must be a space after the case keyword, instead of the test immediately following it.

switch (true) {
    case!isset($a):  //wrong
        doSomething();
        break;
    case !isset($b):  //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
543
						return I18N::translateContext('FEMALE', 'third cousin');
544
					case  4:
0 ignored issues
show
Coding Style introduced by
As per coding-style, case should be followed by a single space.

As per the PSR-2 coding standard, there must be a space after the case keyword, instead of the test immediately following it.

switch (true) {
    case!isset($a):  //wrong
        doSomething();
        break;
    case !isset($b):  //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
545
						return I18N::translateContext('FEMALE', 'fourth cousin');
546
					case  5:
0 ignored issues
show
Coding Style introduced by
As per coding-style, case should be followed by a single space.

As per the PSR-2 coding standard, there must be a space after the case keyword, instead of the test immediately following it.

switch (true) {
    case!isset($a):  //wrong
        doSomething();
        break;
    case !isset($b):  //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
547
						return I18N::translateContext('FEMALE', 'fifth cousin');
548
					case  6:
0 ignored issues
show
Coding Style introduced by
As per coding-style, case should be followed by a single space.

As per the PSR-2 coding standard, there must be a space after the case keyword, instead of the test immediately following it.

switch (true) {
    case!isset($a):  //wrong
        doSomething();
        break;
    case !isset($b):  //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
549
						return I18N::translateContext('FEMALE', 'sixth cousin');
550
					case  7:
0 ignored issues
show
Coding Style introduced by
As per coding-style, case should be followed by a single space.

As per the PSR-2 coding standard, there must be a space after the case keyword, instead of the test immediately following it.

switch (true) {
    case!isset($a):  //wrong
        doSomething();
        break;
    case !isset($b):  //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
551
						return I18N::translateContext('FEMALE', 'seventh cousin');
552
					case  8:
0 ignored issues
show
Coding Style introduced by
As per coding-style, case should be followed by a single space.

As per the PSR-2 coding standard, there must be a space after the case keyword, instead of the test immediately following it.

switch (true) {
    case!isset($a):  //wrong
        doSomething();
        break;
    case !isset($b):  //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
553
						return I18N::translateContext('FEMALE', 'eighth cousin');
554
					case  9:
0 ignored issues
show
Coding Style introduced by
As per coding-style, case should be followed by a single space.

As per the PSR-2 coding standard, there must be a space after the case keyword, instead of the test immediately following it.

switch (true) {
    case!isset($a):  //wrong
        doSomething();
        break;
    case !isset($b):  //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
555
						return I18N::translateContext('FEMALE', 'ninth cousin');
556
					case 10:
557
						return I18N::translateContext('FEMALE', 'tenth cousin');
558
					case 11:
559
						return I18N::translateContext('FEMALE', 'eleventh cousin');
560
					case 12:
561
						return I18N::translateContext('FEMALE', 'twelfth cousin');
562
					case 13:
563
						return I18N::translateContext('FEMALE', 'thirteenth cousin');
564
					case 14:
565
						return I18N::translateContext('FEMALE', 'fourteenth cousin');
566
					case 15:
567
						return I18N::translateContext('FEMALE', 'fifteenth cousin');
568
					default:
569
						return I18N::translateContext('FEMALE', '%s × cousin', I18N::number($n));
570
				}
571 View Code Duplication
			default:
572
				switch ($n) {
573
					case  1:
0 ignored issues
show
Coding Style introduced by
As per coding-style, case should be followed by a single space.

As per the PSR-2 coding standard, there must be a space after the case keyword, instead of the test immediately following it.

switch (true) {
    case!isset($a):  //wrong
        doSomething();
        break;
    case !isset($b):  //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
574
						return I18N::translateContext('MALE/FEMALE', 'first cousin');
575
					case  2:
0 ignored issues
show
Coding Style introduced by
As per coding-style, case should be followed by a single space.

As per the PSR-2 coding standard, there must be a space after the case keyword, instead of the test immediately following it.

switch (true) {
    case!isset($a):  //wrong
        doSomething();
        break;
    case !isset($b):  //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
576
						return I18N::translateContext('MALE/FEMALE', 'second cousin');
577
					case  3:
0 ignored issues
show
Coding Style introduced by
As per coding-style, case should be followed by a single space.

As per the PSR-2 coding standard, there must be a space after the case keyword, instead of the test immediately following it.

switch (true) {
    case!isset($a):  //wrong
        doSomething();
        break;
    case !isset($b):  //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
578
						return I18N::translateContext('MALE/FEMALE', 'third cousin');
579
					case  4:
0 ignored issues
show
Coding Style introduced by
As per coding-style, case should be followed by a single space.

As per the PSR-2 coding standard, there must be a space after the case keyword, instead of the test immediately following it.

switch (true) {
    case!isset($a):  //wrong
        doSomething();
        break;
    case !isset($b):  //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
580
						return I18N::translateContext('MALE/FEMALE', 'fourth cousin');
581
					case  5:
0 ignored issues
show
Coding Style introduced by
As per coding-style, case should be followed by a single space.

As per the PSR-2 coding standard, there must be a space after the case keyword, instead of the test immediately following it.

switch (true) {
    case!isset($a):  //wrong
        doSomething();
        break;
    case !isset($b):  //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
582
						return I18N::translateContext('MALE/FEMALE', 'fifth cousin');
583
					case  6:
0 ignored issues
show
Coding Style introduced by
As per coding-style, case should be followed by a single space.

As per the PSR-2 coding standard, there must be a space after the case keyword, instead of the test immediately following it.

switch (true) {
    case!isset($a):  //wrong
        doSomething();
        break;
    case !isset($b):  //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
584
						return I18N::translateContext('MALE/FEMALE', 'sixth cousin');
585
					case  7:
0 ignored issues
show
Coding Style introduced by
As per coding-style, case should be followed by a single space.

As per the PSR-2 coding standard, there must be a space after the case keyword, instead of the test immediately following it.

switch (true) {
    case!isset($a):  //wrong
        doSomething();
        break;
    case !isset($b):  //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
586
						return I18N::translateContext('MALE/FEMALE', 'seventh cousin');
587
					case  8:
0 ignored issues
show
Coding Style introduced by
As per coding-style, case should be followed by a single space.

As per the PSR-2 coding standard, there must be a space after the case keyword, instead of the test immediately following it.

switch (true) {
    case!isset($a):  //wrong
        doSomething();
        break;
    case !isset($b):  //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
588
						return I18N::translateContext('MALE/FEMALE', 'eighth cousin');
589
					case  9:
0 ignored issues
show
Coding Style introduced by
As per coding-style, case should be followed by a single space.

As per the PSR-2 coding standard, there must be a space after the case keyword, instead of the test immediately following it.

switch (true) {
    case!isset($a):  //wrong
        doSomething();
        break;
    case !isset($b):  //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
590
						return I18N::translateContext('MALE/FEMALE', 'ninth cousin');
591
					case 10:
592
						return I18N::translateContext('MALE/FEMALE', 'tenth cousin');
593
					case 11:
594
						return I18N::translateContext('MALE/FEMALE', 'eleventh cousin');
595
					case 12:
596
						return I18N::translateContext('MALE/FEMALE', 'twelfth cousin');
597
					case 13:
598
						return I18N::translateContext('MALE/FEMALE', 'thirteenth cousin');
599
					case 14:
600
						return I18N::translateContext('MALE/FEMALE', 'fourteenth cousin');
601
					case 15:
602
						return I18N::translateContext('MALE/FEMALE', 'fifteenth cousin');
603
					default:
604
						return I18N::translateContext('MALE/FEMALE', '%s × cousin', I18N::number($n));
605
				}
606
		}
607
	}
608
609
	/**
610
	 * A variation on cousin_name(), for constructs such as “sixth great-nephew”
611
	 * Currently used only by Spanish relationship names.
612
	 *
613
	 * @param int $n
614
	 * @param string $sex
615
	 * @param string $relation
616
	 *
617
	 * @return string
618
	 */
619
	public static function cousinName2($n, $sex, $relation) {
620
		switch ($sex) {
621 View Code Duplication
			case 'M':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
622
				switch ($n) {
623
					case  1: // I18N: A Spanish relationship name, such as third great-nephew
0 ignored issues
show
Coding Style introduced by
As per coding-style, case should be followed by a single space.

As per the PSR-2 coding standard, there must be a space after the case keyword, instead of the test immediately following it.

switch (true) {
    case!isset($a):  //wrong
        doSomething();
        break;
    case !isset($b):  //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
624
						return I18N::translateContext('MALE', 'first %s', $relation);
625
					case  2:
0 ignored issues
show
Coding Style introduced by
As per coding-style, case should be followed by a single space.

As per the PSR-2 coding standard, there must be a space after the case keyword, instead of the test immediately following it.

switch (true) {
    case!isset($a):  //wrong
        doSomething();
        break;
    case !isset($b):  //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
626
						return I18N::translateContext('MALE', 'second %s', $relation);
627
					case  3:
0 ignored issues
show
Coding Style introduced by
As per coding-style, case should be followed by a single space.

As per the PSR-2 coding standard, there must be a space after the case keyword, instead of the test immediately following it.

switch (true) {
    case!isset($a):  //wrong
        doSomething();
        break;
    case !isset($b):  //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
628
						return I18N::translateContext('MALE', 'third %s', $relation);
629
					case  4:
0 ignored issues
show
Coding Style introduced by
As per coding-style, case should be followed by a single space.

As per the PSR-2 coding standard, there must be a space after the case keyword, instead of the test immediately following it.

switch (true) {
    case!isset($a):  //wrong
        doSomething();
        break;
    case !isset($b):  //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
630
						return I18N::translateContext('MALE', 'fourth %s', $relation);
631
					case  5:
0 ignored issues
show
Coding Style introduced by
As per coding-style, case should be followed by a single space.

As per the PSR-2 coding standard, there must be a space after the case keyword, instead of the test immediately following it.

switch (true) {
    case!isset($a):  //wrong
        doSomething();
        break;
    case !isset($b):  //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
632
						return I18N::translateContext('MALE', 'fifth %s', $relation);
633
					default: // I18N: A Spanish relationship name, such as third great-nephew
634
						return I18N::translateContext('MALE', '%1$s × %2$s', I18N::number($n), $relation);
635
				}
636 View Code Duplication
			case 'F':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
637
				switch ($n) {
638
					case  1: // I18N: A Spanish relationship name, such as third great-nephew
0 ignored issues
show
Coding Style introduced by
As per coding-style, case should be followed by a single space.

As per the PSR-2 coding standard, there must be a space after the case keyword, instead of the test immediately following it.

switch (true) {
    case!isset($a):  //wrong
        doSomething();
        break;
    case !isset($b):  //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
639
						return I18N::translateContext('FEMALE', 'first %s', $relation);
640
					case  2:
0 ignored issues
show
Coding Style introduced by
As per coding-style, case should be followed by a single space.

As per the PSR-2 coding standard, there must be a space after the case keyword, instead of the test immediately following it.

switch (true) {
    case!isset($a):  //wrong
        doSomething();
        break;
    case !isset($b):  //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
641
						return I18N::translateContext('FEMALE', 'second %s', $relation);
642
					case  3:
0 ignored issues
show
Coding Style introduced by
As per coding-style, case should be followed by a single space.

As per the PSR-2 coding standard, there must be a space after the case keyword, instead of the test immediately following it.

switch (true) {
    case!isset($a):  //wrong
        doSomething();
        break;
    case !isset($b):  //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
643
						return I18N::translateContext('FEMALE', 'third %s', $relation);
644
					case  4:
0 ignored issues
show
Coding Style introduced by
As per coding-style, case should be followed by a single space.

As per the PSR-2 coding standard, there must be a space after the case keyword, instead of the test immediately following it.

switch (true) {
    case!isset($a):  //wrong
        doSomething();
        break;
    case !isset($b):  //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
645
						return I18N::translateContext('FEMALE', 'fourth %s', $relation);
646
					case  5:
0 ignored issues
show
Coding Style introduced by
As per coding-style, case should be followed by a single space.

As per the PSR-2 coding standard, there must be a space after the case keyword, instead of the test immediately following it.

switch (true) {
    case!isset($a):  //wrong
        doSomething();
        break;
    case !isset($b):  //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
647
						return I18N::translateContext('FEMALE', 'fifth %s', $relation);
648
					default: // I18N: A Spanish relationship name, such as third great-nephew
649
						return I18N::translateContext('FEMALE', '%1$s × %2$s', I18N::number($n), $relation);
650
				}
651 View Code Duplication
			default:
652
				switch ($n) {
653
					case  1: // I18N: A Spanish relationship name, such as third great-nephew
0 ignored issues
show
Coding Style introduced by
As per coding-style, case should be followed by a single space.

As per the PSR-2 coding standard, there must be a space after the case keyword, instead of the test immediately following it.

switch (true) {
    case!isset($a):  //wrong
        doSomething();
        break;
    case !isset($b):  //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
654
						return I18N::translateContext('MALE/FEMALE', 'first %s', $relation);
655
					case  2:
0 ignored issues
show
Coding Style introduced by
As per coding-style, case should be followed by a single space.

As per the PSR-2 coding standard, there must be a space after the case keyword, instead of the test immediately following it.

switch (true) {
    case!isset($a):  //wrong
        doSomething();
        break;
    case !isset($b):  //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
656
						return I18N::translateContext('MALE/FEMALE', 'second %s', $relation);
657
					case  3:
0 ignored issues
show
Coding Style introduced by
As per coding-style, case should be followed by a single space.

As per the PSR-2 coding standard, there must be a space after the case keyword, instead of the test immediately following it.

switch (true) {
    case!isset($a):  //wrong
        doSomething();
        break;
    case !isset($b):  //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
658
						return I18N::translateContext('MALE/FEMALE', 'third %s', $relation);
659
					case  4:
0 ignored issues
show
Coding Style introduced by
As per coding-style, case should be followed by a single space.

As per the PSR-2 coding standard, there must be a space after the case keyword, instead of the test immediately following it.

switch (true) {
    case!isset($a):  //wrong
        doSomething();
        break;
    case !isset($b):  //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
660
						return I18N::translateContext('MALE/FEMALE', 'fourth %s', $relation);
661
					case  5:
0 ignored issues
show
Coding Style introduced by
As per coding-style, case should be followed by a single space.

As per the PSR-2 coding standard, there must be a space after the case keyword, instead of the test immediately following it.

switch (true) {
    case!isset($a):  //wrong
        doSomething();
        break;
    case !isset($b):  //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
662
						return I18N::translateContext('MALE/FEMALE', 'fifth %s', $relation);
663
					default: // I18N: A Spanish relationship name, such as third great-nephew
664
						return I18N::translateContext('MALE/FEMALE', '%1$s × %2$s', I18N::number($n), $relation);
665
				}
666
		}
667
	}
668
669
	/** @var string[] Cache for generic relationships (key stores the path, and value represents the relationship name) */
670
	protected static $relationshipsCache = array();
671
672
	/**
673
	 * Convert a relationship path into a relationship name.
674
	 *
675
	 * @param string $path
676
	 * @param Individual $person1
0 ignored issues
show
Documentation introduced by
Should the type for parameter $person1 not be null|Individual?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
677
	 * @param Individual $person2
0 ignored issues
show
Documentation introduced by
Should the type for parameter $person2 not be null|Individual?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
678
	 *
679
	 * @return string
0 ignored issues
show
Documentation introduced by
Should the return type not be string|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
680
	 */
681
	public static function getRelationshipNameFromPath($path, Individual $person1 = null, Individual $person2 = null) {
682
		if (!preg_match('/^(mot|fat|par|hus|wif|spo|son|dau|chi|bro|sis|sib)*$/', $path)) {
683
			// TODO: Update all the “3 RELA ” values in class_person
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
684
			return '<span class="error">' . $path . '</span>';
685
		}
686
		// The path does not include the starting person. In some languages, the
687
		// translation for a man’s (relative) is different from a woman’s (relative),
688
		// due to inflection.
689
		$sex1 = $person1 ? $person1->getSex() : 'U';
690
691
		// The sex of the last person in the relationship determines the name in
692
		// many cases. e.g. great-aunt / great-uncle
693
		if (preg_match('/(fat|hus|son|bro)$/', $path)) {
694
			$sex2 = 'M';
695
		} elseif (preg_match('/(mot|wif|dau|sis)$/', $path)) {
696
			$sex2 = 'F';
697
		} else {
698
			$sex2 = 'U';
699
		}
700
701
		switch ($path) {
702
			case '':
703
				return I18N::translate('self');
704
			//  Level One relationships
705
			case 'mot':
706
				return I18N::translate('mother');
707
			case 'fat':
708
				return I18N::translate('father');
709
			case 'par':
710
				return I18N::translate('parent');
711 View Code Duplication
			case 'hus':
712
				if ($person1 && $person2) {
713
					foreach ($person1->getSpouseFamilies() as $family) {
714
						if ($person2 === $family->getSpouse($person1)) {
715
							if ($family->getFacts('_NMR')) {
716
								if ($family->getFacts(WT_EVENTS_DIV)) {
717
									return I18N::translateContext('MALE', 'ex-partner');
718
								} else {
719
									return I18N::translateContext('MALE', 'partner');
720
								}
721
							} elseif ($family->getFacts(WT_EVENTS_DIV)) {
722
								return I18N::translate('ex-husband');
723
							}
724
						}
725
					}
726
				}
727
728
				return I18N::translate('husband');
729 View Code Duplication
			case 'wif':
730
				if ($person1 && $person1) {
731
					foreach ($person1->getSpouseFamilies() as $family) {
732
						if ($person2 === $family->getSpouse($person1)) {
733
							if ($family->getFacts('_NMR')) {
734
								if ($family->getFacts(WT_EVENTS_DIV)) {
735
									return I18N::translateContext('FEMALE', 'ex-partner');
736
								} else {
737
									return I18N::translateContext('FEMALE', 'partner');
738
								}
739
							} elseif ($family->getFacts(WT_EVENTS_DIV)) {
740
								return I18N::translate('ex-wife');
741
							}
742
						}
743
					}
744
				}
745
746
				return I18N::translate('wife');
747 View Code Duplication
			case 'spo':
748
				if ($person1 && $person2) {
749
					foreach ($person1->getSpouseFamilies() as $family) {
750
						if ($person2 === $family->getSpouse($person1)) {
751
							if ($family->getFacts('_NMR')) {
752
								if ($family->getFacts(WT_EVENTS_DIV)) {
753
									return I18N::translateContext('MALE/FEMALE', 'ex-partner');
754
								} else {
755
									return I18N::translateContext('MALE/FEMALE', 'partner');
756
								}
757
							} elseif ($family->getFacts(WT_EVENTS_DIV)) {
758
								return I18N::translate('ex-spouse');
759
							}
760
						}
761
					}
762
				}
763
764
				return I18N::translate('spouse');
765
			case 'son':
766
				return I18N::translate('son');
767
			case 'dau':
768
				return I18N::translate('daughter');
769
			case 'chi':
770
				return I18N::translate('child');
771 View Code Duplication
			case 'bro':
772
				if ($person1 && $person2) {
773
					$dob1 = $person1->getBirthDate();
774
					$dob2 = $person2->getBirthDate();
775
					if ($dob1->isOK() && $dob2->isOK()) {
776
						if (abs($dob1->julianDay() - $dob2->julianDay()) < 2 && !$dob1->minimumDate()->d !== 0 && !$dob2->minimumDate()->d !== 0) {
777
							// Exclude BEF, AFT, etc.
778
							return I18N::translate('twin brother');
779
						} elseif ($dob1->maximumJulianDay() < $dob2->minimumJulianDay()) {
780
							return I18N::translate('younger brother');
781
						} elseif ($dob1->minimumJulianDay() > $dob2->maximumJulianDay()) {
782
							return I18N::translate('elder brother');
783
						}
784
					}
785
				}
786
787
				return I18N::translate('brother');
788 View Code Duplication
			case 'sis':
789
				if ($person1 && $person2) {
790
					$dob1 = $person1->getBirthDate();
791
					$dob2 = $person2->getBirthDate();
792
					if ($dob1->isOK() && $dob2->isOK()) {
793
						if (abs($dob1->julianDay() - $dob2->julianDay()) < 2 && !$dob1->minimumDate()->d !== 0 && !$dob2->minimumDate()->d !== 0) {
794
							// Exclude BEF, AFT, etc.
795
							return I18N::translate('twin sister');
796
						} elseif ($dob1->maximumJulianDay() < $dob2->minimumJulianDay()) {
797
							return I18N::translate('younger sister');
798
						} elseif ($dob1->minimumJulianDay() > $dob2->maximumJulianDay()) {
799
							return I18N::translate('elder sister');
800
						}
801
					}
802
				}
803
804
				return I18N::translate('sister');
805 View Code Duplication
			case 'sib':
806
				if ($person1 && $person2) {
807
					$dob1 = $person1->getBirthDate();
808
					$dob2 = $person2->getBirthDate();
809
					if ($dob1->isOK() && $dob2->isOK()) {
810
						if (abs($dob1->julianDay() - $dob2->julianDay()) < 2 && !$dob1->minimumDate()->d !== 0 && !$dob2->minimumDate()->d !== 0) {
811
							// Exclude BEF, AFT, etc.
812
							return I18N::translate('twin sibling');
813
						} elseif ($dob1->maximumJulianDay() < $dob2->minimumJulianDay()) {
814
							return I18N::translate('younger sibling');
815
						} elseif ($dob1->minimumJulianDay() > $dob2->maximumJulianDay()) {
816
							return I18N::translate('elder sibling');
817
						}
818
					}
819
				}
820
821
				return I18N::translate('sibling');
822
823
			// Level Two relationships
824
			case 'brochi':
825
				return I18N::translateContext('brother’s child', 'nephew/niece');
826
			case 'brodau':
827
				return I18N::translateContext('brother’s daughter', 'niece');
828
			case 'broson':
829
				return I18N::translateContext('brother’s son', 'nephew');
830
			case 'browif':
831
				return I18N::translateContext('brother’s wife', 'sister-in-law');
832
			case 'chichi':
833
				return I18N::translateContext('child’s child', 'grandchild');
834
			case 'chidau':
835
				return I18N::translateContext('child’s daughter', 'granddaughter');
836
			case 'chihus':
837
				return I18N::translateContext('child’s husband', 'son-in-law');
838
			case 'chison':
839
				return I18N::translateContext('child’s son', 'grandson');
840
			case 'chispo':
841
				return I18N::translateContext('child’s spouse', 'son/daughter-in-law');
842
			case 'chiwif':
843
				return I18N::translateContext('child’s wife', 'daughter-in-law');
844
			case 'dauchi':
845
				return I18N::translateContext('daughter’s child', 'grandchild');
846
			case 'daudau':
847
				return I18N::translateContext('daughter’s daughter', 'granddaughter');
848
			case 'dauhus':
849
				return I18N::translateContext('daughter’s husband', 'son-in-law');
850
			case 'dauson':
851
				return I18N::translateContext('daughter’s son', 'grandson');
852
			case 'fatbro':
853
				return I18N::translateContext('father’s brother', 'uncle');
854
			case 'fatchi':
855
				return I18N::translateContext('father’s child', 'half-sibling');
856
			case 'fatdau':
857
				return I18N::translateContext('father’s daughter', 'half-sister');
858
			case 'fatfat':
859
				return I18N::translateContext('father’s father', 'paternal grandfather');
860
			case 'fatmot':
861
				return I18N::translateContext('father’s mother', 'paternal grandmother');
862
			case 'fatpar':
863
				return I18N::translateContext('father’s parent', 'paternal grandparent');
864
			case 'fatsib':
865
				return I18N::translateContext('father’s sibling', 'aunt/uncle');
866
			case 'fatsis':
867
				return I18N::translateContext('father’s sister', 'aunt');
868
			case 'fatson':
869
				return I18N::translateContext('father’s son', 'half-brother');
870
			case 'fatwif':
871
				return I18N::translateContext('father’s wife', 'step-mother');
872
			case 'husbro':
873
				return I18N::translateContext('husband’s brother', 'brother-in-law');
874
			case 'huschi':
875
				return I18N::translateContext('husband’s child', 'step-child');
876
			case 'husdau':
877
				return I18N::translateContext('husband’s daughter', 'step-daughter');
878
			case 'husfat':
879
				return I18N::translateContext('husband’s father', 'father-in-law');
880
			case 'husmot':
881
				return I18N::translateContext('husband’s mother', 'mother-in-law');
882
			case 'hussib':
883
				return I18N::translateContext('husband’s sibling', 'brother/sister-in-law');
884
			case 'hussis':
885
				return I18N::translateContext('husband’s sister', 'sister-in-law');
886
			case 'husson':
887
				return I18N::translateContext('husband’s son', 'step-son');
888
			case 'motbro':
889
				return I18N::translateContext('mother’s brother', 'uncle');
890
			case 'motchi':
891
				return I18N::translateContext('mother’s child', 'half-sibling');
892
			case 'motdau':
893
				return I18N::translateContext('mother’s daughter', 'half-sister');
894
			case 'motfat':
895
				return I18N::translateContext('mother’s father', 'maternal grandfather');
896
			case 'mothus':
897
				return I18N::translateContext('mother’s husband', 'step-father');
898
			case 'motmot':
899
				return I18N::translateContext('mother’s mother', 'maternal grandmother');
900
			case 'motpar':
901
				return I18N::translateContext('mother’s parent', 'maternal grandparent');
902
			case 'motsib':
903
				return I18N::translateContext('mother’s sibling', 'aunt/uncle');
904
			case 'motsis':
905
				return I18N::translateContext('mother’s sister', 'aunt');
906
			case 'motson':
907
				return I18N::translateContext('mother’s son', 'half-brother');
908
			case 'parbro':
909
				return I18N::translateContext('parent’s brother', 'uncle');
910
			case 'parchi':
911
				return I18N::translateContext('parent’s child', 'half-sibling');
912
			case 'pardau':
913
				return I18N::translateContext('parent’s daughter', 'half-sister');
914
			case 'parfat':
915
				return I18N::translateContext('parent’s father', 'grandfather');
916
			case 'parmot':
917
				return I18N::translateContext('parent’s mother', 'grandmother');
918
			case 'parpar':
919
				return I18N::translateContext('parent’s parent', 'grandparent');
920
			case 'parsib':
921
				return I18N::translateContext('parent’s sibling', 'aunt/uncle');
922
			case 'parsis':
923
				return I18N::translateContext('parent’s sister', 'aunt');
924
			case 'parson':
925
				return I18N::translateContext('parent’s son', 'half-brother');
926
			case 'parspo':
927
				return I18N::translateContext('parent’s spouse', 'step-parent');
928
			case 'sibchi':
929
				return I18N::translateContext('sibling’s child', 'nephew/niece');
930
			case 'sibdau':
931
				return I18N::translateContext('sibling’s daughter', 'niece');
932
			case 'sibson':
933
				return I18N::translateContext('sibling’s son', 'nephew');
934
			case 'sibspo':
935
				return I18N::translateContext('sibling’s spouse', 'brother/sister-in-law');
936
			case 'sischi':
937
				return I18N::translateContext('sister’s child', 'nephew/niece');
938
			case 'sisdau':
939
				return I18N::translateContext('sister’s daughter', 'niece');
940
			case 'sishus':
941
				return I18N::translateContext('sister’s husband', 'brother-in-law');
942
			case 'sisson':
943
				return I18N::translateContext('sister’s son', 'nephew');
944
			case 'sonchi':
945
				return I18N::translateContext('son’s child', 'grandchild');
946
			case 'sondau':
947
				return I18N::translateContext('son’s daughter', 'granddaughter');
948
			case 'sonson':
949
				return I18N::translateContext('son’s son', 'grandson');
950
			case 'sonwif':
951
				return I18N::translateContext('son’s wife', 'daughter-in-law');
952
			case 'spobro':
953
				return I18N::translateContext('spouse’s brother', 'brother-in-law');
954
			case 'spochi':
955
				return I18N::translateContext('spouse’s child', 'step-child');
956
			case 'spodau':
957
				return I18N::translateContext('spouse’s daughter', 'step-daughter');
958
			case 'spofat':
959
				return I18N::translateContext('spouse’s father', 'father-in-law');
960
			case 'spomot':
961
				return I18N::translateContext('spouse’s mother', 'mother-in-law');
962
			case 'sposis':
963
				return I18N::translateContext('spouse’s sister', 'sister-in-law');
964
			case 'sposon':
965
				return I18N::translateContext('spouse’s son', 'step-son');
966
			case 'spopar':
967
				return I18N::translateContext('spouse’s parent', 'mother/father-in-law');
968
			case 'sposib':
969
				return I18N::translateContext('spouse’s sibling', 'brother/sister-in-law');
970
			case 'wifbro':
971
				return I18N::translateContext('wife’s brother', 'brother-in-law');
972
			case 'wifchi':
973
				return I18N::translateContext('wife’s child', 'step-child');
974
			case 'wifdau':
975
				return I18N::translateContext('wife’s daughter', 'step-daughter');
976
			case 'wiffat':
977
				return I18N::translateContext('wife’s father', 'father-in-law');
978
			case 'wifmot':
979
				return I18N::translateContext('wife’s mother', 'mother-in-law');
980
			case 'wifsib':
981
				return I18N::translateContext('wife’s sibling', 'brother/sister-in-law');
982
			case 'wifsis':
983
				return I18N::translateContext('wife’s sister', 'sister-in-law');
984
			case 'wifson':
985
				return I18N::translateContext('wife’s son', 'step-son');
986
987
			// Level Three relationships
988
			// I have commented out some of the unknown-sex relationships that are unlikely to to occur.
989
			// Feel free to add them in, if you think they might be needed
990
			case 'brochichi':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
991
				if ($sex1 === 'M') {
992
					return I18N::translateContext('(a man’s) brother’s child’s child', 'great-nephew/niece');
993
				} else {
994
					return I18N::translateContext('(a woman’s) brother’s child’s child', 'great-nephew/niece');
995
				}
996 View Code Duplication
			case 'brochidau':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
997
				if ($sex1 === 'M') {
998
					return I18N::translateContext('(a man’s) brother’s child’s daughter', 'great-niece');
999
				} else {
1000
					return I18N::translateContext('(a woman’s) brother’s child’s daughter', 'great-niece');
1001
				}
1002 View Code Duplication
			case 'brochison':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1003
				if ($sex1 === 'M') {
1004
					return I18N::translateContext('(a man’s) brother’s child’s son', 'great-nephew');
1005
				} else {
1006
					return I18N::translateContext('(a woman’s) brother’s child’s son', 'great-nephew');
1007
				}
1008
			case 'brodauchi':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1009
				if ($sex1 === 'M') {
1010
					return I18N::translateContext('(a man’s) brother’s daughter’s child', 'great-nephew/niece');
1011
				} else {
1012
					return I18N::translateContext('(a woman’s) brother’s daughter’s child', 'great-nephew/niece');
1013
				}
1014 View Code Duplication
			case 'brodaudau':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1015
				if ($sex1 === 'M') {
1016
					return I18N::translateContext('(a man’s) brother’s daughter’s daughter', 'great-niece');
1017
				} else {
1018
					return I18N::translateContext('(a woman’s) brother’s daughter’s daughter', 'great-niece');
1019
				}
1020
			case 'brodauhus':
1021
				return I18N::translateContext('brother’s daughter’s husband', 'nephew-in-law');
1022 View Code Duplication
			case 'brodauson':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1023
				if ($sex1 === 'M') {
1024
					return I18N::translateContext('(a man’s) brother’s daughter’s son', 'great-nephew');
1025
				} else {
1026
					return I18N::translateContext('(a woman’s) brother’s daughter’s son', 'great-nephew');
1027
				}
1028
			case 'brosonchi':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1029
				if ($sex1 === 'M') {
1030
					return I18N::translateContext('(a man’s) brother’s son’s child', 'great-nephew/niece');
1031
				} else {
1032
					return I18N::translateContext('(a woman’s) brother’s son’s child', 'great-nephew/niece');
1033
				}
1034 View Code Duplication
			case 'brosondau':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1035
				if ($sex1 === 'M') {
1036
					return I18N::translateContext('(a man’s) brother’s son’s daughter', 'great-niece');
1037
				} else {
1038
					return I18N::translateContext('(a woman’s) brother’s son’s daughter', 'great-niece');
1039
				}
1040 View Code Duplication
			case 'brosonson':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1041
				if ($sex1 === 'M') {
1042
					return I18N::translateContext('(a man’s) brother’s son’s son', 'great-nephew');
1043
				} else {
1044
					return I18N::translateContext('(a woman’s) brother’s son’s son', 'great-nephew');
1045
				}
1046
			case 'brosonwif':
1047
				return I18N::translateContext('brother’s son’s wife', 'niece-in-law');
1048
			case 'browifbro':
1049
				return I18N::translateContext('brother’s wife’s brother', 'brother-in-law');
1050
			case 'browifsib':
1051
				return I18N::translateContext('brother’s wife’s sibling', 'brother/sister-in-law');
1052
			case 'browifsis':
1053
				return I18N::translateContext('brother’s wife’s sister', 'sister-in-law');
1054
			case 'chichichi':
1055
				return I18N::translateContext('child’s child’s child', 'great-grandchild');
1056
			case 'chichidau':
1057
				return I18N::translateContext('child’s child’s daughter', 'great-granddaughter');
1058
			case 'chichison':
1059
				return I18N::translateContext('child’s child’s son', 'great-grandson');
1060
			case 'chidauchi':
1061
				return I18N::translateContext('child’s daughter’s child', 'great-grandchild');
1062
			case 'chidaudau':
1063
				return I18N::translateContext('child’s daughter’s daughter', 'great-granddaughter');
1064
			case 'chidauhus':
1065
				return I18N::translateContext('child’s daughter’s husband', 'granddaughter’s husband');
1066
			case 'chidauson':
1067
				return I18N::translateContext('child’s daughter’s son', 'great-grandson');
1068
			case 'chisonchi':
1069
				return I18N::translateContext('child’s son’s child', 'great-grandchild');
1070
			case 'chisondau':
1071
				return I18N::translateContext('child’s son’s daughter', 'great-granddaughter');
1072
			case 'chisonson':
1073
				return I18N::translateContext('child’s son’s son', 'great-grandson');
1074
			case 'chisonwif':
1075
				return I18N::translateContext('child’s son’s wife', 'grandson’s wife');
1076
			case 'dauchichi':
1077
				return I18N::translateContext('daughter’s child’s child', 'great-grandchild');
1078
			case 'dauchidau':
1079
				return I18N::translateContext('daughter’s child’s daughter', 'great-granddaughter');
1080
			case 'dauchison':
1081
				return I18N::translateContext('daughter’s child’s son', 'great-grandson');
1082
			case 'daudauchi':
1083
				return I18N::translateContext('daughter’s daughter’s child', 'great-grandchild');
1084
			case 'daudaudau':
1085
				return I18N::translateContext('daughter’s daughter’s daughter', 'great-granddaughter');
1086
			case 'daudauhus':
1087
				return I18N::translateContext('daughter’s daughter’s husband', 'granddaughter’s husband');
1088
			case 'daudauson':
1089
				return I18N::translateContext('daughter’s daughter’s son', 'great-grandson');
1090
			case 'dauhusfat':
1091
				return I18N::translateContext('daughter’s husband’s father', 'son-in-law’s father');
1092
			case 'dauhusmot':
1093
				return I18N::translateContext('daughter’s husband’s mother', 'son-in-law’s mother');
1094
			case 'dauhuspar':
1095
				return I18N::translateContext('daughter’s husband’s parent', 'son-in-law’s parent');
1096
			case 'dausonchi':
1097
				return I18N::translateContext('daughter’s son’s child', 'great-grandchild');
1098
			case 'dausondau':
1099
				return I18N::translateContext('daughter’s son’s daughter', 'great-granddaughter');
1100
			case 'dausonson':
1101
				return I18N::translateContext('daughter’s son’s son', 'great-grandson');
1102
			case 'dausonwif':
1103
				return I18N::translateContext('daughter’s son’s wife', 'grandson’s wife');
1104
			case 'fatbrochi':
1105
				return I18N::translateContext('father’s brother’s child', 'first cousin');
1106
			case 'fatbrodau':
1107
				return I18N::translateContext('father’s brother’s daughter', 'first cousin');
1108
			case 'fatbroson':
1109
				return I18N::translateContext('father’s brother’s son', 'first cousin');
1110
			case 'fatbrowif':
1111
				return I18N::translateContext('father’s brother’s wife', 'aunt');
1112
			case 'fatfatbro':
1113
				return I18N::translateContext('father’s father’s brother', 'great-uncle');
1114
			case 'fatfatfat':
1115
				return I18N::translateContext('father’s father’s father', 'great-grandfather');
1116
			case 'fatfatmot':
1117
				return I18N::translateContext('father’s father’s mother', 'great-grandmother');
1118
			case 'fatfatpar':
1119
				return I18N::translateContext('father’s father’s parent', 'great-grandparent');
1120
			case 'fatfatsib':
1121
				return I18N::translateContext('father’s father’s sibling', 'great-aunt/uncle');
1122
			case 'fatfatsis':
1123
				return I18N::translateContext('father’s father’s sister', 'great-aunt');
1124
			case 'fatmotbro':
1125
				return I18N::translateContext('father’s mother’s brother', 'great-uncle');
1126
			case 'fatmotfat':
1127
				return I18N::translateContext('father’s mother’s father', 'great-grandfather');
1128
			case 'fatmotmot':
1129
				return I18N::translateContext('father’s mother’s mother', 'great-grandmother');
1130
			case 'fatmotpar':
1131
				return I18N::translateContext('father’s mother’s parent', 'great-grandparent');
1132
			case 'fatmotsib':
1133
				return I18N::translateContext('father’s mother’s sibling', 'great-aunt/uncle');
1134
			case 'fatmotsis':
1135
				return I18N::translateContext('father’s mother’s sister', 'great-aunt');
1136
			case 'fatparbro':
1137
				return I18N::translateContext('father’s parent’s brother', 'great-uncle');
1138
			case 'fatparfat':
1139
				return I18N::translateContext('father’s parent’s father', 'great-grandfather');
1140
			case 'fatparmot':
1141
				return I18N::translateContext('father’s parent’s mother', 'great-grandmother');
1142
			case 'fatparpar':
1143
				return I18N::translateContext('father’s parent’s parent', 'great-grandparent');
1144
			case 'fatparsib':
1145
				return I18N::translateContext('father’s parent’s sibling', 'great-aunt/uncle');
1146
			case 'fatparsis':
1147
				return I18N::translateContext('father’s parent’s sister', 'great-aunt');
1148
			case 'fatsischi':
1149
				return I18N::translateContext('father’s sister’s child', 'first cousin');
1150
			case 'fatsisdau':
1151
				return I18N::translateContext('father’s sister’s daughter', 'first cousin');
1152
			case 'fatsishus':
1153
				return I18N::translateContext('father’s sister’s husband', 'uncle');
1154
			case 'fatsisson':
1155
				return I18N::translateContext('father’s sister’s son', 'first cousin');
1156
			case 'fatwifchi':
1157
				return I18N::translateContext('father’s wife’s child', 'step-sibling');
1158
			case 'fatwifdau':
1159
				return I18N::translateContext('father’s wife’s daughter', 'step-sister');
1160
			case 'fatwifson':
1161
				return I18N::translateContext('father’s wife’s son', 'step-brother');
1162
			case 'husbrowif':
1163
				return I18N::translateContext('husband’s brother’s wife', 'sister-in-law');
1164
			case 'hussishus':
1165
				return I18N::translateContext('husband’s sister’s husband', 'brother-in-law');
1166
			case 'motbrochi':
1167
				return I18N::translateContext('mother’s brother’s child', 'first cousin');
1168
			case 'motbrodau':
1169
				return I18N::translateContext('mother’s brother’s daughter', 'first cousin');
1170
			case 'motbroson':
1171
				return I18N::translateContext('mother’s brother’s son', 'first cousin');
1172
			case 'motbrowif':
1173
				return I18N::translateContext('mother’s brother’s wife', 'aunt');
1174
			case 'motfatbro':
1175
				return I18N::translateContext('mother’s father’s brother', 'great-uncle');
1176
			case 'motfatfat':
1177
				return I18N::translateContext('mother’s father’s father', 'great-grandfather');
1178
			case 'motfatmot':
1179
				return I18N::translateContext('mother’s father’s mother', 'great-grandmother');
1180
			case 'motfatpar':
1181
				return I18N::translateContext('mother’s father’s parent', 'great-grandparent');
1182
			case 'motfatsib':
1183
				return I18N::translateContext('mother’s father’s sibling', 'great-aunt/uncle');
1184
			case 'motfatsis':
1185
				return I18N::translateContext('mother’s father’s sister', 'great-aunt');
1186
			case 'mothuschi':
1187
				return I18N::translateContext('mother’s husband’s child', 'step-sibling');
1188
			case 'mothusdau':
1189
				return I18N::translateContext('mother’s husband’s daughter', 'step-sister');
1190
			case 'mothusson':
1191
				return I18N::translateContext('mother’s husband’s son', 'step-brother');
1192
			case 'motmotbro':
1193
				return I18N::translateContext('mother’s mother’s brother', 'great-uncle');
1194
			case 'motmotfat':
1195
				return I18N::translateContext('mother’s mother’s father', 'great-grandfather');
1196
			case 'motmotmot':
1197
				return I18N::translateContext('mother’s mother’s mother', 'great-grandmother');
1198
			case 'motmotpar':
1199
				return I18N::translateContext('mother’s mother’s parent', 'great-grandparent');
1200
			case 'motmotsib':
1201
				return I18N::translateContext('mother’s mother’s sibling', 'great-aunt/uncle');
1202
			case 'motmotsis':
1203
				return I18N::translateContext('mother’s mother’s sister', 'great-aunt');
1204
			case 'motparbro':
1205
				return I18N::translateContext('mother’s parent’s brother', 'great-uncle');
1206
			case 'motparfat':
1207
				return I18N::translateContext('mother’s parent’s father', 'great-grandfather');
1208
			case 'motparmot':
1209
				return I18N::translateContext('mother’s parent’s mother', 'great-grandmother');
1210
			case 'motparpar':
1211
				return I18N::translateContext('mother’s parent’s parent', 'great-grandparent');
1212
			case 'motparsib':
1213
				return I18N::translateContext('mother’s parent’s sibling', 'great-aunt/uncle');
1214
			case 'motparsis':
1215
				return I18N::translateContext('mother’s parent’s sister', 'great-aunt');
1216
			case 'motsischi':
1217
				return I18N::translateContext('mother’s sister’s child', 'first cousin');
1218
			case 'motsisdau':
1219
				return I18N::translateContext('mother’s sister’s daughter', 'first cousin');
1220
			case 'motsishus':
1221
				return I18N::translateContext('mother’s sister’s husband', 'uncle');
1222
			case 'motsisson':
1223
				return I18N::translateContext('mother’s sister’s son', 'first cousin');
1224
			case 'parbrowif':
1225
				return I18N::translateContext('parent’s brother’s wife', 'aunt');
1226
			case 'parfatbro':
1227
				return I18N::translateContext('parent’s father’s brother', 'great-uncle');
1228
			case 'parfatfat':
1229
				return I18N::translateContext('parent’s father’s father', 'great-grandfather');
1230
			case 'parfatmot':
1231
				return I18N::translateContext('parent’s father’s mother', 'great-grandmother');
1232
			case 'parfatpar':
1233
				return I18N::translateContext('parent’s father’s parent', 'great-grandparent');
1234
			case 'parfatsib':
1235
				return I18N::translateContext('parent’s father’s sibling', 'great-aunt/uncle');
1236
			case 'parfatsis':
1237
				return I18N::translateContext('parent’s father’s sister', 'great-aunt');
1238
			case 'parmotbro':
1239
				return I18N::translateContext('parent’s mother’s brother', 'great-uncle');
1240
			case 'parmotfat':
1241
				return I18N::translateContext('parent’s mother’s father', 'great-grandfather');
1242
			case 'parmotmot':
1243
				return I18N::translateContext('parent’s mother’s mother', 'great-grandmother');
1244
			case 'parmotpar':
1245
				return I18N::translateContext('parent’s mother’s parent', 'great-grandparent');
1246
			case 'parmotsib':
1247
				return I18N::translateContext('parent’s mother’s sibling', 'great-aunt/uncle');
1248
			case 'parmotsis':
1249
				return I18N::translateContext('parent’s mother’s sister', 'great-aunt');
1250
			case 'parparbro':
1251
				return I18N::translateContext('parent’s parent’s brother', 'great-uncle');
1252
			case 'parparfat':
1253
				return I18N::translateContext('parent’s parent’s father', 'great-grandfather');
1254
			case 'parparmot':
1255
				return I18N::translateContext('parent’s parent’s mother', 'great-grandmother');
1256
			case 'parparpar':
1257
				return I18N::translateContext('parent’s parent’s parent', 'great-grandparent');
1258
			case 'parparsib':
1259
				return I18N::translateContext('parent’s parent’s sibling', 'great-aunt/uncle');
1260
			case 'parparsis':
1261
				return I18N::translateContext('parent’s parent’s sister', 'great-aunt');
1262
			case 'parsishus':
1263
				return I18N::translateContext('parent’s sister’s husband', 'uncle');
1264
			case 'parspochi':
1265
				return I18N::translateContext('parent’s spouse’s child', 'step-sibling');
1266
			case 'parspodau':
1267
				return I18N::translateContext('parent’s spouse’s daughter', 'step-sister');
1268
			case 'parsposon':
1269
				return I18N::translateContext('parent’s spouse’s son', 'step-brother');
1270
			case 'sibchichi':
1271
				return I18N::translateContext('sibling’s child’s child', 'great-nephew/niece');
1272
			case 'sibchidau':
1273
				return I18N::translateContext('sibling’s child’s daughter', 'great-niece');
1274
			case 'sibchison':
1275
				return I18N::translateContext('sibling’s child’s son', 'great-nephew');
1276
			case 'sibdauchi':
1277
				return I18N::translateContext('sibling’s daughter’s child', 'great-nephew/niece');
1278
			case 'sibdaudau':
1279
				return I18N::translateContext('sibling’s daughter’s daughter', 'great-niece');
1280
			case 'sibdauhus':
1281
				return I18N::translateContext('sibling’s daughter’s husband', 'nephew-in-law');
1282
			case 'sibdauson':
1283
				return I18N::translateContext('sibling’s daughter’s son', 'great-nephew');
1284
			case 'sibsonchi':
1285
				return I18N::translateContext('sibling’s son’s child', 'great-nephew/niece');
1286
			case 'sibsondau':
1287
				return I18N::translateContext('sibling’s son’s daughter', 'great-niece');
1288
			case 'sibsonson':
1289
				return I18N::translateContext('sibling’s son’s son', 'great-nephew');
1290
			case 'sibsonwif':
1291
				return I18N::translateContext('sibling’s son’s wife', 'niece-in-law');
1292
			case 'sischichi':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1293
				if ($sex1 === 'M') {
1294
					return I18N::translateContext('(a man’s) sister’s child’s child', 'great-nephew/niece');
1295
				} else {
1296
					return I18N::translateContext('(a woman’s) sister’s child’s child', 'great-nephew/niece');
1297
				}
1298 View Code Duplication
			case 'sischidau':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1299
				if ($sex1 === 'M') {
1300
					return I18N::translateContext('(a man’s) sister’s child’s daughter', 'great-niece');
1301
				} else {
1302
					return I18N::translateContext('(a woman’s) sister’s child’s daughter', 'great-niece');
1303
				}
1304 View Code Duplication
			case 'sischison':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1305
				if ($sex1 === 'M') {
1306
					return I18N::translateContext('(a man’s) sister’s child’s son', 'great-nephew');
1307
				} else {
1308
					return I18N::translateContext('(a woman’s) sister’s child’s son', 'great-nephew');
1309
				}
1310
			case 'sisdauchi':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1311
				if ($sex1 === 'M') {
1312
					return I18N::translateContext('(a man’s) sister’s daughter’s child', 'great-nephew/niece');
1313
				} else {
1314
					return I18N::translateContext('(a woman’s) sister’s daughter’s child', 'great-nephew/niece');
1315
				}
1316 View Code Duplication
			case 'sisdaudau':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1317
				if ($sex1 === 'M') {
1318
					return I18N::translateContext('(a man’s) sister’s daughter’s daughter', 'great-niece');
1319
				} else {
1320
					return I18N::translateContext('(a woman’s) sister’s daughter’s daughter', 'great-niece');
1321
				}
1322
			case 'sisdauhus':
1323
				return I18N::translateContext('sisters’s daughter’s husband', 'nephew-in-law');
1324 View Code Duplication
			case 'sisdauson':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1325
				if ($sex1 === 'M') {
1326
					return I18N::translateContext('(a man’s) sister’s daughter’s son', 'great-nephew');
1327
				} else {
1328
					return I18N::translateContext('(a woman’s) sister’s daughter’s son', 'great-nephew');
1329
				}
1330
			case 'sishusbro':
1331
				return I18N::translateContext('sister’s husband’s brother', 'brother-in-law');
1332
			case 'sishussib':
1333
				return I18N::translateContext('sister’s husband’s sibling', 'brother/sister-in-law');
1334
			case 'sishussis':
1335
				return I18N::translateContext('sister’s husband’s sister', 'sister-in-law');
1336
			case 'sissonchi':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1337
				if ($sex1 === 'M') {
1338
					return I18N::translateContext('(a man’s) sister’s son’s child', 'great-nephew/niece');
1339
				} else {
1340
					return I18N::translateContext('(a woman’s) sister’s son’s child', 'great-nephew/niece');
1341
				}
1342 View Code Duplication
			case 'sissondau':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1343
				if ($sex1 === 'M') {
1344
					return I18N::translateContext('(a man’s) sister’s son’s daughter', 'great-niece');
1345
				} else {
1346
					return I18N::translateContext('(a woman’s) sister’s son’s daughter', 'great-niece');
1347
				}
1348 View Code Duplication
			case 'sissonson':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1349
				if ($sex1 === 'M') {
1350
					return I18N::translateContext('(a man’s) sister’s son’s son', 'great-nephew');
1351
				} else {
1352
					return I18N::translateContext('(a woman’s) sister’s son’s son', 'great-nephew');
1353
				}
1354
			case 'sissonwif':
1355
				return I18N::translateContext('sisters’s son’s wife', 'niece-in-law');
1356
			case 'sonchichi':
1357
				return I18N::translateContext('son’s child’s child', 'great-grandchild');
1358
			case 'sonchidau':
1359
				return I18N::translateContext('son’s child’s daughter', 'great-granddaughter');
1360
			case 'sonchison':
1361
				return I18N::translateContext('son’s child’s son', 'great-grandson');
1362
			case 'sondauchi':
1363
				return I18N::translateContext('son’s daughter’s child', 'great-grandchild');
1364
			case 'sondaudau':
1365
				return I18N::translateContext('son’s daughter’s daughter', 'great-granddaughter');
1366
			case 'sondauhus':
1367
				return I18N::translateContext('son’s daughter’s husband', 'granddaughter’s husband');
1368
			case 'sondauson':
1369
				return I18N::translateContext('son’s daughter’s son', 'great-grandson');
1370
			case 'sonsonchi':
1371
				return I18N::translateContext('son’s son’s child', 'great-grandchild');
1372
			case 'sonsondau':
1373
				return I18N::translateContext('son’s son’s daughter', 'great-granddaughter');
1374
			case 'sonsonson':
1375
				return I18N::translateContext('son’s son’s son', 'great-grandson');
1376
			case 'sonsonwif':
1377
				return I18N::translateContext('son’s son’s wife', 'grandson’s wife');
1378
			case 'sonwiffat':
1379
				return I18N::translateContext('son’s wife’s father', 'daughter-in-law’s father');
1380
			case 'sonwifmot':
1381
				return I18N::translateContext('son’s wife’s mother', 'daughter-in-law’s mother');
1382
			case 'sonwifpar':
1383
				return I18N::translateContext('son’s wife’s parent', 'daughter-in-law’s parent');
1384
			case 'wifbrowif':
1385
				return I18N::translateContext('wife’s brother’s wife', 'sister-in-law');
1386
			case 'wifsishus':
1387
				return I18N::translateContext('wife’s sister’s husband', 'brother-in-law');
1388
1389
			// Some “special case” level four relationships that have specific names in certain languages
1390
			case 'fatfatbrowif':
1391
				return I18N::translateContext('father’s father’s brother’s wife', 'great-aunt');
1392
			case 'fatfatsibspo':
1393
				return I18N::translateContext('father’s father’s sibling’s spouse', 'great-aunt/uncle');
1394
			case 'fatfatsishus':
1395
				return I18N::translateContext('father’s father’s sister’s husband', 'great-uncle');
1396
			case 'fatmotbrowif':
1397
				return I18N::translateContext('father’s mother’s brother’s wife', 'great-aunt');
1398
			case 'fatmotsibspo':
1399
				return I18N::translateContext('father’s mother’s sibling’s spouse', 'great-aunt/uncle');
1400
			case 'fatmotsishus':
1401
				return I18N::translateContext('father’s mother’s sister’s husband', 'great-uncle');
1402
			case 'fatparbrowif':
1403
				return I18N::translateContext('father’s parent’s brother’s wife', 'great-aunt');
1404
			case 'fatparsibspo':
1405
				return I18N::translateContext('father’s parent’s sibling’s spouse', 'great-aunt/uncle');
1406
			case 'fatparsishus':
1407
				return I18N::translateContext('father’s parent’s sister’s husband', 'great-uncle');
1408
			case 'motfatbrowif':
1409
				return I18N::translateContext('mother’s father’s brother’s wife', 'great-aunt');
1410
			case 'motfatsibspo':
1411
				return I18N::translateContext('mother’s father’s sibling’s spouse', 'great-aunt/uncle');
1412
			case 'motfatsishus':
1413
				return I18N::translateContext('mother’s father’s sister’s husband', 'great-uncle');
1414
			case 'motmotbrowif':
1415
				return I18N::translateContext('mother’s mother’s brother’s wife', 'great-aunt');
1416
			case 'motmotsibspo':
1417
				return I18N::translateContext('mother’s mother’s sibling’s spouse', 'great-aunt/uncle');
1418
			case 'motmotsishus':
1419
				return I18N::translateContext('mother’s mother’s sister’s husband', 'great-uncle');
1420
			case 'motparbrowif':
1421
				return I18N::translateContext('mother’s parent’s brother’s wife', 'great-aunt');
1422
			case 'motparsibspo':
1423
				return I18N::translateContext('mother’s parent’s sibling’s spouse', 'great-aunt/uncle');
1424
			case 'motparsishus':
1425
				return I18N::translateContext('mother’s parent’s sister’s husband', 'great-uncle');
1426
			case 'parfatbrowif':
1427
				return I18N::translateContext('parent’s father’s brother’s wife', 'great-aunt');
1428
			case 'parfatsibspo':
1429
				return I18N::translateContext('parent’s father’s sibling’s spouse', 'great-aunt/uncle');
1430
			case 'parfatsishus':
1431
				return I18N::translateContext('parent’s father’s sister’s husband', 'great-uncle');
1432
			case 'parmotbrowif':
1433
				return I18N::translateContext('parent’s mother’s brother’s wife', 'great-aunt');
1434
			case 'parmotsibspo':
1435
				return I18N::translateContext('parent’s mother’s sibling’s spouse', 'great-aunt/uncle');
1436
			case 'parmotsishus':
1437
				return I18N::translateContext('parent’s mother’s sister’s husband', 'great-uncle');
1438
			case 'parparbrowif':
1439
				return I18N::translateContext('parent’s parent’s brother’s wife', 'great-aunt');
1440
			case 'parparsibspo':
1441
				return I18N::translateContext('parent’s parent’s sibling’s spouse', 'great-aunt/uncle');
1442
			case 'parparsishus':
1443
				return I18N::translateContext('parent’s parent’s sister’s husband', 'great-uncle');
1444
			case 'fatfatbrodau':
1445
				return I18N::translateContext('father’s father’s brother’s daughter', 'first cousin once removed ascending');
1446
			case 'fatfatbroson':
1447
				return I18N::translateContext('father’s father’s brother’s son', 'first cousin once removed ascending');
1448
			case 'fatfatbrochi':
1449
				return I18N::translateContext('father’s father’s brother’s child', 'first cousin once removed ascending');
1450
			case 'fatfatsisdau':
1451
				return I18N::translateContext('father’s father’s sister’s daughter', 'first cousin once removed ascending');
1452
			case 'fatfatsisson':
1453
				return I18N::translateContext('father’s father’s sister’s son', 'first cousin once removed ascending');
1454
			case 'fatfatsischi':
1455
				return I18N::translateContext('father’s father’s sister’s child', 'first cousin once removed ascending');
1456
			case 'fatmotbrodau':
1457
				return I18N::translateContext('father’s mother’s brother’s daughter', 'first cousin once removed ascending');
1458
			case 'fatmotbroson':
1459
				return I18N::translateContext('father’s mother’s brother’s son', 'first cousin once removed ascending');
1460
			case 'fatmotbrochi':
1461
				return I18N::translateContext('father’s mother’s brother’s child', 'first cousin once removed ascending');
1462
			case 'fatmotsisdau':
1463
				return I18N::translateContext('father’s mother’s sister’s daughter', 'first cousin once removed ascending');
1464
			case 'fatmotsisson':
1465
				return I18N::translateContext('father’s mother’s sister’s son', 'first cousin once removed ascending');
1466
			case 'fatmotsischi':
1467
				return I18N::translateContext('father’s mother’s sister’s child', 'first cousin once removed ascending');
1468
			case 'motfatbrodau':
1469
				return I18N::translateContext('mother’s father’s brother’s daughter', 'first cousin once removed ascending');
1470
			case 'motfatbroson':
1471
				return I18N::translateContext('mother’s father’s brother’s son', 'first cousin once removed ascending');
1472
			case 'motfatbrochi':
1473
				return I18N::translateContext('mother’s father’s brother’s child', 'first cousin once removed ascending');
1474
			case 'motfatsisdau':
1475
				return I18N::translateContext('mother’s father’s sister’s daughter', 'first cousin once removed ascending');
1476
			case 'motfatsisson':
1477
				return I18N::translateContext('mother’s father’s sister’s son', 'first cousin once removed ascending');
1478
			case 'motfatsischi':
1479
				return I18N::translateContext('mother’s father’s sister’s child', 'first cousin once removed ascending');
1480
			case 'motmotbrodau':
1481
				return I18N::translateContext('mother’s mother’s brother’s daughter', 'first cousin once removed ascending');
1482
			case 'motmotbroson':
1483
				return I18N::translateContext('mother’s mother’s brother’s son', 'first cousin once removed ascending');
1484
			case 'motmotbrochi':
1485
				return I18N::translateContext('mother’s mother’s brother’s child', 'first cousin once removed ascending');
1486
			case 'motmotsisdau':
1487
				return I18N::translateContext('mother’s mother’s sister’s daughter', 'first cousin once removed ascending');
1488
			case 'motmotsisson':
1489
				return I18N::translateContext('mother’s mother’s sister’s son', 'first cousin once removed ascending');
1490
			case 'motmotsischi':
1491
				return I18N::translateContext('mother’s mother’s sister’s child', 'first cousin once removed ascending');
1492
		}
1493
1494
		// Some “special case” level five relationships that have specific names in certain languages
1495
		if (preg_match('/^(mot|fat|par)fatbro(son|dau|chi)dau$/', $path)) {
1496
			return I18N::translateContext('grandfather’s brother’s granddaughter', 'second cousin');
1497
		} elseif (preg_match('/^(mot|fat|par)fatbro(son|dau|chi)son$/', $path)) {
1498
			return I18N::translateContext('grandfather’s brother’s grandson', 'second cousin');
1499
		} elseif (preg_match('/^(mot|fat|par)fatbro(son|dau|chi)chi$/', $path)) {
1500
			return I18N::translateContext('grandfather’s brother’s grandchild', 'second cousin');
1501
		} elseif (preg_match('/^(mot|fat|par)fatsis(son|dau|chi)dau$/', $path)) {
1502
			return I18N::translateContext('grandfather’s sister’s granddaughter', 'second cousin');
1503
		} elseif (preg_match('/^(mot|fat|par)fatsis(son|dau|chi)son$/', $path)) {
1504
			return I18N::translateContext('grandfather’s sister’s grandson', 'second cousin');
1505
		} elseif (preg_match('/^(mot|fat|par)fatsis(son|dau|chi)chi$/', $path)) {
1506
			return I18N::translateContext('grandfather’s sister’s grandchild', 'second cousin');
1507
		} elseif (preg_match('/^(mot|fat|par)fatsib(son|dau|chi)dau$/', $path)) {
1508
			return I18N::translateContext('grandfather’s sibling’s granddaughter', 'second cousin');
1509
		} elseif (preg_match('/^(mot|fat|par)fatsib(son|dau|chi)son$/', $path)) {
1510
			return I18N::translateContext('grandfather’s sibling’s grandson', 'second cousin');
1511
		} elseif (preg_match('/^(mot|fat|par)fatsib(son|dau|chi)chi$/', $path)) {
1512
			return I18N::translateContext('grandfather’s sibling’s grandchild', 'second cousin');
1513
		} elseif (preg_match('/^(mot|fat|par)motbro(son|dau|chi)dau$/', $path)) {
1514
			return I18N::translateContext('grandmother’s brother’s granddaughter', 'second cousin');
1515
		} elseif (preg_match('/^(mot|fat|par)motbro(son|dau|chi)son$/', $path)) {
1516
			return I18N::translateContext('grandmother’s brother’s grandson', 'second cousin');
1517
		} elseif (preg_match('/^(mot|fat|par)motbro(son|dau|chi)chi$/', $path)) {
1518
			return I18N::translateContext('grandmother’s brother’s grandchild', 'second cousin');
1519
		} elseif (preg_match('/^(mot|fat|par)motsis(son|dau|chi)dau$/', $path)) {
1520
			return I18N::translateContext('grandmother’s sister’s granddaughter', 'second cousin');
1521
		} elseif (preg_match('/^(mot|fat|par)motsis(son|dau|chi)son$/', $path)) {
1522
			return I18N::translateContext('grandmother’s sister’s grandson', 'second cousin');
1523
		} elseif (preg_match('/^(mot|fat|par)motsis(son|dau|chi)chi$/', $path)) {
1524
			return I18N::translateContext('grandmother’s sister’s grandchild', 'second cousin');
1525
		} elseif (preg_match('/^(mot|fat|par)motsib(son|dau|chi)dau$/', $path)) {
1526
			return I18N::translateContext('grandmother’s sibling’s granddaughter', 'second cousin');
1527
		} elseif (preg_match('/^(mot|fat|par)motsib(son|dau|chi)son$/', $path)) {
1528
			return I18N::translateContext('grandmother’s sibling’s grandson', 'second cousin');
1529
		} elseif (preg_match('/^(mot|fat|par)motsib(son|dau|chi)chi$/', $path)) {
1530
			return I18N::translateContext('grandmother’s sibling’s grandchild', 'second cousin');
1531
		} elseif (preg_match('/^(mot|fat|par)parbro(son|dau|chi)dau$/', $path)) {
1532
			return I18N::translateContext('grandparent’s brother’s granddaughter', 'second cousin');
1533
		} elseif (preg_match('/^(mot|fat|par)parbro(son|dau|chi)son$/', $path)) {
1534
			return I18N::translateContext('grandparent’s brother’s grandson', 'second cousin');
1535
		} elseif (preg_match('/^(mot|fat|par)parbro(son|dau|chi)chi$/', $path)) {
1536
			return I18N::translateContext('grandparent’s brother’s grandchild', 'second cousin');
1537
		} elseif (preg_match('/^(mot|fat|par)parsis(son|dau|chi)dau$/', $path)) {
1538
			return I18N::translateContext('grandparent’s sister’s granddaughter', 'second cousin');
1539
		} elseif (preg_match('/^(mot|fat|par)parsis(son|dau|chi)son$/', $path)) {
1540
			return I18N::translateContext('grandparent’s sister’s grandson', 'second cousin');
1541
		} elseif (preg_match('/^(mot|fat|par)parsis(son|dau|chi)chi$/', $path)) {
1542
			return I18N::translateContext('grandparent’s sister’s grandchild', 'second cousin');
1543
		} elseif (preg_match('/^(mot|fat|par)parsib(son|dau|chi)dau$/', $path)) {
1544
			return I18N::translateContext('grandparent’s sibling’s granddaughter', 'second cousin');
1545
		} elseif (preg_match('/^(mot|fat|par)parsib(son|dau|chi)son$/', $path)) {
1546
			return I18N::translateContext('grandparent’s sibling’s grandson', 'second cousin');
1547
		} elseif (preg_match('/^(mot|fat|par)parsib(son|dau|chi)chi$/', $path)) {
1548
			return I18N::translateContext('grandparent’s sibling’s grandchild', 'second cousin');
1549
		}
1550
1551
		// Look for generic/pattern relationships.
1552
		if (preg_match('/^((?:mot|fat|par)+)(bro|sis|sib)$/', $path, $match)) {
1553
			// siblings of direct ancestors
1554
			$up       = strlen($match[1]) / 3;
1555
			$bef_last = substr($path, -6, 3);
1556
			switch ($up) {
1557 View Code Duplication
				case 3:
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1558
					switch ($sex2) {
1559
						case 'M':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1560
							if ($bef_last === 'fat') {
1561
								return I18N::translateContext('great-grandfather’s brother', 'great-great-uncle');
1562
							} elseif ($bef_last === 'mot') {
1563
								return I18N::translateContext('great-grandmother’s brother', 'great-great-uncle');
1564
							} else {
1565
								return I18N::translateContext('great-grandparent’s brother', 'great-great-uncle');
1566
							}
1567
						case 'F':
1568
							return I18N::translate('great-great-aunt');
1569
						default:
1570
							return I18N::translate('great-great-aunt/uncle');
1571
					}
1572 View Code Duplication
				case 4:
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1573
					switch ($sex2) {
1574
						case 'M':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1575
							if ($bef_last === 'fat') {
1576
								return I18N::translateContext('great-great-grandfather’s brother', 'great-great-great-uncle');
1577
							} elseif ($bef_last === 'mot') {
1578
								return I18N::translateContext('great-great-grandmother’s brother', 'great-great-great-uncle');
1579
							} else {
1580
								return I18N::translateContext('great-great-grandparent’s brother', 'great-great-great-uncle');
1581
							}
1582
						case 'F':
1583
							return I18N::translate('great-great-great-aunt');
1584
						default:
1585
							return I18N::translate('great-great-great-aunt/uncle');
1586
					}
1587 View Code Duplication
				case 5:
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1588
					switch ($sex2) {
1589
						case 'M':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1590
							if ($bef_last === 'fat') {
1591
								return I18N::translateContext('great-great-great-grandfather’s brother', 'great ×4 uncle');
1592
							} elseif ($bef_last === 'mot') {
1593
								return I18N::translateContext('great-great-great-grandmother’s brother', 'great ×4 uncle');
1594
							} else {
1595
								return I18N::translateContext('great-great-great-grandparent’s brother', 'great ×4 uncle');
1596
							}
1597
						case 'F':
1598
							return I18N::translate('great ×4 aunt');
1599
						default:
1600
							return I18N::translate('great ×4 aunt/uncle');
1601
					}
1602 View Code Duplication
				case 6:
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1603
					switch ($sex2) {
1604
						case 'M':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1605
							if ($bef_last === 'fat') {
1606
								return I18N::translateContext('great ×4 grandfather’s brother', 'great ×5 uncle');
1607
							} elseif ($bef_last === 'mot') {
1608
								return I18N::translateContext('great ×4 grandmother’s brother', 'great ×5 uncle');
1609
							} else {
1610
								return I18N::translateContext('great ×4 grandparent’s brother', 'great ×5 uncle');
1611
							}
1612
						case 'F':
1613
							return I18N::translate('great ×5 aunt');
1614
						default:
1615
							return I18N::translate('great ×5 aunt/uncle');
1616
					}
1617 View Code Duplication
				case 7:
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1618
					switch ($sex2) {
1619
						case 'M':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1620
							if ($bef_last === 'fat') {
1621
								return I18N::translateContext('great ×5 grandfather’s brother', 'great ×6 uncle');
1622
							} elseif ($bef_last === 'mot') {
1623
								return I18N::translateContext('great ×5 grandmother’s brother', 'great ×6 uncle');
1624
							} else {
1625
								return I18N::translateContext('great ×5 grandparent’s brother', 'great ×6 uncle');
1626
							}
1627
						case 'F':
1628
							return I18N::translate('great ×6 aunt');
1629
						default:
1630
							return I18N::translate('great ×6 aunt/uncle');
1631
					}
1632 View Code Duplication
				case 8:
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1633
					switch ($sex2) {
1634
						case 'M':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1635
							if ($bef_last === 'fat') {
1636
								return I18N::translateContext('great ×6 grandfather’s brother', 'great ×7 uncle');
1637
							} elseif ($bef_last === 'mot') {
1638
								return I18N::translateContext('great ×6 grandmother’s brother', 'great ×7 uncle');
1639
							} else {
1640
								return I18N::translateContext('great ×6 grandparent’s brother', 'great ×7 uncle');
1641
							}
1642
						case 'F':
1643
							return I18N::translate('great ×7 aunt');
1644
						default:
1645
							return I18N::translate('great ×7 aunt/uncle');
1646
					}
1647
				default:
1648
					// Different languages have different rules for naming generations.
1649
					// An English great ×12 uncle is a Danish great ×10 uncle.
1650
					//
1651
					// Need to find out which languages use which rules.
1652
					switch (WT_LOCALE) {
1653 View Code Duplication
						case 'da':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1654
							switch ($sex2) {
1655
								case 'M':
1656
									return I18N::translate('great ×%s uncle', I18N::number($up - 4));
1657
								case 'F':
1658
									return I18N::translate('great ×%s aunt', I18N::number($up - 4));
1659
								default:
1660
									return I18N::translate('great ×%s aunt/uncle', I18N::number($up - 4));
1661
							}
1662
						case 'pl':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1663
							switch ($sex2) {
1664
								case 'M':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1665
									if ($bef_last === 'fat') {
1666
										return I18N::translateContext('great ×(%s-1) grandfather’s brother', 'great ×%s uncle', I18N::number($up - 2));
1667
									} elseif ($bef_last === 'mot') {
1668
										return I18N::translateContext('great ×(%s-1) grandmother’s brother', 'great ×%s uncle', I18N::number($up - 2));
1669
									} else {
1670
										return I18N::translateContext('great ×(%s-1) grandparent’s brother', 'great ×%s uncle', I18N::number($up - 2));
1671
									}
1672
								case 'F':
1673
									return I18N::translate('great ×%s aunt', I18N::number($up - 2));
1674
								default:
1675
									return I18N::translate('great ×%s aunt/uncle', I18N::number($up - 2));
1676
							}
1677
						case 'it': // Source: Michele Locati
1678
						case 'en_AU':
1679
						case 'en_GB':
1680
						case 'en_US':
1681 View Code Duplication
						default:
1682
							switch ($sex2) {
1683
								case 'M': // I18N: if you need a different number for %s, contact the developers, as a code-change is required
1684
									return I18N::translate('great ×%s uncle', I18N::number($up - 1));
1685
								case 'F':
1686
									return I18N::translate('great ×%s aunt', I18N::number($up - 1));
1687
								default:
1688
									return I18N::translate('great ×%s aunt/uncle', I18N::number($up - 1));
1689
							}
1690
					}
1691
			}
1692
		}
1693
		if (preg_match('/^(?:bro|sis|sib)((?:son|dau|chi)+)$/', $path, $match)) {
1694
			// direct descendants of siblings
1695
			$down  = strlen($match[1]) / 3 + 1; // Add one, as we count generations from the common ancestor
1696
			$first = substr($path, 0, 3);
1697
			switch ($down) {
1698 View Code Duplication
				case 4:
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1699
					switch ($sex2) {
1700
						case 'M':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1701
							if ($first === 'bro' && $sex1 === 'M') {
1702
								return I18N::translateContext('(a man’s) brother’s great-grandson', 'great-great-nephew');
1703
							} elseif ($first === 'sis' && $sex1 === 'M') {
1704
								return I18N::translateContext('(a man’s) sister’s great-grandson', 'great-great-nephew');
1705
							} else {
1706
								return I18N::translateContext('(a woman’s) great-great-nephew', 'great-great-nephew');
1707
							}
1708
						case 'F':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1709
							if ($first === 'bro' && $sex1 === 'M') {
1710
								return I18N::translateContext('(a man’s) brother’s great-granddaughter', 'great-great-niece');
1711
							} elseif ($first === 'sis' && $sex1 === 'M') {
1712
								return I18N::translateContext('(a man’s) sister’s great-granddaughter', 'great-great-niece');
1713
							} else {
1714
								return I18N::translateContext('(a woman’s) great-great-niece', 'great-great-niece');
1715
							}
1716
						default:
1717
							if ($first === 'bro' && $sex1 === 'M') {
1718
								return I18N::translateContext('(a man’s) brother’s great-grandchild', 'great-great-nephew/niece');
1719
							} elseif ($first === 'sis' && $sex1 === 'M') {
1720
								return I18N::translateContext('(a man’s) sister’s great-grandchild', 'great-great-nephew/niece');
1721
							} else {
1722
								return I18N::translateContext('(a woman’s) great-great-nephew/niece', 'great-great-nephew/niece');
1723
							}
1724
					}
1725 View Code Duplication
				case 5:
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1726
					switch ($sex2) {
1727
						case 'M':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1728
							if ($first === 'bro' && $sex1 === 'M') {
1729
								return I18N::translateContext('(a man’s) brother’s great-great-grandson', 'great-great-great-nephew');
1730
							} elseif ($first === 'sis' && $sex1 === 'M') {
1731
								return I18N::translateContext('(a man’s) sister’s great-great-grandson', 'great-great-great-nephew');
1732
							} else {
1733
								return I18N::translateContext('(a woman’s) great-great-great-nephew', 'great-great-great-nephew');
1734
							}
1735
						case 'F':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1736
							if ($first === 'bro' && $sex1 === 'M') {
1737
								return I18N::translateContext('(a man’s) brother’s great-great-granddaughter', 'great-great-great-niece');
1738
							} elseif ($first === 'sis' && $sex1 === 'M') {
1739
								return I18N::translateContext('(a man’s) sister’s great-great-granddaughter', 'great-great-great-niece');
1740
							} else {
1741
								return I18N::translateContext('(a woman’s) great-great-great-niece', 'great-great-great-niece');
1742
							}
1743
						default:
1744
							if ($first === 'bro' && $sex1 === 'M') {
1745
								return I18N::translateContext('(a man’s) brother’s great-great-grandchild', 'great-great-great-nephew/niece');
1746
							} elseif ($first === 'sis' && $sex1 === 'M') {
1747
								return I18N::translateContext('(a man’s) sister’s great-great-grandchild', 'great-great-great-nephew/niece');
1748
							} else {
1749
								return I18N::translateContext('(a woman’s) great-great-great-nephew/niece', 'great-great-great-nephew/niece');
1750
							}
1751
					}
1752 View Code Duplication
				case 6:
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1753
					switch ($sex2) {
1754
						case 'M':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1755
							if ($first === 'bro' && $sex1 === 'M') {
1756
								return I18N::translateContext('(a man’s) brother’s great-great-great-grandson', 'great ×4 nephew');
1757
							} elseif ($first === 'sis' && $sex1 === 'M') {
1758
								return I18N::translateContext('(a man’s) sister’s great-great-great-grandson', 'great ×4 nephew');
1759
							} else {
1760
								return I18N::translateContext('(a woman’s) great ×4 nephew', 'great ×4 nephew');
1761
							}
1762
						case 'F':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1763
							if ($first === 'bro' && $sex1 === 'M') {
1764
								return I18N::translateContext('(a man’s) brother’s great-great-great-granddaughter', 'great ×4 niece');
1765
							} elseif ($first === 'sis' && $sex1 === 'M') {
1766
								return I18N::translateContext('(a man’s) sister’s great-great-great-granddaughter', 'great ×4 niece');
1767
							} else {
1768
								return I18N::translateContext('(a woman’s) great ×4 niece', 'great ×4 niece');
1769
							}
1770
						default:
1771
							if ($first === 'bro' && $sex1 === 'M') {
1772
								return I18N::translateContext('(a man’s) brother’s great-great-great-grandchild', 'great ×4 nephew/niece');
1773
							} elseif ($first === 'sis' && $sex1 === 'M') {
1774
								return I18N::translateContext('(a man’s) sister’s great-great-great-grandchild', 'great ×4 nephew/niece');
1775
							} else {
1776
								return I18N::translateContext('(a woman’s) great ×4 nephew/niece', 'great ×4 nephew/niece');
1777
							}
1778
					}
1779 View Code Duplication
				case 7:
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1780
					switch ($sex2) {
1781
						case 'M':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1782
							if ($first === 'bro' && $sex1 === 'M') {
1783
								return I18N::translateContext('(a man’s) brother’s great ×4 grandson', 'great ×5 nephew');
1784
							} elseif ($first === 'sis' && $sex1 === 'M') {
1785
								return I18N::translateContext('(a man’s) sister’s great ×4 grandson', 'great ×5 nephew');
1786
							} else {
1787
								return I18N::translateContext('(a woman’s) great ×5 nephew', 'great ×5 nephew');
1788
							}
1789
						case 'F':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1790
							if ($first === 'bro' && $sex1 === 'M') {
1791
								return I18N::translateContext('(a man’s) brother’s great ×4 granddaughter', 'great ×5 niece');
1792
							} elseif ($first === 'sis' && $sex1 === 'M') {
1793
								return I18N::translateContext('(a man’s) sister’s great ×4 granddaughter', 'great ×5 niece');
1794
							} else {
1795
								return I18N::translateContext('(a woman’s) great ×5 niece', 'great ×5 niece');
1796
							}
1797
						default:
1798
							if ($first === 'bro' && $sex1 === 'M') {
1799
								return I18N::translateContext('(a man’s) brother’s great ×4 grandchild', 'great ×5 nephew/niece');
1800
							} elseif ($first === 'sis' && $sex1 === 'M') {
1801
								return I18N::translateContext('(a man’s) sister’s great ×4 grandchild', 'great ×5 nephew/niece');
1802
							} else {
1803
								return I18N::translateContext('(a woman’s) great ×5 nephew/niece', 'great ×5 nephew/niece');
1804
							}
1805
					}
1806
				default:
1807
					// Different languages have different rules for naming generations.
1808
					// An English great ×12 nephew is a Polish great ×11 nephew.
1809
					//
1810
					// Need to find out which languages use which rules.
1811
					switch (WT_LOCALE) {
1812
						case 'pl': // Source: Lukasz Wilenski
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1813
							switch ($sex2) {
1814 View Code Duplication
								case 'M':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1815
									if ($first === 'bro' && $sex1 === 'M') {
1816
										return I18N::translateContext('(a man’s) brother’s great ×(%s-1) grandson', 'great ×%s nephew', I18N::number($down - 3));
1817
									} elseif ($first === 'sis' && $sex1 === 'M') {
1818
										return I18N::translateContext('(a man’s) sister’s great ×(%s-1) grandson', 'great ×%s nephew', I18N::number($down - 3));
1819
									} else {
1820
										return I18N::translateContext('(a woman’s) great ×%s nephew', 'great ×%s nephew', I18N::number($down - 3));
1821
									}
1822 View Code Duplication
								case 'F':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1823
									if ($first === 'bro' && $sex1 === 'M') {
1824
										return I18N::translateContext('(a man’s) brother’s great ×(%s-1) granddaughter', 'great ×%s niece', I18N::number($down - 3));
1825
									} elseif ($first === 'sis' && $sex1 === 'M') {
1826
										return I18N::translateContext('(a man’s) sister’s great ×(%s-1) granddaughter', 'great ×%s niece', I18N::number($down - 3));
1827
									} else {
1828
										return I18N::translateContext('(a woman’s) great ×%s niece', 'great ×%s niece', I18N::number($down - 3));
1829
									}
1830 View Code Duplication
								default:
1831
									if ($first === 'bro' && $sex1 === 'M') {
1832
										return I18N::translateContext('(a man’s) brother’s great ×(%s-1) grandchild', 'great ×%s nephew/niece', I18N::number($down - 3));
1833
									} elseif ($first === 'sis' && $sex1 === 'M') {
1834
										return I18N::translateContext('(a man’s) sister’s great ×(%s-1) grandchild', 'great ×%s nephew/niece', I18N::number($down - 3));
1835
									} else {
1836
										return I18N::translateContext('(a woman’s) great ×%s nephew/niece', 'great ×%s nephew/niece', I18N::number($down - 3));
1837
									}
1838
							}
1839 View Code Duplication
						case 'he': // Source: Meliza Amity
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1840
							switch ($sex2) {
1841
								case 'M':
1842
									return I18N::translate('great ×%s nephew', I18N::number($down - 1));
1843
								case 'F':
1844
									return I18N::translate('great ×%s niece', I18N::number($down - 1));
1845
								default:
1846
									return I18N::translate('great ×%s nephew/niece', I18N::number($down - 1));
1847
							}
1848
						case 'it': // Source: Michele Locati.
1849
						case 'en_AU':
1850
						case 'en_GB':
1851
						case 'en_US':
1852 View Code Duplication
						default:
1853
							switch ($sex2) {
1854
								case 'M': // I18N: if you need a different number for %s, contact the developers, as a code-change is required
1855
									return I18N::translate('great ×%s nephew', I18N::number($down - 2));
1856
								case 'F':
1857
									return I18N::translate('great ×%s niece', I18N::number($down - 2));
1858
								default:
1859
									return I18N::translate('great ×%s nephew/niece', I18N::number($down - 2));
1860
							}
1861
					}
1862
			}
1863
		}
1864
		if (preg_match('/^((?:mot|fat|par)*)$/', $path, $match)) {
1865
			// direct ancestors
1866
			$up = strlen($match[1]) / 3;
1867
			switch ($up) {
1868
				case 4:
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1869
					switch ($sex2) {
1870
						case 'M':
1871
							return I18N::translate('great-great-grandfather');
1872
						case 'F':
1873
							return I18N::translate('great-great-grandmother');
1874
						default:
1875
							return I18N::translate('great-great-grandparent');
1876
					}
1877
				case 5:
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1878
					switch ($sex2) {
1879
						case 'M':
1880
							return I18N::translate('great-great-great-grandfather');
1881
						case 'F':
1882
							return I18N::translate('great-great-great-grandmother');
1883
						default:
1884
							return I18N::translate('great-great-great-grandparent');
1885
					}
1886 View Code Duplication
				case 6:
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1887
					switch ($sex2) {
1888
						case 'M':
1889
							return I18N::translate('great ×4 grandfather');
1890
						case 'F':
1891
							return I18N::translate('great ×4 grandmother');
1892
						default:
1893
							return I18N::translate('great ×4 grandparent');
1894
					}
1895 View Code Duplication
				case 7:
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1896
					switch ($sex2) {
1897
						case 'M':
1898
							return I18N::translate('great ×5 grandfather');
1899
						case 'F':
1900
							return I18N::translate('great ×5 grandmother');
1901
						default:
1902
							return I18N::translate('great ×5 grandparent');
1903
					}
1904 View Code Duplication
				case 8:
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1905
					switch ($sex2) {
1906
						case 'M':
1907
							return I18N::translate('great ×6 grandfather');
1908
						case 'F':
1909
							return I18N::translate('great ×6 grandmother');
1910
						default:
1911
							return I18N::translate('great ×6 grandparent');
1912
					}
1913 View Code Duplication
				case 9:
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1914
					switch ($sex2) {
1915
						case 'M':
1916
							return I18N::translate('great ×7 grandfather');
1917
						case 'F':
1918
							return I18N::translate('great ×7 grandmother');
1919
						default:
1920
							return I18N::translate('great ×7 grandparent');
1921
					}
1922
				default:
1923
					// Different languages have different rules for naming generations.
1924
					// An English great ×12 grandfather is a Danish great ×11 grandfather.
1925
					//
1926
					// Need to find out which languages use which rules.
1927
					switch (WT_LOCALE) {
1928 View Code Duplication
						case 'da': // Source: Patrick Sorensen
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1929
							switch ($sex2) {
1930
								case 'M':
1931
									return I18N::translate('great ×%s grandfather', I18N::number($up - 3));
1932
								case 'F':
1933
									return I18N::translate('great ×%s grandmother', I18N::number($up - 3));
1934
								default:
1935
									return I18N::translate('great ×%s grandparent', I18N::number($up - 3));
1936
							}
1937
						case 'it': // Source: Michele Locati
1938
						case 'es': // Source: Wes Groleau
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1939
							switch ($sex2) {
1940
								case 'M':
1941
									return I18N::translate('great ×%s grandfather', I18N::number($up));
1942
								case 'F':
1943
									return I18N::translate('great ×%s grandmother', I18N::number($up));
1944
								default:
1945
									return I18N::translate('great ×%s grandparent', I18N::number($up));
1946
							}
1947
						case 'fr': // Source: Jacqueline Tetreault
1948 View Code Duplication
						case 'fr_CA':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1949
							switch ($sex2) {
1950
								case 'M':
1951
									return I18N::translate('great ×%s grandfather', I18N::number($up - 1));
1952
								case 'F':
1953
									return I18N::translate('great ×%s grandmother', I18N::number($up - 1));
1954
								default:
1955
									return I18N::translate('great ×%s grandparent', I18N::number($up - 1));
1956
							}
1957
						case 'nn': // Source: Hogne Røed Nilsen (https://bugs.launchpad.net/webtrees/+bug/1168553)
0 ignored issues
show
Unused Code Comprehensibility introduced by
37% 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...
1958 View Code Duplication
						case 'nb':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1959
							switch ($sex2) {
1960
								case 'M': // I18N: if you need a different number for %s, contact the developers, as a code-change is required
1961
									return I18N::translate('great ×%s grandfather', I18N::number($up - 3));
1962
								case 'F':
1963
									return I18N::translate('great ×%s grandmother', I18N::number($up - 3));
1964
								default:
1965
									return I18N::translate('great ×%s grandparent', I18N::number($up - 3));
1966
							}
1967
						case 'en_AU':
1968
						case 'en_GB':
1969
						case 'en_US':
1970 View Code Duplication
						default:
1971
							switch ($sex2) {
1972
								case 'M': // I18N: if you need a different number for %s, contact the developers, as a code-change is required
1973
									return I18N::translate('great ×%s grandfather', I18N::number($up - 2));
1974
								case 'F':
1975
									return I18N::translate('great ×%s grandmother', I18N::number($up - 2));
1976
								default:
1977
									return I18N::translate('great ×%s grandparent', I18N::number($up - 2));
1978
							}
1979
					}
1980
			}
1981
		}
1982
		if (preg_match('/^((?:son|dau|chi)*)$/', $path, $match)) {
1983
			// direct descendants
1984
			$up = strlen($match[1]) / 3;
1985
			switch ($up) {
1986
				case 4:
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1987
					switch ($sex2) {
1988
						case 'M':
1989
							return I18N::translate('great-great-grandson');
1990
						case 'F':
1991
							return I18N::translate('great-great-granddaughter');
1992
						default:
1993
							return I18N::translate('great-great-grandchild');
1994
					}
1995
1996
				case 5:
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
1997
					switch ($sex2) {
1998
						case 'M':
1999
							return I18N::translate('great-great-great-grandson');
2000
						case 'F':
2001
							return I18N::translate('great-great-great-granddaughter');
2002
						default:
2003
							return I18N::translate('great-great-great-grandchild');
2004
					}
2005
2006 View Code Duplication
				case 6:
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
2007
					switch ($sex2) {
2008
						case 'M':
2009
							return I18N::translate('great ×4 grandson');
2010
						case 'F':
2011
							return I18N::translate('great ×4 granddaughter');
2012
						default:
2013
							return I18N::translate('great ×4 grandchild');
2014
					}
2015
2016 View Code Duplication
				case 7:
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
2017
					switch ($sex2) {
2018
						case 'M':
2019
							return I18N::translate('great ×5 grandson');
2020
						case 'F':
2021
							return I18N::translate('great ×5 granddaughter');
2022
						default:
2023
							return I18N::translate('great ×5 grandchild');
2024
					}
2025
2026 View Code Duplication
				case 8:
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
2027
					switch ($sex2) {
2028
						case 'M':
2029
							return I18N::translate('great ×6 grandson');
2030
						case 'F':
2031
							return I18N::translate('great ×6 granddaughter');
2032
						default:
2033
							return I18N::translate('great ×6 grandchild');
2034
					}
2035
2036 View Code Duplication
				case 9:
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
2037
					switch ($sex2) {
2038
						case 'M':
2039
							return I18N::translate('great ×7 grandson');
2040
						case 'F':
2041
							return I18N::translate('great ×7 granddaughter');
2042
						default:
2043
							return I18N::translate('great ×7 grandchild');
2044
					}
2045
2046
				default:
2047
					// Different languages have different rules for naming generations.
2048
					// An English great ×12 grandson is a Danish great ×11 grandson.
2049
					//
2050
					// Need to find out which languages use which rules.
2051
					switch (WT_LOCALE) {
2052
						case 'nn': // Source: Hogne Røed Nilsen
2053
						case 'nb':
2054 View Code Duplication
						case 'da': // Source: Patrick Sorensen
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
2055
							switch ($sex2) {
2056
								case 'M':
2057
									return I18N::translate('great ×%s grandson', I18N::number($up - 3));
2058
								case 'F':
2059
									return I18N::translate('great ×%s granddaughter', I18N::number($up - 3));
2060
								default:
2061
									return I18N::translate('great ×%s grandchild', I18N::number($up - 3));
2062
							}
2063
						case 'it': // Source: Michele Locati
2064
						case 'es': // Source: Wes Groleau (adding doesn’t change behavior, but needs to be better researched)
2065
						case 'en_AU':
2066
						case 'en_GB':
2067
						case 'en_US':
2068 View Code Duplication
						default:
2069
							switch ($sex2) {
2070
2071
								case 'M': // I18N: if you need a different number for %s, contact the developers, as a code-change is required
2072
									return I18N::translate('great ×%s grandson', I18N::number($up - 2));
2073
								case 'F':
2074
									return I18N::translate('great ×%s granddaughter', I18N::number($up - 2));
2075
								default:
2076
									return I18N::translate('great ×%s grandchild', I18N::number($up - 2));
2077
							}
2078
					}
2079
			}
2080
		}
2081
		if (preg_match('/^((?:mot|fat|par)+)(?:bro|sis|sib)((?:son|dau|chi)+)$/', $path, $match)) {
2082
			// cousins in English
2083
			$ascent  = $match[1];
2084
			$descent = $match[2];
2085
			$up      = strlen($ascent) / 3;
2086
			$down    = strlen($descent) / 3;
2087
			$cousin  = min($up, $down); // Moved out of switch (en/default case) so that
2088
			$removed = abs($down - $up); // Spanish (and other languages) can use it, too.
2089
2090
			// Different languages have different rules for naming cousins. For example,
2091
			// an English “second cousin once removed” is a Polish “cousin of 7th degree”.
2092
			//
2093
			// Need to find out which languages use which rules.
2094
			switch (WT_LOCALE) {
2095
				case 'pl': // Source: Lukasz Wilenski
2096
					return self::cousinName($up + $down + 2, $sex2);
2097
				case 'it':
2098
					// Source: Michele Locati. See italian_cousins_names.zip
2099
					// http://webtrees.net/forums/8-translation/1200-great-xn-grandparent?limit=6&start=6
2100
					return self::cousinName($up + $down - 3, $sex2);
2101
				case 'es':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
2102
					// Source: Wes Groleau. See http://UniGen.us/Parentesco.html & http://UniGen.us/Parentesco-D.html
2103
					if ($down == $up) {
2104
						return self::cousinName($cousin, $sex2);
2105
					} elseif ($down < $up) {
2106
						return self::cousinName2($cousin + 1, $sex2, self::getRelationshipNameFromPath('sib' . $descent, null, null));
2107
					} else {
2108
						switch ($sex2) {
2109 View Code Duplication
							case 'M':
2110
								return self::cousinName2($cousin + 1, $sex2, self::getRelationshipNameFromPath('bro' . $descent, null, null));
2111 View Code Duplication
							case 'F':
2112
								return self::cousinName2($cousin + 1, $sex2, self::getRelationshipNameFromPath('sis' . $descent, null, null));
2113 View Code Duplication
							default:
2114
								return self::cousinName2($cousin + 1, $sex2, self::getRelationshipNameFromPath('sib' . $descent, null, null));
2115
						}
2116
					}
2117
				case 'en_AU': // See: http://en.wikipedia.org/wiki/File:CousinTree.svg
2118
				case 'en_GB':
2119
				case 'en_US':
2120
				default:
2121
					switch ($removed) {
2122
						case 0:
2123
							return self::cousinName($cousin, $sex2);
2124 View Code Duplication
						case 1:
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
2125
							if ($up > $down) {
2126
								/* I18N: %s=“fifth cousin”, etc. http://www.ancestry.com/learn/library/article.aspx?article=2856 */
2127
								return I18N::translate('%s once removed ascending', self::cousinName($cousin, $sex2));
2128
							} else {
2129
								/* I18N: %s=“fifth cousin”, etc. http://www.ancestry.com/learn/library/article.aspx?article=2856 */
2130
								return I18N::translate('%s once removed descending', self::cousinName($cousin, $sex2));
2131
							}
2132 View Code Duplication
						case 2:
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
2133
							if ($up > $down) {
2134
								/* I18N: %s=“fifth cousin”, etc. */
2135
								return I18N::translate('%s twice removed ascending', self::cousinName($cousin, $sex2));
2136
							} else {
2137
								/* I18N: %s=“fifth cousin”, etc. */
2138
								return I18N::translate('%s twice removed descending', self::cousinName($cousin, $sex2));
2139
							}
2140 View Code Duplication
						case 3:
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
2141
							if ($up > $down) {
2142
								/* I18N: %s=“fifth cousin”, etc. */
2143
								return I18N::translate('%s three times removed ascending', self::cousinName($cousin, $sex2));
2144
							} else {
2145
								/* I18N: %s=“fifth cousin”, etc. */
2146
								return I18N::translate('%s three times removed descending', self::cousinName($cousin, $sex2));
2147
							}
2148
						default:
2149
							if ($up > $down) {
2150
								/* I18N: %1$s=“fifth cousin”, etc., %2$s>=4 */
0 ignored issues
show
Unused Code Comprehensibility introduced by
37% 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...
2151
								return I18N::translate('%1$s %2$s times removed ascending', self::cousinName($cousin, $sex2), I18N::number($removed));
2152
							} else {
2153
								/* I18N: %1$s=“fifth cousin”, etc., %2$s>=4 */
0 ignored issues
show
Unused Code Comprehensibility introduced by
37% 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...
2154
								return I18N::translate('%1$s %2$s times removed descending', self::cousinName($cousin, $sex2), I18N::number($removed));
2155
							}
2156
					}
2157
			}
2158
		}
2159
2160
		// Split the relationship into sub-relationships, e.g., third-cousin’s great-uncle.
2161
		// Try splitting at every point, and choose the path with the shorted translated name.
2162
		// But before starting to recursively go through all combinations, do a cache look-up
2163
		if (array_key_exists($path, self::$relationshipsCache)) {
2164
			return self::$relationshipsCache[$path];
2165
		}
2166
2167
		$relationship = null;
2168
		$path1        = substr($path, 0, 3);
2169
		$path2        = substr($path, 3);
2170
		while ($path2) {
2171
			$tmp = I18N::translate(
2172
			// I18N: A complex relationship, such as “third-cousin’s great-uncle”
2173
				'%1$s’s %2$s',
2174
				self::getRelationshipNameFromPath($path1, null, null), // TODO: need the actual people
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
2175
				self::getRelationshipNameFromPath($path2, null, null)
2176
			);
2177
			if (!$relationship || strlen($tmp) < strlen($relationship)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $relationship of type null|string is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
2178
				$relationship = $tmp;
2179
			}
2180
			$path1 .= substr($path2, 0, 3);
2181
			$path2 = substr($path2, 3);
2182
		}
2183
		// and store the result in the cache
2184
		self::$relationshipsCache[$path] = $relationship;
2185
2186
		return $relationship;
2187
	}
2188
2189
	/**
2190
	 * Function to build an URL querystring from GET variables
2191
	 * Optionally, add/replace specified values
2192
	 *
2193
	 * @param null|string[] $overwrite
2194
	 * @param null|string $separator
2195
	 *
2196
	 * @return string
2197
	 */
2198
	public static function getQueryUrl($overwrite = null, $separator = '&') {
0 ignored issues
show
Coding Style introduced by
getQueryUrl uses the super-global variable $_GET which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
2199
		if (empty($_GET)) {
2200
			$get = array();
2201
		} else {
2202
			$get = $_GET;
2203
		}
2204
		if (is_array($overwrite)) {
2205
			foreach ($overwrite as $key => $value) {
2206
				$get[$key] = $value;
2207
			}
2208
		}
2209
2210
		$query_string = '';
2211
		foreach ($get as $key => $value) {
2212
			if (!is_array($value)) {
2213
				$query_string .= $separator . rawurlencode($key) . '=' . rawurlencode($value);
2214
			} else {
2215
				foreach ($value as $k => $v) {
2216
					$query_string .= $separator . rawurlencode($key) . '%5B' . rawurlencode($k) . '%5D=' . rawurlencode($v);
2217
				}
2218
			}
2219
		}
2220
		$query_string = substr($query_string, strlen($separator)); // Remove leading “&amp;”
2221
		if ($query_string) {
2222
			return WT_SCRIPT_NAME . '?' . $query_string;
2223
		} else {
2224
			return WT_SCRIPT_NAME;
2225
		}
2226
	}
2227
2228
	/**
2229
	 * Determines whether the passed in filename is a link to an external source (i.e. contains “://”)
2230
	 *
2231
	 * @param string $file
2232
	 *
2233
	 * @return bool
2234
	 */
2235
	public static function isFileExternal($file) {
2236
		return strpos($file, '://') !== false;
2237
	}
2238
}
2239