xref: /webtrees/app/Statistics/Repository/MediaRepository.php (revision 8add1155cb77caede54752196ff44696d1346431)
1*8add1155SRico Sonntag<?php
2*8add1155SRico Sonntag/**
3*8add1155SRico Sonntag * webtrees: online genealogy
4*8add1155SRico Sonntag * Copyright (C) 2018 webtrees development team
5*8add1155SRico Sonntag * This program is free software: you can redistribute it and/or modify
6*8add1155SRico Sonntag * it under the terms of the GNU General Public License as published by
7*8add1155SRico Sonntag * the Free Software Foundation, either version 3 of the License, or
8*8add1155SRico Sonntag * (at your option) any later version.
9*8add1155SRico Sonntag * This program is distributed in the hope that it will be useful,
10*8add1155SRico Sonntag * but WITHOUT ANY WARRANTY; without even the implied warranty of
11*8add1155SRico Sonntag * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12*8add1155SRico Sonntag * GNU General Public License for more details.
13*8add1155SRico Sonntag * You should have received a copy of the GNU General Public License
14*8add1155SRico Sonntag * along with this program. If not, see <http://www.gnu.org/licenses/>.
15*8add1155SRico Sonntag */
16*8add1155SRico Sonntagdeclare(strict_types=1);
17*8add1155SRico Sonntag
18*8add1155SRico Sonntagnamespace Fisharebest\Webtrees\Statistics\Repository;
19*8add1155SRico Sonntag
20*8add1155SRico Sonntaguse Fisharebest\Webtrees\I18N;
21*8add1155SRico Sonntaguse Fisharebest\Webtrees\Statistics\Google\ChartMedia;
22*8add1155SRico Sonntaguse Fisharebest\Webtrees\Statistics\Repository\Interfaces\MediaRepositoryInterface;
23*8add1155SRico Sonntaguse Fisharebest\Webtrees\Tree;
24*8add1155SRico Sonntaguse Illuminate\Database\Capsule\Manager as DB;
25*8add1155SRico Sonntaguse Illuminate\Database\Query\Builder;
26*8add1155SRico Sonntag
27*8add1155SRico Sonntag/**
28*8add1155SRico Sonntag * A repository providing methods for media type related statistics.
29*8add1155SRico Sonntag */
30*8add1155SRico Sonntagclass MediaRepository implements MediaRepositoryInterface
31*8add1155SRico Sonntag{
32*8add1155SRico Sonntag    /**
33*8add1155SRico Sonntag     * @var Tree
34*8add1155SRico Sonntag     */
35*8add1155SRico Sonntag    private $tree;
36*8add1155SRico Sonntag
37*8add1155SRico Sonntag    /**
38*8add1155SRico Sonntag     * Available media types.
39*8add1155SRico Sonntag     */
40*8add1155SRico Sonntag    private const MEDIA_TYPE_ALL         = 'all';
41*8add1155SRico Sonntag    private const MEDIA_TYPE_AUDIO       = 'audio';
42*8add1155SRico Sonntag    private const MEDIA_TYPE_BOOK        = 'book';
43*8add1155SRico Sonntag    private const MEDIA_TYPE_CARD        = 'card';
44*8add1155SRico Sonntag    private const MEDIA_TYPE_CERTIFICATE = 'certificate';
45*8add1155SRico Sonntag    private const MEDIA_TYPE_COAT        = 'coat';
46*8add1155SRico Sonntag    private const MEDIA_TYPE_DOCUMENT    = 'document';
47*8add1155SRico Sonntag    private const MEDIA_TYPE_ELECTRONIC  = 'electronic';
48*8add1155SRico Sonntag    private const MEDIA_TYPE_FICHE       = 'fiche';
49*8add1155SRico Sonntag    private const MEDIA_TYPE_FILM        = 'film';
50*8add1155SRico Sonntag    private const MEDIA_TYPE_MAGAZINE    = 'magazine';
51*8add1155SRico Sonntag    private const MEDIA_TYPE_MANUSCRIPT  = 'manuscript';
52*8add1155SRico Sonntag    private const MEDIA_TYPE_MAP         = 'map';
53*8add1155SRico Sonntag    private const MEDIA_TYPE_NEWSPAPER   = 'newspaper';
54*8add1155SRico Sonntag    private const MEDIA_TYPE_PAINTING    = 'painting';
55*8add1155SRico Sonntag    private const MEDIA_TYPE_PHOTO       = 'photo';
56*8add1155SRico Sonntag    private const MEDIA_TYPE_TOMBSTONE   = 'tombstone';
57*8add1155SRico Sonntag    private const MEDIA_TYPE_VIDEO       = 'video';
58*8add1155SRico Sonntag    private const MEDIA_TYPE_OTHER       = 'other';
59*8add1155SRico Sonntag    private const MEDIA_TYPE_UNKNOWN     = 'unknown';
60*8add1155SRico Sonntag
61*8add1155SRico Sonntag    /**
62*8add1155SRico Sonntag     * List of GEDCOM media types.
63*8add1155SRico Sonntag     *
64*8add1155SRico Sonntag     * @var string[]
65*8add1155SRico Sonntag     */
66*8add1155SRico Sonntag    private const MEDIA_TYPES = [
67*8add1155SRico Sonntag        self::MEDIA_TYPE_AUDIO,
68*8add1155SRico Sonntag        self::MEDIA_TYPE_BOOK,
69*8add1155SRico Sonntag        self::MEDIA_TYPE_CARD,
70*8add1155SRico Sonntag        self::MEDIA_TYPE_CERTIFICATE,
71*8add1155SRico Sonntag        self::MEDIA_TYPE_COAT,
72*8add1155SRico Sonntag        self::MEDIA_TYPE_DOCUMENT,
73*8add1155SRico Sonntag        self::MEDIA_TYPE_ELECTRONIC,
74*8add1155SRico Sonntag        self::MEDIA_TYPE_FICHE,
75*8add1155SRico Sonntag        self::MEDIA_TYPE_FILM,
76*8add1155SRico Sonntag        self::MEDIA_TYPE_MAGAZINE,
77*8add1155SRico Sonntag        self::MEDIA_TYPE_MANUSCRIPT,
78*8add1155SRico Sonntag        self::MEDIA_TYPE_MAP,
79*8add1155SRico Sonntag        self::MEDIA_TYPE_NEWSPAPER,
80*8add1155SRico Sonntag        self::MEDIA_TYPE_PAINTING,
81*8add1155SRico Sonntag        self::MEDIA_TYPE_PHOTO,
82*8add1155SRico Sonntag        self::MEDIA_TYPE_TOMBSTONE,
83*8add1155SRico Sonntag        self::MEDIA_TYPE_VIDEO,
84*8add1155SRico Sonntag        self::MEDIA_TYPE_OTHER,
85*8add1155SRico Sonntag    ];
86*8add1155SRico Sonntag
87*8add1155SRico Sonntag    /**
88*8add1155SRico Sonntag     * Constructor.
89*8add1155SRico Sonntag     *
90*8add1155SRico Sonntag     * @param Tree $tree
91*8add1155SRico Sonntag     */
92*8add1155SRico Sonntag    public function __construct(Tree $tree)
93*8add1155SRico Sonntag    {
94*8add1155SRico Sonntag        $this->tree = $tree;
95*8add1155SRico Sonntag    }
96*8add1155SRico Sonntag
97*8add1155SRico Sonntag    /**
98*8add1155SRico Sonntag     * Returns the number of media records of the given type.
99*8add1155SRico Sonntag     *
100*8add1155SRico Sonntag     * @param string $type The media type to query
101*8add1155SRico Sonntag     *
102*8add1155SRico Sonntag     * @return int
103*8add1155SRico Sonntag     */
104*8add1155SRico Sonntag    private function totalMediaTypeQuery(string $type): int
105*8add1155SRico Sonntag    {
106*8add1155SRico Sonntag        if (($type !== self::MEDIA_TYPE_ALL)
107*8add1155SRico Sonntag            && ($type !== self::MEDIA_TYPE_UNKNOWN)
108*8add1155SRico Sonntag            && !\in_array($type, self::MEDIA_TYPES, true)
109*8add1155SRico Sonntag        ) {
110*8add1155SRico Sonntag            return 0;
111*8add1155SRico Sonntag        }
112*8add1155SRico Sonntag
113*8add1155SRico Sonntag        $query = DB::table('media')
114*8add1155SRico Sonntag            ->where('m_file', '=', $this->tree->id());
115*8add1155SRico Sonntag
116*8add1155SRico Sonntag        if ($type !== self::MEDIA_TYPE_ALL) {
117*8add1155SRico Sonntag            if ($type === self::MEDIA_TYPE_UNKNOWN) {
118*8add1155SRico Sonntag                // There has to be a better way then this :(
119*8add1155SRico Sonntag                foreach (self::MEDIA_TYPES as $t) {
120*8add1155SRico Sonntag                    // Use function to add brackets
121*8add1155SRico Sonntag                    $query->where(function (Builder $query) use ($t) {
122*8add1155SRico Sonntag                        $query->where('m_gedcom', 'not like', '%3 TYPE ' . $t . '%')
123*8add1155SRico Sonntag                            ->where('m_gedcom', 'not like', '%1 _TYPE ' . $t . '%');
124*8add1155SRico Sonntag                    });
125*8add1155SRico Sonntag                }
126*8add1155SRico Sonntag            } else {
127*8add1155SRico Sonntag                // Use function to add brackets
128*8add1155SRico Sonntag                $query->where(function (Builder $query) use ($type) {
129*8add1155SRico Sonntag                    $query->where('m_gedcom', 'like', '%3 TYPE ' . $type . '%')
130*8add1155SRico Sonntag                        ->orWhere('m_gedcom', 'like', '%1 _TYPE ' . $type . '%');
131*8add1155SRico Sonntag                });
132*8add1155SRico Sonntag            }
133*8add1155SRico Sonntag        }
134*8add1155SRico Sonntag
135*8add1155SRico Sonntag        return $query->count();
136*8add1155SRico Sonntag    }
137*8add1155SRico Sonntag
138*8add1155SRico Sonntag    /**
139*8add1155SRico Sonntag     * @inheritDoc
140*8add1155SRico Sonntag     */
141*8add1155SRico Sonntag    public function totalMedia(): string
142*8add1155SRico Sonntag    {
143*8add1155SRico Sonntag        return I18N::number($this->totalMediaTypeQuery(self::MEDIA_TYPE_ALL));
144*8add1155SRico Sonntag    }
145*8add1155SRico Sonntag
146*8add1155SRico Sonntag    /**
147*8add1155SRico Sonntag     * @inheritDoc
148*8add1155SRico Sonntag     */
149*8add1155SRico Sonntag    public function totalMediaAudio(): string
150*8add1155SRico Sonntag    {
151*8add1155SRico Sonntag        return I18N::number($this->totalMediaTypeQuery(self::MEDIA_TYPE_AUDIO));
152*8add1155SRico Sonntag    }
153*8add1155SRico Sonntag
154*8add1155SRico Sonntag    /**
155*8add1155SRico Sonntag     * @inheritDoc
156*8add1155SRico Sonntag     */
157*8add1155SRico Sonntag    public function totalMediaBook(): string
158*8add1155SRico Sonntag    {
159*8add1155SRico Sonntag        return I18N::number($this->totalMediaTypeQuery(self::MEDIA_TYPE_BOOK));
160*8add1155SRico Sonntag    }
161*8add1155SRico Sonntag
162*8add1155SRico Sonntag    /**
163*8add1155SRico Sonntag     * @inheritDoc
164*8add1155SRico Sonntag     */
165*8add1155SRico Sonntag    public function totalMediaCard(): string
166*8add1155SRico Sonntag    {
167*8add1155SRico Sonntag        return I18N::number($this->totalMediaTypeQuery(self::MEDIA_TYPE_CARD));
168*8add1155SRico Sonntag    }
169*8add1155SRico Sonntag
170*8add1155SRico Sonntag    /**
171*8add1155SRico Sonntag     * @inheritDoc
172*8add1155SRico Sonntag     */
173*8add1155SRico Sonntag    public function totalMediaCertificate(): string
174*8add1155SRico Sonntag    {
175*8add1155SRico Sonntag        return I18N::number($this->totalMediaTypeQuery(self::MEDIA_TYPE_CERTIFICATE));
176*8add1155SRico Sonntag    }
177*8add1155SRico Sonntag
178*8add1155SRico Sonntag    /**
179*8add1155SRico Sonntag     * @inheritDoc
180*8add1155SRico Sonntag     */
181*8add1155SRico Sonntag    public function totalMediaCoatOfArms(): string
182*8add1155SRico Sonntag    {
183*8add1155SRico Sonntag        return I18N::number($this->totalMediaTypeQuery(self::MEDIA_TYPE_COAT));
184*8add1155SRico Sonntag    }
185*8add1155SRico Sonntag
186*8add1155SRico Sonntag    /**
187*8add1155SRico Sonntag     * @inheritDoc
188*8add1155SRico Sonntag     */
189*8add1155SRico Sonntag    public function totalMediaDocument(): string
190*8add1155SRico Sonntag    {
191*8add1155SRico Sonntag        return I18N::number($this->totalMediaTypeQuery(self::MEDIA_TYPE_DOCUMENT));
192*8add1155SRico Sonntag    }
193*8add1155SRico Sonntag
194*8add1155SRico Sonntag    /**
195*8add1155SRico Sonntag     * @inheritDoc
196*8add1155SRico Sonntag     */
197*8add1155SRico Sonntag    public function totalMediaElectronic(): string
198*8add1155SRico Sonntag    {
199*8add1155SRico Sonntag        return I18N::number($this->totalMediaTypeQuery(self::MEDIA_TYPE_ELECTRONIC));
200*8add1155SRico Sonntag    }
201*8add1155SRico Sonntag
202*8add1155SRico Sonntag    /**
203*8add1155SRico Sonntag     * @inheritDoc
204*8add1155SRico Sonntag     */
205*8add1155SRico Sonntag    public function totalMediaFiche(): string
206*8add1155SRico Sonntag    {
207*8add1155SRico Sonntag        return I18N::number($this->totalMediaTypeQuery(self::MEDIA_TYPE_FICHE));
208*8add1155SRico Sonntag    }
209*8add1155SRico Sonntag
210*8add1155SRico Sonntag    /**
211*8add1155SRico Sonntag     * @inheritDoc
212*8add1155SRico Sonntag     */
213*8add1155SRico Sonntag    public function totalMediaFilm(): string
214*8add1155SRico Sonntag    {
215*8add1155SRico Sonntag        return I18N::number($this->totalMediaTypeQuery(self::MEDIA_TYPE_FILM));
216*8add1155SRico Sonntag    }
217*8add1155SRico Sonntag
218*8add1155SRico Sonntag    /**
219*8add1155SRico Sonntag     * @inheritDoc
220*8add1155SRico Sonntag     */
221*8add1155SRico Sonntag    public function totalMediaMagazine(): string
222*8add1155SRico Sonntag    {
223*8add1155SRico Sonntag        return I18N::number($this->totalMediaTypeQuery(self::MEDIA_TYPE_MAGAZINE));
224*8add1155SRico Sonntag    }
225*8add1155SRico Sonntag
226*8add1155SRico Sonntag    /**
227*8add1155SRico Sonntag     * @inheritDoc
228*8add1155SRico Sonntag     */
229*8add1155SRico Sonntag    public function totalMediaManuscript(): string
230*8add1155SRico Sonntag    {
231*8add1155SRico Sonntag        return I18N::number($this->totalMediaTypeQuery(self::MEDIA_TYPE_MANUSCRIPT));
232*8add1155SRico Sonntag    }
233*8add1155SRico Sonntag
234*8add1155SRico Sonntag    /**
235*8add1155SRico Sonntag     * @inheritDoc
236*8add1155SRico Sonntag     */
237*8add1155SRico Sonntag    public function totalMediaMap(): string
238*8add1155SRico Sonntag    {
239*8add1155SRico Sonntag        return I18N::number($this->totalMediaTypeQuery(self::MEDIA_TYPE_MAP));
240*8add1155SRico Sonntag    }
241*8add1155SRico Sonntag
242*8add1155SRico Sonntag    /**
243*8add1155SRico Sonntag     * @inheritDoc
244*8add1155SRico Sonntag     */
245*8add1155SRico Sonntag    public function totalMediaNewspaper(): string
246*8add1155SRico Sonntag    {
247*8add1155SRico Sonntag        return I18N::number($this->totalMediaTypeQuery(self::MEDIA_TYPE_NEWSPAPER));
248*8add1155SRico Sonntag    }
249*8add1155SRico Sonntag
250*8add1155SRico Sonntag    /**
251*8add1155SRico Sonntag     * @inheritDoc
252*8add1155SRico Sonntag     */
253*8add1155SRico Sonntag    public function totalMediaPainting(): string
254*8add1155SRico Sonntag    {
255*8add1155SRico Sonntag        return I18N::number($this->totalMediaTypeQuery(self::MEDIA_TYPE_PAINTING));
256*8add1155SRico Sonntag    }
257*8add1155SRico Sonntag
258*8add1155SRico Sonntag    /**
259*8add1155SRico Sonntag     * @inheritDoc
260*8add1155SRico Sonntag     */
261*8add1155SRico Sonntag    public function totalMediaPhoto(): string
262*8add1155SRico Sonntag    {
263*8add1155SRico Sonntag        return I18N::number($this->totalMediaTypeQuery(self::MEDIA_TYPE_PHOTO));
264*8add1155SRico Sonntag    }
265*8add1155SRico Sonntag
266*8add1155SRico Sonntag    /**
267*8add1155SRico Sonntag     * @inheritDoc
268*8add1155SRico Sonntag     */
269*8add1155SRico Sonntag    public function totalMediaTombstone(): string
270*8add1155SRico Sonntag    {
271*8add1155SRico Sonntag        return I18N::number($this->totalMediaTypeQuery(self::MEDIA_TYPE_TOMBSTONE));
272*8add1155SRico Sonntag    }
273*8add1155SRico Sonntag
274*8add1155SRico Sonntag    /**
275*8add1155SRico Sonntag     * @inheritDoc
276*8add1155SRico Sonntag     */
277*8add1155SRico Sonntag    public function totalMediaVideo(): string
278*8add1155SRico Sonntag    {
279*8add1155SRico Sonntag        return I18N::number($this->totalMediaTypeQuery(self::MEDIA_TYPE_VIDEO));
280*8add1155SRico Sonntag    }
281*8add1155SRico Sonntag
282*8add1155SRico Sonntag    /**
283*8add1155SRico Sonntag     * @inheritDoc
284*8add1155SRico Sonntag     */
285*8add1155SRico Sonntag    public function totalMediaOther(): string
286*8add1155SRico Sonntag    {
287*8add1155SRico Sonntag        return I18N::number($this->totalMediaTypeQuery(self::MEDIA_TYPE_OTHER));
288*8add1155SRico Sonntag    }
289*8add1155SRico Sonntag
290*8add1155SRico Sonntag    /**
291*8add1155SRico Sonntag     * @inheritDoc
292*8add1155SRico Sonntag     */
293*8add1155SRico Sonntag    public function totalMediaUnknown(): string
294*8add1155SRico Sonntag    {
295*8add1155SRico Sonntag        return I18N::number($this->totalMediaTypeQuery(self::MEDIA_TYPE_UNKNOWN));
296*8add1155SRico Sonntag    }
297*8add1155SRico Sonntag
298*8add1155SRico Sonntag    /**
299*8add1155SRico Sonntag     * Returns a sorted list of media types and their total counts.
300*8add1155SRico Sonntag     *
301*8add1155SRico Sonntag     * @param int $tot The total number of media files
302*8add1155SRico Sonntag     *
303*8add1155SRico Sonntag     * @return array
304*8add1155SRico Sonntag     */
305*8add1155SRico Sonntag    private function getSortedMediaTypeList(int $tot): array
306*8add1155SRico Sonntag    {
307*8add1155SRico Sonntag        $media = [];
308*8add1155SRico Sonntag        $c     = 0;
309*8add1155SRico Sonntag        $max   = 0;
310*8add1155SRico Sonntag
311*8add1155SRico Sonntag        foreach (self::MEDIA_TYPES as $type) {
312*8add1155SRico Sonntag            $count = $this->totalMediaTypeQuery($type);
313*8add1155SRico Sonntag
314*8add1155SRico Sonntag            if ($count > 0) {
315*8add1155SRico Sonntag                $media[$type] = $count;
316*8add1155SRico Sonntag
317*8add1155SRico Sonntag                if ($count > $max) {
318*8add1155SRico Sonntag                    $max = $count;
319*8add1155SRico Sonntag                }
320*8add1155SRico Sonntag
321*8add1155SRico Sonntag                $c += $count;
322*8add1155SRico Sonntag            }
323*8add1155SRico Sonntag        }
324*8add1155SRico Sonntag
325*8add1155SRico Sonntag        $count = $this->totalMediaTypeQuery(self::MEDIA_TYPE_UNKNOWN);
326*8add1155SRico Sonntag        if ($count > 0) {
327*8add1155SRico Sonntag            $media[self::MEDIA_TYPE_UNKNOWN] = $tot - $c;
328*8add1155SRico Sonntag            if ($tot - $c > $max) {
329*8add1155SRico Sonntag                $max = $count;
330*8add1155SRico Sonntag            }
331*8add1155SRico Sonntag        }
332*8add1155SRico Sonntag
333*8add1155SRico Sonntag        if (($max / $tot) > 0.6 && \count($media) > 10) {
334*8add1155SRico Sonntag            arsort($media);
335*8add1155SRico Sonntag            $media = \array_slice($media, 0, 10);
336*8add1155SRico Sonntag            $c     = $tot;
337*8add1155SRico Sonntag
338*8add1155SRico Sonntag            foreach ($media as $cm) {
339*8add1155SRico Sonntag                $c -= $cm;
340*8add1155SRico Sonntag            }
341*8add1155SRico Sonntag
342*8add1155SRico Sonntag            if (isset($media[self::MEDIA_TYPE_OTHER])) {
343*8add1155SRico Sonntag                $media[self::MEDIA_TYPE_OTHER] += $c;
344*8add1155SRico Sonntag            } else {
345*8add1155SRico Sonntag                $media[self::MEDIA_TYPE_OTHER] = $c;
346*8add1155SRico Sonntag            }
347*8add1155SRico Sonntag        }
348*8add1155SRico Sonntag
349*8add1155SRico Sonntag        asort($media);
350*8add1155SRico Sonntag
351*8add1155SRico Sonntag        return $media;
352*8add1155SRico Sonntag    }
353*8add1155SRico Sonntag
354*8add1155SRico Sonntag    /**
355*8add1155SRico Sonntag     * @inheritDoc
356*8add1155SRico Sonntag     */
357*8add1155SRico Sonntag    public function chartMedia(string $size = null, string $color_from = null, string $color_to = null): string
358*8add1155SRico Sonntag    {
359*8add1155SRico Sonntag        $tot   = $this->totalMediaTypeQuery(self::MEDIA_TYPE_ALL);
360*8add1155SRico Sonntag        $media = $this->getSortedMediaTypeList($tot);
361*8add1155SRico Sonntag
362*8add1155SRico Sonntag        return (new ChartMedia())
363*8add1155SRico Sonntag            ->chartMedia($tot, $media, $size, $color_from, $color_to);
364*8add1155SRico Sonntag    }
365*8add1155SRico Sonntag}
366