xref: /webtrees/app/Module/AlbumModule.php (revision 59f2f229057fe08ec1b09bd435699190641eed6a)
1<?php
2/**
3 * webtrees: online genealogy
4 * Copyright (C) 2018 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 */
16namespace Fisharebest\Webtrees\Module;
17
18use Fisharebest\Webtrees\I18N;
19use Fisharebest\Webtrees\Individual;
20use Fisharebest\Webtrees\Media;
21
22/**
23 * Class AlbumModule
24 */
25class AlbumModule extends AbstractModule implements ModuleTabInterface
26{
27    /** @var Media[] List of media objects. */
28    private $media_list;
29
30    /**
31     * How should this module be labelled on tabs, menus, etc.?
32     *
33     * @return string
34     */
35    public function getTitle()
36    {
37        /* I18N: Name of a module */
38        return I18N::translate('Album');
39    }
40
41    /**
42     * A sentence describing what this module does.
43     *
44     * @return string
45     */
46    public function getDescription()
47    {
48        /* I18N: Description of the “Album” module */
49        return I18N::translate('An alternative to the “media” tab, and an enhanced image viewer.');
50    }
51
52    /**
53     * The user can re-arrange the tab order, but until they do, this
54     * is the order in which tabs are shown.
55     *
56     * @return int
57     */
58    public function defaultTabOrder()
59    {
60        return 60;
61    }
62
63    /**
64     * Is this tab empty? If so, we don't always need to display it.
65     *
66     * @param Individual $individual
67     *
68     * @return bool
69     */
70    public function hasTabContent(Individual $individual)
71    {
72        return $individual->canEdit() || $this->getMedia($individual);
73    }
74
75    /**
76     * A greyed out tab has no actual content, but may perhaps have
77     * options to create content.
78     *
79     * @param Individual $individual
80     *
81     * @return bool
82     */
83    public function isGrayedOut(Individual $individual)
84    {
85        return !$this->getMedia($individual);
86    }
87
88    /**
89     * Generate the HTML content of this tab.
90     *
91     * @param Individual $individual
92     *
93     * @return string
94     */
95    public function getTabContent(Individual $individual)
96    {
97        return view('modules/lightbox/tab', [
98            'media_list' => $this->getMedia($individual),
99        ]);
100    }
101
102    /**
103     * Get all facts containing media links for this person and their spouse-family records
104     *
105     * @param Individual $individual
106     *
107     * @return Media[]
108     */
109    private function getMedia(Individual $individual)
110    {
111        if ($this->media_list === null) {
112            // Use facts from this individual and all their spouses
113            $facts = $individual->getFacts();
114            foreach ($individual->getSpouseFamilies() as $family) {
115                foreach ($family->getFacts() as $fact) {
116                    $facts[] = $fact;
117                }
118            }
119            // Use all media from each fact
120            $this->media_list = [];
121            foreach ($facts as $fact) {
122                // Don't show pending edits, as the user just sees duplicates
123                if (!$fact->isPendingDeletion()) {
124                    preg_match_all('/(?:^1|\n\d) OBJE @(' . WT_REGEX_XREF . ')@/', $fact->getGedcom(), $matches);
125                    foreach ($matches[1] as $match) {
126                        $media = Media::getInstance($match, $individual->getTree());
127                        if ($media && $media->canShow()) {
128                            $this->media_list[] = $media;
129                        }
130                    }
131                }
132            }
133            // If a media object is linked twice, only show it once
134            $this->media_list = array_unique($this->media_list);
135            // Sort these using _WT_OBJE_SORT
136            $wt_obje_sort = [];
137            foreach ($individual->getFacts('_WT_OBJE_SORT') as $fact) {
138                $wt_obje_sort[] = trim($fact->getValue(), '@');
139            }
140            usort($this->media_list, function (Media $x, Media $y) use ($wt_obje_sort) {
141                return array_search($x->getXref(), $wt_obje_sort) - array_search($y->getXref(), $wt_obje_sort);
142            });
143        }
144
145        return $this->media_list;
146    }
147
148    /**
149     * Can this tab load asynchronously?
150     *
151     * @return bool
152     */
153    public function canLoadAjax()
154    {
155        return false;
156    }
157}
158