| Total Complexity | 116 |
| Total Lines | 540 |
| Duplicated Lines | 0 % |
| Changes | 0 | ||
Complex classes like IndividualListController 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.
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 IndividualListController, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 28 | class IndividualListController extends PageController { |
||
| 29 | /** |
||
| 30 | * Get a list of initial letters, for lists of names. |
||
| 31 | * |
||
| 32 | * @param string $locale Return the alphabet for this locale |
||
| 33 | * |
||
| 34 | * @return string[] |
||
| 35 | */ |
||
| 36 | private function getAlphabetForLocale($locale) { |
||
| 37 | switch ($locale) { |
||
| 38 | case 'ar': |
||
| 39 | return [ |
||
| 40 | 'ا', 'ب', 'ت', 'ث', 'ج', 'ح', 'خ', 'د', 'ذ', 'ر', 'ز', 'س', 'ش', 'ص', 'ض', 'ط', 'ظ', 'ع', 'غ', 'ف', 'ق', 'ك', 'ل', 'م', 'ن', 'ه', 'و', 'ي', 'آ', 'ة', 'ى', 'ی', |
||
| 41 | ]; |
||
| 42 | case 'cs': |
||
| 43 | return [ |
||
| 44 | 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'CH', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', |
||
| 45 | ]; |
||
| 46 | case 'da': |
||
| 47 | case 'nb': |
||
| 48 | case 'nn': |
||
| 49 | return [ |
||
| 50 | 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'Æ', 'Ø', 'Å', |
||
| 51 | ]; |
||
| 52 | case 'el': |
||
| 53 | return [ |
||
| 54 | 'Α', 'Β', 'Γ', 'Δ', 'Ε', 'Ζ', 'Η', 'Θ', 'Ι', 'Κ', 'Λ', 'Μ', 'Ν', 'Ξ', 'Ο', 'Π', 'Ρ', 'Σ', 'Τ', 'Υ', 'Φ', 'Χ', 'Ψ', 'Ω', |
||
| 55 | ]; |
||
| 56 | case 'es': |
||
| 57 | return [ |
||
| 58 | 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'Ñ', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', |
||
| 59 | ]; |
||
| 60 | case 'et': |
||
| 61 | return [ |
||
| 62 | 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'Š', 'Z', 'Ž', 'T', 'U', 'V', 'W', 'Õ', 'Ä', 'Ö', 'Ü', 'X', 'Y', |
||
| 63 | ]; |
||
| 64 | case 'fi': |
||
| 65 | case 'sv': |
||
| 66 | return [ |
||
| 67 | 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'Å', 'Ä', 'Ö', |
||
| 68 | ]; |
||
| 69 | case 'he': |
||
| 70 | return [ |
||
| 71 | 'א', 'ב', 'ג', 'ד', 'ה', 'ו', 'ז', 'ח', 'ט', 'י', 'כ', 'ל', 'מ', 'נ', 'ס', 'ע', 'פ', 'צ', 'ק', 'ר', 'ש', 'ת', |
||
| 72 | ]; |
||
| 73 | case 'hu': |
||
| 74 | return [ |
||
| 75 | 'A', 'B', 'C', 'CS', 'D', 'DZ', 'DZS', 'E', 'F', 'G', 'GY', 'H', 'I', 'J', 'K', 'L', 'LY', 'M', 'N', 'NY', 'O', 'Ö', 'P', 'Q', 'R', 'S', 'SZ', 'T', 'TY', 'U', 'Ü', 'V', 'W', 'X', 'Y', 'Z', 'ZS', |
||
| 76 | ]; |
||
| 77 | case 'lt': |
||
| 78 | return [ |
||
| 79 | 'A', 'Ą', 'B', 'C', 'Č', 'D', 'E', 'Ę', 'Ė', 'F', 'G', 'H', 'I', 'Y', 'Į', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'R', 'S', 'Š', 'T', 'U', 'Ų', 'Ū', 'V', 'Z', 'Ž', |
||
| 80 | ]; |
||
| 81 | case 'nl': |
||
| 82 | return [ |
||
| 83 | 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'IJ', |
||
| 84 | ]; |
||
| 85 | case 'pl': |
||
| 86 | return [ |
||
| 87 | 'A', 'B', 'C', 'Ć', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'Ł', 'M', 'N', 'O', 'Ó', 'P', 'Q', 'R', 'S', 'Ś', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'Ź', 'Ż', |
||
| 88 | ]; |
||
| 89 | case 'ro': |
||
| 90 | return [ |
||
| 91 | 'A', 'Ă', 'Â', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'Î', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'Ş', 'T', 'Ţ', 'U', 'V', 'W', 'X', 'Y', 'Z', |
||
| 92 | ]; |
||
| 93 | case 'ru': |
||
| 94 | return [ |
||
| 95 | 'А', 'Б', 'В', 'Г', 'Д', 'Е', 'Ё', 'Ж', 'З', 'И', 'Й', 'К', 'Л', 'М', 'Н', 'О', 'П', 'Р', 'С', 'Т', 'У', 'Ф', 'Х', 'Ц', 'Ч', 'Ш', 'Щ', 'Ъ', 'Ы', 'Ь', 'Э', 'Ю', 'Я', |
||
| 96 | ]; |
||
| 97 | case 'sk': |
||
| 98 | return [ |
||
| 99 | 'A', 'Á', 'Ä', 'B', 'C', 'Č', 'D', 'Ď', 'E', 'É', 'F', 'G', 'H', 'I', 'Í', 'J', 'K', 'L', 'Ľ', 'Ĺ', 'M', 'N', 'Ň', 'O', 'Ó', 'Ô', 'P', 'Q', 'R', 'Ŕ', 'S', 'Š', 'T', 'Ť', 'U', 'Ú', 'V', 'W', 'X', 'Y', 'Ý', 'Z', 'Ž', |
||
| 100 | ]; |
||
| 101 | case 'sl': |
||
| 102 | return [ |
||
| 103 | 'A', 'B', 'C', 'Č', 'Ć', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'Š', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'Ž', |
||
| 104 | ]; |
||
| 105 | case 'sr': |
||
| 106 | return [ |
||
| 107 | 'A', 'B', 'C', 'Č', 'Ć', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'Š', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'Ž', |
||
| 108 | ]; |
||
| 109 | case 'tr': |
||
| 110 | return [ |
||
| 111 | 'A', 'B', 'C', 'Ç', 'D', 'E', 'F', 'G', 'Ğ', 'H', 'I', 'İ', 'J', 'K', 'L', 'M', 'N', 'O', 'Ö', 'P', 'R', 'S', 'Ş', 'T', 'U', 'Ü', 'V', 'Y', 'Z', |
||
| 112 | ]; |
||
| 113 | default: |
||
| 114 | return [ |
||
| 115 | 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', |
||
| 116 | ]; |
||
| 117 | } |
||
| 118 | } |
||
| 119 | |||
| 120 | /** |
||
| 121 | * Get the initial letter of a name, taking care of multi-letter sequences and equivalences. |
||
| 122 | * |
||
| 123 | * @param string $name |
||
| 124 | * |
||
| 125 | * @return string |
||
| 126 | */ |
||
| 127 | public function initialLetter($name) { |
||
| 171 | } |
||
| 172 | |||
| 173 | /** |
||
| 174 | * Generate SQL to match a given letter, taking care of cases that |
||
| 175 | * are not covered by the collation setting. |
||
| 176 | * |
||
| 177 | * We must consider: |
||
| 178 | * potential substrings, such as Czech "CH" and "C" |
||
| 179 | * equivalent letters, such as Danish "AA" and "Å" |
||
| 180 | * |
||
| 181 | * We COULD write something that handles all languages generically, |
||
| 182 | * but its performance would most likely be poor. |
||
| 183 | * |
||
| 184 | * For languages that don't appear in this list, we could write |
||
| 185 | * simpler versions of the surnameAlpha() and givenAlpha() functions, |
||
| 186 | * but it gives no noticable improvement in performance. |
||
| 187 | * |
||
| 188 | * @param string $field |
||
| 189 | * @param string $letter |
||
| 190 | * |
||
| 191 | * @return string |
||
| 192 | */ |
||
| 193 | private function getInitialSql($field, $letter) { |
||
| 194 | switch (WT_LOCALE) { |
||
| 195 | case 'cs': |
||
| 196 | switch ($letter) { |
||
| 197 | case 'C': return $field . " LIKE 'C%' COLLATE " . I18N::collation() . " AND " . $field . " NOT LIKE 'CH%' COLLATE " . I18N::collation(); |
||
| 198 | } |
||
| 199 | break; |
||
| 200 | case 'da': |
||
| 201 | case 'nb': |
||
| 202 | case 'nn': |
||
| 203 | switch ($letter) { |
||
| 204 | // AA gets listed under Å |
||
| 205 | case 'A': return $field . " LIKE 'A%' COLLATE " . I18N::collation() . " AND " . $field . " NOT LIKE 'AA%' COLLATE " . I18N::collation(); |
||
| 206 | case 'Å': return "(" . $field . " LIKE 'Å%' COLLATE " . I18N::collation() . " OR " . $field . " LIKE 'AA%' COLLATE " . I18N::collation() . ")"; |
||
| 207 | } |
||
| 208 | break; |
||
| 209 | case 'hu': |
||
| 210 | switch ($letter) { |
||
| 211 | case 'C': return $field . " LIKE 'C%' COLLATE " . I18N::collation() . " AND " . $field . " NOT LIKE 'CS%' COLLATE " . I18N::collation(); |
||
| 212 | case 'D': return $field . " LIKE 'D%' COLLATE " . I18N::collation() . " AND " . $field . " NOT LIKE 'DZ%' COLLATE " . I18N::collation(); |
||
| 213 | case 'DZ': return $field . " LIKE 'DZ%' COLLATE " . I18N::collation() . " AND " . $field . " NOT LIKE 'DZS%' COLLATE " . I18N::collation(); |
||
| 214 | case 'G': return $field . " LIKE 'G%' COLLATE " . I18N::collation() . " AND " . $field . " NOT LIKE 'GY%' COLLATE " . I18N::collation(); |
||
| 215 | case 'L': return $field . " LIKE 'L%' COLLATE " . I18N::collation() . " AND " . $field . " NOT LIKE 'LY%' COLLATE " . I18N::collation(); |
||
| 216 | case 'N': return $field . " LIKE 'N%' COLLATE " . I18N::collation() . " AND " . $field . " NOT LIKE 'NY%' COLLATE " . I18N::collation(); |
||
| 217 | case 'S': return $field . " LIKE 'S%' COLLATE " . I18N::collation() . " AND " . $field . " NOT LIKE 'SZ%' COLLATE " . I18N::collation(); |
||
| 218 | case 'T': return $field . " LIKE 'T%' COLLATE " . I18N::collation() . " AND " . $field . " NOT LIKE 'TY%' COLLATE " . I18N::collation(); |
||
| 219 | case 'Z': return $field . " LIKE 'Z%' COLLATE " . I18N::collation() . " AND " . $field . " NOT LIKE 'ZS%' COLLATE " . I18N::collation(); |
||
| 220 | } |
||
| 221 | break; |
||
| 222 | case 'nl': |
||
| 223 | switch ($letter) { |
||
| 224 | case 'I': return $field . " LIKE 'I%' COLLATE " . I18N::collation() . " AND " . $field . " NOT LIKE 'IJ%' COLLATE " . I18N::collation(); |
||
| 225 | } |
||
| 226 | break; |
||
| 227 | } |
||
| 228 | |||
| 229 | // Easy cases: the MySQL collation rules take care of it |
||
| 230 | return "$field LIKE CONCAT('@'," . Database::quote($letter) . ",'%') COLLATE " . I18N::collation() . " ESCAPE '@'"; |
||
| 231 | } |
||
| 232 | |||
| 233 | /** |
||
| 234 | * Get a list of initial surname letters for indilist.php and famlist.php |
||
| 235 | * |
||
| 236 | * @param bool $marnm if set, include married names |
||
| 237 | * @param bool $fams if set, only consider individuals with FAMS records |
||
| 238 | * @param bool $totals if set, count the number of names beginning with each letter |
||
| 239 | * |
||
| 240 | * @return int[] |
||
| 241 | */ |
||
| 242 | public function surnameAlpha($marnm, $fams, $totals = true) { |
||
| 305 | } |
||
| 306 | |||
| 307 | /** |
||
| 308 | * Get a list of initial given name letters for indilist.php and famlist.php |
||
| 309 | * |
||
| 310 | * @param string $surn if set, only consider people with this surname |
||
| 311 | * @param string $salpha if set, only consider surnames starting with this letter |
||
| 312 | * @param bool $marnm if set, include married names |
||
| 313 | * @param bool $fams if set, only consider individuals with FAMS records |
||
| 314 | * |
||
| 315 | * @return int[] |
||
| 316 | */ |
||
| 317 | public function givenAlpha($surn, $salpha, $marnm, $fams) { |
||
| 318 | $alphas = []; |
||
| 319 | |||
| 320 | $sql = |
||
| 321 | "SELECT SQL_CACHE COUNT(DISTINCT n_id)" . |
||
| 322 | " FROM `##name`" . |
||
| 323 | ($fams ? " JOIN `##link` ON (n_id=l_from AND n_file=l_file AND l_type='FAMS') " : "") . |
||
| 324 | " WHERE n_file=" . $this->tree()->getTreeId() . " " . |
||
| 325 | ($marnm ? "" : " AND n_type!='_MARNM'"); |
||
| 326 | |||
| 327 | if ($surn) { |
||
| 328 | $sql .= " AND n_surn=" . Database::quote($surn) . " COLLATE '" . I18N::collation() . "'"; |
||
| 329 | } elseif ($salpha == ',') { |
||
| 330 | $sql .= " AND n_surn=''"; |
||
| 331 | } elseif ($salpha == '@') { |
||
| 332 | $sql .= " AND n_surn='@N.N.'"; |
||
| 333 | } elseif ($salpha) { |
||
| 334 | $sql .= " AND " . $this->getInitialSql('n_surn', $salpha); |
||
| 335 | } else { |
||
| 336 | // All surnames |
||
| 337 | $sql .= " AND n_surn NOT IN ('', '@N.N.')"; |
||
| 338 | } |
||
| 339 | |||
| 340 | // Fetch all the letters in our alphabet, whether or not there |
||
| 341 | // are any names beginning with that letter. It looks better to |
||
| 342 | // show the full alphabet, rather than omitting rare letters such as X |
||
| 343 | foreach ($this->getAlphabetForLocale(WT_LOCALE) as $letter) { |
||
| 344 | $count = Database::prepare($sql . " AND " . $this->getInitialSql('n_givn', $letter))->fetchOne(); |
||
| 345 | $alphas[$letter] = $count; |
||
| 346 | } |
||
| 347 | |||
| 348 | // Now fetch initial letters that are not in our alphabet, |
||
| 349 | // including "@" (for "@N.N.") and "" for no surname |
||
| 350 | $sql = |
||
| 351 | "SELECT SQL_CACHE initial, total FROM (SELECT UPPER(LEFT(n_givn, 1)) AS initial, COUNT(DISTINCT n_id) AS total" . |
||
| 352 | " FROM `##name` " . |
||
| 353 | ($fams ? " JOIN `##link` ON (n_id = l_from AND n_file = l_file AND l_type = 'FAMS') " : "") . |
||
| 354 | " WHERE n_file = :tree_id" . |
||
| 355 | ($marnm ? "" : " AND n_type != '_MARNM'"); |
||
| 356 | |||
| 357 | $args = [ |
||
| 358 | 'tree_id' => $this->tree()->getTreeId(), |
||
| 359 | ]; |
||
| 360 | |||
| 361 | if ($surn) { |
||
| 362 | $sql .= " AND n_surn COLLATE :collate_1 = :surn"; |
||
| 363 | $args['collate_1'] = I18N::collation(); |
||
| 364 | $args['surn'] = $surn; |
||
| 365 | } elseif ($salpha === ',') { |
||
| 366 | $sql .= " AND n_surn = ''"; |
||
| 367 | } elseif ($salpha === '@') { |
||
| 368 | $sql .= " AND n_surn = '@N.N.'"; |
||
| 369 | } elseif ($salpha) { |
||
| 370 | $sql .= " AND " . $this->getInitialSql('n_surn', $salpha); |
||
| 371 | } else { |
||
| 372 | // All surnames |
||
| 373 | $sql .= " AND n_surn NOT IN ('', '@N.N.')"; |
||
| 374 | } |
||
| 375 | |||
| 376 | foreach ($this->getAlphabetForLocale(WT_LOCALE) as $letter) { |
||
| 377 | $sql .= " AND n_givn NOT LIKE '" . $letter . "%' COLLATE " . I18N::collation(); |
||
| 378 | } |
||
| 379 | $sql .= " GROUP BY UPPER(LEFT(n_givn, 1))) AS subquery ORDER BY initial = '@', initial = '', initial"; |
||
| 380 | |||
| 381 | foreach (Database::prepare($sql)->execute($args)->fetchAssoc() as $alpha => $count) { |
||
| 382 | $alphas[$alpha] = $count; |
||
| 383 | } |
||
| 384 | |||
| 385 | return $alphas; |
||
| 386 | } |
||
| 387 | |||
| 388 | /** |
||
| 389 | * Get a list of actual surnames and variants, based on a "root" surname. |
||
| 390 | * |
||
| 391 | * @param string $surn if set, only fetch people with this surname |
||
| 392 | * @param string $salpha if set, only consider surnames starting with this letter |
||
| 393 | * @param bool $marnm if set, include married names |
||
| 394 | * @param bool $fams if set, only consider individuals with FAMS records |
||
| 395 | * |
||
| 396 | * @return array |
||
| 397 | */ |
||
| 398 | public function surnames($surn, $salpha, $marnm, $fams) { |
||
| 399 | $sql = |
||
| 400 | "SELECT SQL_CACHE n2.n_surn, n1.n_surname, n1.n_id" . |
||
| 401 | " FROM `##name` n1 " . |
||
| 402 | ($fams ? " JOIN `##link` ON n_id = l_from AND n_file = l_file AND l_type = 'FAMS' " : "") . |
||
| 403 | " JOIN (SELECT n_surn COLLATE :collate_0 AS n_surn, n_file FROM `##name`" . |
||
| 404 | " WHERE n_file = :tree_id" . |
||
| 405 | ($marnm ? "" : " AND n_type != '_MARNM'"); |
||
| 406 | |||
| 407 | $args = [ |
||
| 408 | 'tree_id' => $this->tree()->getTreeId(), |
||
| 409 | 'collate_0' => I18N::collation(), |
||
| 410 | ]; |
||
| 411 | |||
| 412 | if ($surn) { |
||
| 413 | $sql .= " AND n_surn COLLATE :collate_1 = :surn"; |
||
| 414 | $args['collate_1'] = I18N::collation(); |
||
| 415 | $args['surn'] = $surn; |
||
| 416 | } elseif ($salpha === ',') { |
||
| 417 | $sql .= " AND n_surn = ''"; |
||
| 418 | } elseif ($salpha === '@') { |
||
| 419 | $sql .= " AND n_surn = '@N.N.'"; |
||
| 420 | } elseif ($salpha) { |
||
| 421 | $sql .= " AND " . $this->getInitialSql('n_surn', $salpha); |
||
| 422 | } else { |
||
| 423 | // All surnames |
||
| 424 | $sql .= " AND n_surn NOT IN ('', '@N.N.')"; |
||
| 425 | } |
||
| 426 | $sql .= " GROUP BY n_surn COLLATE :collate_2, n_file) AS n2 ON (n1.n_surn = n2.n_surn COLLATE :collate_3 AND n1.n_file = n2.n_file)"; |
||
| 427 | $args['collate_2'] = I18N::collation(); |
||
| 428 | $args['collate_3'] = I18N::collation(); |
||
| 429 | |||
| 430 | $list = []; |
||
| 431 | foreach (Database::prepare($sql)->execute($args)->fetchAll() as $row) { |
||
| 432 | $list[I18N::strtoupper($row->n_surn)][$row->n_surname][$row->n_id] = true; |
||
| 433 | } |
||
| 434 | |||
| 435 | return $list; |
||
| 436 | } |
||
| 437 | |||
| 438 | /** |
||
| 439 | * Fetch a list of individuals with specified names |
||
| 440 | * |
||
| 441 | * To search for unknown names, use $surn="@N.N.", $salpha="@" or $galpha="@" |
||
| 442 | * To search for names with no surnames, use $salpha="," |
||
| 443 | * |
||
| 444 | * @param string $surn if set, only fetch people with this surname |
||
| 445 | * @param string $salpha if set, only fetch surnames starting with this letter |
||
| 446 | * @param string $galpha if set, only fetch given names starting with this letter |
||
| 447 | * @param bool $marnm if set, include married names |
||
| 448 | * @param bool $fams if set, only fetch individuals with FAMS records |
||
| 449 | * |
||
| 450 | * @return Individual[] |
||
| 451 | */ |
||
| 452 | public function individuals($surn, $salpha, $galpha, $marnm, $fams) { |
||
| 453 | $sql = |
||
| 454 | "SELECT i_id AS xref, i_gedcom AS gedcom, n_full " . |
||
| 455 | "FROM `##individuals` " . |
||
| 456 | "JOIN `##name` ON n_id = i_id AND n_file = i_file " . |
||
| 457 | ($fams ? "JOIN `##link` ON n_id = l_from AND n_file = l_file AND l_type = 'FAMS' " : "") . |
||
| 458 | "WHERE n_file = :tree_id " . |
||
| 459 | ($marnm ? "" : "AND n_type != '_MARNM'"); |
||
| 460 | |||
| 461 | $args = [ |
||
| 462 | 'tree_id' => $this->tree()->getTreeId(), |
||
| 463 | ]; |
||
| 464 | |||
| 465 | if ($surn) { |
||
| 466 | $sql .= " AND n_surn COLLATE :collate_1 = :surn"; |
||
| 467 | $args['collate_1'] = I18N::collation(); |
||
| 468 | $args['surn'] = $surn; |
||
| 469 | } elseif ($salpha === ',') { |
||
| 470 | $sql .= " AND n_surn = ''"; |
||
| 471 | } elseif ($salpha === '@') { |
||
| 472 | $sql .= " AND n_surn = '@N.N.'"; |
||
| 473 | } elseif ($salpha) { |
||
| 474 | $sql .= " AND " . $this->getInitialSql('n_surn', $salpha); |
||
| 475 | } else { |
||
| 476 | // All surnames |
||
| 477 | $sql .= " AND n_surn NOT IN ('', '@N.N.')"; |
||
| 478 | } |
||
| 479 | if ($galpha) { |
||
| 480 | $sql .= " AND " . $this->getInitialSql('n_givn', $galpha); |
||
| 481 | } |
||
| 482 | |||
| 483 | $sql .= " ORDER BY CASE n_surn WHEN '@N.N.' THEN 1 ELSE 0 END, n_surn COLLATE :collate_2, CASE n_givn WHEN '@P.N.' THEN 1 ELSE 0 END, n_givn COLLATE :collate_3"; |
||
| 484 | $args['collate_2'] = I18N::collation(); |
||
| 485 | $args['collate_3'] = I18N::collation(); |
||
| 486 | |||
| 487 | $list = []; |
||
| 488 | $rows = Database::prepare($sql)->execute($args)->fetchAll(); |
||
| 489 | foreach ($rows as $row) { |
||
| 490 | $person = Individual::getInstance($row->xref, $this->tree(), $row->gedcom); |
||
| 491 | // The name from the database may be private - check the filtered list... |
||
| 492 | foreach ($person->getAllNames() as $n => $name) { |
||
| 493 | if ($name['fullNN'] == $row->n_full) { |
||
| 494 | $person->setPrimaryName($n); |
||
| 495 | // We need to clone $person, as we may have multiple references to the |
||
| 496 | // same person in this list, and the "primary name" would otherwise |
||
| 497 | // be shared amongst all of them. |
||
| 498 | $list[] = clone $person; |
||
| 499 | break; |
||
| 500 | } |
||
| 501 | } |
||
| 502 | } |
||
| 503 | |||
| 504 | return $list; |
||
| 505 | } |
||
| 506 | |||
| 507 | /** |
||
| 508 | * Fetch a list of families with specified names |
||
| 509 | * |
||
| 510 | * To search for unknown names, use $surn="@N.N.", $salpha="@" or $galpha="@" |
||
| 511 | * To search for names with no surnames, use $salpha="," |
||
| 512 | * |
||
| 513 | * @param string $surn if set, only fetch people with this surname |
||
| 514 | * @param string $salpha if set, only fetch surnames starting with this letter |
||
| 515 | * @param string $galpha if set, only fetch given names starting with this letter |
||
| 516 | * @param bool $marnm if set, include married names |
||
| 517 | * |
||
| 518 | * @return Family[] |
||
| 519 | */ |
||
| 520 | public function families($surn, $salpha, $galpha, $marnm) { |
||
| 521 | $list = []; |
||
| 522 | foreach ($this->individuals($surn, $salpha, $galpha, $marnm, true) as $indi) { |
||
| 523 | foreach ($indi->getSpouseFamilies() as $family) { |
||
| 524 | $list[$family->getXref()] = $family; |
||
| 525 | } |
||
| 526 | } |
||
| 527 | usort($list, '\Fisharebest\Webtrees\GedcomRecord::compare'); |
||
| 528 | |||
| 529 | return $list; |
||
| 530 | } |
||
| 531 | |||
| 532 | /** |
||
| 533 | * Some initial letters have a special meaning |
||
| 534 | * |
||
| 535 | * @param string $initial |
||
| 536 | * |
||
| 537 | * @return string |
||
| 538 | */ |
||
| 539 | public function givenNameInitial($initial) { |
||
| 547 | } |
||
| 548 | } |
||
| 549 | |||
| 550 | /** |
||
| 551 | * Some initial letters have a special meaning |
||
| 552 | * |
||
| 553 | * @param string $initial |
||
| 554 | * |
||
| 555 | * @return string |
||
| 556 | */ |
||
| 557 | public function surnameInitial($initial) { |
||
| 568 | } |
||
| 569 | } |
||
| 570 | } |
||
| 571 |
According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.
}
To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.