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