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