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