xref: /webtrees/app/Statistics.php (revision f1d4b4a2fcc65f3b3bd1d9fb6ff4b678a9e0aea4)
1<?php
2
3/**
4 * webtrees: online genealogy
5 * Copyright (C) 2019 webtrees development team
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17declare(strict_types=1);
18
19namespace Fisharebest\Webtrees;
20
21use Psr\Http\Message\ServerRequestInterface;
22
23use function app;
24use function count;
25
26use Fisharebest\Webtrees\Module\ModuleBlockInterface;
27use Fisharebest\Webtrees\Module\ModuleInterface;
28use Fisharebest\Webtrees\Services\ModuleService;
29use Fisharebest\Webtrees\Services\UserService;
30use Fisharebest\Webtrees\Statistics\Repository\BrowserRepository;
31use Fisharebest\Webtrees\Statistics\Repository\ContactRepository;
32use Fisharebest\Webtrees\Statistics\Repository\EventRepository;
33use Fisharebest\Webtrees\Statistics\Repository\FamilyDatesRepository;
34use Fisharebest\Webtrees\Statistics\Repository\FamilyRepository;
35use Fisharebest\Webtrees\Statistics\Repository\FavoritesRepository;
36use Fisharebest\Webtrees\Statistics\Repository\GedcomRepository;
37use Fisharebest\Webtrees\Statistics\Repository\HitCountRepository;
38use Fisharebest\Webtrees\Statistics\Repository\IndividualRepository;
39use Fisharebest\Webtrees\Statistics\Repository\Interfaces\BrowserRepositoryInterface;
40use Fisharebest\Webtrees\Statistics\Repository\Interfaces\ContactRepositoryInterface;
41use Fisharebest\Webtrees\Statistics\Repository\Interfaces\EventRepositoryInterface;
42use Fisharebest\Webtrees\Statistics\Repository\Interfaces\FamilyDatesRepositoryInterface;
43use Fisharebest\Webtrees\Statistics\Repository\Interfaces\FavoritesRepositoryInterface;
44use Fisharebest\Webtrees\Statistics\Repository\Interfaces\GedcomRepositoryInterface;
45use Fisharebest\Webtrees\Statistics\Repository\Interfaces\HitCountRepositoryInterface;
46use Fisharebest\Webtrees\Statistics\Repository\Interfaces\IndividualRepositoryInterface;
47use Fisharebest\Webtrees\Statistics\Repository\Interfaces\LatestUserRepositoryInterface;
48use Fisharebest\Webtrees\Statistics\Repository\Interfaces\MediaRepositoryInterface;
49use Fisharebest\Webtrees\Statistics\Repository\Interfaces\MessageRepositoryInterface;
50use Fisharebest\Webtrees\Statistics\Repository\Interfaces\NewsRepositoryInterface;
51use Fisharebest\Webtrees\Statistics\Repository\Interfaces\PlaceRepositoryInterface;
52use Fisharebest\Webtrees\Statistics\Repository\Interfaces\ServerRepositoryInterface;
53use Fisharebest\Webtrees\Statistics\Repository\Interfaces\UserRepositoryInterface;
54use Fisharebest\Webtrees\Statistics\Repository\LatestUserRepository;
55use Fisharebest\Webtrees\Statistics\Repository\MediaRepository;
56use Fisharebest\Webtrees\Statistics\Repository\MessageRepository;
57use Fisharebest\Webtrees\Statistics\Repository\NewsRepository;
58use Fisharebest\Webtrees\Statistics\Repository\PlaceRepository;
59use Fisharebest\Webtrees\Statistics\Repository\ServerRepository;
60use Fisharebest\Webtrees\Statistics\Repository\UserRepository;
61use Illuminate\Database\Query\Builder;
62
63use function in_array;
64
65use ReflectionMethod;
66
67/**
68 * A selection of pre-formatted statistical queries.
69 * These are primarily used for embedded keywords on HTML blocks, but
70 * are also used elsewhere in the code.
71 */
72class Statistics implements
73    GedcomRepositoryInterface,
74    IndividualRepositoryInterface,
75    EventRepositoryInterface,
76    MediaRepositoryInterface,
77    UserRepositoryInterface,
78    ServerRepositoryInterface,
79    BrowserRepositoryInterface,
80    HitCountRepositoryInterface,
81    LatestUserRepositoryInterface,
82    FavoritesRepositoryInterface,
83    NewsRepositoryInterface,
84    MessageRepositoryInterface,
85    ContactRepositoryInterface,
86    FamilyDatesRepositoryInterface,
87    PlaceRepositoryInterface
88{
89    /**
90     * Generate statistics for a specified tree.
91     *
92     * @var Tree
93     */
94    private $tree;
95
96    /**
97     * All public functions are available as keywords - except these ones
98     *
99     * @var string[]
100     */
101    private static $public_but_not_allowed = [
102        '__construct',
103        'embedTags',
104        'iso3166',
105        'getAllCountries',
106        'getAllTagsTable',
107        'getAllTagsText',
108        'statsPlaces',
109        'statsAgeQuery',
110        'statsChildrenQuery',
111        'statsMarrAgeQuery',
112    ];
113
114    /**
115     * @var GedcomRepository
116     */
117    private $gedcomRepository;
118
119    /**
120     * @var IndividualRepository
121     */
122    private $individualRepository;
123
124    /**
125     * @var FamilyRepository
126     */
127    private $familyRepository;
128
129    /**
130     * @var MediaRepository
131     */
132    private $mediaRepository;
133
134    /**
135     * @var EventRepository
136     */
137    private $eventRepository;
138
139    /**
140     * @var UserRepository
141     */
142    private $userRepository;
143
144    /**
145     * @var ServerRepository
146     */
147    private $serverRepository;
148
149    /**
150     * @var BrowserRepository
151     */
152    private $browserRepository;
153
154    /**
155     * @var HitCountRepository
156     */
157    private $hitCountRepository;
158
159    /**
160     * @var LatestUserRepository
161     */
162    private $latestUserRepository;
163
164    /**
165     * @var FavoritesRepository
166     */
167    private $favoritesRepository;
168
169    /**
170     * @var NewsRepository
171     */
172    private $newsRepository;
173
174    /**
175     * @var MessageRepository
176     */
177    private $messageRepository;
178
179    /**
180     * @var ContactRepository
181     */
182    private $contactRepository;
183
184    /**
185     * @var FamilyDatesRepository
186     */
187    private $familyDatesRepository;
188
189    /**
190     * @var PlaceRepository
191     */
192    private $placeRepository;
193
194    /**
195     * @var ModuleService
196     */
197    private $module_service;
198
199    /**
200     * Create the statistics for a tree.
201     *
202     * @param ModuleService $module_service
203     * @param Tree          $tree Generate statistics for this tree
204     * @param UserService   $user_service
205     */
206    public function __construct(
207        ModuleService $module_service,
208        Tree $tree,
209        UserService $user_service
210    ) {
211        $this->tree                  = $tree;
212        $this->gedcomRepository      = new GedcomRepository($tree);
213        $this->individualRepository  = new IndividualRepository($tree);
214        $this->familyRepository      = new FamilyRepository($tree);
215        $this->familyDatesRepository = new FamilyDatesRepository($tree);
216        $this->mediaRepository       = new MediaRepository($tree);
217        $this->eventRepository       = new EventRepository($tree);
218        $this->userRepository        = new UserRepository($tree, $user_service);
219        $this->serverRepository      = new ServerRepository();
220        $this->browserRepository     = new BrowserRepository();
221        $this->hitCountRepository    = new HitCountRepository($tree, $user_service);
222        $this->latestUserRepository  = new LatestUserRepository($user_service);
223        $this->favoritesRepository   = new FavoritesRepository($tree, $module_service);
224        $this->newsRepository        = new NewsRepository($tree);
225        $this->messageRepository     = new MessageRepository();
226        $this->contactRepository     = new ContactRepository($tree, $user_service);
227        $this->placeRepository       = new PlaceRepository($tree);
228        $this->module_service        = $module_service;
229    }
230
231    /**
232     * Return a string of all supported tags and an example of its output in table row form.
233     *
234     * @return string
235     */
236    public function getAllTagsTable(): string
237    {
238        $examples = [];
239
240        foreach (get_class_methods($this) as $method) {
241            $reflection = new ReflectionMethod($this, $method);
242            if ($reflection->isPublic() && !in_array($method, self::$public_but_not_allowed, true) && (string) $reflection->getReturnType() !== Builder::class) {
243                $examples[$method] = $this->$method();
244            }
245        }
246
247        ksort($examples);
248
249        $html = '';
250        foreach ($examples as $tag => $value) {
251            $html .= '<dt>#' . $tag . '#</dt>';
252            $html .= '<dd>' . $value . '</dd>';
253        }
254
255        return '<dl>' . $html . '</dl>';
256    }
257
258    /**
259     * Return a string of all supported tags in plain text.
260     *
261     * @return string
262     */
263    public function getAllTagsText(): string
264    {
265        $examples = [];
266
267        foreach (get_class_methods($this) as $method) {
268            $reflection = new ReflectionMethod($this, $method);
269            if ($reflection->isPublic() && !in_array($method, self::$public_but_not_allowed, true) && (string) $reflection->getReturnType() !== Builder::class) {
270                $examples[$method] = $method;
271            }
272        }
273
274        ksort($examples);
275
276        return implode('<br>', $examples);
277    }
278
279    /**
280     * Get tags and their parsed results.
281     *
282     * @param string $text
283     *
284     * @return string[]
285     */
286    private function getTags(string $text): array
287    {
288        $tags    = [];
289        $matches = [];
290
291        preg_match_all('/#([^#]+)#/', $text, $matches, PREG_SET_ORDER);
292
293        foreach ($matches as $match) {
294            $params = explode(':', $match[1]);
295            $method = array_shift($params);
296
297            if (method_exists($this, $method)) {
298                $tags[$match[0]] = $this->$method(...$params);
299            }
300        }
301
302        return $tags;
303    }
304
305    /**
306     * Embed tags in text
307     *
308     * @param string $text
309     *
310     * @return string
311     */
312    public function embedTags(string $text): string
313    {
314        if (strpos($text, '#') !== false) {
315            $text = strtr($text, $this->getTags($text));
316        }
317
318        return $text;
319    }
320
321    /**
322     * @inheritDoc
323     */
324    public function gedcomFilename(): string
325    {
326        return $this->gedcomRepository->gedcomFilename();
327    }
328
329    /**
330     * @inheritDoc
331     */
332    public function gedcomId(): int
333    {
334        return $this->gedcomRepository->gedcomId();
335    }
336
337    /**
338     * @inheritDoc
339     */
340    public function gedcomTitle(): string
341    {
342        return $this->gedcomRepository->gedcomTitle();
343    }
344
345    /**
346     * @inheritDoc
347     */
348    public function gedcomCreatedSoftware(): string
349    {
350        return $this->gedcomRepository->gedcomCreatedSoftware();
351    }
352
353    /**
354     * @inheritDoc
355     */
356    public function gedcomCreatedVersion(): string
357    {
358        return $this->gedcomRepository->gedcomCreatedVersion();
359    }
360
361    /**
362     * @inheritDoc
363     */
364    public function gedcomDate(): string
365    {
366        return $this->gedcomRepository->gedcomDate();
367    }
368
369    /**
370     * @inheritDoc
371     */
372    public function gedcomUpdated(): string
373    {
374        return $this->gedcomRepository->gedcomUpdated();
375    }
376
377    /**
378     * @inheritDoc
379     */
380    public function gedcomRootId(): string
381    {
382        return $this->gedcomRepository->gedcomRootId();
383    }
384
385    /**
386     * @inheritDoc
387     */
388    public function totalRecords(): string
389    {
390        return $this->individualRepository->totalRecords();
391    }
392
393    /**
394     * @inheritDoc
395     */
396    public function totalIndividuals(): string
397    {
398        return $this->individualRepository->totalIndividuals();
399    }
400
401    /**
402     * @inheritDoc
403     */
404    public function totalIndisWithSources(): string
405    {
406        return $this->individualRepository->totalIndisWithSources();
407    }
408
409    /**
410     * @inheritDoc
411     */
412    public function chartIndisWithSources(
413        string $color_from = null,
414        string $color_to = null
415    ): string {
416        return $this->individualRepository->chartIndisWithSources($color_from, $color_to);
417    }
418
419    /**
420     * @inheritDoc
421     */
422    public function totalIndividualsPercentage(): string
423    {
424        return $this->individualRepository->totalIndividualsPercentage();
425    }
426
427    /**
428     * @inheritDoc
429     */
430    public function totalFamilies(): string
431    {
432        return $this->individualRepository->totalFamilies();
433    }
434
435    /**
436     * @inheritDoc
437     */
438    public function totalFamiliesPercentage(): string
439    {
440        return $this->individualRepository->totalFamiliesPercentage();
441    }
442
443    /**
444     * @inheritDoc
445     */
446    public function totalFamsWithSources(): string
447    {
448        return $this->individualRepository->totalFamsWithSources();
449    }
450
451    /**
452     * @inheritDoc
453     */
454    public function chartFamsWithSources(
455        string $color_from = null,
456        string $color_to = null
457    ): string {
458        return $this->individualRepository->chartFamsWithSources($color_from, $color_to);
459    }
460
461    /**
462     * @inheritDoc
463     */
464    public function totalSources(): string
465    {
466        return $this->individualRepository->totalSources();
467    }
468
469    /**
470     * @inheritDoc
471     */
472    public function totalSourcesPercentage(): string
473    {
474        return $this->individualRepository->totalSourcesPercentage();
475    }
476
477    /**
478     * @inheritDoc
479     */
480    public function totalNotes(): string
481    {
482        return $this->individualRepository->totalNotes();
483    }
484
485    /**
486     * @inheritDoc
487     */
488    public function totalNotesPercentage(): string
489    {
490        return $this->individualRepository->totalNotesPercentage();
491    }
492
493    /**
494     * @inheritDoc
495     */
496    public function totalRepositories(): string
497    {
498        return $this->individualRepository->totalRepositories();
499    }
500
501    /**
502     * @inheritDoc
503     */
504    public function totalRepositoriesPercentage(): string
505    {
506        return $this->individualRepository->totalRepositoriesPercentage();
507    }
508
509    /**
510     * @inheritDoc
511     */
512    public function totalSurnames(...$params): string
513    {
514        return $this->individualRepository->totalSurnames(...$params);
515    }
516
517    /**
518     * @inheritDoc
519     */
520    public function totalGivennames(...$params): string
521    {
522        return $this->individualRepository->totalGivennames(...$params);
523    }
524
525    /**
526     * @inheritDoc
527     */
528    public function totalEvents(array $events = []): string
529    {
530        return $this->eventRepository->totalEvents($events);
531    }
532
533    /**
534     * @inheritDoc
535     */
536    public function totalEventsBirth(): string
537    {
538        return $this->eventRepository->totalEventsBirth();
539    }
540
541    /**
542     * @inheritDoc
543     */
544    public function totalBirths(): string
545    {
546        return $this->eventRepository->totalBirths();
547    }
548
549    /**
550     * @inheritDoc
551     */
552    public function totalEventsDeath(): string
553    {
554        return $this->eventRepository->totalEventsDeath();
555    }
556
557    /**
558     * @inheritDoc
559     */
560    public function totalDeaths(): string
561    {
562        return $this->eventRepository->totalDeaths();
563    }
564
565    /**
566     * @inheritDoc
567     */
568    public function totalEventsMarriage(): string
569    {
570        return $this->eventRepository->totalEventsMarriage();
571    }
572
573    /**
574     * @inheritDoc
575     */
576    public function totalMarriages(): string
577    {
578        return $this->eventRepository->totalMarriages();
579    }
580
581    /**
582     * @inheritDoc
583     */
584    public function totalEventsDivorce(): string
585    {
586        return $this->eventRepository->totalEventsDivorce();
587    }
588
589    /**
590     * @inheritDoc
591     */
592    public function totalDivorces(): string
593    {
594        return $this->eventRepository->totalDivorces();
595    }
596
597    /**
598     * @inheritDoc
599     */
600    public function totalEventsOther(): string
601    {
602        return $this->eventRepository->totalEventsOther();
603    }
604
605    /**
606     * @inheritDoc
607     */
608    public function totalSexMales(): string
609    {
610        return $this->individualRepository->totalSexMales();
611    }
612
613    /**
614     * @inheritDoc
615     */
616    public function totalSexMalesPercentage(): string
617    {
618        return $this->individualRepository->totalSexMalesPercentage();
619    }
620
621    /**
622     * @inheritDoc
623     */
624    public function totalSexFemales(): string
625    {
626        return $this->individualRepository->totalSexFemales();
627    }
628
629    /**
630     * @inheritDoc
631     */
632    public function totalSexFemalesPercentage(): string
633    {
634        return $this->individualRepository->totalSexFemalesPercentage();
635    }
636
637    /**
638     * @inheritDoc
639     */
640    public function totalSexUnknown(): string
641    {
642        return $this->individualRepository->totalSexUnknown();
643    }
644
645    /**
646     * @inheritDoc
647     */
648    public function totalSexUnknownPercentage(): string
649    {
650        return $this->individualRepository->totalSexUnknownPercentage();
651    }
652
653    /**
654     * @inheritDoc
655     */
656    public function chartSex(
657        string $color_female = null,
658        string $color_male = null,
659        string $color_unknown = null
660    ): string {
661        return $this->individualRepository->chartSex($color_female, $color_male, $color_unknown);
662    }
663
664    /**
665     * @inheritDoc
666     */
667    public function totalLiving(): string
668    {
669        return $this->individualRepository->totalLiving();
670    }
671
672    /**
673     * @inheritDoc
674     */
675    public function totalLivingPercentage(): string
676    {
677        return $this->individualRepository->totalLivingPercentage();
678    }
679
680    /**
681     * @inheritDoc
682     */
683    public function totalDeceased(): string
684    {
685        return $this->individualRepository->totalDeceased();
686    }
687
688    /**
689     * @inheritDoc
690     */
691    public function totalDeceasedPercentage(): string
692    {
693        return $this->individualRepository->totalDeceasedPercentage();
694    }
695
696    /**
697     * @inheritDoc
698     */
699    public function chartMortality(string $color_living = null, string $color_dead = null): string
700    {
701        return $this->individualRepository->chartMortality($color_living, $color_dead);
702    }
703
704    /**
705     * @inheritDoc
706     */
707    public function totalMedia(): string
708    {
709        return $this->mediaRepository->totalMedia();
710    }
711
712    /**
713     * @inheritDoc
714     */
715    public function totalMediaAudio(): string
716    {
717        return $this->mediaRepository->totalMediaAudio();
718    }
719
720    /**
721     * @inheritDoc
722     */
723    public function totalMediaBook(): string
724    {
725        return $this->mediaRepository->totalMediaBook();
726    }
727
728    /**
729     * @inheritDoc
730     */
731    public function totalMediaCard(): string
732    {
733        return $this->mediaRepository->totalMediaCard();
734    }
735
736    /**
737     * @inheritDoc
738     */
739    public function totalMediaCertificate(): string
740    {
741        return $this->mediaRepository->totalMediaCertificate();
742    }
743
744    /**
745     * @inheritDoc
746     */
747    public function totalMediaCoatOfArms(): string
748    {
749        return $this->mediaRepository->totalMediaCoatOfArms();
750    }
751
752    /**
753     * @inheritDoc
754     */
755    public function totalMediaDocument(): string
756    {
757        return $this->mediaRepository->totalMediaDocument();
758    }
759
760    /**
761     * @inheritDoc
762     */
763    public function totalMediaElectronic(): string
764    {
765        return $this->mediaRepository->totalMediaElectronic();
766    }
767
768    /**
769     * @inheritDoc
770     */
771    public function totalMediaMagazine(): string
772    {
773        return $this->mediaRepository->totalMediaMagazine();
774    }
775
776    /**
777     * @inheritDoc
778     */
779    public function totalMediaManuscript(): string
780    {
781        return $this->mediaRepository->totalMediaManuscript();
782    }
783
784    /**
785     * @inheritDoc
786     */
787    public function totalMediaMap(): string
788    {
789        return $this->mediaRepository->totalMediaMap();
790    }
791
792    /**
793     * @inheritDoc
794     */
795    public function totalMediaFiche(): string
796    {
797        return $this->mediaRepository->totalMediaFiche();
798    }
799
800    /**
801     * @inheritDoc
802     */
803    public function totalMediaFilm(): string
804    {
805        return $this->mediaRepository->totalMediaFilm();
806    }
807
808    /**
809     * @inheritDoc
810     */
811    public function totalMediaNewspaper(): string
812    {
813        return $this->mediaRepository->totalMediaNewspaper();
814    }
815
816    /**
817     * @inheritDoc
818     */
819    public function totalMediaPainting(): string
820    {
821        return $this->mediaRepository->totalMediaPainting();
822    }
823
824    /**
825     * @inheritDoc
826     */
827    public function totalMediaPhoto(): string
828    {
829        return $this->mediaRepository->totalMediaPhoto();
830    }
831
832    /**
833     * @inheritDoc
834     */
835    public function totalMediaTombstone(): string
836    {
837        return $this->mediaRepository->totalMediaTombstone();
838    }
839
840    /**
841     * @inheritDoc
842     */
843    public function totalMediaVideo(): string
844    {
845        return $this->mediaRepository->totalMediaVideo();
846    }
847
848    /**
849     * @inheritDoc
850     */
851    public function totalMediaOther(): string
852    {
853        return $this->mediaRepository->totalMediaOther();
854    }
855
856    /**
857     * @inheritDoc
858     */
859    public function totalMediaUnknown(): string
860    {
861        return $this->mediaRepository->totalMediaUnknown();
862    }
863
864    /**
865     * @inheritDoc
866     */
867    public function chartMedia(string $color_from = null, string $color_to = null): string
868    {
869        return $this->mediaRepository->chartMedia($color_from, $color_to);
870    }
871
872    /**
873     * @inheritDoc
874     */
875    public function statsPlaces(string $what = 'ALL', string $fact = '', int $parent = 0, bool $country = false): array
876    {
877        return $this->placeRepository->statsPlaces($what, $fact, $parent, $country);
878    }
879
880    /**
881     * @inheritDoc
882     */
883    public function totalPlaces(): string
884    {
885        return $this->placeRepository->totalPlaces();
886    }
887
888    /**
889     * @inheritDoc
890     */
891    public function chartDistribution(
892        string $chart_shows = 'world',
893        string $chart_type = '',
894        string $surname = ''
895    ): string {
896        return $this->placeRepository->chartDistribution($chart_shows, $chart_type, $surname);
897    }
898
899    /**
900     * @inheritDoc
901     */
902    public function commonCountriesList(): string
903    {
904        return $this->placeRepository->commonCountriesList();
905    }
906
907    /**
908     * @inheritDoc
909     */
910    public function commonBirthPlacesList(): string
911    {
912        return $this->placeRepository->commonBirthPlacesList();
913    }
914
915    /**
916     * @inheritDoc
917     */
918    public function commonDeathPlacesList(): string
919    {
920        return $this->placeRepository->commonDeathPlacesList();
921    }
922
923    /**
924     * @inheritDoc
925     */
926    public function commonMarriagePlacesList(): string
927    {
928        return $this->placeRepository->commonMarriagePlacesList();
929    }
930
931    /**
932     * @inheritDoc
933     */
934    public function firstBirth(): string
935    {
936        return $this->familyDatesRepository->firstBirth();
937    }
938
939    /**
940     * @inheritDoc
941     */
942    public function firstBirthYear(): string
943    {
944        return $this->familyDatesRepository->firstBirthYear();
945    }
946
947    /**
948     * @inheritDoc
949     */
950    public function firstBirthName(): string
951    {
952        return $this->familyDatesRepository->firstBirthName();
953    }
954
955    /**
956     * @inheritDoc
957     */
958    public function firstBirthPlace(): string
959    {
960        return $this->familyDatesRepository->firstBirthPlace();
961    }
962
963    /**
964     * @inheritDoc
965     */
966    public function lastBirth(): string
967    {
968        return $this->familyDatesRepository->lastBirth();
969    }
970
971    /**
972     * @inheritDoc
973     */
974    public function lastBirthYear(): string
975    {
976        return $this->familyDatesRepository->lastBirthYear();
977    }
978
979    /**
980     * @inheritDoc
981     */
982    public function lastBirthName(): string
983    {
984        return $this->familyDatesRepository->lastBirthName();
985    }
986
987    /**
988     * @inheritDoc
989     */
990    public function lastBirthPlace(): string
991    {
992        return $this->familyDatesRepository->lastBirthPlace();
993    }
994
995    /**
996     * @inheritDoc
997     */
998    public function statsBirthQuery(int $year1 = -1, int $year2 = -1): Builder
999    {
1000        return $this->individualRepository->statsBirthQuery($year1, $year2);
1001    }
1002
1003    /**
1004     * @inheritDoc
1005     */
1006    public function statsBirthBySexQuery(int $year1 = -1, int $year2 = -1): Builder
1007    {
1008        return $this->individualRepository->statsBirthBySexQuery($year1, $year2);
1009    }
1010
1011    /**
1012     * @inheritDoc
1013     */
1014    public function statsBirth(string $color_from = null, string $color_to = null): string
1015    {
1016        return $this->individualRepository->statsBirth($color_from, $color_to);
1017    }
1018
1019    /**
1020     * @inheritDoc
1021     */
1022    public function firstDeath(): string
1023    {
1024        return $this->familyDatesRepository->firstDeath();
1025    }
1026
1027    /**
1028     * @inheritDoc
1029     */
1030    public function firstDeathYear(): string
1031    {
1032        return $this->familyDatesRepository->firstDeathYear();
1033    }
1034
1035    /**
1036     * @inheritDoc
1037     */
1038    public function firstDeathName(): string
1039    {
1040        return $this->familyDatesRepository->firstDeathName();
1041    }
1042
1043    /**
1044     * @inheritDoc
1045     */
1046    public function firstDeathPlace(): string
1047    {
1048        return $this->familyDatesRepository->firstDeathPlace();
1049    }
1050
1051    /**
1052     * @inheritDoc
1053     */
1054    public function lastDeath(): string
1055    {
1056        return $this->familyDatesRepository->lastDeath();
1057    }
1058
1059    /**
1060     * @inheritDoc
1061     */
1062    public function lastDeathYear(): string
1063    {
1064        return $this->familyDatesRepository->lastDeathYear();
1065    }
1066
1067    /**
1068     * @inheritDoc
1069     */
1070    public function lastDeathName(): string
1071    {
1072        return $this->familyDatesRepository->lastDeathName();
1073    }
1074
1075    /**
1076     * @inheritDoc
1077     */
1078    public function lastDeathPlace(): string
1079    {
1080        return $this->familyDatesRepository->lastDeathPlace();
1081    }
1082
1083    /**
1084     * @inheritDoc
1085     */
1086    public function statsDeathQuery(int $year1 = -1, int $year2 = -1): Builder
1087    {
1088        return $this->individualRepository->statsDeathQuery($year1, $year2);
1089    }
1090
1091    /**
1092     * @inheritDoc
1093     */
1094    public function statsDeathBySexQuery(int $year1 = -1, int $year2 = -1): Builder
1095    {
1096        return $this->individualRepository->statsDeathBySexQuery($year1, $year2);
1097    }
1098
1099    /**
1100     * @inheritDoc
1101     */
1102    public function statsDeath(string $color_from = null, string $color_to = null): string
1103    {
1104        return $this->individualRepository->statsDeath($color_from, $color_to);
1105    }
1106
1107    /**
1108     * @inheritDoc
1109     */
1110    public function statsAgeQuery(string $related = 'BIRT', string $sex = 'BOTH', int $year1 = -1, int $year2 = -1)
1111    {
1112        return $this->individualRepository->statsAgeQuery($related, $sex, $year1, $year2);
1113    }
1114
1115    /**
1116     * @inheritDoc
1117     */
1118    public function statsAge(): string
1119    {
1120        return $this->individualRepository->statsAge();
1121    }
1122
1123    /**
1124     * @inheritDoc
1125     */
1126    public function longestLife(): string
1127    {
1128        return $this->individualRepository->longestLife();
1129    }
1130
1131    /**
1132     * @inheritDoc
1133     */
1134    public function longestLifeAge(): string
1135    {
1136        return $this->individualRepository->longestLifeAge();
1137    }
1138
1139    /**
1140     * @inheritDoc
1141     */
1142    public function longestLifeName(): string
1143    {
1144        return $this->individualRepository->longestLifeName();
1145    }
1146
1147    /**
1148     * @inheritDoc
1149     */
1150    public function longestLifeFemale(): string
1151    {
1152        return $this->individualRepository->longestLifeFemale();
1153    }
1154
1155    /**
1156     * @inheritDoc
1157     */
1158    public function longestLifeFemaleAge(): string
1159    {
1160        return $this->individualRepository->longestLifeFemaleAge();
1161    }
1162
1163    /**
1164     * @inheritDoc
1165     */
1166    public function longestLifeFemaleName(): string
1167    {
1168        return $this->individualRepository->longestLifeFemaleName();
1169    }
1170
1171    /**
1172     * @inheritDoc
1173     */
1174    public function longestLifeMale(): string
1175    {
1176        return $this->individualRepository->longestLifeMale();
1177    }
1178
1179    /**
1180     * @inheritDoc
1181     */
1182    public function longestLifeMaleAge(): string
1183    {
1184        return $this->individualRepository->longestLifeMaleAge();
1185    }
1186
1187    /**
1188     * @inheritDoc
1189     */
1190    public function longestLifeMaleName(): string
1191    {
1192        return $this->individualRepository->longestLifeMaleName();
1193    }
1194
1195    /**
1196     * @inheritDoc
1197     */
1198    public function topTenOldest(string $total = '10'): string
1199    {
1200        return $this->individualRepository->topTenOldest((int) $total);
1201    }
1202
1203    /**
1204     * @inheritDoc
1205     */
1206    public function topTenOldestList(string $total = '10'): string
1207    {
1208        return $this->individualRepository->topTenOldestList((int) $total);
1209    }
1210
1211    /**
1212     * @inheritDoc
1213     */
1214    public function topTenOldestFemale(string $total = '10'): string
1215    {
1216        return $this->individualRepository->topTenOldestFemale((int) $total);
1217    }
1218
1219    /**
1220     * @inheritDoc
1221     */
1222    public function topTenOldestFemaleList(string $total = '10'): string
1223    {
1224        return $this->individualRepository->topTenOldestFemaleList((int) $total);
1225    }
1226
1227    /**
1228     * @inheritDoc
1229     */
1230    public function topTenOldestMale(string $total = '10'): string
1231    {
1232        return $this->individualRepository->topTenOldestMale((int) $total);
1233    }
1234
1235    /**
1236     * @inheritDoc
1237     */
1238    public function topTenOldestMaleList(string $total = '10'): string
1239    {
1240        return $this->individualRepository->topTenOldestMaleList((int) $total);
1241    }
1242
1243    /**
1244     * @inheritDoc
1245     */
1246    public function topTenOldestAlive(string $total = '10'): string
1247    {
1248        return $this->individualRepository->topTenOldestAlive((int) $total);
1249    }
1250
1251    /**
1252     * @inheritDoc
1253     */
1254    public function topTenOldestListAlive(string $total = '10'): string
1255    {
1256        return $this->individualRepository->topTenOldestListAlive((int) $total);
1257    }
1258
1259    /**
1260     * @inheritDoc
1261     */
1262    public function topTenOldestFemaleAlive(string $total = '10'): string
1263    {
1264        return $this->individualRepository->topTenOldestFemaleAlive((int) $total);
1265    }
1266
1267    /**
1268     * @inheritDoc
1269     */
1270    public function topTenOldestFemaleListAlive(string $total = '10'): string
1271    {
1272        return $this->individualRepository->topTenOldestFemaleListAlive((int) $total);
1273    }
1274
1275    /**
1276     * @inheritDoc
1277     */
1278    public function topTenOldestMaleAlive(string $total = '10'): string
1279    {
1280        return $this->individualRepository->topTenOldestMaleAlive((int) $total);
1281    }
1282
1283    /**
1284     * @inheritDoc
1285     */
1286    public function topTenOldestMaleListAlive(string $total = '10'): string
1287    {
1288        return $this->individualRepository->topTenOldestMaleListAlive((int) $total);
1289    }
1290
1291    /**
1292     * @inheritDoc
1293     */
1294    public function averageLifespan(bool $show_years = false): string
1295    {
1296        return $this->individualRepository->averageLifespan($show_years);
1297    }
1298
1299    /**
1300     * @inheritDoc
1301     */
1302    public function averageLifespanFemale(bool $show_years = false): string
1303    {
1304        return $this->individualRepository->averageLifespanFemale($show_years);
1305    }
1306
1307    /**
1308     * @inheritDoc
1309     */
1310    public function averageLifespanMale(bool $show_years = false): string
1311    {
1312        return $this->individualRepository->averageLifespanMale($show_years);
1313    }
1314
1315    /**
1316     * @inheritDoc
1317     */
1318    public function firstEvent(): string
1319    {
1320        return $this->eventRepository->firstEvent();
1321    }
1322
1323    /**
1324     * @inheritDoc
1325     */
1326    public function firstEventYear(): string
1327    {
1328        return $this->eventRepository->firstEventYear();
1329    }
1330
1331    /**
1332     * @inheritDoc
1333     */
1334    public function firstEventType(): string
1335    {
1336        return $this->eventRepository->firstEventType();
1337    }
1338
1339    /**
1340     * @inheritDoc
1341     */
1342    public function firstEventName(): string
1343    {
1344        return $this->eventRepository->firstEventName();
1345    }
1346
1347    /**
1348     * @inheritDoc
1349     */
1350    public function firstEventPlace(): string
1351    {
1352        return $this->eventRepository->firstEventPlace();
1353    }
1354
1355    /**
1356     * @inheritDoc
1357     */
1358    public function lastEvent(): string
1359    {
1360        return $this->eventRepository->lastEvent();
1361    }
1362
1363    /**
1364     * @inheritDoc
1365     */
1366    public function lastEventYear(): string
1367    {
1368        return $this->eventRepository->lastEventYear();
1369    }
1370
1371    /**
1372     * @inheritDoc
1373     */
1374    public function lastEventType(): string
1375    {
1376        return $this->eventRepository->lastEventType();
1377    }
1378
1379    /**
1380     * @inheritDoc
1381     */
1382    public function lastEventName(): string
1383    {
1384        return $this->eventRepository->lastEventName();
1385    }
1386
1387    /**
1388     * @inheritDoc
1389     */
1390    public function lastEventPlace(): string
1391    {
1392        return $this->eventRepository->lastEventType();
1393    }
1394
1395    /**
1396     * @inheritDoc
1397     */
1398    public function firstMarriage(): string
1399    {
1400        return $this->familyDatesRepository->firstMarriage();
1401    }
1402
1403    /**
1404     * @inheritDoc
1405     */
1406    public function firstMarriageYear(): string
1407    {
1408        return $this->familyDatesRepository->firstMarriageYear();
1409    }
1410
1411    /**
1412     * @inheritDoc
1413     */
1414    public function firstMarriageName(): string
1415    {
1416        return $this->familyDatesRepository->firstMarriageName();
1417    }
1418
1419    /**
1420     * @inheritDoc
1421     */
1422    public function firstMarriagePlace(): string
1423    {
1424        return $this->familyDatesRepository->firstMarriagePlace();
1425    }
1426
1427    /**
1428     * @inheritDoc
1429     */
1430    public function lastMarriage(): string
1431    {
1432        return $this->familyDatesRepository->lastMarriage();
1433    }
1434
1435    /**
1436     * @inheritDoc
1437     */
1438    public function lastMarriageYear(): string
1439    {
1440        return $this->familyDatesRepository->lastMarriageYear();
1441    }
1442
1443    /**
1444     * @inheritDoc
1445     */
1446    public function lastMarriageName(): string
1447    {
1448        return $this->familyDatesRepository->lastMarriageName();
1449    }
1450
1451    /**
1452     * @inheritDoc
1453     */
1454    public function lastMarriagePlace(): string
1455    {
1456        return $this->familyDatesRepository->lastMarriagePlace();
1457    }
1458
1459    /**
1460     * @inheritDoc
1461     */
1462    public function statsMarriageQuery(int $year1 = -1, int $year2 = -1): Builder
1463    {
1464        return $this->familyRepository->statsMarriageQuery($year1, $year2);
1465    }
1466
1467    /**
1468     * @inheritDoc
1469     */
1470    public function statsFirstMarriageQuery(int $year1 = -1, int $year2 = -1): Builder
1471    {
1472        return $this->familyRepository->statsFirstMarriageQuery($year1, $year2);
1473    }
1474
1475    /**
1476     * @inheritDoc
1477     */
1478    public function statsMarr(string $color_from = null, string $color_to = null): string
1479    {
1480        return $this->familyRepository->statsMarr($color_from, $color_to);
1481    }
1482
1483    /**
1484     * @inheritDoc
1485     */
1486    public function firstDivorce(): string
1487    {
1488        return $this->familyDatesRepository->firstDivorce();
1489    }
1490
1491    /**
1492     * @inheritDoc
1493     */
1494    public function firstDivorceYear(): string
1495    {
1496        return $this->familyDatesRepository->firstDivorceYear();
1497    }
1498
1499    /**
1500     * @inheritDoc
1501     */
1502    public function firstDivorceName(): string
1503    {
1504        return $this->familyDatesRepository->firstDivorceName();
1505    }
1506
1507    /**
1508     * @inheritDoc
1509     */
1510    public function firstDivorcePlace(): string
1511    {
1512        return $this->familyDatesRepository->firstDivorcePlace();
1513    }
1514
1515    /**
1516     * @inheritDoc
1517     */
1518    public function lastDivorce(): string
1519    {
1520        return $this->familyDatesRepository->lastDivorce();
1521    }
1522
1523    /**
1524     * @inheritDoc
1525     */
1526    public function lastDivorceYear(): string
1527    {
1528        return $this->familyDatesRepository->lastDivorceYear();
1529    }
1530
1531    /**
1532     * @inheritDoc
1533     */
1534    public function lastDivorceName(): string
1535    {
1536        return $this->familyDatesRepository->lastDivorceName();
1537    }
1538
1539    /**
1540     * @inheritDoc
1541     */
1542    public function lastDivorcePlace(): string
1543    {
1544        return $this->familyDatesRepository->lastDivorcePlace();
1545    }
1546
1547    /**
1548     * @inheritDoc
1549     */
1550    public function statsDiv(string $color_from = null, string $color_to = null): string
1551    {
1552        return $this->familyRepository->statsDiv($color_from, $color_to);
1553    }
1554
1555    /**
1556     * @inheritDoc
1557     */
1558    public function youngestMarriageFemale(): string
1559    {
1560        return $this->familyRepository->youngestMarriageFemale();
1561    }
1562
1563    /**
1564     * @inheritDoc
1565     */
1566    public function youngestMarriageFemaleName(): string
1567    {
1568        return $this->familyRepository->youngestMarriageFemaleName();
1569    }
1570
1571    /**
1572     * @inheritDoc
1573     */
1574    public function youngestMarriageFemaleAge(string $show_years = ''): string
1575    {
1576        return $this->familyRepository->youngestMarriageFemaleAge($show_years);
1577    }
1578
1579    /**
1580     * @inheritDoc
1581     */
1582    public function oldestMarriageFemale(): string
1583    {
1584        return $this->familyRepository->oldestMarriageFemale();
1585    }
1586
1587    /**
1588     * @inheritDoc
1589     */
1590    public function oldestMarriageFemaleName(): string
1591    {
1592        return $this->familyRepository->oldestMarriageFemaleName();
1593    }
1594
1595    /**
1596     * @inheritDoc
1597     */
1598    public function oldestMarriageFemaleAge(string $show_years = ''): string
1599    {
1600        return $this->familyRepository->oldestMarriageFemaleAge($show_years);
1601    }
1602
1603    /**
1604     * @inheritDoc
1605     */
1606    public function youngestMarriageMale(): string
1607    {
1608        return $this->familyRepository->youngestMarriageMale();
1609    }
1610
1611    /**
1612     * @inheritDoc
1613     */
1614    public function youngestMarriageMaleName(): string
1615    {
1616        return $this->familyRepository->youngestMarriageMaleName();
1617    }
1618
1619    /**
1620     * @inheritDoc
1621     */
1622    public function youngestMarriageMaleAge(string $show_years = ''): string
1623    {
1624        return $this->familyRepository->youngestMarriageMaleAge($show_years);
1625    }
1626
1627    /**
1628     * @inheritDoc
1629     */
1630    public function oldestMarriageMale(): string
1631    {
1632        return $this->familyRepository->oldestMarriageMale();
1633    }
1634
1635    /**
1636     * @inheritDoc
1637     */
1638    public function oldestMarriageMaleName(): string
1639    {
1640        return $this->familyRepository->oldestMarriageMaleName();
1641    }
1642
1643    /**
1644     * @inheritDoc
1645     */
1646    public function oldestMarriageMaleAge(string $show_years = ''): string
1647    {
1648        return $this->familyRepository->oldestMarriageMaleAge($show_years);
1649    }
1650
1651    /**
1652     * @inheritDoc
1653     */
1654    public function statsMarrAgeQuery(string $sex, int $year1 = -1, int $year2 = -1): array
1655    {
1656        return $this->familyRepository->statsMarrAgeQuery($sex, $year1, $year2);
1657    }
1658
1659    /**
1660     * @inheritDoc
1661     */
1662    public function statsMarrAge(): string
1663    {
1664        return $this->familyRepository->statsMarrAge();
1665    }
1666
1667    /**
1668     * @inheritDoc
1669     */
1670    public function ageBetweenSpousesMF(string $total = '10'): string
1671    {
1672        return $this->familyRepository->ageBetweenSpousesMF((int) $total);
1673    }
1674
1675    /**
1676     * @inheritDoc
1677     */
1678    public function ageBetweenSpousesMFList(string $total = '10'): string
1679    {
1680        return $this->familyRepository->ageBetweenSpousesMFList((int) $total);
1681    }
1682
1683    /**
1684     * @inheritDoc
1685     */
1686    public function ageBetweenSpousesFM(string $total = '10'): string
1687    {
1688        return $this->familyRepository->ageBetweenSpousesFM((int) $total);
1689    }
1690
1691    /**
1692     * @inheritDoc
1693     */
1694    public function ageBetweenSpousesFMList(string $total = '10'): string
1695    {
1696        return $this->familyRepository->ageBetweenSpousesFMList((int) $total);
1697    }
1698
1699    /**
1700     * @inheritDoc
1701     */
1702    public function topAgeOfMarriageFamily(): string
1703    {
1704        return $this->familyRepository->topAgeOfMarriageFamily();
1705    }
1706
1707    /**
1708     * @inheritDoc
1709     */
1710    public function topAgeOfMarriage(): string
1711    {
1712        return $this->familyRepository->topAgeOfMarriage();
1713    }
1714
1715    /**
1716     * @inheritDoc
1717     */
1718    public function topAgeOfMarriageFamilies(string $total = '10'): string
1719    {
1720        return $this->familyRepository->topAgeOfMarriageFamilies((int) $total);
1721    }
1722
1723    /**
1724     * @inheritDoc
1725     */
1726    public function topAgeOfMarriageFamiliesList(string $total = '10'): string
1727    {
1728        return $this->familyRepository->topAgeOfMarriageFamiliesList((int) $total);
1729    }
1730
1731    /**
1732     * @inheritDoc
1733     */
1734    public function minAgeOfMarriageFamily(): string
1735    {
1736        return $this->familyRepository->minAgeOfMarriageFamily();
1737    }
1738
1739    /**
1740     * @inheritDoc
1741     */
1742    public function minAgeOfMarriage(): string
1743    {
1744        return $this->familyRepository->minAgeOfMarriage();
1745    }
1746
1747    /**
1748     * @inheritDoc
1749     */
1750    public function minAgeOfMarriageFamilies(string $total = '10'): string
1751    {
1752        return $this->familyRepository->minAgeOfMarriageFamilies((int) $total);
1753    }
1754
1755    /**
1756     * @inheritDoc
1757     */
1758    public function minAgeOfMarriageFamiliesList(string $total = '10'): string
1759    {
1760        return $this->familyRepository->minAgeOfMarriageFamiliesList((int) $total);
1761    }
1762
1763    /**
1764     * @inheritDoc
1765     */
1766    public function youngestMother(): string
1767    {
1768        return $this->familyRepository->youngestMother();
1769    }
1770
1771    /**
1772     * @inheritDoc
1773     */
1774    public function youngestMotherName(): string
1775    {
1776        return $this->familyRepository->youngestMotherName();
1777    }
1778
1779    /**
1780     * @inheritDoc
1781     */
1782    public function youngestMotherAge(string $show_years = ''): string
1783    {
1784        return $this->familyRepository->youngestMotherAge($show_years);
1785    }
1786
1787    /**
1788     * @inheritDoc
1789     */
1790    public function oldestMother(): string
1791    {
1792        return $this->familyRepository->oldestMother();
1793    }
1794
1795    /**
1796     * @inheritDoc
1797     */
1798    public function oldestMotherName(): string
1799    {
1800        return $this->familyRepository->oldestMotherName();
1801    }
1802
1803    /**
1804     * @inheritDoc
1805     */
1806    public function oldestMotherAge(string $show_years = ''): string
1807    {
1808        return $this->familyRepository->oldestMotherAge($show_years);
1809    }
1810
1811    /**
1812     * @inheritDoc
1813     */
1814    public function youngestFather(): string
1815    {
1816        return $this->familyRepository->youngestFather();
1817    }
1818
1819    /**
1820     * @inheritDoc
1821     */
1822    public function youngestFatherName(): string
1823    {
1824        return $this->familyRepository->youngestFatherName();
1825    }
1826
1827    /**
1828     * @inheritDoc
1829     */
1830    public function youngestFatherAge(string $show_years = ''): string
1831    {
1832        return $this->familyRepository->youngestFatherAge($show_years);
1833    }
1834
1835    /**
1836     * @inheritDoc
1837     */
1838    public function oldestFather(): string
1839    {
1840        return $this->familyRepository->oldestFather();
1841    }
1842
1843    /**
1844     * @inheritDoc
1845     */
1846    public function oldestFatherName(): string
1847    {
1848        return $this->familyRepository->oldestFatherName();
1849    }
1850
1851    /**
1852     * @inheritDoc
1853     */
1854    public function oldestFatherAge(string $show_years = ''): string
1855    {
1856        return $this->familyRepository->oldestFatherAge($show_years);
1857    }
1858
1859    /**
1860     * @inheritDoc
1861     */
1862    public function totalMarriedMales(): string
1863    {
1864        return $this->familyRepository->totalMarriedMales();
1865    }
1866
1867    /**
1868     * @inheritDoc
1869     */
1870    public function totalMarriedFemales(): string
1871    {
1872        return $this->familyRepository->totalMarriedFemales();
1873    }
1874
1875    /**
1876     * @inheritDoc
1877     */
1878    public function monthFirstChildQuery(int $year1 = -1, int $year2 = -1): Builder
1879    {
1880        return $this->familyRepository->monthFirstChildQuery($year1, $year2);
1881    }
1882
1883    /**
1884     * @inheritDoc
1885     */
1886    public function monthFirstChildBySexQuery(int $year1 = -1, int $year2 = -1): Builder
1887    {
1888        return $this->familyRepository->monthFirstChildBySexQuery($year1, $year2);
1889    }
1890
1891    /**
1892     * @inheritDoc
1893     */
1894    public function largestFamily(): string
1895    {
1896        return $this->familyRepository->largestFamily();
1897    }
1898
1899    /**
1900     * @inheritDoc
1901     */
1902    public function largestFamilySize(): string
1903    {
1904        return $this->familyRepository->largestFamilySize();
1905    }
1906
1907    /**
1908     * @inheritDoc
1909     */
1910    public function largestFamilyName(): string
1911    {
1912        return $this->familyRepository->largestFamilyName();
1913    }
1914
1915    /**
1916     * @inheritDoc
1917     */
1918    public function topTenLargestFamily(string $total = '10'): string
1919    {
1920        return $this->familyRepository->topTenLargestFamily((int) $total);
1921    }
1922
1923    /**
1924     * @inheritDoc
1925     */
1926    public function topTenLargestFamilyList(string $total = '10'): string
1927    {
1928        return $this->familyRepository->topTenLargestFamilyList((int) $total);
1929    }
1930
1931    /**
1932     * @inheritDoc
1933     */
1934    public function chartLargestFamilies(
1935        string $color_from = null,
1936        string $color_to = null,
1937        string $total = '10'
1938    ): string {
1939        return $this->familyRepository->chartLargestFamilies($color_from, $color_to, (int) $total);
1940    }
1941
1942    /**
1943     * @inheritDoc
1944     */
1945    public function totalChildren(): string
1946    {
1947        return $this->familyRepository->totalChildren();
1948    }
1949
1950    /**
1951     * @inheritDoc
1952     */
1953    public function averageChildren(): string
1954    {
1955        return $this->familyRepository->averageChildren();
1956    }
1957
1958    /**
1959     * @inheritDoc
1960     */
1961    public function statsChildrenQuery(int $year1 = -1, int $year2 = -1): array
1962    {
1963        return $this->familyRepository->statsChildrenQuery($year1, $year2);
1964    }
1965
1966    /**
1967     * @inheritDoc
1968     */
1969    public function statsChildren(): string
1970    {
1971        return $this->familyRepository->statsChildren();
1972    }
1973
1974    /**
1975     * @inheritDoc
1976     */
1977    public function topAgeBetweenSiblingsName(string $total = '10'): string
1978    {
1979        return $this->familyRepository->topAgeBetweenSiblingsName((int) $total);
1980    }
1981
1982    /**
1983     * @inheritDoc
1984     */
1985    public function topAgeBetweenSiblings(string $total = '10'): string
1986    {
1987        return $this->familyRepository->topAgeBetweenSiblings((int) $total);
1988    }
1989
1990    /**
1991     * @inheritDoc
1992     */
1993    public function topAgeBetweenSiblingsFullName(string $total = '10'): string
1994    {
1995        return $this->familyRepository->topAgeBetweenSiblingsFullName((int) $total);
1996    }
1997
1998    /**
1999     * @inheritDoc
2000     */
2001    public function topAgeBetweenSiblingsList(string $total = '10', string $one = ''): string
2002    {
2003        return $this->familyRepository->topAgeBetweenSiblingsList((int) $total, $one);
2004    }
2005
2006    /**
2007     * @inheritDoc
2008     */
2009    public function noChildrenFamilies(): string
2010    {
2011        return $this->familyRepository->noChildrenFamilies();
2012    }
2013
2014    /**
2015     * @inheritDoc
2016     */
2017    public function noChildrenFamiliesList(string $type = 'list'): string
2018    {
2019        return $this->familyRepository->noChildrenFamiliesList($type);
2020    }
2021
2022    /**
2023     * @inheritDoc
2024     */
2025    public function chartNoChildrenFamilies(
2026        string $year1 = '-1',
2027        string $year2 = '-1'
2028    ): string {
2029        return $this->familyRepository->chartNoChildrenFamilies((int) $year1, (int) $year2);
2030    }
2031
2032    /**
2033     * @inheritDoc
2034     */
2035    public function topTenLargestGrandFamily(string $total = '10'): string
2036    {
2037        return $this->familyRepository->topTenLargestGrandFamily((int) $total);
2038    }
2039
2040    /**
2041     * @inheritDoc
2042     */
2043    public function topTenLargestGrandFamilyList(string $total = '10'): string
2044    {
2045        return $this->familyRepository->topTenLargestGrandFamilyList((int) $total);
2046    }
2047
2048    /**
2049     * @inheritDoc
2050     */
2051    public function getCommonSurname(): string
2052    {
2053        return $this->individualRepository->getCommonSurname();
2054    }
2055
2056    /**
2057     * @inheritDoc
2058     */
2059    public function commonSurnames(
2060        string $threshold = '1',
2061        string $number_of_surnames = '10',
2062        string $sorting = 'alpha'
2063    ): string {
2064        return $this->individualRepository->commonSurnames((int) $threshold, (int) $number_of_surnames, $sorting);
2065    }
2066
2067    /**
2068     * @inheritDoc
2069     */
2070    public function commonSurnamesTotals(
2071        string $threshold = '1',
2072        string $number_of_surnames = '10',
2073        string $sorting = 'rcount'
2074    ): string {
2075        return $this->individualRepository->commonSurnamesTotals((int) $threshold, (int) $number_of_surnames, $sorting);
2076    }
2077
2078    /**
2079     * @inheritDoc
2080     */
2081    public function commonSurnamesList(
2082        string $threshold = '1',
2083        string $number_of_surnames = '10',
2084        string $sorting = 'alpha'
2085    ): string {
2086        return $this->individualRepository->commonSurnamesList((int) $threshold, (int) $number_of_surnames, $sorting);
2087    }
2088
2089    /**
2090     * @inheritDoc
2091     */
2092    public function commonSurnamesListTotals(
2093        string $threshold = '1',
2094        string $number_of_surnames = '10',
2095        string $sorting = 'rcount'
2096    ): string {
2097        return $this->individualRepository
2098            ->commonSurnamesListTotals((int) $threshold, (int) $number_of_surnames, $sorting);
2099    }
2100
2101    /**
2102     * @inheritDoc
2103     */
2104    public function chartCommonSurnames(
2105        string $color_from = null,
2106        string $color_to = null,
2107        string $number_of_surnames = '10'
2108    ): string {
2109        return $this->individualRepository
2110            ->chartCommonSurnames($color_from, $color_to, (int) $number_of_surnames);
2111    }
2112
2113    /**
2114     * @inheritDoc
2115     */
2116    public function commonGiven(string $threshold = '1', string $maxtoshow = '10'): string
2117    {
2118        return $this->individualRepository->commonGiven((int) $threshold, (int) $maxtoshow);
2119    }
2120
2121    /**
2122     * @inheritDoc
2123     */
2124    public function commonGivenTotals(string $threshold = '1', string $maxtoshow = '10'): string
2125    {
2126        return $this->individualRepository->commonGivenTotals((int) $threshold, (int) $maxtoshow);
2127    }
2128
2129    /**
2130     * @inheritDoc
2131     */
2132    public function commonGivenList(string $threshold = '1', string $maxtoshow = '10'): string
2133    {
2134        return $this->individualRepository->commonGivenList((int) $threshold, (int) $maxtoshow);
2135    }
2136
2137    /**
2138     * @inheritDoc
2139     */
2140    public function commonGivenListTotals(string $threshold = '1', string $maxtoshow = '10'): string
2141    {
2142        return $this->individualRepository->commonGivenListTotals((int) $threshold, (int) $maxtoshow);
2143    }
2144
2145    /**
2146     * @inheritDoc
2147     */
2148    public function commonGivenTable(string $threshold = '1', string $maxtoshow = '10'): string
2149    {
2150        return $this->individualRepository->commonGivenTable((int) $threshold, (int) $maxtoshow);
2151    }
2152
2153    /**
2154     * @inheritDoc
2155     */
2156    public function commonGivenFemale(string $threshold = '1', string $maxtoshow = '10'): string
2157    {
2158        return $this->individualRepository->commonGivenFemale((int) $threshold, (int) $maxtoshow);
2159    }
2160
2161    /**
2162     * @inheritDoc
2163     */
2164    public function commonGivenFemaleTotals(string $threshold = '1', string $maxtoshow = '10'): string
2165    {
2166        return $this->individualRepository->commonGivenFemaleTotals((int) $threshold, (int) $maxtoshow);
2167    }
2168
2169    /**
2170     * @inheritDoc
2171     */
2172    public function commonGivenFemaleList(string $threshold = '1', string $maxtoshow = '10'): string
2173    {
2174        return $this->individualRepository->commonGivenFemaleList((int) $threshold, (int) $maxtoshow);
2175    }
2176
2177    /**
2178     * @inheritDoc
2179     */
2180    public function commonGivenFemaleListTotals(string $threshold = '1', string $maxtoshow = '10'): string
2181    {
2182        return $this->individualRepository->commonGivenFemaleListTotals((int) $threshold, (int) $maxtoshow);
2183    }
2184
2185    /**
2186     * @inheritDoc
2187     */
2188    public function commonGivenFemaleTable(string $threshold = '1', string $maxtoshow = '10'): string
2189    {
2190        return $this->individualRepository->commonGivenFemaleTable((int) $threshold, (int) $maxtoshow);
2191    }
2192
2193    /**
2194     * @inheritDoc
2195     */
2196    public function commonGivenMale(string $threshold = '1', string $maxtoshow = '10'): string
2197    {
2198        return $this->individualRepository->commonGivenMale((int) $threshold, (int) $maxtoshow);
2199    }
2200
2201    /**
2202     * @inheritDoc
2203     */
2204    public function commonGivenMaleTotals(string $threshold = '1', string $maxtoshow = '10'): string
2205    {
2206        return $this->individualRepository->commonGivenMaleTotals((int) $threshold, (int) $maxtoshow);
2207    }
2208
2209    /**
2210     * @inheritDoc
2211     */
2212    public function commonGivenMaleList(string $threshold = '1', string $maxtoshow = '10'): string
2213    {
2214        return $this->individualRepository->commonGivenMaleList((int) $threshold, (int) $maxtoshow);
2215    }
2216
2217    /**
2218     * @inheritDoc
2219     */
2220    public function commonGivenMaleListTotals(string $threshold = '1', string $maxtoshow = '10'): string
2221    {
2222        return $this->individualRepository->commonGivenMaleListTotals((int) $threshold, (int) $maxtoshow);
2223    }
2224
2225    /**
2226     * @inheritDoc
2227     */
2228    public function commonGivenMaleTable(string $threshold = '1', string $maxtoshow = '10'): string
2229    {
2230        return $this->individualRepository->commonGivenMaleTable((int) $threshold, (int) $maxtoshow);
2231    }
2232
2233    /**
2234     * @inheritDoc
2235     */
2236    public function commonGivenUnknown(string $threshold = '1', string $maxtoshow = '10'): string
2237    {
2238        return $this->individualRepository->commonGivenUnknown((int) $threshold, (int) $maxtoshow);
2239    }
2240
2241    /**
2242     * @inheritDoc
2243     */
2244    public function commonGivenUnknownTotals(string $threshold = '1', string $maxtoshow = '10'): string
2245    {
2246        return $this->individualRepository->commonGivenUnknownTotals((int) $threshold, (int) $maxtoshow);
2247    }
2248
2249    /**
2250     * @inheritDoc
2251     */
2252    public function commonGivenUnknownList(string $threshold = '1', string $maxtoshow = '10'): string
2253    {
2254        return $this->individualRepository->commonGivenUnknownList((int) $threshold, (int) $maxtoshow);
2255    }
2256
2257    /**
2258     * @inheritDoc
2259     */
2260    public function commonGivenUnknownListTotals(string $threshold = '1', string $maxtoshow = '10'): string
2261    {
2262        return $this->individualRepository->commonGivenUnknownListTotals((int) $threshold, (int) $maxtoshow);
2263    }
2264
2265    /**
2266     * @inheritDoc
2267     */
2268    public function commonGivenUnknownTable(string $threshold = '1', string $maxtoshow = '10'): string
2269    {
2270        return $this->individualRepository->commonGivenUnknownTable((int) $threshold, (int) $maxtoshow);
2271    }
2272
2273    /**
2274     * @inheritDoc
2275     */
2276    public function chartCommonGiven(
2277        string $color_from = null,
2278        string $color_to = null,
2279        string $maxtoshow = '7'
2280    ): string {
2281        return $this->individualRepository->chartCommonGiven($color_from, $color_to, (int) $maxtoshow);
2282    }
2283
2284    /**
2285     * @inheritDoc
2286     */
2287    public function usersLoggedIn(): string
2288    {
2289        return $this->userRepository->usersLoggedIn();
2290    }
2291
2292    /**
2293     * @inheritDoc
2294     */
2295    public function usersLoggedInList(): string
2296    {
2297        return $this->userRepository->usersLoggedInList();
2298    }
2299
2300    /**
2301     * @inheritDoc
2302     */
2303    public function usersLoggedInTotal(): int
2304    {
2305        return $this->userRepository->usersLoggedInTotal();
2306    }
2307
2308    /**
2309     * @inheritDoc
2310     */
2311    public function usersLoggedInTotalAnon(): int
2312    {
2313        return $this->userRepository->usersLoggedInTotalAnon();
2314    }
2315
2316    /**
2317     * @inheritDoc
2318     */
2319    public function usersLoggedInTotalVisible(): int
2320    {
2321        return $this->userRepository->usersLoggedInTotalVisible();
2322    }
2323
2324    /**
2325     * @inheritDoc
2326     */
2327    public function userId(): string
2328    {
2329        return $this->userRepository->userId();
2330    }
2331
2332    /**
2333     * @inheritDoc
2334     */
2335    public function userName(string $visitor_text = ''): string
2336    {
2337        return $this->userRepository->userName($visitor_text);
2338    }
2339
2340    /**
2341     * @inheritDoc
2342     */
2343    public function userFullName(): string
2344    {
2345        return $this->userRepository->userFullName();
2346    }
2347
2348    /**
2349     * @inheritDoc
2350     */
2351    public function totalUsers(): string
2352    {
2353        return $this->userRepository->totalUsers();
2354    }
2355
2356    /**
2357     * @inheritDoc
2358     */
2359    public function totalAdmins(): string
2360    {
2361        return $this->userRepository->totalAdmins();
2362    }
2363
2364    /**
2365     * @inheritDoc
2366     */
2367    public function totalNonAdmins(): string
2368    {
2369        return $this->userRepository->totalNonAdmins();
2370    }
2371
2372    /**
2373     * @inheritDoc
2374     */
2375    public function latestUserId(): string
2376    {
2377        return $this->latestUserRepository->latestUserId();
2378    }
2379
2380    /**
2381     * @inheritDoc
2382     */
2383    public function latestUserName(): string
2384    {
2385        return $this->latestUserRepository->latestUserName();
2386    }
2387
2388    /**
2389     * @inheritDoc
2390     */
2391    public function latestUserFullName(): string
2392    {
2393        return $this->latestUserRepository->latestUserFullName();
2394    }
2395
2396    /**
2397     * @inheritDoc
2398     */
2399    public function latestUserRegDate(string $format = null): string
2400    {
2401        return $this->latestUserRepository->latestUserRegDate($format);
2402    }
2403
2404    /**
2405     * @inheritDoc
2406     */
2407    public function latestUserRegTime(string $format = null): string
2408    {
2409        return $this->latestUserRepository->latestUserRegTime($format);
2410    }
2411
2412    /**
2413     * @inheritDoc
2414     */
2415    public function latestUserLoggedin(string $yes = null, string $no = null): string
2416    {
2417        return $this->latestUserRepository->latestUserLoggedin($yes, $no);
2418    }
2419
2420    /**
2421     * @inheritDoc
2422     */
2423    public function contactWebmaster(): string
2424    {
2425        $request = app(ServerRequestInterface::class);
2426
2427        return $this->contactRepository->contactWebmaster($request);
2428    }
2429
2430    /**
2431     * @inheritDoc
2432     */
2433    public function contactGedcom(): string
2434    {
2435        $request = app(ServerRequestInterface::class);
2436
2437        return $this->contactRepository->contactGedcom($request);
2438    }
2439
2440    /**
2441     * @inheritDoc
2442     */
2443    public function serverDate(): string
2444    {
2445        return $this->serverRepository->serverDate();
2446    }
2447
2448    /**
2449     * @inheritDoc
2450     */
2451    public function serverTime(): string
2452    {
2453        return $this->serverRepository->serverTime();
2454    }
2455
2456    /**
2457     * @inheritDoc
2458     */
2459    public function serverTime24(): string
2460    {
2461        return $this->serverRepository->serverTime24();
2462    }
2463
2464    /**
2465     * What is the timezone of the server.
2466     *
2467     * @return string
2468     */
2469    public function serverTimezone(): string
2470    {
2471        return $this->serverRepository->serverTimezone();
2472    }
2473
2474    /**
2475     * @inheritDoc
2476     */
2477    public function browserDate(): string
2478    {
2479        return $this->browserRepository->browserDate();
2480    }
2481
2482    /**
2483     * @inheritDoc
2484     */
2485    public function browserTime(): string
2486    {
2487        return $this->browserRepository->browserTime();
2488    }
2489
2490    /**
2491     * @inheritDoc
2492     */
2493    public function browserTimezone(): string
2494    {
2495        return $this->browserRepository->browserTimezone();
2496    }
2497
2498    /**
2499     * @inheritDoc
2500     */
2501    public function hitCount(string $page_parameter = ''): string
2502    {
2503        return $this->hitCountRepository->hitCount($page_parameter);
2504    }
2505
2506    /**
2507     * @inheritDoc
2508     */
2509    public function hitCountUser(string $page_parameter = ''): string
2510    {
2511        return $this->hitCountRepository->hitCountUser($page_parameter);
2512    }
2513
2514    /**
2515     * @inheritDoc
2516     */
2517    public function hitCountIndi(string $page_parameter = ''): string
2518    {
2519        return $this->hitCountRepository->hitCountIndi($page_parameter);
2520    }
2521
2522    /**
2523     * @inheritDoc
2524     */
2525    public function hitCountFam(string $page_parameter = ''): string
2526    {
2527        return $this->hitCountRepository->hitCountFam($page_parameter);
2528    }
2529
2530    /**
2531     * @inheritDoc
2532     */
2533    public function hitCountSour(string $page_parameter = ''): string
2534    {
2535        return $this->hitCountRepository->hitCountSour($page_parameter);
2536    }
2537
2538    /**
2539     * @inheritDoc
2540     */
2541    public function hitCountRepo(string $page_parameter = ''): string
2542    {
2543        return $this->hitCountRepository->hitCountRepo($page_parameter);
2544    }
2545
2546    /**
2547     * @inheritDoc
2548     */
2549    public function hitCountNote(string $page_parameter = ''): string
2550    {
2551        return $this->hitCountRepository->hitCountNote($page_parameter);
2552    }
2553
2554    /**
2555     * @inheritDoc
2556     */
2557    public function hitCountObje(string $page_parameter = ''): string
2558    {
2559        return $this->hitCountRepository->hitCountObje($page_parameter);
2560    }
2561
2562    /**
2563     * @inheritDoc
2564     */
2565    public function gedcomFavorites(): string
2566    {
2567        return $this->favoritesRepository->gedcomFavorites();
2568    }
2569
2570    /**
2571     * @inheritDoc
2572     */
2573    public function userFavorites(): string
2574    {
2575        return $this->favoritesRepository->userFavorites();
2576    }
2577
2578    /**
2579     * @inheritDoc
2580     */
2581    public function totalGedcomFavorites(): string
2582    {
2583        return $this->favoritesRepository->totalGedcomFavorites();
2584    }
2585
2586    /**
2587     * @inheritDoc
2588     */
2589    public function totalUserFavorites(): string
2590    {
2591        return $this->favoritesRepository->totalUserFavorites();
2592    }
2593
2594    /**
2595     * @inheritDoc
2596     */
2597    public function totalUserMessages(): string
2598    {
2599        return $this->messageRepository->totalUserMessages();
2600    }
2601
2602    /**
2603     * @inheritDoc
2604     */
2605    public function totalUserJournal(): string
2606    {
2607        return $this->newsRepository->totalUserJournal();
2608    }
2609
2610    /**
2611     * @inheritDoc
2612     */
2613    public function totalGedcomNews(): string
2614    {
2615        return $this->newsRepository->totalGedcomNews();
2616    }
2617
2618    /**
2619     * Create any of the other blocks.
2620     * Use as #callBlock:block_name#
2621     *
2622     * @param string $block
2623     * @param string ...$params
2624     *
2625     * @return string|null
2626     */
2627    public function callBlock(string $block = '', ...$params): ?string
2628    {
2629        /** @var ModuleBlockInterface|null $module */
2630        $module = $this->module_service
2631            ->findByComponent(ModuleBlockInterface::class, $this->tree, Auth::user())
2632            ->first(static function (ModuleInterface $module) use ($block): bool {
2633                return $module->name() === $block && $module->name() !== 'html';
2634            });
2635
2636        if ($module === null) {
2637            return '';
2638        }
2639
2640        // Build the config array
2641        $cfg = [];
2642        foreach ($params as $config) {
2643            $bits = explode('=', $config);
2644
2645            if (count($bits) < 2) {
2646                continue;
2647            }
2648
2649            $v       = array_shift($bits);
2650            $cfg[$v] = implode('=', $bits);
2651        }
2652
2653        return $module->getBlock($this->tree, 0, ModuleBlockInterface::CONTEXT_EMBED, $cfg);
2654    }
2655
2656    /**
2657     * What is the current version of webtrees.
2658     *
2659     * @return string
2660     */
2661    public function webtreesVersion(): string
2662    {
2663        return Webtrees::VERSION;
2664    }
2665}
2666