xref: /webtrees/app/Statistics.php (revision ad7270802ba57a28d195fc58fcc55f26458a779a)
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 $size = null,
408        string $color_from = null,
409        string $color_to = null
410    ): string {
411        return $this->individualRepository->chartIndisWithSources($size, $color_from, $color_to);
412    }
413
414    /**
415     * @inheritDoc
416     */
417    public function totalIndividualsPercentage(): string
418    {
419        return $this->individualRepository->totalIndividualsPercentage();
420    }
421
422    /**
423     * @inheritDoc
424     */
425    public function totalFamilies(): string
426    {
427        return $this->individualRepository->totalFamilies();
428    }
429
430    /**
431     * @inheritDoc
432     */
433    public function totalFamiliesPercentage(): string
434    {
435        return $this->individualRepository->totalFamiliesPercentage();
436    }
437
438    /**
439     * @inheritDoc
440     */
441    public function totalFamsWithSources(): string
442    {
443        return $this->individualRepository->totalFamsWithSources();
444    }
445
446    /**
447     * @inheritDoc
448     */
449    public function chartFamsWithSources(
450        string $size = null,
451        string $color_from = null,
452        string $color_to = null
453    ): string {
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        return $this->individualRepository->chartSex($size, $color_female, $color_male, $color_unknown);
659    }
660
661    /**
662     * @inheritDoc
663     */
664    public function totalLiving(): string
665    {
666        return $this->individualRepository->totalLiving();
667    }
668
669    /**
670     * @inheritDoc
671     */
672    public function totalLivingPercentage(): string
673    {
674        return $this->individualRepository->totalLivingPercentage();
675    }
676
677    /**
678     * @inheritDoc
679     */
680    public function totalDeceased(): string
681    {
682        return $this->individualRepository->totalDeceased();
683    }
684
685    /**
686     * @inheritDoc
687     */
688    public function totalDeceasedPercentage(): string
689    {
690        return $this->individualRepository->totalDeceasedPercentage();
691    }
692
693    /**
694     * @inheritDoc
695     */
696    public function chartMortality(string $size = null, string $color_living = null, string $color_dead = null): string
697    {
698        return $this->individualRepository->chartMortality($size, $color_living, $color_dead);
699    }
700
701    /**
702     * @inheritDoc
703     */
704    public function totalMedia(): string
705    {
706        return $this->mediaRepository->totalMedia();
707    }
708
709    /**
710     * @inheritDoc
711     */
712    public function totalMediaAudio(): string
713    {
714        return $this->mediaRepository->totalMediaAudio();
715    }
716
717    /**
718     * @inheritDoc
719     */
720    public function totalMediaBook(): string
721    {
722        return $this->mediaRepository->totalMediaBook();
723    }
724
725    /**
726     * @inheritDoc
727     */
728    public function totalMediaCard(): string
729    {
730        return $this->mediaRepository->totalMediaCard();
731    }
732
733    /**
734     * @inheritDoc
735     */
736    public function totalMediaCertificate(): string
737    {
738        return $this->mediaRepository->totalMediaCertificate();
739    }
740
741    /**
742     * @inheritDoc
743     */
744    public function totalMediaCoatOfArms(): string
745    {
746        return $this->mediaRepository->totalMediaCoatOfArms();
747    }
748
749    /**
750     * @inheritDoc
751     */
752    public function totalMediaDocument(): string
753    {
754        return $this->mediaRepository->totalMediaDocument();
755    }
756
757    /**
758     * @inheritDoc
759     */
760    public function totalMediaElectronic(): string
761    {
762        return $this->mediaRepository->totalMediaElectronic();
763    }
764
765    /**
766     * @inheritDoc
767     */
768    public function totalMediaMagazine(): string
769    {
770        return $this->mediaRepository->totalMediaMagazine();
771    }
772
773    /**
774     * @inheritDoc
775     */
776    public function totalMediaManuscript(): string
777    {
778        return $this->mediaRepository->totalMediaManuscript();
779    }
780
781    /**
782     * @inheritDoc
783     */
784    public function totalMediaMap(): string
785    {
786        return $this->mediaRepository->totalMediaMap();
787    }
788
789    /**
790     * @inheritDoc
791     */
792    public function totalMediaFiche(): string
793    {
794        return $this->mediaRepository->totalMediaFiche();
795    }
796
797    /**
798     * @inheritDoc
799     */
800    public function totalMediaFilm(): string
801    {
802        return $this->mediaRepository->totalMediaFilm();
803    }
804
805    /**
806     * @inheritDoc
807     */
808    public function totalMediaNewspaper(): string
809    {
810        return $this->mediaRepository->totalMediaNewspaper();
811    }
812
813    /**
814     * @inheritDoc
815     */
816    public function totalMediaPainting(): string
817    {
818        return $this->mediaRepository->totalMediaPainting();
819    }
820
821    /**
822     * @inheritDoc
823     */
824    public function totalMediaPhoto(): string
825    {
826        return $this->mediaRepository->totalMediaPhoto();
827    }
828
829    /**
830     * @inheritDoc
831     */
832    public function totalMediaTombstone(): string
833    {
834        return $this->mediaRepository->totalMediaTombstone();
835    }
836
837    /**
838     * @inheritDoc
839     */
840    public function totalMediaVideo(): string
841    {
842        return $this->mediaRepository->totalMediaVideo();
843    }
844
845    /**
846     * @inheritDoc
847     */
848    public function totalMediaOther(): string
849    {
850        return $this->mediaRepository->totalMediaOther();
851    }
852
853    /**
854     * @inheritDoc
855     */
856    public function totalMediaUnknown(): string
857    {
858        return $this->mediaRepository->totalMediaUnknown();
859    }
860
861    /**
862     * @inheritDoc
863     */
864    public function chartMedia(string $size = null, string $color_from = null, string $color_to = null): string
865    {
866        return $this->mediaRepository->chartMedia($size, $color_from, $color_to);
867    }
868
869    /**
870     * @inheritDoc
871     */
872    public function statsPlaces(string $what = 'ALL', string $fact = '', int $parent = 0, bool $country = false): array
873    {
874        return $this->placeRepository->statsPlaces($what, $fact, $parent, $country);
875    }
876
877    /**
878     * @inheritDoc
879     */
880    public function totalPlaces(): string
881    {
882        return $this->placeRepository->totalPlaces();
883    }
884
885    /**
886     * @inheritDoc
887     */
888    public function chartDistribution(
889        string $chart_shows = 'world',
890        string $chart_type = '',
891        string $surname = ''
892    ): string {
893        return $this->placeRepository->chartDistribution($chart_shows, $chart_type, $surname);
894    }
895
896    /**
897     * @inheritDoc
898     */
899    public function commonCountriesList(): string
900    {
901        return $this->placeRepository->commonCountriesList();
902    }
903
904    /**
905     * @inheritDoc
906     */
907    public function commonBirthPlacesList(): string
908    {
909        return $this->placeRepository->commonBirthPlacesList();
910    }
911
912    /**
913     * @inheritDoc
914     */
915    public function commonDeathPlacesList(): string
916    {
917        return $this->placeRepository->commonDeathPlacesList();
918    }
919
920    /**
921     * @inheritDoc
922     */
923    public function commonMarriagePlacesList(): string
924    {
925        return $this->placeRepository->commonMarriagePlacesList();
926    }
927
928    /**
929     * @inheritDoc
930     */
931    public function firstBirth(): string
932    {
933        return $this->familyDatesRepository->firstBirth();
934    }
935
936    /**
937     * @inheritDoc
938     */
939    public function firstBirthYear(): string
940    {
941        return $this->familyDatesRepository->firstBirthYear();
942    }
943
944    /**
945     * @inheritDoc
946     */
947    public function firstBirthName(): string
948    {
949        return $this->familyDatesRepository->firstBirthName();
950    }
951
952    /**
953     * @inheritDoc
954     */
955    public function firstBirthPlace(): string
956    {
957        return $this->familyDatesRepository->firstBirthPlace();
958    }
959
960    /**
961     * @inheritDoc
962     */
963    public function lastBirth(): string
964    {
965        return $this->familyDatesRepository->lastBirth();
966    }
967
968    /**
969     * @inheritDoc
970     */
971    public function lastBirthYear(): string
972    {
973        return $this->familyDatesRepository->lastBirthYear();
974    }
975
976    /**
977     * @inheritDoc
978     */
979    public function lastBirthName(): string
980    {
981        return $this->familyDatesRepository->lastBirthName();
982    }
983
984    /**
985     * @inheritDoc
986     */
987    public function lastBirthPlace(): string
988    {
989        return $this->familyDatesRepository->lastBirthPlace();
990    }
991
992    /**
993     * @inheritDoc
994     */
995    public function statsBirthQuery(bool $sex = false, int $year1 = -1, int $year2 = -1): array
996    {
997        return $this->individualRepository->statsBirthQuery($sex, $year1, $year2);
998    }
999
1000    /**
1001     * @inheritDoc
1002     */
1003    public function statsBirth(string $size = null, string $color_from = null, string $color_to = null): string
1004    {
1005        return $this->individualRepository->statsBirth($size, $color_from, $color_to);
1006    }
1007
1008    /**
1009     * @inheritDoc
1010     */
1011    public function firstDeath(): string
1012    {
1013        return $this->familyDatesRepository->firstDeath();
1014    }
1015
1016    /**
1017     * @inheritDoc
1018     */
1019    public function firstDeathYear(): string
1020    {
1021        return $this->familyDatesRepository->firstDeathYear();
1022    }
1023
1024    /**
1025     * @inheritDoc
1026     */
1027    public function firstDeathName(): string
1028    {
1029        return $this->familyDatesRepository->firstDeathName();
1030    }
1031
1032    /**
1033     * @inheritDoc
1034     */
1035    public function firstDeathPlace(): string
1036    {
1037        return $this->familyDatesRepository->firstDeathPlace();
1038    }
1039
1040    /**
1041     * @inheritDoc
1042     */
1043    public function lastDeath(): string
1044    {
1045        return $this->familyDatesRepository->lastDeath();
1046    }
1047
1048    /**
1049     * @inheritDoc
1050     */
1051    public function lastDeathYear(): string
1052    {
1053        return $this->familyDatesRepository->lastDeathYear();
1054    }
1055
1056    /**
1057     * @inheritDoc
1058     */
1059    public function lastDeathName(): string
1060    {
1061        return $this->familyDatesRepository->lastDeathName();
1062    }
1063
1064    /**
1065     * @inheritDoc
1066     */
1067    public function lastDeathPlace(): string
1068    {
1069        return $this->familyDatesRepository->lastDeathPlace();
1070    }
1071
1072    /**
1073     * @inheritDoc
1074     */
1075    public function statsDeathQuery(bool $sex = false, int $year1 = -1, int $year2 = -1): array
1076    {
1077        return $this->individualRepository->statsDeathQuery($sex, $year1, $year2);
1078    }
1079
1080    /**
1081     * @inheritDoc
1082     */
1083    public function statsDeath(string $size = null, string $color_from = null, string $color_to = null): string
1084    {
1085        return $this->individualRepository->statsDeath($size, $color_from, $color_to);
1086    }
1087
1088    /**
1089     * @inheritDoc
1090     */
1091    public function statsAgeQuery(string $related = 'BIRT', string $sex = 'BOTH', int $year1 = -1, int $year2 = -1)
1092    {
1093        return $this->individualRepository->statsAgeQuery($related, $sex, $year1, $year2);
1094    }
1095
1096    /**
1097     * @inheritDoc
1098     */
1099    public function statsAge(string $size = '230x250'): string
1100    {
1101        return $this->individualRepository->statsAge($size);
1102    }
1103
1104    /**
1105     * @inheritDoc
1106     */
1107    public function longestLife(): string
1108    {
1109        return $this->individualRepository->longestLife();
1110    }
1111
1112    /**
1113     * @inheritDoc
1114     */
1115    public function longestLifeAge(): string
1116    {
1117        return $this->individualRepository->longestLifeAge();
1118    }
1119
1120    /**
1121     * @inheritDoc
1122     */
1123    public function longestLifeName(): string
1124    {
1125        return $this->individualRepository->longestLifeName();
1126    }
1127
1128    /**
1129     * @inheritDoc
1130     */
1131    public function longestLifeFemale(): string
1132    {
1133        return $this->individualRepository->longestLifeFemale();
1134    }
1135
1136    /**
1137     * @inheritDoc
1138     */
1139    public function longestLifeFemaleAge(): string
1140    {
1141        return $this->individualRepository->longestLifeFemaleAge();
1142    }
1143
1144    /**
1145     * @inheritDoc
1146     */
1147    public function longestLifeFemaleName(): string
1148    {
1149        return $this->individualRepository->longestLifeFemaleName();
1150    }
1151
1152    /**
1153     * @inheritDoc
1154     */
1155    public function longestLifeMale(): string
1156    {
1157        return $this->individualRepository->longestLifeMale();
1158    }
1159
1160    /**
1161     * @inheritDoc
1162     */
1163    public function longestLifeMaleAge(): string
1164    {
1165        return $this->individualRepository->longestLifeMaleAge();
1166    }
1167
1168    /**
1169     * @inheritDoc
1170     */
1171    public function longestLifeMaleName(): string
1172    {
1173        return $this->individualRepository->longestLifeMaleName();
1174    }
1175
1176    /**
1177     * @inheritDoc
1178     */
1179    public function topTenOldest(string $total = '10'): string
1180    {
1181        return $this->individualRepository->topTenOldest((int) $total);
1182    }
1183
1184    /**
1185     * @inheritDoc
1186     */
1187    public function topTenOldestList(string $total = '10'): string
1188    {
1189        return $this->individualRepository->topTenOldestList((int) $total);
1190    }
1191
1192    /**
1193     * @inheritDoc
1194     */
1195    public function topTenOldestFemale(string $total = '10'): string
1196    {
1197        return $this->individualRepository->topTenOldestFemale((int) $total);
1198    }
1199
1200    /**
1201     * @inheritDoc
1202     */
1203    public function topTenOldestFemaleList(string $total = '10'): string
1204    {
1205        return $this->individualRepository->topTenOldestFemaleList((int) $total);
1206    }
1207
1208    /**
1209     * @inheritDoc
1210     */
1211    public function topTenOldestMale(string $total = '10'): string
1212    {
1213        return $this->individualRepository->topTenOldestMale((int) $total);
1214    }
1215
1216    /**
1217     * @inheritDoc
1218     */
1219    public function topTenOldestMaleList(string $total = '10'): string
1220    {
1221        return $this->individualRepository->topTenOldestMaleList((int) $total);
1222    }
1223
1224    /**
1225     * @inheritDoc
1226     */
1227    public function topTenOldestAlive(string $total = '10'): string
1228    {
1229        return $this->individualRepository->topTenOldestAlive((int) $total);
1230    }
1231
1232    /**
1233     * @inheritDoc
1234     */
1235    public function topTenOldestListAlive(string $total = '10'): string
1236    {
1237        return $this->individualRepository->topTenOldestListAlive((int) $total);
1238    }
1239
1240    /**
1241     * @inheritDoc
1242     */
1243    public function topTenOldestFemaleAlive(string $total = '10'): string
1244    {
1245        return $this->individualRepository->topTenOldestFemaleAlive((int) $total);
1246    }
1247
1248    /**
1249     * @inheritDoc
1250     */
1251    public function topTenOldestFemaleListAlive(string $total = '10'): string
1252    {
1253        return $this->individualRepository->topTenOldestFemaleListAlive((int) $total);
1254    }
1255
1256    /**
1257     * @inheritDoc
1258     */
1259    public function topTenOldestMaleAlive(string $total = '10'): string
1260    {
1261        return $this->individualRepository->topTenOldestMaleAlive((int) $total);
1262    }
1263
1264    /**
1265     * @inheritDoc
1266     */
1267    public function topTenOldestMaleListAlive(string $total = '10'): string
1268    {
1269        return $this->individualRepository->topTenOldestMaleListAlive((int) $total);
1270    }
1271
1272    /**
1273     * @inheritDoc
1274     */
1275    public function averageLifespan(bool $show_years = false): string
1276    {
1277        return $this->individualRepository->averageLifespan($show_years);
1278    }
1279
1280    /**
1281     * @inheritDoc
1282     */
1283    public function averageLifespanFemale(bool $show_years = false): string
1284    {
1285        return $this->individualRepository->averageLifespanFemale($show_years);
1286    }
1287
1288    /**
1289     * @inheritDoc
1290     */
1291    public function averageLifespanMale(bool $show_years = false): string
1292    {
1293        return $this->individualRepository->averageLifespanMale($show_years);
1294    }
1295
1296    /**
1297     * @inheritDoc
1298     */
1299    public function firstEvent(): string
1300    {
1301        return $this->eventRepository->firstEvent();
1302    }
1303
1304    /**
1305     * @inheritDoc
1306     */
1307    public function firstEventYear(): string
1308    {
1309        return $this->eventRepository->firstEventYear();
1310    }
1311
1312    /**
1313     * @inheritDoc
1314     */
1315    public function firstEventType(): string
1316    {
1317        return $this->eventRepository->firstEventType();
1318    }
1319
1320    /**
1321     * @inheritDoc
1322     */
1323    public function firstEventName(): string
1324    {
1325        return $this->eventRepository->firstEventName();
1326    }
1327
1328    /**
1329     * @inheritDoc
1330     */
1331    public function firstEventPlace(): string
1332    {
1333        return $this->eventRepository->firstEventPlace();
1334    }
1335
1336    /**
1337     * @inheritDoc
1338     */
1339    public function lastEvent(): string
1340    {
1341        return $this->eventRepository->lastEvent();
1342    }
1343
1344    /**
1345     * @inheritDoc
1346     */
1347    public function lastEventYear(): string
1348    {
1349        return $this->eventRepository->lastEventYear();
1350    }
1351
1352    /**
1353     * @inheritDoc
1354     */
1355    public function lastEventType(): string
1356    {
1357        return $this->eventRepository->lastEventType();
1358    }
1359
1360    /**
1361     * @inheritDoc
1362     */
1363    public function lastEventName(): string
1364    {
1365        return $this->eventRepository->lastEventName();
1366    }
1367
1368    /**
1369     * @inheritDoc
1370     */
1371    public function lastEventPlace(): string
1372    {
1373        return $this->eventRepository->lastEventType();
1374    }
1375
1376    /**
1377     * @inheritDoc
1378     */
1379    public function firstMarriage(): string
1380    {
1381        return $this->familyDatesRepository->firstMarriage();
1382    }
1383
1384    /**
1385     * @inheritDoc
1386     */
1387    public function firstMarriageYear(): string
1388    {
1389        return $this->familyDatesRepository->firstMarriageYear();
1390    }
1391
1392    /**
1393     * @inheritDoc
1394     */
1395    public function firstMarriageName(): string
1396    {
1397        return $this->familyDatesRepository->firstMarriageName();
1398    }
1399
1400    /**
1401     * @inheritDoc
1402     */
1403    public function firstMarriagePlace(): string
1404    {
1405        return $this->familyDatesRepository->firstMarriagePlace();
1406    }
1407
1408    /**
1409     * @inheritDoc
1410     */
1411    public function lastMarriage(): string
1412    {
1413        return $this->familyDatesRepository->lastMarriage();
1414    }
1415
1416    /**
1417     * @inheritDoc
1418     */
1419    public function lastMarriageYear(): string
1420    {
1421        return $this->familyDatesRepository->lastMarriageYear();
1422    }
1423
1424    /**
1425     * @inheritDoc
1426     */
1427    public function lastMarriageName(): string
1428    {
1429        return $this->familyDatesRepository->lastMarriageName();
1430    }
1431
1432    /**
1433     * @inheritDoc
1434     */
1435    public function lastMarriagePlace(): string
1436    {
1437        return $this->familyDatesRepository->lastMarriagePlace();
1438    }
1439
1440    /**
1441     * @inheritDoc
1442     */
1443    public function statsMarrQuery(bool $first = false, int $year1 = -1, int $year2 = -1): array
1444    {
1445        return $this->familyRepository->statsMarrQuery($first, $year1, $year2);
1446    }
1447
1448    /**
1449     * @inheritDoc
1450     */
1451    public function statsMarr(string $size = null, string $color_from = null, string $color_to = null): string
1452    {
1453        return $this->familyRepository->statsMarr($size, $color_from, $color_to);
1454    }
1455
1456    /**
1457     * @inheritDoc
1458     */
1459    public function firstDivorce(): string
1460    {
1461        return $this->familyDatesRepository->firstDivorce();
1462    }
1463
1464    /**
1465     * @inheritDoc
1466     */
1467    public function firstDivorceYear(): string
1468    {
1469        return $this->familyDatesRepository->firstDivorceYear();
1470    }
1471
1472    /**
1473     * @inheritDoc
1474     */
1475    public function firstDivorceName(): string
1476    {
1477        return $this->familyDatesRepository->firstDivorceName();
1478    }
1479
1480    /**
1481     * @inheritDoc
1482     */
1483    public function firstDivorcePlace(): string
1484    {
1485        return $this->familyDatesRepository->firstDivorcePlace();
1486    }
1487
1488    /**
1489     * @inheritDoc
1490     */
1491    public function lastDivorce(): string
1492    {
1493        return $this->familyDatesRepository->lastDivorce();
1494    }
1495
1496    /**
1497     * @inheritDoc
1498     */
1499    public function lastDivorceYear(): string
1500    {
1501        return $this->familyDatesRepository->lastDivorceYear();
1502    }
1503
1504    /**
1505     * @inheritDoc
1506     */
1507    public function lastDivorceName(): string
1508    {
1509        return $this->familyDatesRepository->lastDivorceName();
1510    }
1511
1512    /**
1513     * @inheritDoc
1514     */
1515    public function lastDivorcePlace(): string
1516    {
1517        return $this->familyDatesRepository->lastDivorcePlace();
1518    }
1519
1520    /**
1521     * @inheritDoc
1522     */
1523    public function statsDiv(string $size = null, string $color_from = null, string $color_to = null): string
1524    {
1525        return $this->familyRepository->statsDiv($size, $color_from, $color_to);
1526    }
1527
1528    /**
1529     * @inheritDoc
1530     */
1531    public function youngestMarriageFemale(): string
1532    {
1533        return $this->familyRepository->youngestMarriageFemale();
1534    }
1535
1536    /**
1537     * @inheritDoc
1538     */
1539    public function youngestMarriageFemaleName(): string
1540    {
1541        return $this->familyRepository->youngestMarriageFemaleName();
1542    }
1543
1544    /**
1545     * @inheritDoc
1546     */
1547    public function youngestMarriageFemaleAge(string $show_years = ''): string
1548    {
1549        return $this->familyRepository->youngestMarriageFemaleAge($show_years);
1550    }
1551
1552    /**
1553     * @inheritDoc
1554     */
1555    public function oldestMarriageFemale(): string
1556    {
1557        return $this->familyRepository->oldestMarriageFemale();
1558    }
1559
1560    /**
1561     * @inheritDoc
1562     */
1563    public function oldestMarriageFemaleName(): string
1564    {
1565        return $this->familyRepository->oldestMarriageFemaleName();
1566    }
1567
1568    /**
1569     * @inheritDoc
1570     */
1571    public function oldestMarriageFemaleAge(string $show_years = ''): string
1572    {
1573        return $this->familyRepository->oldestMarriageFemaleAge($show_years);
1574    }
1575
1576    /**
1577     * @inheritDoc
1578     */
1579    public function youngestMarriageMale(): string
1580    {
1581        return $this->familyRepository->youngestMarriageMale();
1582    }
1583
1584    /**
1585     * @inheritDoc
1586     */
1587    public function youngestMarriageMaleName(): string
1588    {
1589        return $this->familyRepository->youngestMarriageMaleName();
1590    }
1591
1592    /**
1593     * @inheritDoc
1594     */
1595    public function youngestMarriageMaleAge(string $show_years = ''): string
1596    {
1597        return $this->familyRepository->youngestMarriageMaleAge($show_years);
1598    }
1599
1600    /**
1601     * @inheritDoc
1602     */
1603    public function oldestMarriageMale(): string
1604    {
1605        return $this->familyRepository->oldestMarriageMale();
1606    }
1607
1608    /**
1609     * @inheritDoc
1610     */
1611    public function oldestMarriageMaleName(): string
1612    {
1613        return $this->familyRepository->oldestMarriageMaleName();
1614    }
1615
1616    /**
1617     * @inheritDoc
1618     */
1619    public function oldestMarriageMaleAge(string $show_years = ''): string
1620    {
1621        return $this->familyRepository->oldestMarriageMaleAge($show_years);
1622    }
1623
1624    /**
1625     * @inheritDoc
1626     */
1627    public function statsMarrAgeQuery(string $sex = 'M', int $year1 = -1, int $year2 = -1): array
1628    {
1629        return $this->familyRepository->statsMarrAgeQuery($sex, $year1, $year2);
1630    }
1631
1632    /**
1633     * @inheritDoc
1634     */
1635    public function statsMarrAge(string $size = '200x250'): string
1636    {
1637        return $this->familyRepository->statsMarrAge($size);
1638    }
1639
1640    /**
1641     * @inheritDoc
1642     */
1643    public function ageBetweenSpousesMF(string $total = '10'): string
1644    {
1645        return $this->familyRepository->ageBetweenSpousesMF((int) $total);
1646    }
1647
1648    /**
1649     * @inheritDoc
1650     */
1651    public function ageBetweenSpousesMFList(string $total = '10'): string
1652    {
1653        return $this->familyRepository->ageBetweenSpousesMFList((int) $total);
1654    }
1655
1656    /**
1657     * @inheritDoc
1658     */
1659    public function ageBetweenSpousesFM(string $total = '10'): string
1660    {
1661        return $this->familyRepository->ageBetweenSpousesFM((int) $total);
1662    }
1663
1664    /**
1665     * @inheritDoc
1666     */
1667    public function ageBetweenSpousesFMList(string $total = '10'): string
1668    {
1669        return $this->familyRepository->ageBetweenSpousesFMList((int) $total);
1670    }
1671
1672    /**
1673     * @inheritDoc
1674     */
1675    public function topAgeOfMarriageFamily(): string
1676    {
1677        return $this->familyRepository->topAgeOfMarriageFamily();
1678    }
1679
1680    /**
1681     * @inheritDoc
1682     */
1683    public function topAgeOfMarriage(): string
1684    {
1685        return $this->familyRepository->topAgeOfMarriage();
1686    }
1687
1688    /**
1689     * @inheritDoc
1690     */
1691    public function topAgeOfMarriageFamilies(string $total = '10'): string
1692    {
1693        return $this->familyRepository->topAgeOfMarriageFamilies((int) $total);
1694    }
1695
1696    /**
1697     * @inheritDoc
1698     */
1699    public function topAgeOfMarriageFamiliesList(string $total = '10'): string
1700    {
1701        return $this->familyRepository->topAgeOfMarriageFamiliesList((int) $total);
1702    }
1703
1704    /**
1705     * @inheritDoc
1706     */
1707    public function minAgeOfMarriageFamily(): string
1708    {
1709        return $this->familyRepository->minAgeOfMarriageFamily();
1710    }
1711
1712    /**
1713     * @inheritDoc
1714     */
1715    public function minAgeOfMarriage(): string
1716    {
1717        return $this->familyRepository->minAgeOfMarriage();
1718    }
1719
1720    /**
1721     * @inheritDoc
1722     */
1723    public function minAgeOfMarriageFamilies(string $total = '10'): string
1724    {
1725        return $this->familyRepository->minAgeOfMarriageFamilies((int) $total);
1726    }
1727
1728    /**
1729     * @inheritDoc
1730     */
1731    public function minAgeOfMarriageFamiliesList(string $total = '10'): string
1732    {
1733        return $this->familyRepository->minAgeOfMarriageFamiliesList((int) $total);
1734    }
1735
1736    /**
1737     * @inheritDoc
1738     */
1739    public function youngestMother(): string
1740    {
1741        return $this->familyRepository->youngestMother();
1742    }
1743
1744    /**
1745     * @inheritDoc
1746     */
1747    public function youngestMotherName(): string
1748    {
1749        return $this->familyRepository->youngestMotherName();
1750    }
1751
1752    /**
1753     * @inheritDoc
1754     */
1755    public function youngestMotherAge(string $show_years = ''): string
1756    {
1757        return $this->familyRepository->youngestMotherAge($show_years);
1758    }
1759
1760    /**
1761     * @inheritDoc
1762     */
1763    public function oldestMother(): string
1764    {
1765        return $this->familyRepository->oldestMother();
1766    }
1767
1768    /**
1769     * @inheritDoc
1770     */
1771    public function oldestMotherName(): string
1772    {
1773        return $this->familyRepository->oldestMotherName();
1774    }
1775
1776    /**
1777     * @inheritDoc
1778     */
1779    public function oldestMotherAge(string $show_years = ''): string
1780    {
1781        return $this->familyRepository->oldestMotherAge($show_years);
1782    }
1783
1784    /**
1785     * @inheritDoc
1786     */
1787    public function youngestFather(): string
1788    {
1789        return $this->familyRepository->youngestFather();
1790    }
1791
1792    /**
1793     * @inheritDoc
1794     */
1795    public function youngestFatherName(): string
1796    {
1797        return $this->familyRepository->youngestFatherName();
1798    }
1799
1800    /**
1801     * @inheritDoc
1802     */
1803    public function youngestFatherAge(string $show_years = ''): string
1804    {
1805        return $this->familyRepository->youngestFatherAge($show_years);
1806    }
1807
1808    /**
1809     * @inheritDoc
1810     */
1811    public function oldestFather(): string
1812    {
1813        return $this->familyRepository->oldestFather();
1814    }
1815
1816    /**
1817     * @inheritDoc
1818     */
1819    public function oldestFatherName(): string
1820    {
1821        return $this->familyRepository->oldestFatherName();
1822    }
1823
1824    /**
1825     * @inheritDoc
1826     */
1827    public function oldestFatherAge(string $show_years = ''): string
1828    {
1829        return $this->familyRepository->oldestFatherAge($show_years);
1830    }
1831
1832    /**
1833     * @inheritDoc
1834     */
1835    public function totalMarriedMales(): string
1836    {
1837        return $this->familyRepository->totalMarriedMales();
1838    }
1839
1840    /**
1841     * @inheritDoc
1842     */
1843    public function totalMarriedFemales(): string
1844    {
1845        return $this->familyRepository->totalMarriedFemales();
1846    }
1847
1848    /**
1849     * @inheritDoc
1850     */
1851    public function monthFirstChildQuery(bool $sex = false): array
1852    {
1853        return $this->familyRepository->monthFirstChildQuery($sex);
1854    }
1855
1856    /**
1857     * @inheritDoc
1858     */
1859    public function largestFamily(): string
1860    {
1861        return $this->familyRepository->largestFamily();
1862    }
1863
1864    /**
1865     * @inheritDoc
1866     */
1867    public function largestFamilySize(): string
1868    {
1869        return $this->familyRepository->largestFamilySize();
1870    }
1871
1872    /**
1873     * @inheritDoc
1874     */
1875    public function largestFamilyName(): string
1876    {
1877        return $this->familyRepository->largestFamilyName();
1878    }
1879
1880    /**
1881     * @inheritDoc
1882     */
1883    public function topTenLargestFamily(string $total = '10'): string
1884    {
1885        return $this->familyRepository->topTenLargestFamily((int) $total);
1886    }
1887
1888    /**
1889     * @inheritDoc
1890     */
1891    public function topTenLargestFamilyList(string $total = '10'): string
1892    {
1893        return $this->familyRepository->topTenLargestFamilyList((int) $total);
1894    }
1895
1896    /**
1897     * @inheritDoc
1898     */
1899    public function chartLargestFamilies(
1900        string $size = null,
1901        string $color_from = null,
1902        string $color_to = null,
1903        string $total = '10'
1904    ): string {
1905        return $this->familyRepository->chartLargestFamilies($size, $color_from, $color_to, (int) $total);
1906    }
1907
1908    /**
1909     * @inheritDoc
1910     */
1911    public function totalChildren(): string
1912    {
1913        return $this->familyRepository->totalChildren();
1914    }
1915
1916    /**
1917     * @inheritDoc
1918     */
1919    public function averageChildren(): string
1920    {
1921        return $this->familyRepository->averageChildren();
1922    }
1923
1924    /**
1925     * @inheritDoc
1926     */
1927    public function statsChildrenQuery(string $sex = 'BOTH', int $year1 = -1, int $year2 = -1): array
1928    {
1929        return $this->familyRepository->statsChildrenQuery($sex, $year1, $year2);
1930    }
1931
1932    /**
1933     * @inheritDoc
1934     */
1935    public function statsChildren(string $size = '220x200'): string
1936    {
1937        return $this->familyRepository->statsChildren($size);
1938    }
1939
1940    /**
1941     * @inheritDoc
1942     */
1943    public function topAgeBetweenSiblingsName(string $total = '10'): string
1944    {
1945        return $this->familyRepository->topAgeBetweenSiblingsName((int) $total);
1946    }
1947
1948    /**
1949     * @inheritDoc
1950     */
1951    public function topAgeBetweenSiblings(string $total = '10'): string
1952    {
1953        return $this->familyRepository->topAgeBetweenSiblings((int) $total);
1954    }
1955
1956    /**
1957     * @inheritDoc
1958     */
1959    public function topAgeBetweenSiblingsFullName(string $total = '10'): string
1960    {
1961        return $this->familyRepository->topAgeBetweenSiblingsFullName((int) $total);
1962    }
1963
1964    /**
1965     * @inheritDoc
1966     */
1967    public function topAgeBetweenSiblingsList(string $total = '10', string $one = ''): string
1968    {
1969        return $this->familyRepository->topAgeBetweenSiblingsList((int) $total, $one);
1970    }
1971
1972    /**
1973     * @inheritDoc
1974     */
1975    public function noChildrenFamilies(): string
1976    {
1977        return $this->familyRepository->noChildrenFamilies();
1978    }
1979
1980    /**
1981     * @inheritDoc
1982     */
1983    public function noChildrenFamiliesList(string $type = 'list'): string
1984    {
1985        return $this->familyRepository->noChildrenFamiliesList($type);
1986    }
1987
1988    /**
1989     * @inheritDoc
1990     */
1991    public function chartNoChildrenFamilies(
1992        string $size = '220x200',
1993        string $year1 = '-1',
1994        string $year2 = '-1'
1995    ): string {
1996        return $this->familyRepository->chartNoChildrenFamilies($size, (int) $year1, (int) $year2);
1997    }
1998
1999    /**
2000     * @inheritDoc
2001     */
2002    public function topTenLargestGrandFamily(string $total = '10'): string
2003    {
2004        return $this->familyRepository->topTenLargestGrandFamily((int) $total);
2005    }
2006
2007    /**
2008     * @inheritDoc
2009     */
2010    public function topTenLargestGrandFamilyList(string $total = '10'): string
2011    {
2012        return $this->familyRepository->topTenLargestGrandFamilyList((int) $total);
2013    }
2014
2015    /**
2016     * @inheritDoc
2017     */
2018    public function getCommonSurname(): string
2019    {
2020        return $this->individualRepository->getCommonSurname();
2021    }
2022
2023    /**
2024     * @inheritDoc
2025     */
2026    public function commonSurnames(
2027        string $threshold = '1',
2028        string $number_of_surnames = '10',
2029        string $sorting = 'alpha'
2030    ): string {
2031        return $this->individualRepository->commonSurnames((int) $threshold, (int) $number_of_surnames, $sorting);
2032    }
2033
2034    /**
2035     * @inheritDoc
2036     */
2037    public function commonSurnamesTotals(
2038        string $threshold = '1',
2039        string $number_of_surnames = '10',
2040        string $sorting = 'rcount'
2041    ): string {
2042        return $this->individualRepository->commonSurnamesTotals((int) $threshold, (int) $number_of_surnames, $sorting);
2043    }
2044
2045    /**
2046     * @inheritDoc
2047     */
2048    public function commonSurnamesList(
2049        string $threshold = '1',
2050        string $number_of_surnames = '10',
2051        string $sorting = 'alpha'
2052    ): string {
2053        return $this->individualRepository->commonSurnamesList((int) $threshold, (int) $number_of_surnames, $sorting);
2054    }
2055
2056    /**
2057     * @inheritDoc
2058     */
2059    public function commonSurnamesListTotals(
2060        string $threshold = '1',
2061        string $number_of_surnames = '10',
2062        string $sorting = 'rcount'
2063    ): string {
2064        return $this->individualRepository
2065            ->commonSurnamesListTotals((int) $threshold, (int) $number_of_surnames, $sorting);
2066    }
2067
2068    /**
2069     * @inheritDoc
2070     */
2071    public function chartCommonSurnames(
2072        string $size = null,
2073        string $color_from = null,
2074        string $color_to = null,
2075        string $number_of_surnames = '10'
2076    ): string {
2077        return $this->individualRepository
2078            ->chartCommonSurnames($size, $color_from, $color_to, (int) $number_of_surnames);
2079    }
2080
2081    /**
2082     * @inheritDoc
2083     */
2084    public function commonGiven(string $threshold = '1', string $maxtoshow = '10'): string
2085    {
2086        return $this->individualRepository->commonGiven((int) $threshold, (int) $maxtoshow);
2087    }
2088
2089    /**
2090     * @inheritDoc
2091     */
2092    public function commonGivenTotals(string $threshold = '1', string $maxtoshow = '10'): string
2093    {
2094        return $this->individualRepository->commonGivenTotals((int) $threshold, (int) $maxtoshow);
2095    }
2096
2097    /**
2098     * @inheritDoc
2099     */
2100    public function commonGivenList(string $threshold = '1', string $maxtoshow = '10'): string
2101    {
2102        return $this->individualRepository->commonGivenList((int) $threshold, (int) $maxtoshow);
2103    }
2104
2105    /**
2106     * @inheritDoc
2107     */
2108    public function commonGivenListTotals(string $threshold = '1', string $maxtoshow = '10'): string
2109    {
2110        return $this->individualRepository->commonGivenListTotals((int) $threshold, (int) $maxtoshow);
2111    }
2112
2113    /**
2114     * @inheritDoc
2115     */
2116    public function commonGivenTable(string $threshold = '1', string $maxtoshow = '10'): string
2117    {
2118        return $this->individualRepository->commonGivenTable((int) $threshold, (int) $maxtoshow);
2119    }
2120
2121    /**
2122     * @inheritDoc
2123     */
2124    public function commonGivenFemale(string $threshold = '1', string $maxtoshow = '10'): string
2125    {
2126        return $this->individualRepository->commonGivenFemale((int) $threshold, (int) $maxtoshow);
2127    }
2128
2129    /**
2130     * @inheritDoc
2131     */
2132    public function commonGivenFemaleTotals(string $threshold = '1', string $maxtoshow = '10'): string
2133    {
2134        return $this->individualRepository->commonGivenFemaleTotals((int) $threshold, (int) $maxtoshow);
2135    }
2136
2137    /**
2138     * @inheritDoc
2139     */
2140    public function commonGivenFemaleList(string $threshold = '1', string $maxtoshow = '10'): string
2141    {
2142        return $this->individualRepository->commonGivenFemaleList((int) $threshold, (int) $maxtoshow);
2143    }
2144
2145    /**
2146     * @inheritDoc
2147     */
2148    public function commonGivenFemaleListTotals(string $threshold = '1', string $maxtoshow = '10'): string
2149    {
2150        return $this->individualRepository->commonGivenFemaleListTotals((int) $threshold, (int) $maxtoshow);
2151    }
2152
2153    /**
2154     * @inheritDoc
2155     */
2156    public function commonGivenFemaleTable(string $threshold = '1', string $maxtoshow = '10'): string
2157    {
2158        return $this->individualRepository->commonGivenFemaleTable((int) $threshold, (int) $maxtoshow);
2159    }
2160
2161    /**
2162     * @inheritDoc
2163     */
2164    public function commonGivenMale(string $threshold = '1', string $maxtoshow = '10'): string
2165    {
2166        return $this->individualRepository->commonGivenMale((int) $threshold, (int) $maxtoshow);
2167    }
2168
2169    /**
2170     * @inheritDoc
2171     */
2172    public function commonGivenMaleTotals(string $threshold = '1', string $maxtoshow = '10'): string
2173    {
2174        return $this->individualRepository->commonGivenMaleTotals((int) $threshold, (int) $maxtoshow);
2175    }
2176
2177    /**
2178     * @inheritDoc
2179     */
2180    public function commonGivenMaleList(string $threshold = '1', string $maxtoshow = '10'): string
2181    {
2182        return $this->individualRepository->commonGivenMaleList((int) $threshold, (int) $maxtoshow);
2183    }
2184
2185    /**
2186     * @inheritDoc
2187     */
2188    public function commonGivenMaleListTotals(string $threshold = '1', string $maxtoshow = '10'): string
2189    {
2190        return $this->individualRepository->commonGivenMaleListTotals((int) $threshold, (int) $maxtoshow);
2191    }
2192
2193    /**
2194     * @inheritDoc
2195     */
2196    public function commonGivenMaleTable(string $threshold = '1', string $maxtoshow = '10'): string
2197    {
2198        return $this->individualRepository->commonGivenMaleTable((int) $threshold, (int) $maxtoshow);
2199    }
2200
2201    /**
2202     * @inheritDoc
2203     */
2204    public function commonGivenUnknown(string $threshold = '1', string $maxtoshow = '10'): string
2205    {
2206        return $this->individualRepository->commonGivenUnknown((int) $threshold, (int) $maxtoshow);
2207    }
2208
2209    /**
2210     * @inheritDoc
2211     */
2212    public function commonGivenUnknownTotals(string $threshold = '1', string $maxtoshow = '10'): string
2213    {
2214        return $this->individualRepository->commonGivenUnknownTotals((int) $threshold, (int) $maxtoshow);
2215    }
2216
2217    /**
2218     * @inheritDoc
2219     */
2220    public function commonGivenUnknownList(string $threshold = '1', string $maxtoshow = '10'): string
2221    {
2222        return $this->individualRepository->commonGivenUnknownList((int) $threshold, (int) $maxtoshow);
2223    }
2224
2225    /**
2226     * @inheritDoc
2227     */
2228    public function commonGivenUnknownListTotals(string $threshold = '1', string $maxtoshow = '10'): string
2229    {
2230        return $this->individualRepository->commonGivenUnknownListTotals((int) $threshold, (int) $maxtoshow);
2231    }
2232
2233    /**
2234     * @inheritDoc
2235     */
2236    public function commonGivenUnknownTable(string $threshold = '1', string $maxtoshow = '10'): string
2237    {
2238        return $this->individualRepository->commonGivenUnknownTable((int) $threshold, (int) $maxtoshow);
2239    }
2240
2241    /**
2242     * @inheritDoc
2243     */
2244    public function chartCommonGiven(
2245        string $size = null,
2246        string $color_from = null,
2247        string $color_to = null,
2248        string $maxtoshow = '7'
2249    ): string {
2250        return $this->individualRepository->chartCommonGiven($size, $color_from, $color_to, (int) $maxtoshow);
2251    }
2252
2253    /**
2254     * @inheritDoc
2255     */
2256    public function usersLoggedIn(): string
2257    {
2258        return $this->userRepository->usersLoggedIn();
2259    }
2260
2261    /**
2262     * @inheritDoc
2263     */
2264    public function usersLoggedInList(): string
2265    {
2266        return $this->userRepository->usersLoggedInList();
2267    }
2268
2269    /**
2270     * @inheritDoc
2271     */
2272    public function usersLoggedInTotal(): int
2273    {
2274        return $this->userRepository->usersLoggedInTotal();
2275    }
2276
2277    /**
2278     * @inheritDoc
2279     */
2280    public function usersLoggedInTotalAnon(): int
2281    {
2282        return $this->userRepository->usersLoggedInTotalAnon();
2283    }
2284
2285    /**
2286     * @inheritDoc
2287     */
2288    public function usersLoggedInTotalVisible(): int
2289    {
2290        return $this->userRepository->usersLoggedInTotalVisible();
2291    }
2292
2293    /**
2294     * @inheritDoc
2295     */
2296    public function userId(): string
2297    {
2298        return $this->userRepository->userId();
2299    }
2300
2301    /**
2302     * @inheritDoc
2303     */
2304    public function userName(string $visitor_text = ''): string
2305    {
2306        return $this->userRepository->userName();
2307    }
2308
2309    /**
2310     * @inheritDoc
2311     */
2312    public function userFullName(): string
2313    {
2314        return $this->userRepository->userFullName();
2315    }
2316
2317    /**
2318     * @inheritDoc
2319     */
2320    public function totalUsers(): string
2321    {
2322        return $this->userRepository->totalUsers();
2323    }
2324
2325    /**
2326     * @inheritDoc
2327     */
2328    public function totalAdmins(): string
2329    {
2330        return $this->userRepository->totalAdmins();
2331    }
2332
2333    /**
2334     * @inheritDoc
2335     */
2336    public function totalNonAdmins(): string
2337    {
2338        return $this->userRepository->totalNonAdmins();
2339    }
2340
2341    /**
2342     * @inheritDoc
2343     */
2344    public function latestUserId(): string
2345    {
2346        return $this->latestUserRepository->latestUserId();
2347    }
2348
2349    /**
2350     * @inheritDoc
2351     */
2352    public function latestUserName(): string
2353    {
2354        return $this->latestUserRepository->latestUserName();
2355    }
2356
2357    /**
2358     * @inheritDoc
2359     */
2360    public function latestUserFullName(): string
2361    {
2362        return $this->latestUserRepository->latestUserFullName();
2363    }
2364
2365    /**
2366     * @inheritDoc
2367     */
2368    public function latestUserRegDate(string $format = null): string
2369    {
2370        return $this->latestUserRepository->latestUserRegDate();
2371    }
2372
2373    /**
2374     * @inheritDoc
2375     */
2376    public function latestUserRegTime(string $format = null): string
2377    {
2378        return $this->latestUserRepository->latestUserRegTime();
2379    }
2380
2381    /**
2382     * @inheritDoc
2383     */
2384    public function latestUserLoggedin(string $yes = null, string $no = null): string
2385    {
2386        return $this->latestUserRepository->latestUserLoggedin();
2387    }
2388
2389    /**
2390     * @inheritDoc
2391     */
2392    public function contactWebmaster(): string
2393    {
2394        return $this->contactRepository->contactWebmaster();
2395    }
2396
2397    /**
2398     * @inheritDoc
2399     */
2400    public function contactGedcom(): string
2401    {
2402        return $this->contactRepository->contactGedcom();
2403    }
2404
2405    /**
2406     * @inheritDoc
2407     */
2408    public function serverDate(): string
2409    {
2410        return $this->serverRepository->serverDate();
2411    }
2412
2413    /**
2414     * @inheritDoc
2415     */
2416    public function serverTime(): string
2417    {
2418        return $this->serverRepository->serverTime();
2419    }
2420
2421    /**
2422     * @inheritDoc
2423     */
2424    public function serverTime24(): string
2425    {
2426        return $this->serverRepository->serverTime24();
2427    }
2428
2429    /**
2430     * What is the timezone of the server.
2431     *
2432     * @return string
2433     */
2434    public function serverTimezone(): string
2435    {
2436        return $this->serverRepository->serverTimezone();
2437    }
2438
2439    /**
2440     * @inheritDoc
2441     */
2442    public function browserDate(): string
2443    {
2444        return $this->browserRepository->browserDate();
2445    }
2446
2447    /**
2448     * @inheritDoc
2449     */
2450    public function browserTime(): string
2451    {
2452        return $this->browserRepository->browserTime();
2453    }
2454
2455    /**
2456     * @inheritDoc
2457     */
2458    public function browserTimezone(): string
2459    {
2460        return $this->browserRepository->browserTimezone();
2461    }
2462
2463    /**
2464     * @inheritDoc
2465     */
2466    public function hitCount(string $page_parameter = ''): string
2467    {
2468        return $this->hitCountRepository->hitCount($page_parameter);
2469    }
2470
2471    /**
2472     * @inheritDoc
2473     */
2474    public function hitCountUser(string $page_parameter = ''): string
2475    {
2476        return $this->hitCountRepository->hitCountUser($page_parameter);
2477    }
2478
2479    /**
2480     * @inheritDoc
2481     */
2482    public function hitCountIndi(string $page_parameter = ''): string
2483    {
2484        return $this->hitCountRepository->hitCountIndi($page_parameter);
2485    }
2486
2487    /**
2488     * @inheritDoc
2489     */
2490    public function hitCountFam(string $page_parameter = ''): string
2491    {
2492        return $this->hitCountRepository->hitCountFam($page_parameter);
2493    }
2494
2495    /**
2496     * @inheritDoc
2497     */
2498    public function hitCountSour(string $page_parameter = ''): string
2499    {
2500        return $this->hitCountRepository->hitCountSour($page_parameter);
2501    }
2502
2503    /**
2504     * @inheritDoc
2505     */
2506    public function hitCountRepo(string $page_parameter = ''): string
2507    {
2508        return $this->hitCountRepository->hitCountRepo($page_parameter);
2509    }
2510
2511    /**
2512     * @inheritDoc
2513     */
2514    public function hitCountNote(string $page_parameter = ''): string
2515    {
2516        return $this->hitCountRepository->hitCountNote($page_parameter);
2517    }
2518
2519    /**
2520     * @inheritDoc
2521     */
2522    public function hitCountObje(string $page_parameter = ''): string
2523    {
2524        return $this->hitCountRepository->hitCountObje($page_parameter);
2525    }
2526
2527    /**
2528     * @inheritDoc
2529     */
2530    public function gedcomFavorites(): string
2531    {
2532        return $this->favoritesRepository->gedcomFavorites();
2533    }
2534
2535    /**
2536     * @inheritDoc
2537     */
2538    public function userFavorites(): string
2539    {
2540        return $this->favoritesRepository->userFavorites();
2541    }
2542
2543    /**
2544     * @inheritDoc
2545     */
2546    public function totalGedcomFavorites(): string
2547    {
2548        return $this->favoritesRepository->totalGedcomFavorites();
2549    }
2550
2551    /**
2552     * @inheritDoc
2553     */
2554    public function totalUserFavorites(): string
2555    {
2556        return $this->favoritesRepository->totalUserFavorites();
2557    }
2558
2559    /**
2560     * @inheritDoc
2561     */
2562    public function totalUserMessages(): string
2563    {
2564        return $this->messageRepository->totalUserMessages();
2565    }
2566
2567    /**
2568     * @inheritDoc
2569     */
2570    public function totalUserJournal(): string
2571    {
2572        return $this->newsRepository->totalUserJournal();
2573    }
2574
2575    /**
2576     * @inheritDoc
2577     */
2578    public function totalGedcomNews(): string
2579    {
2580        return $this->newsRepository->totalGedcomNews();
2581    }
2582
2583    /**
2584     * Create any of the other blocks.
2585     * Use as #callBlock:block_name#
2586     *
2587     * @param string $block
2588     * @param string ...$params
2589     *
2590     * @return null|string
2591     */
2592    public function callBlock(string $block = '', ...$params): ?string
2593    {
2594        /** @var ModuleBlockInterface $module */
2595        $module = $this->module_service
2596            ->findByComponent('block', $this->tree, Auth::user())
2597            ->filter(function (ModuleInterface $module) use ($block): bool {
2598                return $module->name() === $block && $module->name() !== 'html';
2599            })
2600            ->first();
2601
2602        if ($module === null) {
2603            return '';
2604        }
2605
2606        // Build the config array
2607        $cfg = [];
2608        foreach ($params as $config) {
2609            $bits = explode('=', $config);
2610
2611            if (\count($bits) < 2) {
2612                continue;
2613            }
2614
2615            $v       = array_shift($bits);
2616            $cfg[$v] = implode('=', $bits);
2617        }
2618
2619        return $module->getBlock($this->tree, 0, '', $cfg);
2620    }
2621
2622    /**
2623     * What is the current version of webtrees.
2624     *
2625     * @return string
2626     */
2627    public function webtreesVersion(): string
2628    {
2629        return Webtrees::VERSION;
2630    }
2631}
2632