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