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