Total Complexity | 344 |
Total Lines | 2474 |
Duplicated Lines | 0 % |
Changes | 0 |
Complex classes like Statistics 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 Statistics, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
61 | class Statistics |
||
62 | { |
||
63 | private Tree $tree; |
||
64 | |||
65 | private ModuleService $module_service; |
||
66 | |||
67 | private UserService $user_service; |
||
68 | |||
69 | private StatisticsData $data; |
||
70 | |||
71 | private StatisticsFormat $format; |
||
72 | |||
73 | public function __construct( |
||
74 | ModuleService $module_service, |
||
75 | Tree $tree, |
||
76 | UserService $user_service |
||
77 | ) { |
||
78 | $this->module_service = $module_service; |
||
79 | $this->user_service = $user_service; |
||
80 | $this->tree = $tree; |
||
81 | $this->data = new StatisticsData($tree, $user_service); |
||
82 | $this->format = new StatisticsFormat(); |
||
83 | } |
||
84 | |||
85 | public function ageBetweenSpousesFM(string $limit = '10'): string |
||
86 | { |
||
87 | return $this->data->ageBetweenSpousesFM((int) $limit); |
||
88 | } |
||
89 | |||
90 | public function ageBetweenSpousesFMList(string $limit = '10'): string |
||
91 | { |
||
92 | return $this->data->ageBetweenSpousesFMList((int) $limit); |
||
93 | } |
||
94 | |||
95 | public function ageBetweenSpousesMF(string $limit = '10'): string |
||
96 | { |
||
97 | return $this->data->ageBetweenSpousesMF((int) $limit); |
||
98 | } |
||
99 | |||
100 | public function ageBetweenSpousesMFList(string $limit = '10'): string |
||
101 | { |
||
102 | return $this->data->ageBetweenSpousesMFList((int) $limit); |
||
103 | } |
||
104 | |||
105 | public function averageChildren(): string |
||
106 | { |
||
107 | return I18N::number($this->data->averageChildrenPerFamily(), 2); |
||
108 | } |
||
109 | |||
110 | public function averageLifespan(string $show_years = '0'): string |
||
111 | { |
||
112 | $days = $this->data->averageLifespanDays('ALL'); |
||
113 | |||
114 | return $show_years ? $this->format->age($days) : I18N::number((int) ($days / 365.25)); |
||
115 | } |
||
116 | |||
117 | public function averageLifespanFemale(string $show_years = '0'): string |
||
118 | { |
||
119 | $days = $this->data->averageLifespanDays('F'); |
||
120 | |||
121 | return $show_years ? $this->format->age($days) : I18N::number((int) ($days / 365.25)); |
||
122 | } |
||
123 | |||
124 | public function averageLifespanMale(string $show_years = '0'): string |
||
125 | { |
||
126 | $days = $this->data->averageLifespanDays('M'); |
||
127 | |||
128 | return $show_years ? $this->format->age($days) : I18N::number((int) ($days / 365.25)); |
||
129 | } |
||
130 | |||
131 | public function browserDate(): string |
||
132 | { |
||
133 | return Registry::timestampFactory()->now()->format(strtr(I18N::dateFormat(), ['%' => ''])); |
||
134 | } |
||
135 | |||
136 | public function browserTime(): string |
||
137 | { |
||
138 | return Registry::timestampFactory()->now()->format(strtr(I18N::timeFormat(), ['%' => ''])); |
||
139 | } |
||
140 | |||
141 | public function browserTimezone(): string |
||
142 | { |
||
143 | return Registry::timestampFactory()->now()->format('T'); |
||
144 | } |
||
145 | |||
146 | /** |
||
147 | * Create any of the other blocks. |
||
148 | * Use as #callBlock:block_name# |
||
149 | * |
||
150 | * @param string ...$params |
||
151 | */ |
||
152 | public function callBlock(string $block = '', ...$params): string |
||
153 | { |
||
154 | $module = $this->module_service |
||
155 | ->findByComponent(ModuleBlockInterface::class, $this->tree, Auth::user()) |
||
156 | ->first(static fn (ModuleInterface $module): bool => $module->name() === $block && $module->name() !== 'html'); |
||
157 | |||
158 | if ($module === null) { |
||
159 | return ''; |
||
160 | } |
||
161 | |||
162 | // Build the config array |
||
163 | $cfg = []; |
||
164 | foreach ($params as $config) { |
||
165 | $bits = explode('=', $config); |
||
166 | |||
167 | if (count($bits) < 2) { |
||
168 | continue; |
||
169 | } |
||
170 | |||
171 | $v = array_shift($bits); |
||
172 | $cfg[$v] = implode('=', $bits); |
||
173 | } |
||
174 | |||
175 | return $module->getBlock($this->tree, 0, ModuleBlockInterface::CONTEXT_EMBED, $cfg); |
||
176 | } |
||
177 | |||
178 | public function chartCommonGiven(string $color1 = 'ffffff', string $color2 = '84beff', string $limit = '7'): string |
||
179 | { |
||
180 | $given = $this->data->commonGivenNames('ALL', 1, (int) $limit)->all(); |
||
181 | |||
182 | if ($given === []) { |
||
183 | return I18N::translate('This information is not available.'); |
||
184 | } |
||
185 | |||
186 | $tot = 0; |
||
187 | foreach ($given as $count) { |
||
188 | $tot += $count; |
||
189 | } |
||
190 | |||
191 | $data = [ |
||
192 | [ |
||
193 | I18N::translate('Name'), |
||
194 | I18N::translate('Total'), |
||
195 | ], |
||
196 | ]; |
||
197 | |||
198 | foreach ($given as $name => $count) { |
||
199 | $data[] = [$name, $count]; |
||
200 | } |
||
201 | |||
202 | $count_all_names = $this->data->commonGivenNames('ALL', 1, PHP_INT_MAX)->sum(); |
||
203 | |||
204 | $data[] = [ |
||
205 | I18N::translate('Other'), |
||
206 | $count_all_names - $tot, |
||
207 | ]; |
||
208 | |||
209 | $colors = $this->format->interpolateRgb($color1, $color2, count($data) - 1); |
||
210 | |||
211 | return view('statistics/other/charts/pie', [ |
||
212 | 'title' => null, |
||
213 | 'data' => $data, |
||
214 | 'colors' => $colors, |
||
215 | 'language' => I18N::languageTag(), |
||
216 | ]); |
||
217 | } |
||
218 | |||
219 | public function chartCommonSurnames( |
||
220 | string $color1 = 'ffffff', |
||
221 | string $color2 = '84beff', |
||
222 | string $limit = '10' |
||
223 | ): string { |
||
224 | $all_surnames = $this->data->commonSurnames((int) $limit, 0, 'count'); |
||
225 | |||
226 | if ($all_surnames === []) { |
||
227 | return I18N::translate('This information is not available.'); |
||
228 | } |
||
229 | |||
230 | $surname_tradition = Registry::surnameTraditionFactory() |
||
231 | ->make($this->tree->getPreference('SURNAME_TRADITION')); |
||
232 | |||
233 | $tot = 0; |
||
234 | foreach ($all_surnames as $surnames) { |
||
235 | $tot += array_sum($surnames); |
||
236 | } |
||
237 | |||
238 | $data = [ |
||
239 | [ |
||
240 | I18N::translate('Name'), |
||
241 | I18N::translate('Total') |
||
242 | ], |
||
243 | ]; |
||
244 | |||
245 | foreach ($all_surnames as $surns) { |
||
246 | $max_name = 0; |
||
247 | $count_per = 0; |
||
248 | $top_name = ''; |
||
249 | |||
250 | foreach ($surns as $spfxsurn => $count) { |
||
251 | $per = $count; |
||
252 | $count_per += $per; |
||
253 | |||
254 | // select most common surname from all variants |
||
255 | if ($per > $max_name) { |
||
256 | $max_name = $per; |
||
257 | $top_name = $spfxsurn; |
||
258 | } |
||
259 | } |
||
260 | |||
261 | if ($surname_tradition instanceof PolishSurnameTradition) { |
||
262 | // Most common surname should be in male variant (Kowalski, not Kowalska) |
||
263 | $top_name = preg_replace( |
||
264 | [ |
||
265 | '/ska$/', |
||
266 | '/cka$/', |
||
267 | '/dzka$/', |
||
268 | '/żka$/', |
||
269 | ], |
||
270 | [ |
||
271 | 'ski', |
||
272 | 'cki', |
||
273 | 'dzki', |
||
274 | 'żki', |
||
275 | ], |
||
276 | $top_name |
||
277 | ); |
||
278 | } |
||
279 | |||
280 | $data[] = [(string) $top_name, $count_per]; |
||
281 | } |
||
282 | |||
283 | $data[] = [ |
||
284 | I18N::translate('Other'), |
||
285 | $this->data->countIndividuals() - $tot |
||
286 | ]; |
||
287 | |||
288 | $colors = $this->format->interpolateRgb($color1, $color2, count($data) - 1); |
||
289 | |||
290 | return view('statistics/other/charts/pie', [ |
||
291 | 'title' => null, |
||
292 | 'data' => $data, |
||
293 | 'colors' => $colors, |
||
294 | 'language' => I18N::languageTag(), |
||
295 | ]); |
||
296 | } |
||
297 | |||
298 | public function chartDistribution( |
||
299 | string $chart_shows = 'world', |
||
300 | string $chart_type = '', |
||
301 | string $surname = '' |
||
302 | ): string { |
||
303 | return $this->data->chartDistribution($chart_shows, $chart_type, $surname); |
||
304 | } |
||
305 | |||
306 | public function chartFamsWithSources(string $color1 = 'c2dfff', string $color2 = '84beff'): string |
||
307 | { |
||
308 | $total_families = $this->data->countFamilies(); |
||
309 | $total_families_with_sources = $this->data->countFamiliesWithSources(); |
||
310 | |||
311 | $data = [ |
||
312 | [I18N::translate('Without sources'), $total_families - $total_families_with_sources], |
||
313 | [I18N::translate('With sources'), $total_families_with_sources], |
||
314 | ]; |
||
315 | |||
316 | return $this->format->pieChart( |
||
317 | $data, |
||
318 | [$color1, $color2], |
||
319 | I18N::translate('Families with sources'), |
||
320 | I18N::translate('Type'), |
||
321 | I18N::translate('Total'), |
||
322 | true |
||
323 | ); |
||
324 | } |
||
325 | |||
326 | public function chartIndisWithSources(string $color1 = 'c2dfff', string $color2 = '84beff'): string |
||
327 | { |
||
328 | $total_individuals = $this->data->countIndividuals(); |
||
329 | $total_individuals_with_sources = $this->data->countIndividualsWithSources(); |
||
330 | |||
331 | $data = [ |
||
332 | [I18N::translate('Without sources'), $total_individuals - $total_individuals_with_sources], |
||
333 | [I18N::translate('With sources'), $total_individuals_with_sources], |
||
334 | ]; |
||
335 | |||
336 | return $this->format->pieChart( |
||
337 | $data, |
||
338 | [$color1, $color2], |
||
339 | I18N::translate('Individuals with sources'), |
||
340 | I18N::translate('Type'), |
||
341 | I18N::translate('Total'), |
||
342 | true |
||
343 | ); |
||
344 | } |
||
345 | |||
346 | public function chartLargestFamilies( |
||
347 | string $color1 = 'ffffff', |
||
348 | string $color2 = '84beff', |
||
349 | string $limit = '7' |
||
350 | ): string { |
||
351 | $data = DB::table('families') |
||
352 | ->select(['f_numchil AS total', 'f_id AS id']) |
||
353 | ->where('f_file', '=', $this->tree->id()) |
||
354 | ->orderBy('total', 'desc') |
||
355 | ->limit((int) $limit) |
||
356 | ->get() |
||
357 | ->map(fn (object $row): array => [ |
||
358 | htmlspecialchars_decode(strip_tags(Registry::familyFactory()->make($row->id, $this->tree)->fullName())), |
||
359 | (int) $row->total, |
||
360 | ]) |
||
361 | ->all(); |
||
362 | |||
363 | return $this->format->pieChart( |
||
364 | $data, |
||
365 | $this->format->interpolateRgb($color1, $color2, count($data)), |
||
366 | I18N::translate('Largest families'), |
||
367 | I18N::translate('Family'), |
||
368 | I18N::translate('Children') |
||
369 | ); |
||
370 | } |
||
371 | |||
372 | public function chartMedia(string $color1 = 'ffffff', string $color2 = '84beff'): string |
||
373 | { |
||
374 | $data = $this->data->countMediaByType(); |
||
375 | |||
376 | return $this->format->pieChart( |
||
377 | $data, |
||
378 | $this->format->interpolateRgb($color1, $color2, count($data)), |
||
379 | I18N::translate('Media by type'), |
||
380 | I18N::translate('Type'), |
||
381 | I18N::translate('Total'), |
||
382 | ); |
||
383 | } |
||
384 | |||
385 | public function chartMortality(string $color_living = '#ffffff', string $color_dead = '#cccccc'): string |
||
386 | { |
||
387 | $total_living = $this->data->countIndividualsLiving(); |
||
388 | $total_dead = $this->data->countIndividualsDeceased(); |
||
389 | |||
390 | $data = [ |
||
391 | [I18N::translate('Century'), I18N::translate('Total')], |
||
392 | ]; |
||
393 | |||
394 | if ($total_living > 0 || $total_dead > 0) { |
||
395 | $data[] = [I18N::translate('Living'), $total_living]; |
||
396 | $data[] = [I18N::translate('Dead'), $total_dead]; |
||
397 | } |
||
398 | |||
399 | $colors = $this->format->interpolateRgb($color_living, $color_dead, count($data) - 1); |
||
400 | |||
401 | return view('statistics/other/charts/pie', [ |
||
402 | 'title' => null, |
||
403 | 'data' => $data, |
||
404 | 'colors' => $colors, |
||
405 | 'labeledValueText' => 'percentage', |
||
406 | 'language' => I18N::languageTag(), |
||
407 | ]); |
||
408 | } |
||
409 | |||
410 | public function chartNoChildrenFamilies(): string |
||
411 | { |
||
412 | $data = [ |
||
413 | [ |
||
414 | I18N::translate('Century'), |
||
415 | I18N::translate('Total'), |
||
416 | ], |
||
417 | ]; |
||
418 | |||
419 | $records = DB::table('families') |
||
420 | ->selectRaw('ROUND((d_year + 49) / 100, 0) AS century') |
||
421 | ->selectRaw('COUNT(*) AS total') |
||
422 | ->join('dates', static function (JoinClause $join): void { |
||
423 | $join->on('d_file', '=', 'f_file') |
||
424 | ->on('d_gid', '=', 'f_id'); |
||
425 | }) |
||
426 | ->where('f_file', '=', $this->tree->id()) |
||
427 | ->where('f_numchil', '=', 0) |
||
428 | ->where('d_fact', '=', 'MARR') |
||
429 | ->whereIn('d_type', ['@#DGREGORIAN@', '@#DJULIAN@']) |
||
430 | ->groupBy(['century']) |
||
431 | ->orderBy('century') |
||
432 | ->get() |
||
433 | ->map(static fn (object $row): object => (object) [ |
||
434 | 'century' => (int) $row->century, |
||
435 | 'total' => (int) $row->total, |
||
436 | ]) |
||
437 | ->all(); |
||
438 | |||
439 | $total = 0; |
||
440 | |||
441 | foreach ($records as $record) { |
||
442 | $total += $record->total; |
||
443 | |||
444 | $data[] = [ |
||
445 | $this->format->century($record->century), |
||
446 | $record->total, |
||
447 | ]; |
||
448 | } |
||
449 | |||
450 | $families_with_no_children = $this->data->countFamiliesWithNoChildren(); |
||
451 | |||
452 | if ($families_with_no_children - $total > 0) { |
||
453 | $data[] = [ |
||
454 | I18N::translateContext('unknown century', 'Unknown'), |
||
455 | $families_with_no_children - $total, |
||
456 | ]; |
||
457 | } |
||
458 | |||
459 | $chart_title = I18N::translate('Number of families without children'); |
||
460 | $chart_options = [ |
||
461 | 'title' => $chart_title, |
||
462 | 'subtitle' => '', |
||
463 | 'legend' => [ |
||
464 | 'position' => 'none', |
||
465 | ], |
||
466 | 'vAxis' => [ |
||
467 | 'title' => I18N::translate('Total families'), |
||
468 | ], |
||
469 | 'hAxis' => [ |
||
470 | 'showTextEvery' => 1, |
||
471 | 'slantedText' => false, |
||
472 | 'title' => I18N::translate('Century'), |
||
473 | ], |
||
474 | 'colors' => [ |
||
475 | '#84beff', |
||
476 | ], |
||
477 | ]; |
||
478 | |||
479 | return view('statistics/other/charts/column', [ |
||
480 | 'data' => $data, |
||
481 | 'chart_options' => $chart_options, |
||
482 | 'chart_title' => $chart_title, |
||
483 | 'language' => I18N::languageTag(), |
||
484 | ]); |
||
485 | } |
||
486 | |||
487 | public function chartSex( |
||
488 | string $color_female = '#ffd1dc', |
||
489 | string $color_male = '#84beff', |
||
490 | string $color_unknown = '#777777', |
||
491 | string $color_other = '#777777' |
||
492 | ): string { |
||
493 | $data = [ |
||
494 | [I18N::translate('Males'), $this->data->countIndividualsBySex('M')], |
||
495 | [I18N::translate('Females'), $this->data->countIndividualsBySex('F')], |
||
496 | [I18N::translate('Unknown'), $this->data->countIndividualsBySex('U')], |
||
497 | [I18N::translate('Other'), $this->data->countIndividualsBySex('X')], |
||
498 | ]; |
||
499 | |||
500 | return $this->format->pieChart( |
||
501 | $data, |
||
502 | [$color_male, $color_female, $color_unknown, $color_other], |
||
503 | I18N::translate('Sex'), |
||
504 | I18N::translate('Sex'), |
||
505 | I18N::translate('Total'), |
||
506 | true |
||
507 | ); |
||
508 | } |
||
509 | |||
510 | public function commonBirthPlacesList(string $limit = '10'): string |
||
511 | { |
||
512 | return view('statistics/other/top10-list', ['records' => $this->data->countPlacesForIndividuals('BIRT', (int) $limit)]); |
||
513 | } |
||
514 | |||
515 | public function commonCountriesList(string $limit = '10'): string |
||
516 | { |
||
517 | return view('statistics/other/top10-list', ['records' => $this->data->countCountries((int) $limit)]); |
||
518 | } |
||
519 | |||
520 | public function commonDeathPlacesList(string $limit = '10'): string |
||
521 | { |
||
522 | return view('statistics/other/top10-list', ['records' => $this->data->countPlacesForIndividuals('DEAT', (int) $limit)]); |
||
523 | } |
||
524 | |||
525 | public function commonGiven(string $threshold = '1', string $limit = '10'): string |
||
526 | { |
||
527 | return $this->data->commonGivenNames('ALL', (int) $threshold, (int) $limit) |
||
528 | ->mapWithKeys(static fn (int $value, mixed $key): array => [ |
||
529 | $key => '<bdi>' . e($key) . '</bdi>', |
||
530 | ]) |
||
531 | ->implode(I18N::$list_separator); |
||
532 | } |
||
533 | |||
534 | public function commonGivenFemale(string $threshold = '1', string $limit = '10'): string |
||
535 | { |
||
536 | return $this->data->commonGivenNames('F', (int) $threshold, (int) $limit) |
||
537 | ->mapWithKeys(static fn (int $value, mixed $key): array => [ |
||
538 | $key => '<bdi>' . e($key) . '</bdi>', |
||
539 | ]) |
||
540 | ->implode(I18N::$list_separator); |
||
541 | } |
||
542 | |||
543 | public function commonGivenFemaleList(string $threshold = '1', string $limit = '10'): string |
||
544 | { |
||
545 | return view('lists/given-names-list', [ |
||
546 | 'given_names' => $this->data->commonGivenNames('F', (int) $threshold, (int) $limit)->all(), |
||
547 | 'show_totals' => false, |
||
548 | ]); |
||
549 | } |
||
550 | |||
551 | public function commonGivenFemaleListTotals(string $threshold = '1', string $limit = '10'): string |
||
552 | { |
||
553 | return view('lists/given-names-list', [ |
||
554 | 'given_names' => $this->data->commonGivenNames('F', (int) $threshold, (int) $limit)->all(), |
||
555 | 'show_totals' => true, |
||
556 | ]); |
||
557 | } |
||
558 | |||
559 | public function commonGivenFemaleTable(string $threshold = '1', string $limit = '10'): string |
||
560 | { |
||
561 | return view('lists/given-names-table', [ |
||
562 | 'given_names' => $this->data->commonGivenNames('F', (int) $threshold, (int) $limit)->all(), |
||
563 | 'order' => [[1, 'desc']], |
||
564 | ]); |
||
565 | } |
||
566 | |||
567 | public function commonGivenFemaleTotals(string $threshold = '1', string $limit = '10'): string |
||
568 | { |
||
569 | return $this->data->commonGivenNames('F', (int) $threshold, (int) $limit) |
||
570 | ->mapWithKeys(static fn (int $value, mixed $key): array => [ |
||
571 | $key => '<bdi>' . e($key) . '</bdi> (' . I18N::number($value) . ')', |
||
572 | ]) |
||
573 | ->implode(I18N::$list_separator); |
||
574 | } |
||
575 | |||
576 | public function commonGivenList(string $threshold = '1', string $limit = '10'): string |
||
577 | { |
||
578 | return view('lists/given-names-list', [ |
||
579 | 'given_names' => $this->data->commonGivenNames('ALL', (int) $threshold, (int) $limit)->all(), |
||
580 | 'show_totals' => false, |
||
581 | ]); |
||
582 | } |
||
583 | |||
584 | public function commonGivenListTotals(string $threshold = '1', string $limit = '10'): string |
||
585 | { |
||
586 | return view('lists/given-names-list', [ |
||
587 | 'given_names' => $this->data->commonGivenNames('ALL', (int) $threshold, (int) $limit)->all(), |
||
588 | 'show_totals' => true, |
||
589 | ]); |
||
590 | } |
||
591 | |||
592 | public function commonGivenMale(string $threshold = '1', string $limit = '10'): string |
||
593 | { |
||
594 | return $this->data->commonGivenNames('M', (int) $threshold, (int) $limit) |
||
595 | ->mapWithKeys(static fn (int $value, mixed $key): array => [ |
||
596 | $key => '<bdi>' . e($key) . '</bdi>', |
||
597 | ]) |
||
598 | ->implode(I18N::$list_separator); |
||
599 | } |
||
600 | |||
601 | public function commonGivenMaleList(string $threshold = '1', string $limit = '10'): string |
||
602 | { |
||
603 | return view('lists/given-names-list', [ |
||
604 | 'given_names' => $this->data->commonGivenNames('M', (int) $threshold, (int) $limit)->all(), |
||
605 | 'show_totals' => false, |
||
606 | ]); |
||
607 | } |
||
608 | |||
609 | public function commonGivenMaleListTotals(string $threshold = '1', string $limit = '10'): string |
||
610 | { |
||
611 | return view('lists/given-names-list', [ |
||
612 | 'given_names' => $this->data->commonGivenNames('M', (int) $threshold, (int) $limit)->all(), |
||
613 | 'show_totals' => true, |
||
614 | ]); |
||
615 | } |
||
616 | |||
617 | public function commonGivenMaleTable(string $threshold = '1', string $limit = '10'): string |
||
618 | { |
||
619 | return view('lists/given-names-table', [ |
||
620 | 'given_names' => $this->data->commonGivenNames('M', (int) $threshold, (int) $limit)->all(), |
||
621 | 'order' => [[1, 'desc']], |
||
622 | ]); |
||
623 | } |
||
624 | |||
625 | public function commonGivenMaleTotals(string $threshold = '1', string $limit = '10'): string |
||
626 | { |
||
627 | return $this->data->commonGivenNames('M', (int) $threshold, (int) $limit) |
||
628 | ->mapWithKeys(static fn (int $value, mixed $key): array => [ |
||
629 | $key => '<bdi>' . e($key) . '</bdi> (' . I18N::number($value) . ')', |
||
630 | ]) |
||
631 | ->implode(I18N::$list_separator); |
||
632 | } |
||
633 | |||
634 | public function commonGivenOther(string $threshold = '1', string $limit = '10'): string |
||
635 | { |
||
636 | return $this->data->commonGivenNames('X', (int) $threshold, (int) $limit) |
||
637 | ->mapWithKeys(static fn (int $value, mixed $key): array => [ |
||
638 | $key => '<bdi>' . e($key) . '</bdi>', |
||
639 | ]) |
||
640 | ->implode(I18N::$list_separator); |
||
641 | } |
||
642 | |||
643 | public function commonGivenOtherList(string $threshold = '1', string $limit = '10'): string |
||
644 | { |
||
645 | return view('lists/given-names-list', [ |
||
646 | 'given_names' => $this->data->commonGivenNames('X', (int) $threshold, (int) $limit)->all(), |
||
647 | 'show_totals' => false, |
||
648 | ]); |
||
649 | } |
||
650 | |||
651 | public function commonGivenOtherListTotals(string $threshold = '1', string $limit = '10'): string |
||
652 | { |
||
653 | return view('lists/given-names-list', [ |
||
654 | 'given_names' => $this->data->commonGivenNames('X', (int) $threshold, (int) $limit)->all(), |
||
655 | 'show_totals' => true, |
||
656 | ]); |
||
657 | } |
||
658 | |||
659 | public function commonGivenOtherTable(string $threshold = '1', string $limit = '10'): string |
||
660 | { |
||
661 | return view('lists/given-names-table', [ |
||
662 | 'given_names' => $this->data->commonGivenNames('X', (int) $threshold, (int) $limit)->all(), |
||
663 | 'order' => [[1, 'desc']], |
||
664 | ]); |
||
665 | } |
||
666 | |||
667 | public function commonGivenOtherTotals(string $threshold = '1', string $limit = '10'): string |
||
668 | { |
||
669 | return $this->data->commonGivenNames('X', (int) $threshold, (int) $limit) |
||
670 | ->mapWithKeys(static fn (int $value, mixed $key): array => [ |
||
671 | $key => '<bdi>' . e($key) . '</bdi> (' . I18N::number($value) . ')', |
||
672 | ]) |
||
673 | ->implode(I18N::$list_separator); |
||
674 | } |
||
675 | |||
676 | public function commonGivenTable(string $threshold = '1', string $limit = '10'): string |
||
677 | { |
||
678 | return view('lists/given-names-table', [ |
||
679 | 'given_names' => $this->data->commonGivenNames('ALL', (int) $threshold, (int) $limit)->all(), |
||
680 | 'order' => [[1, 'desc']], |
||
681 | ]); |
||
682 | } |
||
683 | |||
684 | public function commonGivenTotals(string $threshold = '1', string $limit = '10'): string |
||
685 | { |
||
686 | return $this->data->commonGivenNames('ALL', (int) $threshold, (int) $limit) |
||
687 | ->mapWithKeys(static fn (int $value, mixed $key): array => [ |
||
688 | $key => '<bdi>' . e($key) . '</bdi> (' . I18N::number($value) . ')', |
||
689 | ]) |
||
690 | ->implode(I18N::$list_separator); |
||
691 | } |
||
692 | |||
693 | public function commonGivenUnknown(string $threshold = '1', string $limit = '10'): string |
||
694 | { |
||
695 | return $this->data->commonGivenNames('U', (int) $threshold, (int) $limit) |
||
696 | ->mapWithKeys(static fn (int $value, mixed $key): array => [ |
||
697 | $key => '<bdi>' . e($key) . '</bdi>', |
||
698 | ]) |
||
699 | ->implode(I18N::$list_separator); |
||
700 | } |
||
701 | |||
702 | public function commonGivenUnknownList(string $threshold = '1', string $limit = '10'): string |
||
703 | { |
||
704 | return view('lists/given-names-list', [ |
||
705 | 'given_names' => $this->data->commonGivenNames('U', (int) $threshold, (int) $limit)->all(), |
||
706 | 'show_totals' => false, |
||
707 | ]); |
||
708 | } |
||
709 | |||
710 | public function commonGivenUnknownListTotals(string $threshold = '1', string $limit = '10'): string |
||
711 | { |
||
712 | return view('lists/given-names-list', [ |
||
713 | 'given_names' => $this->data->commonGivenNames('U', (int) $threshold, (int) $limit)->all(), |
||
714 | 'show_totals' => true, |
||
715 | ]); |
||
716 | } |
||
717 | |||
718 | public function commonGivenUnknownTable(string $threshold = '1', string $limit = '10'): string |
||
719 | { |
||
720 | return view('lists/given-names-table', [ |
||
721 | 'given_names' => $this->data->commonGivenNames('U', (int) $threshold, (int) $limit)->all(), |
||
722 | 'order' => [[1, 'desc']], |
||
723 | ]); |
||
724 | } |
||
725 | |||
726 | public function commonGivenUnknownTotals(string $threshold = '1', string $limit = '10'): string |
||
727 | { |
||
728 | return $this->data->commonGivenNames('U', (int) $threshold, (int) $limit) |
||
729 | ->mapWithKeys(static fn (int $value, mixed $key): array => [ |
||
730 | $key => '<bdi>' . e($key) . '</bdi> (' . I18N::number($value) . ')', |
||
731 | ]) |
||
732 | ->implode(I18N::$list_separator); |
||
733 | } |
||
734 | |||
735 | public function commonMarriagePlacesList(string $limit = '10'): string |
||
736 | { |
||
737 | return view('statistics/other/top10-list', ['records' => $this->data->countPlacesForFamilies('MARR', (int) $limit)]); |
||
738 | } |
||
739 | |||
740 | public function commonSurnames(string $threshold = '1', string $limit = '10', string $sort = 'alpha'): string |
||
741 | { |
||
742 | return $this->data->commonSurnamesQuery('nolist', false, (int) $threshold, (int) $limit, $sort); |
||
743 | } |
||
744 | |||
745 | public function commonSurnamesList(string $threshold = '1', string $limit = '10', string $sort = 'alpha'): string |
||
746 | { |
||
747 | return $this->data->commonSurnamesQuery('list', false, (int) $threshold, (int) $limit, $sort); |
||
748 | } |
||
749 | |||
750 | public function commonSurnamesListTotals(string $threshold = '1', string $limit = '10', string $sort = 'count'): string |
||
751 | { |
||
752 | return $this->data->commonSurnamesQuery('list', true, (int) $threshold, (int) $limit, $sort); |
||
753 | } |
||
754 | |||
755 | public function commonSurnamesTotals(string $threshold = '1', string $limit = '10', string $sort = 'count'): string |
||
756 | { |
||
757 | return $this->data->commonSurnamesQuery('nolist', true, (int) $threshold, (int) $limit, $sort); |
||
758 | } |
||
759 | |||
760 | public function contactGedcom(): string |
||
761 | { |
||
762 | $user_id = (int) $this->tree->getPreference('CONTACT_USER_ID'); |
||
763 | $user = $this->user_service->find($user_id); |
||
764 | |||
765 | if ($user instanceof User) { |
||
766 | $request = app(ServerRequestInterface::class); |
||
767 | |||
768 | return $this->user_service->contactLink($user, $request); |
||
769 | } |
||
770 | |||
771 | return ''; |
||
772 | } |
||
773 | |||
774 | public function contactWebmaster(): string |
||
775 | { |
||
776 | $user_id = (int) $this->tree->getPreference('WEBMASTER_USER_ID'); |
||
777 | $user = $this->user_service->find($user_id); |
||
778 | |||
779 | if ($user instanceof User) { |
||
780 | $request = app(ServerRequestInterface::class); |
||
781 | |||
782 | return $this->user_service->contactLink($user, $request); |
||
783 | } |
||
784 | |||
785 | return ''; |
||
786 | } |
||
787 | |||
788 | public function embedTags(string $text): string |
||
789 | { |
||
790 | return strtr($text, $this->getTags($text)); |
||
791 | } |
||
792 | |||
793 | public function firstBirth(): string |
||
794 | { |
||
795 | return $this->data->firstEventRecord(['BIRT'], true); |
||
796 | } |
||
797 | |||
798 | public function firstBirthName(): string |
||
799 | { |
||
800 | return $this->data->firstEventName(['BIRT'], true); |
||
801 | } |
||
802 | |||
803 | public function firstBirthPlace(): string |
||
804 | { |
||
805 | return $this->data->firstEventPlace(['BIRT'], true); |
||
806 | } |
||
807 | |||
808 | public function firstBirthYear(): string |
||
809 | { |
||
810 | return $this->data->firstEventYear(['BIRT'], true); |
||
811 | } |
||
812 | |||
813 | public function firstDeath(): string |
||
814 | { |
||
815 | return $this->data->firstEventRecord(['DEAT'], true); |
||
816 | } |
||
817 | |||
818 | public function firstDeathName(): string |
||
819 | { |
||
820 | return $this->data->firstEventName(['DEAT'], true); |
||
821 | } |
||
822 | |||
823 | public function firstDeathPlace(): string |
||
824 | { |
||
825 | return $this->data->firstEventPlace(['DEAT'], true); |
||
826 | } |
||
827 | |||
828 | public function firstDeathYear(): string |
||
829 | { |
||
830 | return $this->data->firstEventYear(['DEAT'], true); |
||
831 | } |
||
832 | |||
833 | public function firstDivorce(): string |
||
834 | { |
||
835 | return $this->data->firstEventRecord(['DIV'], true); |
||
836 | } |
||
837 | |||
838 | public function firstDivorceName(): string |
||
839 | { |
||
840 | return $this->data->firstEventName(['DIV'], true); |
||
841 | } |
||
842 | |||
843 | public function firstDivorcePlace(): string |
||
844 | { |
||
845 | return $this->data->firstEventPlace(['DIV'], true); |
||
846 | } |
||
847 | |||
848 | public function firstDivorceYear(): string |
||
849 | { |
||
850 | return $this->data->firstEventYear(['DIV'], true); |
||
851 | } |
||
852 | |||
853 | public function firstEvent(): string |
||
854 | { |
||
855 | return $this->data->firstEventRecord([], true); |
||
856 | } |
||
857 | |||
858 | public function firstEventName(): string |
||
859 | { |
||
860 | return $this->data->firstEventName([], true); |
||
861 | } |
||
862 | |||
863 | public function firstEventPlace(): string |
||
864 | { |
||
865 | return $this->data->firstEventPlace([], true); |
||
866 | } |
||
867 | |||
868 | public function firstEventType(): string |
||
869 | { |
||
870 | return $this->data->firstEventType([], true); |
||
871 | } |
||
872 | |||
873 | public function firstEventYear(): string |
||
874 | { |
||
875 | return $this->data->firstEventYear([], true); |
||
876 | } |
||
877 | |||
878 | public function firstMarriage(): string |
||
879 | { |
||
880 | return $this->data->firstEventRecord(['MARR'], true); |
||
881 | } |
||
882 | |||
883 | public function firstMarriageName(): string |
||
884 | { |
||
885 | return $this->data->firstEventName(['MARR'], true); |
||
886 | } |
||
887 | |||
888 | public function firstMarriagePlace(): string |
||
889 | { |
||
890 | return $this->data->firstEventPlace(['MARR'], true); |
||
891 | } |
||
892 | |||
893 | public function firstMarriageYear(): string |
||
894 | { |
||
895 | return $this->data->firstEventYear(['MARR'], true); |
||
896 | } |
||
897 | |||
898 | public function gedcomCreatedSoftware(): string |
||
899 | { |
||
900 | $head = Registry::headerFactory()->make('HEAD', $this->tree); |
||
901 | |||
902 | if ($head instanceof Header) { |
||
903 | $sour = $head->facts(['SOUR'])->first(); |
||
904 | |||
905 | if ($sour instanceof Fact) { |
||
906 | return $sour->attribute('NAME'); |
||
907 | } |
||
908 | } |
||
909 | |||
910 | return ''; |
||
911 | } |
||
912 | |||
913 | public function gedcomCreatedVersion(): string |
||
914 | { |
||
915 | $head = Registry::headerFactory()->make('HEAD', $this->tree); |
||
916 | |||
917 | if ($head instanceof Header) { |
||
918 | $sour = $head->facts(['SOUR'])->first(); |
||
919 | |||
920 | if ($sour instanceof Fact) { |
||
921 | $version = $sour->attribute('VERS'); |
||
922 | |||
923 | if (str_contains($version, 'Family Tree Maker ')) { |
||
924 | $p = strpos($version, '(') + 1; |
||
925 | $p2 = strpos($version, ')'); |
||
926 | $version = substr($version, $p, $p2 - $p); |
||
927 | } |
||
928 | |||
929 | // Fix EasyTree version |
||
930 | if ($sour->value() === 'EasyTree') { |
||
931 | $version = substr($version, 1); |
||
932 | } |
||
933 | |||
934 | return $version; |
||
935 | } |
||
936 | } |
||
937 | |||
938 | return ''; |
||
939 | } |
||
940 | |||
941 | public function gedcomDate(): string |
||
942 | { |
||
943 | $head = Registry::headerFactory()->make('HEAD', $this->tree); |
||
944 | |||
945 | if ($head instanceof Header) { |
||
946 | $fact = $head->facts(['DATE'])->first(); |
||
947 | |||
948 | if ($fact instanceof Fact) { |
||
949 | try { |
||
950 | return Registry::timestampFactory()->fromString($fact->value(), 'j M Y')->isoFormat('LL'); |
||
951 | } catch (InvalidArgumentException $ex) { |
||
952 | // HEAD:DATE invalid. |
||
953 | } |
||
954 | } |
||
955 | } |
||
956 | |||
957 | return ''; |
||
958 | } |
||
959 | |||
960 | public function gedcomFavorites(): string |
||
961 | { |
||
962 | return $this->callBlock('gedcom_favorites'); |
||
963 | } |
||
964 | |||
965 | public function gedcomFilename(): string |
||
966 | { |
||
967 | return $this->tree->name(); |
||
968 | } |
||
969 | |||
970 | public function gedcomRootId(): string |
||
971 | { |
||
972 | return $this->tree->getPreference('PEDIGREE_ROOT_ID'); |
||
973 | } |
||
974 | |||
975 | public function gedcomTitle(): string |
||
976 | { |
||
977 | return e($this->tree->title()); |
||
978 | } |
||
979 | |||
980 | public function gedcomUpdated(): string |
||
981 | { |
||
982 | $row = DB::table('change') |
||
983 | ->where('gedcom_id', '=', $this->tree->id()) |
||
984 | ->where('status', '=', 'accepted') |
||
985 | ->orderBy('change_id', 'DESC') |
||
986 | ->select(['change_time']) |
||
987 | ->first(); |
||
988 | |||
989 | if ($row === null) { |
||
990 | return $this->gedcomDate(); |
||
991 | } |
||
992 | |||
993 | return Registry::timestampFactory()->fromString($row->change_time)->isoFormat('LL'); |
||
994 | } |
||
995 | |||
996 | public function getAllTagsTable(): string |
||
997 | { |
||
998 | try { |
||
999 | $class = new ReflectionClass($this); |
||
1000 | |||
1001 | $public_methods = $class->getMethods(ReflectionMethod::IS_PUBLIC); |
||
1002 | |||
1003 | $exclude = ['embedTags', 'getAllTagsTable']; |
||
1004 | |||
1005 | $examples = Collection::make($public_methods) |
||
1006 | ->filter(static fn (ReflectionMethod $method): bool => !in_array($method->getName(), $exclude, true)) |
||
1007 | ->filter(static fn(ReflectionMethod $method): bool => $method->getReturnType() instanceof ReflectionNamedType && $method->getReturnType()->getName() === 'string') |
||
1008 | ->sort(static fn (ReflectionMethod $x, ReflectionMethod $y): int => $x->getName() <=> $y->getName()) |
||
1009 | ->map(function (ReflectionMethod $method): string { |
||
1010 | $tag = $method->getName(); |
||
1011 | |||
1012 | return '<dt>#' . $tag . '#</dt><dd>' . $this->$tag() . '</dd>'; |
||
1013 | }); |
||
1014 | |||
1015 | return '<dl>' . $examples->implode('') . '</dl>'; |
||
1016 | } catch (ReflectionException $ex) { |
||
1017 | return $ex->getMessage(); |
||
1018 | } |
||
1019 | } |
||
1020 | |||
1021 | public function getCommonSurname(): string |
||
1022 | { |
||
1023 | $top_surname = $this->data->commonSurnames(1, 0, 'count'); |
||
1024 | |||
1025 | return implode(I18N::$list_separator, array_keys(array_shift($top_surname) ?? [])); |
||
1026 | } |
||
1027 | |||
1028 | /** |
||
1029 | * @return array<string,string> |
||
1030 | */ |
||
1031 | private function getTags(string $text): array |
||
1032 | { |
||
1033 | $tags = []; |
||
1034 | $matches = []; |
||
1035 | |||
1036 | preg_match_all('/#([^#\n]+)(?=#)/', $text, $matches, PREG_SET_ORDER); |
||
1037 | |||
1038 | foreach ($matches as $match) { |
||
1039 | $params = explode(':', $match[1]); |
||
1040 | $method = array_shift($params); |
||
1041 | |||
1042 | if (method_exists($this, $method)) { |
||
1043 | $tags[$match[0] . '#'] = $this->$method(...$params); |
||
1044 | } |
||
1045 | } |
||
1046 | |||
1047 | return $tags; |
||
1048 | } |
||
1049 | |||
1050 | public function hitCount(): string |
||
1051 | { |
||
1052 | return $this->format->hitCount($this->data->countHits('index.php', 'gedcom:' . $this->tree->id())); |
||
1053 | } |
||
1054 | |||
1055 | public function hitCountFam(string $xref = ''): string |
||
1056 | { |
||
1057 | return $this->format->hitCount($this->data->countHits('family.php', $xref)); |
||
1058 | } |
||
1059 | |||
1060 | public function hitCountIndi(string $xref = ''): string |
||
1061 | { |
||
1062 | return $this->format->hitCount($this->data->countHits('individual.php', $xref)); |
||
1063 | } |
||
1064 | |||
1065 | public function hitCountNote(string $xref = ''): string |
||
1066 | { |
||
1067 | return $this->format->hitCount($this->data->countHits('note.php', $xref)); |
||
1068 | } |
||
1069 | |||
1070 | public function hitCountObje(string $xref = ''): string |
||
1071 | { |
||
1072 | return $this->format->hitCount($this->data->countHits('mediaviewer.php', $xref)); |
||
1073 | } |
||
1074 | |||
1075 | public function hitCountRepo(string $xref = ''): string |
||
1076 | { |
||
1077 | return $this->format->hitCount($this->data->countHits('repo.php', $xref)); |
||
1078 | } |
||
1079 | |||
1080 | public function hitCountSour(string $xref = ''): string |
||
1081 | { |
||
1082 | return $this->format->hitCount($this->data->countHits('source.php', $xref)); |
||
1083 | } |
||
1084 | |||
1085 | public function hitCountUser(): string |
||
1086 | { |
||
1087 | return $this->format->hitCount($this->data->countHits('index.php', 'user:' . Auth::id())); |
||
1088 | } |
||
1089 | |||
1090 | public function largestFamily(): string |
||
1091 | { |
||
1092 | $family = $this->data->familiesWithTheMostChildren(1)[0]->family ?? null; |
||
1093 | |||
1094 | if ($family === null) { |
||
1095 | return $this->format->missing(); |
||
1096 | } |
||
1097 | |||
1098 | return $family->formatList(); |
||
1099 | } |
||
1100 | |||
1101 | public function largestFamilyName(): string |
||
1102 | { |
||
1103 | return $this->format->record($this->data->familiesWithTheMostChildren(1)[0]->family ?? null); |
||
1104 | } |
||
1105 | |||
1106 | public function largestFamilySize(): string |
||
1107 | { |
||
1108 | return I18N::number($this->data->familiesWithTheMostChildren(1)[0]->children ?? 0); |
||
1109 | } |
||
1110 | |||
1111 | public function lastBirth(): string |
||
1114 | } |
||
1115 | |||
1116 | public function lastBirthName(): string |
||
1117 | { |
||
1118 | return $this->data->firstEventName(['BIRT'], false); |
||
1119 | } |
||
1120 | |||
1121 | public function lastBirthPlace(): string |
||
1122 | { |
||
1123 | return $this->data->firstEventPlace(['BIRT'], false); |
||
1124 | } |
||
1125 | |||
1126 | public function lastBirthYear(): string |
||
1127 | { |
||
1128 | return $this->data->firstEventYear(['BIRT'], false); |
||
1129 | } |
||
1130 | |||
1131 | public function lastDeath(): string |
||
1132 | { |
||
1133 | return $this->data->firstEventRecord(['DEAT'], false); |
||
1134 | } |
||
1135 | |||
1136 | public function lastDeathName(): string |
||
1137 | { |
||
1138 | return $this->data->firstEventName(['DEAT'], false); |
||
1139 | } |
||
1140 | |||
1141 | public function lastDeathPlace(): string |
||
1142 | { |
||
1143 | return $this->data->firstEventPlace(['DEAT'], false); |
||
1144 | } |
||
1145 | |||
1146 | public function lastDeathYear(): string |
||
1147 | { |
||
1148 | return $this->data->firstEventYear(['DEAT'], false); |
||
1149 | } |
||
1150 | |||
1151 | public function lastDivorce(): string |
||
1152 | { |
||
1153 | return $this->data->firstEventRecord(['DIV'], false); |
||
1154 | } |
||
1155 | |||
1156 | public function lastDivorceName(): string |
||
1157 | { |
||
1158 | return $this->data->firstEventName(['DIV'], true); |
||
1159 | } |
||
1160 | |||
1161 | public function lastDivorcePlace(): string |
||
1162 | { |
||
1163 | return $this->data->firstEventPlace(['DIV'], true); |
||
1164 | } |
||
1165 | |||
1166 | public function lastDivorceYear(): string |
||
1167 | { |
||
1168 | return $this->data->firstEventYear(['DIV'], true); |
||
1169 | } |
||
1170 | |||
1171 | public function lastEvent(): string |
||
1172 | { |
||
1173 | return $this->data->firstEventRecord([], false); |
||
1174 | } |
||
1175 | |||
1176 | public function lastEventName(): string |
||
1177 | { |
||
1178 | return $this->data->firstEventName([], false); |
||
1179 | } |
||
1180 | |||
1181 | public function lastEventPlace(): string |
||
1182 | { |
||
1183 | return $this->data->firstEventPlace([], false); |
||
1184 | } |
||
1185 | |||
1186 | public function lastEventType(): string |
||
1187 | { |
||
1188 | return $this->data->firstEventType([], false); |
||
1189 | } |
||
1190 | |||
1191 | public function lastEventYear(): string |
||
1192 | { |
||
1193 | return $this->data->firstEventYear([], false); |
||
1194 | } |
||
1195 | |||
1196 | public function lastMarriage(): string |
||
1197 | { |
||
1198 | return $this->data->firstEventRecord(['MARR'], false); |
||
1199 | } |
||
1200 | |||
1201 | public function lastMarriageName(): string |
||
1202 | { |
||
1203 | return $this->data->firstEventName(['MARR'], false); |
||
1204 | } |
||
1205 | |||
1206 | public function lastMarriagePlace(): string |
||
1207 | { |
||
1208 | return $this->data->firstEventPlace(['MARR'], false); |
||
1209 | } |
||
1210 | |||
1211 | public function lastMarriageYear(): string |
||
1212 | { |
||
1213 | return $this->data->firstEventYear(['MARR'], false); |
||
1214 | } |
||
1215 | |||
1216 | public function latestUserFullName(): string |
||
1217 | { |
||
1218 | $user = $this->user_service->find($this->data->latestUserId()) ?? Auth::user(); |
||
1219 | |||
1220 | return e($user->realName()); |
||
1221 | } |
||
1222 | |||
1223 | public function latestUserId(): string |
||
1224 | { |
||
1225 | $user = $this->user_service->find($this->data->latestUserId()) ?? Auth::user(); |
||
1226 | |||
1227 | return (string) $user->id(); |
||
1228 | } |
||
1229 | |||
1230 | public function latestUserLoggedin(?string $yes = null, ?string $no = null): string |
||
1231 | { |
||
1232 | if ($this->data->isUserLoggedIn($this->data->latestUserId())) { |
||
1233 | return $yes ?? I18N::translate('Yes'); |
||
1234 | } |
||
1235 | |||
1236 | return $no ?? I18N::translate('No'); |
||
1237 | } |
||
1238 | |||
1239 | public function latestUserName(): string |
||
1240 | { |
||
1241 | $user = $this->user_service->find($this->data->latestUserId()) ?? Auth::user(); |
||
1242 | |||
1243 | return e($user->userName()); |
||
1244 | } |
||
1245 | |||
1246 | public function latestUserRegDate(?string $format = null): string |
||
1247 | { |
||
1248 | $format ??= I18N::dateFormat(); |
||
1249 | $user = $this->user_service->find($this->data->latestUserId()) ?? Auth::user(); |
||
1250 | $timestamp = (int) $user->getPreference(UserInterface::PREF_TIMESTAMP_REGISTERED); |
||
1251 | |||
1252 | if ($timestamp === 0) { |
||
1253 | return I18N::translate('Never'); |
||
1254 | } |
||
1255 | |||
1256 | return Registry::timestampFactory()->make($timestamp)->format(strtr($format, ['%' => ''])); |
||
1257 | } |
||
1258 | |||
1259 | public function latestUserRegTime(?string $format = null): string |
||
1260 | { |
||
1261 | $format ??= I18N::timeFormat(); |
||
1262 | $user = $this->user_service->find($this->data->latestUserId()) ?? Auth::user(); |
||
1263 | $timestamp = (int) $user->getPreference(UserInterface::PREF_TIMESTAMP_REGISTERED); |
||
1264 | |||
1265 | if ($timestamp === 0) { |
||
1266 | return I18N::translate('Never'); |
||
1267 | } |
||
1268 | |||
1269 | return Registry::timestampFactory()->make($timestamp)->format(strtr($format, ['%' => ''])); |
||
1270 | } |
||
1271 | |||
1272 | public function longestLife(): string |
||
1273 | { |
||
1274 | $row = $this->data->longlifeQuery('ALL'); |
||
1275 | |||
1276 | if ($row === null) { |
||
1277 | return ''; |
||
1278 | } |
||
1279 | |||
1280 | return $row->individual->formatList(); |
||
1281 | } |
||
1282 | |||
1283 | public function longestLifeAge(): string |
||
1284 | { |
||
1285 | $row = $this->data->longlifeQuery('ALL'); |
||
1286 | |||
1287 | if ($row === null) { |
||
1288 | return ''; |
||
1289 | } |
||
1290 | |||
1291 | return I18N::number((int) ($row->days / 365.25)); |
||
1292 | } |
||
1293 | |||
1294 | public function longestLifeFemale(): string |
||
1295 | { |
||
1296 | $row = $this->data->longlifeQuery('F'); |
||
1297 | |||
1298 | if ($row === null) { |
||
1299 | return ''; |
||
1300 | } |
||
1301 | |||
1302 | return $row->individual->formatList(); |
||
1303 | } |
||
1304 | |||
1305 | public function longestLifeFemaleAge(): string |
||
1306 | { |
||
1307 | $row = $this->data->longlifeQuery('F'); |
||
1308 | |||
1309 | if ($row === null) { |
||
1310 | return ''; |
||
1311 | } |
||
1312 | |||
1313 | return I18N::number((int) ($row->days / 365.25)); |
||
1314 | } |
||
1315 | |||
1316 | public function longestLifeFemaleName(): string |
||
1317 | { |
||
1318 | return $this->format->record($this->data->longlifeQuery('F')->individual ?? null); |
||
1319 | } |
||
1320 | |||
1321 | public function longestLifeMale(): string |
||
1322 | { |
||
1323 | $row = $this->data->longlifeQuery('M'); |
||
1324 | |||
1325 | if ($row === null) { |
||
1326 | return ''; |
||
1327 | } |
||
1328 | |||
1329 | return $row->individual->formatList(); |
||
1330 | } |
||
1331 | |||
1332 | public function longestLifeMaleAge(): string |
||
1333 | { |
||
1334 | $row = $this->data->longlifeQuery('M'); |
||
1335 | |||
1336 | if ($row === null) { |
||
1337 | return ''; |
||
1338 | } |
||
1339 | |||
1340 | return I18N::number((int) ($row->days / 365.25)); |
||
1341 | } |
||
1342 | |||
1343 | public function longestLifeMaleName(): string |
||
1344 | { |
||
1345 | return $this->format->record($this->data->longlifeQuery('M')->individual ?? null); |
||
1346 | } |
||
1347 | |||
1348 | public function longestLifeName(): string |
||
1349 | { |
||
1350 | return $this->format->record($this->data->longlifeQuery('ALL')->individual ?? null); |
||
1351 | } |
||
1352 | |||
1353 | public function minAgeOfMarriage(): string |
||
1354 | { |
||
1355 | return $this->data->ageOfMarriageQuery('age', 'ASC', 1); |
||
1356 | } |
||
1357 | |||
1358 | public function minAgeOfMarriageFamilies(string $limit = '10'): string |
||
1359 | { |
||
1360 | return $this->data->ageOfMarriageQuery('nolist', 'ASC', (int) $limit); |
||
1361 | } |
||
1362 | |||
1363 | public function minAgeOfMarriageFamiliesList(string $limit = '10'): string |
||
1364 | { |
||
1365 | return $this->data->ageOfMarriageQuery('list', 'ASC', (int) $limit); |
||
1366 | } |
||
1367 | |||
1368 | public function minAgeOfMarriageFamily(): string |
||
1369 | { |
||
1370 | return $this->data->ageOfMarriageQuery('name', 'ASC', 1); |
||
1371 | } |
||
1372 | |||
1373 | public function noChildrenFamilies(): string |
||
1374 | { |
||
1375 | return I18N::number($this->data->countFamiliesWithNoChildren()); |
||
1376 | } |
||
1377 | |||
1378 | public function noChildrenFamiliesList(string $type = 'list'): string |
||
1379 | { |
||
1380 | return $this->data->noChildrenFamiliesList($type); |
||
1381 | } |
||
1382 | |||
1383 | public function oldestFather(): string |
||
1384 | { |
||
1385 | return $this->data->parentsQuery('full', 'DESC', 'M', false); |
||
1386 | } |
||
1387 | |||
1388 | public function oldestFatherAge(string $show_years = '0'): string |
||
1389 | { |
||
1390 | return $this->data->parentsQuery('age', 'DESC', 'M', (bool) $show_years); |
||
1391 | } |
||
1392 | |||
1393 | public function oldestFatherName(): string |
||
1394 | { |
||
1395 | return $this->data->parentsQuery('name', 'DESC', 'M', false); |
||
1396 | } |
||
1397 | |||
1398 | public function oldestMarriageFemale(): string |
||
1399 | { |
||
1400 | return $this->data->marriageQuery('full', 'DESC', 'F', false); |
||
1401 | } |
||
1402 | |||
1403 | public function oldestMarriageFemaleAge(string $show_years = '0'): string |
||
1404 | { |
||
1405 | return $this->data->marriageQuery('age', 'DESC', 'F', (bool) $show_years); |
||
1406 | } |
||
1407 | |||
1408 | public function oldestMarriageFemaleName(): string |
||
1409 | { |
||
1410 | return $this->data->marriageQuery('name', 'DESC', 'F', false); |
||
1411 | } |
||
1412 | |||
1413 | public function oldestMarriageMale(): string |
||
1414 | { |
||
1415 | return $this->data->marriageQuery('full', 'DESC', 'M', false); |
||
1416 | } |
||
1417 | |||
1418 | public function oldestMarriageMaleAge(string $show_years = '0'): string |
||
1419 | { |
||
1420 | return $this->data->marriageQuery('age', 'DESC', 'M', (bool) $show_years); |
||
1421 | } |
||
1422 | |||
1423 | public function oldestMarriageMaleName(): string |
||
1424 | { |
||
1425 | return $this->data->marriageQuery('name', 'DESC', 'M', false); |
||
1426 | } |
||
1427 | |||
1428 | public function oldestMother(): string |
||
1429 | { |
||
1430 | return $this->data->parentsQuery('full', 'DESC', 'F', false); |
||
1431 | } |
||
1432 | |||
1433 | public function oldestMotherAge(string $show_years = '0'): string |
||
1434 | { |
||
1435 | return $this->data->parentsQuery('age', 'DESC', 'F', (bool) $show_years); |
||
1436 | } |
||
1437 | |||
1438 | public function oldestMotherName(): string |
||
1439 | { |
||
1440 | return $this->data->parentsQuery('name', 'DESC', 'F', false); |
||
1441 | } |
||
1442 | |||
1443 | public function serverDate(): string |
||
1444 | { |
||
1445 | return Registry::timestampFactory()->now(new SiteUser())->format(strtr(I18N::dateFormat(), ['%' => ''])); |
||
1446 | } |
||
1447 | |||
1448 | public function serverTime(): string |
||
1449 | { |
||
1450 | return Registry::timestampFactory()->now(new SiteUser())->format(strtr(I18N::timeFormat(), ['%' => ''])); |
||
1451 | } |
||
1452 | |||
1453 | public function serverTime24(): string |
||
1454 | { |
||
1455 | return Registry::timestampFactory()->now(new SiteUser())->format('G:i'); |
||
1456 | } |
||
1457 | |||
1458 | public function serverTimezone(): string |
||
1459 | { |
||
1460 | return Registry::timestampFactory()->now(new SiteUser())->format('T'); |
||
1461 | } |
||
1462 | |||
1463 | public function statsAge(): string |
||
1464 | { |
||
1465 | $records = $this->data->statsAge(); |
||
1466 | |||
1467 | $out = []; |
||
1468 | |||
1469 | foreach ($records as $record) { |
||
1470 | $out[$record->century][$record->sex] = $record->age; |
||
1471 | } |
||
1472 | |||
1473 | $data = [ |
||
1474 | [ |
||
1475 | I18N::translate('Century'), |
||
1476 | I18N::translate('Males'), |
||
1477 | I18N::translate('Females'), |
||
1478 | I18N::translate('Average age'), |
||
1479 | ] |
||
1480 | ]; |
||
1481 | |||
1482 | foreach ($out as $century => $values) { |
||
1483 | $female_age = $values['F'] ?? 0; |
||
1484 | $male_age = $values['M'] ?? 0; |
||
1485 | $average_age = ($female_age + $male_age) / 2.0; |
||
1486 | |||
1487 | $data[] = [ |
||
1488 | $this->format->century($century), |
||
1489 | round($male_age, 1), |
||
1490 | round($female_age, 1), |
||
1491 | round($average_age, 1), |
||
1492 | ]; |
||
1493 | } |
||
1494 | |||
1495 | $chart_title = I18N::translate('Average age related to death century'); |
||
1496 | $chart_options = [ |
||
1497 | 'title' => $chart_title, |
||
1498 | 'subtitle' => I18N::translate('Average age at death'), |
||
1499 | 'vAxis' => [ |
||
1500 | 'title' => I18N::translate('Age'), |
||
1501 | ], |
||
1502 | 'hAxis' => [ |
||
1503 | 'showTextEvery' => 1, |
||
1504 | 'slantedText' => false, |
||
1505 | 'title' => I18N::translate('Century'), |
||
1506 | ], |
||
1507 | 'colors' => [ |
||
1508 | '#84beff', |
||
1509 | '#ffd1dc', |
||
1510 | '#ff0000', |
||
1511 | ], |
||
1512 | ]; |
||
1513 | |||
1514 | return view('statistics/other/charts/combo', [ |
||
1515 | 'data' => $data, |
||
1516 | 'chart_options' => $chart_options, |
||
1517 | 'chart_title' => $chart_title, |
||
1518 | 'language' => I18N::languageTag(), |
||
1519 | ]); |
||
1520 | } |
||
1521 | |||
1522 | public function statsBirth(string $color1 = 'ffffff', string $color2 = '84beff'): string |
||
1523 | { |
||
1524 | $data = $this->data->countEventsByCentury('BIRT'); |
||
1525 | $colors = $this->format->interpolateRgb($color1, $color2, count($data)); |
||
1526 | |||
1527 | return $this->format->pieChart( |
||
1528 | $data, |
||
1529 | $colors, |
||
1530 | I18N::translate('Births by century'), |
||
1531 | I18N::translate('Century'), |
||
1532 | I18N::translate('Total'), |
||
1533 | ); |
||
1534 | } |
||
1535 | |||
1536 | public function statsChildren(): string |
||
1537 | { |
||
1538 | $records = DB::table('families') |
||
1539 | ->selectRaw('AVG(f_numchil) AS total') |
||
1540 | ->selectRaw('ROUND((d_year + 49) / 100, 0) AS century') |
||
1541 | ->join('dates', static function (JoinClause $join): void { |
||
1542 | $join->on('d_file', '=', 'f_file') |
||
1543 | ->on('d_gid', '=', 'f_id'); |
||
1544 | }) |
||
1545 | ->where('f_file', '=', $this->tree->id()) |
||
1546 | ->where('d_julianday1', '<>', 0) |
||
1547 | ->where('d_fact', '=', 'MARR') |
||
1548 | ->whereIn('d_type', ['@#DGREGORIAN@', '@#DJULIAN@']) |
||
1549 | ->groupBy(['century']) |
||
1550 | ->orderBy('century') |
||
1551 | ->get() |
||
1552 | ->map(static fn (object $row): object => (object) [ |
||
1553 | 'century' => (int) $row->century, |
||
1554 | 'total' => (float) $row->total, |
||
1555 | ]); |
||
1556 | |||
1557 | $data = [ |
||
1558 | [ |
||
1559 | I18N::translate('Century'), |
||
1560 | I18N::translate('Average number'), |
||
1561 | ], |
||
1562 | ]; |
||
1563 | |||
1564 | foreach ($records as $record) { |
||
1565 | $data[] = [ |
||
1566 | $this->format->century($record->century), |
||
1567 | round($record->total, 2), |
||
1568 | ]; |
||
1569 | } |
||
1570 | |||
1571 | $chart_title = I18N::translate('Average number of children per family'); |
||
1572 | $chart_options = [ |
||
1573 | 'title' => $chart_title, |
||
1574 | 'subtitle' => '', |
||
1575 | 'legend' => [ |
||
1576 | 'position' => 'none', |
||
1577 | ], |
||
1578 | 'vAxis' => [ |
||
1579 | 'title' => I18N::translate('Number of children'), |
||
1580 | ], |
||
1581 | 'hAxis' => [ |
||
1582 | 'showTextEvery' => 1, |
||
1583 | 'slantedText' => false, |
||
1584 | 'title' => I18N::translate('Century'), |
||
1585 | ], |
||
1586 | 'colors' => [ |
||
1587 | '#84beff', |
||
1588 | ], |
||
1589 | ]; |
||
1590 | |||
1591 | return view('statistics/other/charts/column', [ |
||
1592 | 'data' => $data, |
||
1593 | 'chart_options' => $chart_options, |
||
1594 | 'chart_title' => $chart_title, |
||
1595 | 'language' => I18N::languageTag(), |
||
1596 | ]); |
||
1597 | } |
||
1598 | |||
1599 | /** |
||
1600 | * @return array<object{f_numchil:int,total:int}> |
||
1601 | */ |
||
1602 | public function statsChildrenQuery(int $year1 = 0, int $year2 = 0): array |
||
1603 | { |
||
1604 | return $this->data->statsChildrenQuery($year1, $year2); |
||
1605 | } |
||
1606 | |||
1607 | public function statsDeath(string $color1 = 'ffffff', string $color2 = '84beff'): string |
||
1608 | { |
||
1609 | $data = $this->data->countEventsByCentury('DEAT'); |
||
1610 | $colors = $this->format->interpolateRgb($color1, $color2, count($data)); |
||
1611 | |||
1612 | return $this->format->pieChart( |
||
1613 | $data, |
||
1614 | $colors, |
||
1615 | I18N::translate('Births by century'), |
||
1616 | I18N::translate('Century'), |
||
1617 | I18N::translate('Total'), |
||
1618 | ); |
||
1619 | } |
||
1620 | |||
1621 | public function statsDiv(string $color1 = 'ffffff', string $color2 = '84beff'): string |
||
1622 | { |
||
1623 | $data = $this->data->countEventsByCentury('DIV'); |
||
1624 | $colors = $this->format->interpolateRgb($color1, $color2, count($data)); |
||
1625 | |||
1626 | return $this->format->pieChart( |
||
1627 | $data, |
||
1628 | $colors, |
||
1629 | I18N::translate('Divorces by century'), |
||
1630 | I18N::translate('Century'), |
||
1631 | I18N::translate('Total'), |
||
1632 | ); |
||
1633 | } |
||
1634 | |||
1635 | public function statsMarr(string $color1 = 'ffffff', string $color2 = '84beff'): string |
||
1636 | { |
||
1637 | $data = $this->data->countEventsByCentury('MARR'); |
||
1638 | $colors = $this->format->interpolateRgb($color1, $color2, count($data)); |
||
1639 | |||
1640 | return $this->format->pieChart( |
||
1641 | $data, |
||
1642 | $colors, |
||
1643 | I18N::translate('Marriages by century'), |
||
1644 | I18N::translate('Century'), |
||
1645 | I18N::translate('Total'), |
||
1646 | ); |
||
1647 | } |
||
1648 | |||
1649 | public function statsMarrAge(): string |
||
1650 | { |
||
1651 | $prefix = DB::connection()->getTablePrefix(); |
||
1652 | |||
1653 | $out = []; |
||
1654 | |||
1655 | $male = DB::table('dates as married') |
||
1656 | ->select([ |
||
1657 | new Expression('AVG(' . $prefix . 'married.d_julianday2 - ' . $prefix . 'birth.d_julianday1 - 182.5) / 365.25 AS age'), |
||
1658 | new Expression('ROUND((' . $prefix . 'married.d_year + 49) / 100, 0) AS century'), |
||
1659 | new Expression("'M' as sex"), |
||
1660 | ]) |
||
1661 | ->join('families as fam', static function (JoinClause $join): void { |
||
1662 | $join->on('fam.f_id', '=', 'married.d_gid') |
||
1663 | ->on('fam.f_file', '=', 'married.d_file'); |
||
1664 | }) |
||
1665 | ->join('dates as birth', static function (JoinClause $join): void { |
||
1666 | $join->on('birth.d_gid', '=', 'fam.f_husb') |
||
1667 | ->on('birth.d_file', '=', 'fam.f_file'); |
||
1668 | }) |
||
1669 | ->whereIn('married.d_type', ['@#DGREGORIAN@', '@#DJULIAN@']) |
||
1670 | ->where('married.d_file', '=', $this->tree->id()) |
||
1671 | ->where('married.d_fact', '=', 'MARR') |
||
1672 | ->where('married.d_julianday1', '>', new Expression($prefix . 'birth.d_julianday1')) |
||
1673 | ->whereIn('birth.d_type', ['@#DGREGORIAN@', '@#DJULIAN@']) |
||
1674 | ->where('birth.d_fact', '=', 'BIRT') |
||
1675 | ->where('birth.d_julianday1', '<>', 0) |
||
1676 | ->groupBy(['century', 'sex']); |
||
1677 | |||
1678 | $female = DB::table('dates as married') |
||
1679 | ->select([ |
||
1680 | new Expression('ROUND(AVG(' . $prefix . 'married.d_julianday2 - ' . $prefix . 'birth.d_julianday1 - 182.5) / 365.25, 1) AS age'), |
||
1681 | new Expression('ROUND((' . $prefix . 'married.d_year + 49) / 100, 0) AS century'), |
||
1682 | new Expression("'F' as sex"), |
||
1683 | ]) |
||
1684 | ->join('families as fam', static function (JoinClause $join): void { |
||
1685 | $join->on('fam.f_id', '=', 'married.d_gid') |
||
1686 | ->on('fam.f_file', '=', 'married.d_file'); |
||
1687 | }) |
||
1688 | ->join('dates as birth', static function (JoinClause $join): void { |
||
1689 | $join->on('birth.d_gid', '=', 'fam.f_wife') |
||
1690 | ->on('birth.d_file', '=', 'fam.f_file'); |
||
1691 | }) |
||
1692 | ->whereIn('married.d_type', ['@#DGREGORIAN@', '@#DJULIAN@']) |
||
1693 | ->where('married.d_file', '=', $this->tree->id()) |
||
1694 | ->where('married.d_fact', '=', 'MARR') |
||
1695 | ->where('married.d_julianday1', '>', new Expression($prefix . 'birth.d_julianday1')) |
||
1696 | ->whereIn('birth.d_type', ['@#DGREGORIAN@', '@#DJULIAN@']) |
||
1697 | ->where('birth.d_fact', '=', 'BIRT') |
||
1698 | ->where('birth.d_julianday1', '<>', 0) |
||
1699 | ->groupBy(['century', 'sex']); |
||
1700 | |||
1701 | $records = $male->unionAll($female) |
||
1702 | ->orderBy('century') |
||
1703 | ->get() |
||
1704 | ->map(static fn (object $row): object => (object) [ |
||
1705 | 'age' => (float) $row->age, |
||
1706 | 'century' => (int) $row->century, |
||
1707 | 'sex' => $row->sex, |
||
1708 | ]); |
||
1709 | |||
1710 | |||
1711 | foreach ($records as $record) { |
||
1712 | $out[$record->century][$record->sex] = $record->age; |
||
1713 | } |
||
1714 | |||
1715 | $data = [ |
||
1716 | [ |
||
1717 | I18N::translate('Century'), |
||
1718 | I18N::translate('Males'), |
||
1719 | I18N::translate('Females'), |
||
1720 | I18N::translate('Average age'), |
||
1721 | ], |
||
1722 | ]; |
||
1723 | |||
1724 | foreach ($out as $century => $values) { |
||
1725 | $female_age = $values['F'] ?? 0; |
||
1726 | $male_age = $values['M'] ?? 0; |
||
1727 | $average_age = ($female_age + $male_age) / 2.0; |
||
1728 | |||
1729 | $data[] = [ |
||
1730 | $this->format->century($century), |
||
1731 | round($male_age, 1), |
||
1732 | round($female_age, 1), |
||
1733 | round($average_age, 1), |
||
1734 | ]; |
||
1735 | } |
||
1736 | |||
1737 | $chart_title = I18N::translate('Average age in century of marriage'); |
||
1738 | $chart_options = [ |
||
1739 | 'title' => $chart_title, |
||
1740 | 'subtitle' => I18N::translate('Average age at marriage'), |
||
1741 | 'vAxis' => [ |
||
1742 | 'title' => I18N::translate('Age'), |
||
1743 | ], |
||
1744 | 'hAxis' => [ |
||
1745 | 'showTextEvery' => 1, |
||
1746 | 'slantedText' => false, |
||
1747 | 'title' => I18N::translate('Century'), |
||
1748 | ], |
||
1749 | 'colors' => [ |
||
1750 | '#84beff', |
||
1751 | '#ffd1dc', |
||
1752 | '#ff0000', |
||
1753 | ], |
||
1754 | ]; |
||
1755 | |||
1756 | return view('statistics/other/charts/combo', [ |
||
1757 | 'data' => $data, |
||
1758 | 'chart_options' => $chart_options, |
||
1759 | 'chart_title' => $chart_title, |
||
1760 | 'language' => I18N::languageTag(), |
||
1761 | ]); |
||
1762 | } |
||
1763 | |||
1764 | /** |
||
1765 | * @return array<object{f_id:string,d_gid:string,age:int}> |
||
1766 | */ |
||
1767 | public function statsMarrAgeQuery(string $sex, int $year1 = 0, int $year2 = 0): array |
||
1768 | { |
||
1769 | return $this->data->statsMarrAgeQuery($sex, $year1, $year2); |
||
1770 | } |
||
1771 | |||
1772 | public function topAgeBetweenSiblings(): string |
||
1773 | { |
||
1774 | return $this->data->topAgeBetweenSiblings(); |
||
1775 | } |
||
1776 | |||
1777 | public function topAgeBetweenSiblingsFullName(): string |
||
1778 | { |
||
1779 | return $this->data->topAgeBetweenSiblingsFullName(); |
||
1780 | } |
||
1781 | |||
1782 | public function topAgeBetweenSiblingsList(string $limit = '10', string $one = '0'): string |
||
1783 | { |
||
1784 | return $this->data->topAgeBetweenSiblingsList((int) $limit, (bool) $one); |
||
1785 | } |
||
1786 | |||
1787 | public function topAgeBetweenSiblingsName(): string |
||
1788 | { |
||
1789 | $row = $this->data->maximumAgeBetweenSiblings(1)[0] ?? null; |
||
1790 | |||
1791 | if ($row === null) { |
||
1792 | return $this->format->missing(); |
||
1793 | } |
||
1794 | |||
1795 | return |
||
1796 | $this->format->record($row->child2) . ' ' . |
||
1797 | I18N::translate('and') . ' ' . |
||
1798 | $this->format->record($row->child1) . ' ' . |
||
1799 | '<a href="' . e($row->family->url()) . '">[' . I18N::translate('View this family') . ']</a>'; |
||
1800 | } |
||
1801 | |||
1802 | public function topAgeOfMarriage(): string |
||
1803 | { |
||
1804 | return $this->data->ageOfMarriageQuery('age', 'DESC', 1); |
||
1805 | } |
||
1806 | |||
1807 | public function topAgeOfMarriageFamilies(string $limit = '10'): string |
||
1808 | { |
||
1809 | return $this->data->ageOfMarriageQuery('nolist', 'DESC', (int) $limit); |
||
1810 | } |
||
1811 | |||
1812 | public function topAgeOfMarriageFamiliesList(string $limit = '10'): string |
||
1813 | { |
||
1814 | return $this->data->ageOfMarriageQuery('list', 'DESC', (int) $limit); |
||
1815 | } |
||
1816 | |||
1817 | public function topAgeOfMarriageFamily(): string |
||
1818 | { |
||
1819 | return $this->data->ageOfMarriageQuery('name', 'DESC', 1); |
||
1820 | } |
||
1821 | |||
1822 | public function topTenLargestFamily(string $limit = '10'): string |
||
1823 | { |
||
1824 | return $this->data->topTenLargestFamily((int) $limit); |
||
1825 | } |
||
1826 | |||
1827 | public function topTenLargestFamilyList(string $limit = '10'): string |
||
1828 | { |
||
1829 | return $this->data->topTenLargestFamilyList((int) $limit); |
||
1830 | } |
||
1831 | |||
1832 | public function topTenLargestGrandFamily(string $limit = '10'): string |
||
1833 | { |
||
1834 | return $this->data->topTenLargestGrandFamily((int) $limit); |
||
1835 | } |
||
1836 | |||
1837 | public function topTenLargestGrandFamilyList(string $limit = '10'): string |
||
1838 | { |
||
1839 | return $this->data->topTenLargestGrandFamilyList((int) $limit); |
||
1840 | } |
||
1841 | |||
1842 | public function topTenOldest(string $limit = '10'): string |
||
1843 | { |
||
1844 | $records = $this->data->topTenOldestQuery('ALL', (int) $limit) |
||
1845 | ->map(fn (object $row): array => [ |
||
1846 | 'person' => $row->individual, |
||
1847 | 'age' => $this->format->age($row->days), |
||
1848 | ]) |
||
1849 | ->all(); |
||
1850 | |||
1851 | return view('statistics/individuals/top10-nolist', [ |
||
1852 | 'records' => $records, |
||
1853 | ]); |
||
1854 | } |
||
1855 | |||
1856 | public function topTenOldestAlive(string $limit = '10'): string |
||
1857 | { |
||
1858 | if (!Auth::isMember($this->tree)) { |
||
1859 | return I18N::translate('This information is private and cannot be shown.'); |
||
1860 | } |
||
1861 | |||
1862 | $records = $this->data->topTenOldestAliveQuery('ALL', (int) $limit) |
||
1863 | ->map(fn (Individual $individual): array => [ |
||
1864 | 'person' => $individual, |
||
1865 | 'age' => $this->format->age(Registry::timestampFactory()->now()->julianDay() - $individual->getBirthDate()->minimumJulianDay()), |
||
1866 | ]) |
||
1867 | ->all(); |
||
1868 | |||
1869 | return view('statistics/individuals/top10-nolist', [ |
||
1870 | 'records' => $records, |
||
1871 | ]); |
||
1872 | } |
||
1873 | |||
1874 | public function topTenOldestFemale(string $limit = '10'): string |
||
1875 | { |
||
1876 | $records = $this->data->topTenOldestQuery('F', (int) $limit) |
||
1877 | ->map(fn (object $row): array => [ |
||
1878 | 'person' => $row->individual, |
||
1879 | 'age' => $this->format->age($row->days), |
||
1880 | ]) |
||
1881 | ->all(); |
||
1882 | |||
1883 | return view('statistics/individuals/top10-nolist', [ |
||
1884 | 'records' => $records, |
||
1885 | ]); |
||
1886 | } |
||
1887 | |||
1888 | public function topTenOldestFemaleAlive(string $limit = '10'): string |
||
1889 | { |
||
1890 | if (!Auth::isMember($this->tree)) { |
||
1891 | return I18N::translate('This information is private and cannot be shown.'); |
||
1892 | } |
||
1893 | |||
1894 | $records = $this->data->topTenOldestAliveQuery('F', (int) $limit) |
||
1895 | ->map(fn (Individual $individual): array => [ |
||
1896 | 'person' => $individual, |
||
1897 | 'age' => $this->format->age(Registry::timestampFactory()->now()->julianDay() - $individual->getBirthDate()->minimumJulianDay()), |
||
1898 | ]) |
||
1899 | ->all(); |
||
1900 | |||
1901 | return view('statistics/individuals/top10-nolist', [ |
||
1902 | 'records' => $records, |
||
1903 | ]); |
||
1904 | } |
||
1905 | |||
1906 | public function topTenOldestFemaleList(string $limit = '10'): string |
||
1907 | { |
||
1908 | $records = $this->data->topTenOldestQuery('F', (int) $limit) |
||
1909 | ->map(fn (object $row): array => [ |
||
1910 | 'person' => $row->individual, |
||
1911 | 'age' => $this->format->age($row->days), |
||
1912 | ]) |
||
1913 | ->all(); |
||
1914 | |||
1915 | return view('statistics/individuals/top10-list', [ |
||
1916 | 'records' => $records, |
||
1917 | ]); |
||
1918 | } |
||
1919 | |||
1920 | public function topTenOldestFemaleListAlive(string $limit = '10'): string |
||
1921 | { |
||
1922 | if (!Auth::isMember($this->tree)) { |
||
1923 | return I18N::translate('This information is private and cannot be shown.'); |
||
1924 | } |
||
1925 | |||
1926 | $records = $this->data->topTenOldestAliveQuery('F', (int) $limit) |
||
1927 | ->map(fn (Individual $individual): array => [ |
||
1928 | 'person' => $individual, |
||
1929 | 'age' => $this->format->age(Registry::timestampFactory()->now()->julianDay() - $individual->getBirthDate()->minimumJulianDay()), |
||
1930 | ]) |
||
1931 | ->all(); |
||
1932 | |||
1933 | return view('statistics/individuals/top10-list', [ |
||
1934 | 'records' => $records, |
||
1935 | ]); |
||
1936 | } |
||
1937 | |||
1938 | public function topTenOldestList(string $limit = '10'): string |
||
1939 | { |
||
1940 | $records = $this->data->topTenOldestQuery('ALL', (int) $limit) |
||
1941 | ->map(fn (object $row): array => [ |
||
1942 | 'person' => $row->individual, |
||
1943 | 'age' => $this->format->age($row->days), |
||
1944 | ]) |
||
1945 | ->all(); |
||
1946 | |||
1947 | return view('statistics/individuals/top10-list', [ |
||
1948 | 'records' => $records, |
||
1949 | ]); |
||
1950 | } |
||
1951 | |||
1952 | public function topTenOldestListAlive(string $limit = '10'): string |
||
1953 | { |
||
1954 | if (!Auth::isMember($this->tree)) { |
||
1955 | return I18N::translate('This information is private and cannot be shown.'); |
||
1956 | } |
||
1957 | |||
1958 | $records = $this->data->topTenOldestAliveQuery('ALL', (int) $limit) |
||
1959 | ->map(fn (Individual $individual): array => [ |
||
1960 | 'person' => $individual, |
||
1961 | 'age' => $this->format->age(Registry::timestampFactory()->now()->julianDay() - $individual->getBirthDate()->minimumJulianDay()), |
||
1962 | ]) |
||
1963 | ->all(); |
||
1964 | |||
1965 | return view('statistics/individuals/top10-list', [ |
||
1966 | 'records' => $records, |
||
1967 | ]); |
||
1968 | } |
||
1969 | |||
1970 | public function topTenOldestMale(string $limit = '10'): string |
||
1971 | { |
||
1972 | $records = $this->data->topTenOldestQuery('M', (int) $limit) |
||
1973 | ->map(fn (object $row): array => [ |
||
1974 | 'person' => $row->individual, |
||
1975 | 'age' => $this->format->age($row->days), |
||
1976 | ]) |
||
1977 | ->all(); |
||
1978 | |||
1979 | return view('statistics/individuals/top10-nolist', [ |
||
1980 | 'records' => $records, |
||
1981 | ]); |
||
1982 | } |
||
1983 | |||
1984 | public function topTenOldestMaleAlive(string $limit = '10'): string |
||
1985 | { |
||
1986 | if (!Auth::isMember($this->tree)) { |
||
1987 | return I18N::translate('This information is private and cannot be shown.'); |
||
1988 | } |
||
1989 | |||
1990 | $records = $this->data->topTenOldestAliveQuery('M', (int) $limit) |
||
1991 | ->map(fn (Individual $individual): array => [ |
||
1992 | 'person' => $individual, |
||
1993 | 'age' => $this->format->age(Registry::timestampFactory()->now()->julianDay() - $individual->getBirthDate()->minimumJulianDay()), |
||
1994 | ]) |
||
1995 | ->all(); |
||
1996 | |||
1997 | return view('statistics/individuals/top10-nolist', [ |
||
1998 | 'records' => $records, |
||
1999 | ]); |
||
2000 | } |
||
2001 | |||
2002 | public function topTenOldestMaleList(string $limit = '10'): string |
||
2003 | { |
||
2004 | $records = $this->data->topTenOldestQuery('M', (int) $limit) |
||
2005 | ->map(fn (object $row): array => [ |
||
2006 | 'person' => $row->individual, |
||
2007 | 'age' => $this->format->age($row->days), |
||
2008 | ]) |
||
2009 | ->all(); |
||
2010 | |||
2011 | return view('statistics/individuals/top10-list', [ |
||
2012 | 'records' => $records, |
||
2013 | ]); |
||
2014 | } |
||
2015 | |||
2016 | public function topTenOldestMaleListAlive(string $limit = '10'): string |
||
2017 | { |
||
2018 | if (!Auth::isMember($this->tree)) { |
||
2019 | return I18N::translate('This information is private and cannot be shown.'); |
||
2020 | } |
||
2021 | |||
2022 | $records = $this->data->topTenOldestAliveQuery('M', (int) $limit) |
||
2023 | ->map(fn (Individual $individual): array => [ |
||
2024 | 'person' => $individual, |
||
2025 | 'age' => $this->format->age(Registry::timestampFactory()->now()->julianDay() - $individual->getBirthDate()->minimumJulianDay()), |
||
2026 | ]) |
||
2027 | ->all(); |
||
2028 | |||
2029 | return view('statistics/individuals/top10-list', [ |
||
2030 | 'records' => $records, |
||
2031 | ]); |
||
2032 | } |
||
2033 | |||
2034 | public function totalAdmins(): string |
||
2035 | { |
||
2036 | return I18N::number($this->user_service->administrators()->count()); |
||
2037 | } |
||
2038 | |||
2039 | public function totalBirths(): string |
||
2040 | { |
||
2041 | return I18N::number($this->data->countIndividualsWithEvents(['BIRT'])); |
||
2042 | } |
||
2043 | |||
2044 | public function totalChildren(): string |
||
2045 | { |
||
2046 | return I18N::number($this->data->countChildren()); |
||
2047 | } |
||
2048 | |||
2049 | public function totalDeaths(): string |
||
2050 | { |
||
2051 | return I18N::number($this->data->countIndividualsWithEvents(['DEAT'])); |
||
2052 | } |
||
2053 | |||
2054 | public function totalDeceased(): string |
||
2055 | { |
||
2056 | return I18N::number($this->data->countIndividualsDeceased()); |
||
2057 | } |
||
2058 | |||
2059 | public function totalDeceasedPercentage(): string |
||
2060 | { |
||
2061 | return $this->format->percentage( |
||
2062 | $this->data->countIndividualsDeceased(), |
||
2063 | $this->data->countIndividuals() |
||
2064 | ); |
||
2065 | } |
||
2066 | |||
2067 | public function totalDivorces(): string |
||
2068 | { |
||
2069 | return I18N::number($this->data->countFamiliesWithEvents(['DIV'])); |
||
2070 | } |
||
2071 | |||
2072 | public function totalEvents(): string |
||
2073 | { |
||
2074 | return I18N::number($this->data->countOtherEvents(['CHAN'])); |
||
2075 | } |
||
2076 | |||
2077 | public function totalEventsBirth(): string |
||
2078 | { |
||
2079 | return I18N::number($this->data->countAllEvents(Gedcom::BIRTH_EVENTS)); |
||
2080 | } |
||
2081 | |||
2082 | public function totalEventsDeath(): string |
||
2083 | { |
||
2084 | return I18N::number($this->data->countAllEvents(Gedcom::DEATH_EVENTS)); |
||
2085 | } |
||
2086 | |||
2087 | public function totalEventsDivorce(): string |
||
2088 | { |
||
2089 | return I18N::number($this->data->countAllEvents(Gedcom::DIVORCE_EVENTS)); |
||
2090 | } |
||
2091 | |||
2092 | public function totalEventsMarriage(): string |
||
2093 | { |
||
2094 | return I18N::number($this->data->countAllEvents(Gedcom::MARRIAGE_EVENTS)); |
||
2095 | } |
||
2096 | |||
2097 | public function totalEventsOther(): string |
||
2098 | { |
||
2099 | return I18N::number($this->data->countOtherEvents(array_merge( |
||
2100 | ['CHAN'], |
||
2101 | Gedcom::BIRTH_EVENTS, |
||
2102 | Gedcom::DEATH_EVENTS, |
||
2103 | Gedcom::MARRIAGE_EVENTS, |
||
2104 | Gedcom::DIVORCE_EVENTS, |
||
2105 | ))); |
||
2106 | } |
||
2107 | |||
2108 | public function totalFamilies(): string |
||
2109 | { |
||
2110 | return I18N::number($this->data->countFamilies()); |
||
2111 | } |
||
2112 | |||
2113 | public function totalFamiliesPercentage(): string |
||
2114 | { |
||
2115 | return $this->format->percentage( |
||
2116 | $this->data->countFamilies(), |
||
2117 | $this->data->countAllRecords() |
||
2118 | ); |
||
2119 | } |
||
2120 | |||
2121 | public function totalFamsWithSources(): string |
||
2122 | { |
||
2123 | return I18N::number($this->data->countFamiliesWithSources()); |
||
2124 | } |
||
2125 | |||
2126 | public function totalFamsWithSourcesPercentage(): string |
||
2127 | { |
||
2128 | return $this->format->percentage( |
||
2129 | $this->data->countFamiliesWithSources(), |
||
2130 | $this->data->countFamilies() |
||
2131 | ); |
||
2132 | } |
||
2133 | |||
2134 | public function totalGedcomFavorites(): string |
||
2135 | { |
||
2136 | return I18N::number($this->data->countTreeFavorites()); |
||
2137 | } |
||
2138 | |||
2139 | public function totalGivennames(string ...$names): string |
||
2140 | { |
||
2141 | return I18N::number($this->data->countGivenNames($names)); |
||
2142 | } |
||
2143 | |||
2144 | public function totalIndisWithSources(): string |
||
2145 | { |
||
2146 | return I18N::number($this->data->countIndividualsWithSources()); |
||
2147 | } |
||
2148 | |||
2149 | public function totalIndisWithSourcesPercentage(): string |
||
2150 | { |
||
2151 | return $this->format->percentage( |
||
2152 | $this->data->countIndividualsWithSources(), |
||
2153 | $this->data->countIndividuals() |
||
2154 | ); |
||
2155 | } |
||
2156 | |||
2157 | public function totalIndividuals(): string |
||
2158 | { |
||
2159 | return I18N::number($this->data->countIndividuals()); |
||
2160 | } |
||
2161 | |||
2162 | public function totalIndividualsPercentage(): string |
||
2163 | { |
||
2164 | return $this->format->percentage( |
||
2165 | $this->data->countIndividuals(), |
||
2166 | $this->data->countAllRecords() |
||
2167 | ); |
||
2168 | } |
||
2169 | |||
2170 | public function totalLiving(): string |
||
2171 | { |
||
2172 | return I18N::number($this->data->countIndividualsLiving()); |
||
2173 | } |
||
2174 | |||
2175 | public function totalLivingPercentage(): string |
||
2176 | { |
||
2177 | return $this->format->percentage( |
||
2178 | $this->data->countIndividualsLiving(), |
||
2179 | $this->data->countIndividuals() |
||
2180 | ); |
||
2181 | } |
||
2182 | |||
2183 | public function totalMarriages(): string |
||
2184 | { |
||
2185 | return I18N::number($this->data->countFamiliesWithEvents(['MARR'])); |
||
2186 | } |
||
2187 | |||
2188 | public function totalMarriedFemales(): string |
||
2189 | { |
||
2190 | return I18N::number($this->data->countMarriedFemales()); |
||
2191 | } |
||
2192 | |||
2193 | public function totalMarriedMales(): string |
||
2194 | { |
||
2195 | return I18N::number($this->data->countMarriedMales()); |
||
2196 | } |
||
2197 | |||
2198 | public function totalMedia(): string |
||
2199 | { |
||
2200 | return I18N::number($this->data->countMedia()); |
||
2201 | } |
||
2202 | |||
2203 | public function totalMediaAudio(): string |
||
2204 | { |
||
2205 | return I18N::number($this->data->countMedia('audio')); |
||
2206 | } |
||
2207 | |||
2208 | public function totalMediaBook(): string |
||
2209 | { |
||
2210 | return I18N::number($this->data->countMedia('book')); |
||
2211 | } |
||
2212 | |||
2213 | public function totalMediaCard(): string |
||
2214 | { |
||
2215 | return I18N::number($this->data->countMedia('card')); |
||
2216 | } |
||
2217 | |||
2218 | public function totalMediaCertificate(): string |
||
2219 | { |
||
2220 | return I18N::number($this->data->countMedia('certificate')); |
||
2221 | } |
||
2222 | |||
2223 | public function totalMediaCoatOfArms(): string |
||
2224 | { |
||
2225 | return I18N::number($this->data->countMedia('coat')); |
||
2226 | } |
||
2227 | |||
2228 | public function totalMediaDocument(): string |
||
2229 | { |
||
2230 | return I18N::number($this->data->countMedia('document')); |
||
2231 | } |
||
2232 | |||
2233 | public function totalMediaElectronic(): string |
||
2234 | { |
||
2235 | return I18N::number($this->data->countMedia('electronic')); |
||
2236 | } |
||
2237 | |||
2238 | public function totalMediaFiche(): string |
||
2239 | { |
||
2240 | return I18N::number($this->data->countMedia('fiche')); |
||
2241 | } |
||
2242 | |||
2243 | public function totalMediaFilm(): string |
||
2244 | { |
||
2245 | return I18N::number($this->data->countMedia('film')); |
||
2246 | } |
||
2247 | |||
2248 | public function totalMediaMagazine(): string |
||
2249 | { |
||
2250 | return I18N::number($this->data->countMedia('magazine')); |
||
2251 | } |
||
2252 | |||
2253 | public function totalMediaManuscript(): string |
||
2254 | { |
||
2255 | return I18N::number($this->data->countMedia('manuscript')); |
||
2256 | } |
||
2257 | |||
2258 | public function totalMediaMap(): string |
||
2259 | { |
||
2260 | return I18N::number($this->data->countMedia('map')); |
||
2261 | } |
||
2262 | |||
2263 | public function totalMediaNewspaper(): string |
||
2264 | { |
||
2265 | return I18N::number($this->data->countMedia('newspaper')); |
||
2266 | } |
||
2267 | |||
2268 | public function totalMediaOther(): string |
||
2269 | { |
||
2270 | return I18N::number($this->data->countMedia('other')); |
||
2271 | } |
||
2272 | |||
2273 | public function totalMediaPainting(): string |
||
2274 | { |
||
2275 | return I18N::number($this->data->countMedia('painting')); |
||
2276 | } |
||
2277 | |||
2278 | public function totalMediaPhoto(): string |
||
2279 | { |
||
2280 | return I18N::number($this->data->countMedia('photo')); |
||
2281 | } |
||
2282 | |||
2283 | public function totalMediaTombstone(): string |
||
2284 | { |
||
2285 | return I18N::number($this->data->countMedia('tombstone')); |
||
2286 | } |
||
2287 | |||
2288 | public function totalMediaUnknown(): string |
||
2289 | { |
||
2290 | return I18N::number($this->data->countMedia('')); |
||
2291 | } |
||
2292 | |||
2293 | public function totalMediaVideo(): string |
||
2294 | { |
||
2295 | return I18N::number($this->data->countMedia('video')); |
||
2296 | } |
||
2297 | |||
2298 | public function totalNonAdmins(): string |
||
2299 | { |
||
2300 | return I18N::number($this->user_service->all()->count() - $this->user_service->administrators()->count()); |
||
2301 | } |
||
2302 | |||
2303 | public function totalNotes(): string |
||
2306 | } |
||
2307 | |||
2308 | public function totalNotesPercentage(): string |
||
2309 | { |
||
2310 | return $this->format->percentage( |
||
2311 | $this->data->countNotes(), |
||
2312 | $this->data->countAllRecords() |
||
2313 | ); |
||
2314 | } |
||
2315 | |||
2316 | public function totalPlaces(): string |
||
2317 | { |
||
2318 | return I18N::number($this->data->countAllPlaces()); |
||
2319 | } |
||
2320 | |||
2321 | public function totalRecords(): string |
||
2322 | { |
||
2323 | return I18N::number($this->data->countAllRecords()); |
||
2324 | } |
||
2325 | |||
2326 | public function totalRepositories(): string |
||
2327 | { |
||
2328 | return I18N::number($this->data->countRepositories()); |
||
2329 | } |
||
2330 | |||
2331 | public function totalRepositoriesPercentage(): string |
||
2332 | { |
||
2333 | return $this->format->percentage( |
||
2334 | $this->data->countRepositories(), |
||
2335 | $this->data->countAllRecords() |
||
2336 | ); |
||
2337 | } |
||
2338 | |||
2339 | public function totalSexFemales(): string |
||
2340 | { |
||
2341 | return I18N::number($this->data->countIndividualsBySex('F')); |
||
2342 | } |
||
2343 | |||
2344 | public function totalSexFemalesPercentage(): string |
||
2345 | { |
||
2346 | return $this->format->percentage( |
||
2347 | $this->data->countIndividualsBySex('F'), |
||
2348 | $this->data->countIndividuals() |
||
2349 | ); |
||
2350 | } |
||
2351 | |||
2352 | public function totalSexMales(): string |
||
2353 | { |
||
2354 | return I18N::number($this->data->countIndividualsBySex('M')); |
||
2355 | } |
||
2356 | |||
2357 | public function totalSexMalesPercentage(): string |
||
2358 | { |
||
2359 | return $this->format->percentage( |
||
2360 | $this->data->countIndividualsBySex('M'), |
||
2361 | $this->data->countIndividuals() |
||
2362 | ); |
||
2363 | } |
||
2364 | |||
2365 | public function totalSexOther(): string |
||
2366 | { |
||
2367 | return I18N::number($this->data->countIndividualsBySex('X')); |
||
2368 | } |
||
2369 | |||
2370 | public function totalSexOtherPercentage(): string |
||
2371 | { |
||
2372 | return $this->format->percentage( |
||
2373 | $this->data->countIndividualsBySex('X'), |
||
2374 | $this->data->countIndividuals() |
||
2375 | ); |
||
2376 | } |
||
2377 | |||
2378 | public function totalSexUnknown(): string |
||
2379 | { |
||
2380 | return I18N::number($this->data->countIndividualsBySex('U')); |
||
2381 | } |
||
2382 | |||
2383 | public function totalSexUnknownPercentage(): string |
||
2384 | { |
||
2385 | return $this->format->percentage( |
||
2386 | $this->data->countIndividualsBySex('U'), |
||
2387 | $this->data->countIndividuals() |
||
2388 | ); |
||
2389 | } |
||
2390 | |||
2391 | public function totalSources(): string |
||
2392 | { |
||
2393 | return I18N::number($this->data->countSources()); |
||
2394 | } |
||
2395 | |||
2396 | public function totalSourcesPercentage(): string |
||
2397 | { |
||
2398 | return $this->format->percentage( |
||
2399 | $this->data->countSources(), |
||
2400 | $this->data->countAllRecords() |
||
2401 | ); |
||
2402 | } |
||
2403 | |||
2404 | public function totalSurnames(string ...$names): string |
||
2405 | { |
||
2406 | return I18N::number($this->data->countSurnames($names)); |
||
2407 | } |
||
2408 | |||
2409 | public function totalTreeNews(): string |
||
2410 | { |
||
2411 | return I18N::number($this->data->countTreeNews()); |
||
2412 | } |
||
2413 | |||
2414 | public function totalUserFavorites(): string |
||
2415 | { |
||
2416 | return I18N::number($this->data->countUserfavorites()); |
||
2417 | } |
||
2418 | |||
2419 | public function totalUserJournal(): string |
||
2420 | { |
||
2421 | return I18N::number($this->data->countUserJournal()); |
||
2422 | } |
||
2423 | |||
2424 | public function totalUserMessages(): string |
||
2425 | { |
||
2426 | return I18N::number($this->data->countUserMessages()); |
||
2427 | } |
||
2428 | |||
2429 | public function totalUsers(): string |
||
2430 | { |
||
2431 | return I18N::number($this->user_service->all()->count()); |
||
2432 | } |
||
2433 | |||
2434 | public function userFavorites(): string |
||
2435 | { |
||
2436 | return $this->callBlock('user_favorites'); |
||
2437 | } |
||
2438 | |||
2439 | public function userFullName(): string |
||
2440 | { |
||
2441 | return Auth::check() ? '<bdi>' . e(Auth::user()->realName()) . '</bdi>' : ''; |
||
2442 | } |
||
2443 | |||
2444 | public function userId(): string |
||
2445 | { |
||
2446 | return (string) Auth::id(); |
||
2447 | } |
||
2448 | |||
2449 | public function userName(string $visitor_text = ''): string |
||
2450 | { |
||
2451 | if (Auth::check()) { |
||
2452 | return e(Auth::user()->userName()); |
||
2453 | } |
||
2454 | |||
2455 | if ($visitor_text === '') { |
||
2456 | return I18N::translate('Visitor'); |
||
2457 | } |
||
2458 | |||
2459 | return e($visitor_text); |
||
2460 | } |
||
2461 | |||
2462 | public function usersLoggedIn(): string |
||
2463 | { |
||
2464 | return $this->data->usersLoggedIn(); |
||
2465 | } |
||
2466 | |||
2467 | public function usersLoggedInList(): string |
||
2468 | { |
||
2469 | return $this->data->usersLoggedInList(); |
||
2470 | } |
||
2471 | |||
2472 | public function webtreesVersion(): string |
||
2473 | { |
||
2474 | return Webtrees::VERSION; |
||
2475 | } |
||
2476 | |||
2477 | public function youngestFather(): string |
||
2478 | { |
||
2479 | return $this->data->parentsQuery('full', 'ASC', 'M', false); |
||
2480 | } |
||
2481 | |||
2482 | public function youngestFatherAge(string $show_years = '0'): string |
||
2483 | { |
||
2484 | return $this->data->parentsQuery('age', 'ASC', 'M', (bool) $show_years); |
||
2485 | } |
||
2486 | |||
2487 | public function youngestFatherName(): string |
||
2488 | { |
||
2489 | return $this->data->parentsQuery('name', 'ASC', 'M', false); |
||
2490 | } |
||
2491 | |||
2492 | public function youngestMarriageFemale(): string |
||
2493 | { |
||
2494 | return $this->data->marriageQuery('full', 'ASC', 'F', false); |
||
2495 | } |
||
2496 | |||
2497 | public function youngestMarriageFemaleAge(string $show_years = '0'): string |
||
2498 | { |
||
2499 | return $this->data->marriageQuery('age', 'ASC', 'F', (bool) $show_years); |
||
2500 | } |
||
2501 | |||
2502 | public function youngestMarriageFemaleName(): string |
||
2503 | { |
||
2504 | return $this->data->marriageQuery('name', 'ASC', 'F', false); |
||
2505 | } |
||
2506 | |||
2507 | public function youngestMarriageMale(): string |
||
2508 | { |
||
2509 | return $this->data->marriageQuery('full', 'ASC', 'M', false); |
||
2510 | } |
||
2511 | |||
2512 | public function youngestMarriageMaleAge(string $show_years = '0'): string |
||
2515 | } |
||
2516 | |||
2517 | public function youngestMarriageMaleName(): string |
||
2518 | { |
||
2519 | return $this->data->marriageQuery('name', 'ASC', 'M', false); |
||
2520 | } |
||
2521 | |||
2522 | public function youngestMother(): string |
||
2523 | { |
||
2524 | return $this->data->parentsQuery('full', 'ASC', 'F', false); |
||
2525 | } |
||
2526 | |||
2527 | public function youngestMotherAge(string $show_years = '0'): string |
||
2528 | { |
||
2529 | return $this->data->parentsQuery('age', 'ASC', 'F', (bool) $show_years); |
||
2530 | } |
||
2531 | |||
2532 | public function youngestMotherName(): string |
||
2533 | { |
||
2534 | return $this->data->parentsQuery('name', 'ASC', 'F', false); |
||
2535 | } |
||
2536 | } |
||
2537 |
Let?s assume that you have a directory layout like this:
and let?s assume the following content of
Bar.php
:If both files
OtherDir/Foo.php
andSomeDir/Foo.php
are loaded in the same runtime, you will see a PHP error such as the following:PHP Fatal error: Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php
However, as
OtherDir/Foo.php
does not necessarily have to be loaded and the error is only triggered if it is loaded beforeOtherDir/Bar.php
, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias: