xref: /webtrees/app/Module/AlbumModule.php (revision 2a6fda6001c209d27013f958519efeae6d48e2fb)
1<?php
2/**
3 * webtrees: online genealogy
4 * Copyright (C) 2017 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\Auth;
19use Fisharebest\Webtrees\I18N;
20use Fisharebest\Webtrees\Media;
21
22/**
23 * Class AlbumModule
24 */
25class AlbumModule extends AbstractModule implements ModuleTabInterface {
26	/** @var Media[] List of media objects. */
27	private $media_list;
28
29	/**
30	 * How should this module be labelled on tabs, menus, etc.?
31	 *
32	 * @return string
33	 */
34	public function getTitle() {
35		return /* I18N: Name of a module */ I18N::translate('Album');
36	}
37
38	/**
39	 * A sentence describing what this module does.
40	 *
41	 * @return string
42	 */
43	public function getDescription() {
44		return /* I18N: Description of the “Album” module */ I18N::translate('An alternative to the “media” tab, and an enhanced image viewer.');
45	}
46
47	/**
48	 * The user can re-arrange the tab order, but until they do, this
49	 * is the order in which tabs are shown.
50	 *
51	 * @return int
52	 */
53	public function defaultTabOrder() {
54		return 60;
55	}
56
57	/**
58	 * Is this tab empty? If so, we don't always need to display it.
59	 *
60	 * @return bool
61	 */
62	public function hasTabContent() {
63		global $WT_TREE;
64
65		return Auth::isEditor($WT_TREE) || $this->getMedia();
66	}
67
68	/**
69	 * A greyed out tab has no actual content, but may perhaps have
70	 * options to create content.
71	 *
72	 * @return bool
73	 */
74	public function isGrayedOut() {
75		return !$this->getMedia();
76	}
77
78	/**
79	 * Generate the HTML content of this tab.
80	 *
81	 * @return string
82	 */
83	public function getTabContent() {
84		global $WT_TREE, $controller;
85
86		$html = '<div id="' . $this->getName() . '_content">';
87		//Show Lightbox-Album header Links
88		if (Auth::isEditor($WT_TREE)) {
89			$html .= '<table class="facts_table"><tr><td class="descriptionbox rela">';
90			// Add a media object
91			if ($WT_TREE->getPreference('MEDIA_UPLOAD') >= Auth::accessLevel($WT_TREE)) {
92				$html .= '<a href="edit_interface.php?action=add-media-link&amp;ged=' . $controller->record->getTree()->getNameHtml() . '&amp;xref=' . $controller->record->getXref() . '">' . I18N::translate('Add a media object') . '</a>';
93			}
94
95			if (Auth::isManager($WT_TREE) && $this->getMedia()) {
96				$html .= '<span><a href="edit_interface.php?action=reorder-media&amp;ged=' . $controller->record->getTree()->getNameHtml() . '&amp;xref=' . $controller->record->getXref() . '">';
97				$html .= I18N::translate('Re-order media');
98				$html .= '</a></span>';
99			}
100			$html .= '</td></tr></table>';
101		}
102
103		$html .= '<div class="facts_value">';
104		$html .= '<ul class="album-list">';
105		foreach ($this->getMedia() as $media) {
106			$html .= '<li class="album-list-item">';
107			$html .= '<div class="album-image">' . $media->displayImage(100, 100, 'contain', []) . '</div>';
108			$html .= '<div class="album-title"><a href="' . $media->getXref() . '">' . $media->getFullName() . '</a></div>';
109			$html .= '</li>';
110		}
111		$html .= '</ul>';
112		$html .= '</div>';
113		$html .= '</div>';
114
115		return $html;
116	}
117
118	/**
119	 * Get all facts containing media links for this person and their spouse-family records
120	 *
121	 * @return Media[]
122	 */
123	private function getMedia() {
124		global $controller;
125
126		if ($this->media_list === null) {
127			// Use facts from this individual and all their spouses
128			$facts = $controller->record->getFacts();
129			foreach ($controller->record->getSpouseFamilies() as $family) {
130				foreach ($family->getFacts() as $fact) {
131					$facts[] = $fact;
132				}
133			}
134			// Use all media from each fact
135			$this->media_list = [];
136			foreach ($facts as $fact) {
137				// Don't show pending edits, as the user just sees duplicates
138				if (!$fact->isPendingDeletion()) {
139					preg_match_all('/(?:^1|\n\d) OBJE @(' . WT_REGEX_XREF . ')@/', $fact->getGedcom(), $matches);
140					foreach ($matches[1] as $match) {
141						$media = Media::getInstance($match, $controller->record->getTree());
142						if ($media && $media->canShow()) {
143							$this->media_list[] = $media;
144						}
145					}
146				}
147			}
148			// If a media object is linked twice, only show it once
149			$this->media_list = array_unique($this->media_list);
150			// Sort these using _WT_OBJE_SORT
151			$wt_obje_sort = [];
152			foreach ($controller->record->getFacts('_WT_OBJE_SORT') as $fact) {
153				$wt_obje_sort[] = trim($fact->getValue(), '@');
154			}
155			usort($this->media_list, function (Media $x, Media $y) use ($wt_obje_sort) {
156				return array_search($x->getXref(), $wt_obje_sort) - array_search($y->getXref(), $wt_obje_sort);
157			});
158		}
159
160		return $this->media_list;
161	}
162
163	/**
164	 * Can this tab load asynchronously?
165	 *
166	 * @return bool
167	 */
168	public function canLoadAjax() {
169		return false;
170	}
171
172	/**
173	 * Any content (e.g. Javascript) that needs to be rendered before the tabs.
174	 *
175	 * This function is probably not needed, as there are better ways to achieve this.
176	 *
177	 * @return string
178	 */
179	public function getPreLoadContent() {
180		return '';
181	}
182}
183