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