xref: /webtrees/app/Module/AlbumModule.php (revision 369c0ce6d43eee62858778711fa4744ed347814a)
18c2e8227SGreg Roach<?php
28c2e8227SGreg Roach/**
38c2e8227SGreg Roach * webtrees: online genealogy
4*369c0ce6SGreg Roach * Copyright (C) 2016 webtrees development team
58c2e8227SGreg Roach * This program is free software: you can redistribute it and/or modify
68c2e8227SGreg Roach * it under the terms of the GNU General Public License as published by
78c2e8227SGreg Roach * the Free Software Foundation, either version 3 of the License, or
88c2e8227SGreg Roach * (at your option) any later version.
98c2e8227SGreg Roach * This program is distributed in the hope that it will be useful,
108c2e8227SGreg Roach * but WITHOUT ANY WARRANTY; without even the implied warranty of
118c2e8227SGreg Roach * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
128c2e8227SGreg Roach * GNU General Public License for more details.
138c2e8227SGreg Roach * You should have received a copy of the GNU General Public License
148c2e8227SGreg Roach * along with this program. If not, see <http://www.gnu.org/licenses/>.
158c2e8227SGreg Roach */
1676692c8bSGreg Roachnamespace Fisharebest\Webtrees\Module;
1776692c8bSGreg Roach
180e62c4b8SGreg Roachuse Fisharebest\Webtrees\Auth;
190e62c4b8SGreg Roachuse Fisharebest\Webtrees\Filter;
203d7a8a4cSGreg Roachuse Fisharebest\Webtrees\Functions\FunctionsPrint;
210e62c4b8SGreg Roachuse Fisharebest\Webtrees\I18N;
220e62c4b8SGreg Roachuse Fisharebest\Webtrees\Media;
230e62c4b8SGreg Roachuse Fisharebest\Webtrees\Menu;
240e62c4b8SGreg Roachuse Fisharebest\Webtrees\Module;
250e62c4b8SGreg Roachuse Fisharebest\Webtrees\Theme;
268c2e8227SGreg Roach
278c2e8227SGreg Roach/**
288c2e8227SGreg Roach * Class AlbumModule
298c2e8227SGreg Roach */
30e2a378d3SGreg Roachclass AlbumModule extends AbstractModule implements ModuleTabInterface {
3176692c8bSGreg Roach	/** @var Media[] List of media objects. */
328c2e8227SGreg Roach	private $media_list;
338c2e8227SGreg Roach
3476692c8bSGreg Roach	/**
3576692c8bSGreg Roach	 * How should this module be labelled on tabs, menus, etc.?
3676692c8bSGreg Roach	 *
3776692c8bSGreg Roach	 * @return string
3876692c8bSGreg Roach	 */
398c2e8227SGreg Roach	public function getTitle() {
408c2e8227SGreg Roach		return /* I18N: Name of a module */ I18N::translate('Album');
418c2e8227SGreg Roach	}
428c2e8227SGreg Roach
4376692c8bSGreg Roach	/**
4476692c8bSGreg Roach	 * A sentence describing what this module does.
4576692c8bSGreg Roach	 *
4676692c8bSGreg Roach	 * @return string
4776692c8bSGreg Roach	 */
488c2e8227SGreg Roach	public function getDescription() {
498c2e8227SGreg Roach		return /* I18N: Description of the “Album” module */ I18N::translate('An alternative to the “media” tab, and an enhanced image viewer.');
508c2e8227SGreg Roach	}
518c2e8227SGreg Roach
5276692c8bSGreg Roach	/**
5376692c8bSGreg Roach	 * The user can re-arrange the tab order, but until they do, this
5476692c8bSGreg Roach	 * is the order in which tabs are shown.
5576692c8bSGreg Roach	 *
5676692c8bSGreg Roach	 * @return int
5776692c8bSGreg Roach	 */
588c2e8227SGreg Roach	public function defaultTabOrder() {
598c2e8227SGreg Roach		return 60;
608c2e8227SGreg Roach	}
618c2e8227SGreg Roach
6276692c8bSGreg Roach	/**
6376692c8bSGreg Roach	 * Is this tab empty? If so, we don't always need to display it.
6476692c8bSGreg Roach	 *
6576692c8bSGreg Roach	 * @return bool
6676692c8bSGreg Roach	 */
678c2e8227SGreg Roach	public function hasTabContent() {
684b9ff166SGreg Roach		global $WT_TREE;
694b9ff166SGreg Roach
704b9ff166SGreg Roach		return Auth::isEditor($WT_TREE) || $this->getMedia();
718c2e8227SGreg Roach	}
728c2e8227SGreg Roach
7376692c8bSGreg Roach	/**
7476692c8bSGreg Roach	 * A greyed out tab has no actual content, but may perhaps have
7576692c8bSGreg Roach	 * options to create content.
7676692c8bSGreg Roach	 *
7776692c8bSGreg Roach	 * @return bool
7876692c8bSGreg Roach	 */
798c2e8227SGreg Roach	public function isGrayedOut() {
80764a01d9SGreg Roach		return !$this->getMedia();
818c2e8227SGreg Roach	}
828c2e8227SGreg Roach
8376692c8bSGreg Roach	/**
8476692c8bSGreg Roach	 * Generate the HTML content of this tab.
8576692c8bSGreg Roach	 *
8676692c8bSGreg Roach	 * @return string
8776692c8bSGreg Roach	 */
888c2e8227SGreg Roach	public function getTabContent() {
898c2e8227SGreg Roach		global $WT_TREE, $controller;
908c2e8227SGreg Roach
918c2e8227SGreg Roach		$html = '<div id="' . $this->getName() . '_content">';
928c2e8227SGreg Roach		//Show Lightbox-Album header Links
934b9ff166SGreg Roach		if (Auth::isEditor($WT_TREE)) {
948c2e8227SGreg Roach			$html .= '<table class="facts_table"><tr><td class="descriptionbox rela">';
958c2e8227SGreg Roach			// Add a new media object
964b9ff166SGreg Roach			if ($WT_TREE->getPreference('MEDIA_UPLOAD') >= Auth::accessLevel($WT_TREE)) {
978c2e8227SGreg Roach				$html .= '<span><a href="#" onclick="window.open(\'addmedia.php?action=showmediaform&linktoid=' . $controller->record->getXref() . '\', \'_blank\', \'resizable=1,scrollbars=1,top=50,height=780,width=600\');return false;">';
988c2e8227SGreg Roach				$html .= '<img src="' . Theme::theme()->assetUrl() . 'images/image_add.png" id="head_icon" class="icon" title="' . I18N::translate('Add a new media object') . '" alt="' . I18N::translate('Add a new media object') . '">';
998c2e8227SGreg Roach				$html .= I18N::translate('Add a new media object');
1008c2e8227SGreg Roach				$html .= '</a></span>';
1018c2e8227SGreg Roach				// Link to an existing item
1028c2e8227SGreg Roach				$html .= '<span><a href="#" onclick="window.open(\'inverselink.php?linktoid=' . $controller->record->getXref() . '&linkto=person\', \'_blank\', \'resizable=1,scrollbars=1,top=50,height=300,width=450\');">';
1038c2e8227SGreg Roach				$html .= '<img src="' . Theme::theme()->assetUrl() . 'images/image_link.png" id="head_icon" class="icon" title="' . I18N::translate('Link to an existing media object') . '" alt="' . I18N::translate('Link to an existing media object') . '">';
1048c2e8227SGreg Roach				$html .= I18N::translate('Link to an existing media object');
1058c2e8227SGreg Roach				$html .= '</a></span>';
1068c2e8227SGreg Roach			}
1074b9ff166SGreg Roach			if (Auth::isManager($WT_TREE) && $this->getMedia()) {
1088c2e8227SGreg Roach				// Popup Reorder Media
1098c2e8227SGreg Roach				$html .= '<span><a href="#" onclick="reorder_media(\'' . $controller->record->getXref() . '\')">';
1108c2e8227SGreg Roach				$html .= '<img src="' . Theme::theme()->assetUrl() . 'images/images.png" id="head_icon" class="icon" title="' . I18N::translate('Re-order media') . '" alt="' . I18N::translate('Re-order media') . '">';
1118c2e8227SGreg Roach				$html .= I18N::translate('Re-order media');
1128c2e8227SGreg Roach				$html .= '</a></span>';
1138c2e8227SGreg Roach			}
1148c2e8227SGreg Roach			$html .= '</td></tr></table>';
1158c2e8227SGreg Roach		}
1168c2e8227SGreg Roach
1178c2e8227SGreg Roach		// Used when sorting media on album tab page
1188c2e8227SGreg Roach		$html .= '<table class="facts_table"><tr><td class="facts_value">'; // one-cell table - for presentation only
1198c2e8227SGreg Roach		$html .= '<ul class="album-list">';
120764a01d9SGreg Roach		foreach ($this->getMedia() as $media) {
1218c2e8227SGreg Roach			//View Edit Menu ----------------------------------
1228c2e8227SGreg Roach
1238c2e8227SGreg Roach			//Get media item Notes
1248c2e8227SGreg Roach			$haystack = $media->getGedcom();
1258c2e8227SGreg Roach			$needle   = '1 NOTE';
1268c2e8227SGreg Roach			$before   = substr($haystack, 0, strpos($haystack, $needle));
1278c2e8227SGreg Roach			$after    = substr(strstr($haystack, $needle), strlen($needle));
1283d7a8a4cSGreg Roach			$notes    = FunctionsPrint::printFactNotes($before . $needle . $after, 1, true);
1298c2e8227SGreg Roach
1308c2e8227SGreg Roach			// Prepare Below Thumbnail  menu ----------------------------------------------------
1318c2e8227SGreg Roach			$menu = new Menu('<div style="overflow: hidden; text-overflow: ellipsis; white-space: nowrap">' . $media->getFullName() . '</div>');
1328c2e8227SGreg Roach			$menu->addClass('', 'submenu');
1338c2e8227SGreg Roach
1348c2e8227SGreg Roach			// View Notes
1358c2e8227SGreg Roach			if (strpos($media->getGedcom(), "\n1 NOTE")) {
1363cf92ae2SGreg Roach				$submenu = new Menu(I18N::translate('View notes'), '#', '', array(
1373cf92ae2SGreg Roach					'onclick' => 'modalNotes("' . Filter::escapeJs($notes) . '","' . I18N::translate('View notes') . '"); return false;',
1383cf92ae2SGreg Roach				));
1398c2e8227SGreg Roach				$submenu->addClass("submenuitem");
1408c2e8227SGreg Roach				$menu->addSubmenu($submenu);
1418c2e8227SGreg Roach			}
1428c2e8227SGreg Roach			//View Details
1438c2e8227SGreg Roach			$submenu = new Menu(I18N::translate('View details'), $media->getHtmlUrl());
1448c2e8227SGreg Roach			$submenu->addClass("submenuitem");
1458c2e8227SGreg Roach			$menu->addSubmenu($submenu);
1468c2e8227SGreg Roach
1478c2e8227SGreg Roach			//View Sources
1488c2e8227SGreg Roach			foreach ($media->getFacts('SOUR') as $source_fact) {
1498c2e8227SGreg Roach				$source = $source_fact->getTarget();
1508c2e8227SGreg Roach				if ($source && $source->canShow()) {
1518c2e8227SGreg Roach					$submenu = new Menu(I18N::translate('Source') . ' – ' . $source->getFullName(), $source->getHtmlUrl());
1528c2e8227SGreg Roach					$submenu->addClass('submenuitem');
1538c2e8227SGreg Roach					$menu->addSubmenu($submenu);
1548c2e8227SGreg Roach				}
1558c2e8227SGreg Roach			}
1568c2e8227SGreg Roach
1574b9ff166SGreg Roach			if (Auth::isEditor($media->getTree())) {
1588c2e8227SGreg Roach				// Edit Media
1593cf92ae2SGreg Roach				$submenu = new Menu(I18N::translate('Edit media'), '#', '', array(
1603cf92ae2SGreg Roach					'onclick' => 'return window.open("addmedia.php?action=editmedia&pid=' . $media->getXref() . '", "_blank", edit_window_specs);',
1613cf92ae2SGreg Roach				));
1628c2e8227SGreg Roach				$submenu->addClass("submenuitem");
1638c2e8227SGreg Roach				$menu->addSubmenu($submenu);
1648c2e8227SGreg Roach				if (Auth::isAdmin()) {
1658c2e8227SGreg Roach					if (Module::getModuleByName('GEDFact_assistant')) {
1663cf92ae2SGreg Roach						$submenu = new Menu(I18N::translate('Manage links'), '#', '', array(
1673cf92ae2SGreg Roach							'onclick' => 'return window.open("inverselink.php?mediaid=' . $media->getXref() . '&linkto=manage", "_blank", find_window_specs);',
1683cf92ae2SGreg Roach						));
1698c2e8227SGreg Roach						$submenu->addClass("submenuitem");
1708c2e8227SGreg Roach						$menu->addSubmenu($submenu);
1718c2e8227SGreg Roach					} else {
1723cf92ae2SGreg Roach						$submenu = new Menu(I18N::translate('Link this media object to an individual'), '#', 'menu-obje-link-indi', array(
1733cf92ae2SGreg Roach							'onclick' => 'return ilinkitem("' . $media->getXref() . '","person");',
1743cf92ae2SGreg Roach						));
1758c2e8227SGreg Roach						$submenu->addClass('submenuitem');
1768c2e8227SGreg Roach						$menu->addSubmenu($submenu);
1778c2e8227SGreg Roach
1783cf92ae2SGreg Roach						$submenu = new Menu(I18N::translate('Link this media object to a family'), '#', 'menu-obje-link-fam', array(
1793cf92ae2SGreg Roach							'onclick' => 'return ilinkitem("' . $media->getXref() . '","family");',
1803cf92ae2SGreg Roach						));
1818c2e8227SGreg Roach						$submenu->addClass('submenuitem');
1828c2e8227SGreg Roach						$menu->addSubmenu($submenu);
1838c2e8227SGreg Roach
1843cf92ae2SGreg Roach						$submenu = new Menu(I18N::translate('Link this media object to a source'), '#', 'menu-obje-link-sour', array(
1853cf92ae2SGreg Roach							'onclick' => 'return ilinkitem("' . $media->getXref() . '","source");',
1863cf92ae2SGreg Roach						));
1878c2e8227SGreg Roach						$submenu->addClass('submenuitem');
1888c2e8227SGreg Roach						$menu->addSubmenu($submenu);
1898c2e8227SGreg Roach					}
1903cf92ae2SGreg Roach					$submenu = new Menu(I18N::translate('Unlink media'), '#', '', array(
1913cf92ae2SGreg Roach						'onclick' => 'return unlink_media("' . I18N::translate('Are you sure you want to remove links to this media object?') . '", "' . $controller->record->getXref() . '", "' . $media->getXref() . '");',
1923cf92ae2SGreg Roach					));
1938c2e8227SGreg Roach					$submenu->addClass("submenuitem");
1948c2e8227SGreg Roach					$menu->addSubmenu($submenu);
1958c2e8227SGreg Roach				}
1968c2e8227SGreg Roach			}
1978c2e8227SGreg Roach			$html .= '<li class="album-list-item">';
1988c2e8227SGreg Roach			$html .= '<div class="album-image">' . $media->displayImage() . '</div>';
1998c2e8227SGreg Roach			$html .= '<div class="album-title">' . $menu->getMenu() . '</div>';
2008c2e8227SGreg Roach			$html .= '</li>';
2018c2e8227SGreg Roach		}
2028c2e8227SGreg Roach		$html .= '</ul>';
2038c2e8227SGreg Roach		$html .= '</td></tr></table>';
204cbc1590aSGreg Roach
2058c2e8227SGreg Roach		return $html;
2068c2e8227SGreg Roach	}
2078c2e8227SGreg Roach
2088c2e8227SGreg Roach	/**
2098c2e8227SGreg Roach	 * Get all facts containing media links for this person and their spouse-family records
2108c2e8227SGreg Roach	 *
2118c2e8227SGreg Roach	 * @return Media[]
2128c2e8227SGreg Roach	 */
213764a01d9SGreg Roach	private function getMedia() {
2148c2e8227SGreg Roach		global $controller;
2158c2e8227SGreg Roach
2168c2e8227SGreg Roach		if ($this->media_list === null) {
2178c2e8227SGreg Roach			// Use facts from this individual and all their spouses
2188c2e8227SGreg Roach			$facts = $controller->record->getFacts();
2198c2e8227SGreg Roach			foreach ($controller->record->getSpouseFamilies() as $family) {
2208c2e8227SGreg Roach				foreach ($family->getFacts() as $fact) {
2218c2e8227SGreg Roach					$facts[] = $fact;
2228c2e8227SGreg Roach				}
2238c2e8227SGreg Roach			}
2248c2e8227SGreg Roach			// Use all media from each fact
2258c2e8227SGreg Roach			$this->media_list = array();
2268c2e8227SGreg Roach			foreach ($facts as $fact) {
2278c2e8227SGreg Roach				// Don't show pending edits, as the user just sees duplicates
2288c2e8227SGreg Roach				if (!$fact->isPendingDeletion()) {
2298c2e8227SGreg Roach					preg_match_all('/(?:^1|\n\d) OBJE @(' . WT_REGEX_XREF . ')@/', $fact->getGedcom(), $matches);
2308c2e8227SGreg Roach					foreach ($matches[1] as $match) {
23124ec66ceSGreg Roach						$media = Media::getInstance($match, $controller->record->getTree());
2328c2e8227SGreg Roach						if ($media && $media->canShow()) {
2338c2e8227SGreg Roach							$this->media_list[] = $media;
2348c2e8227SGreg Roach						}
2358c2e8227SGreg Roach					}
2368c2e8227SGreg Roach				}
2378c2e8227SGreg Roach			}
2388c2e8227SGreg Roach			// If a media object is linked twice, only show it once
2398c2e8227SGreg Roach			$this->media_list = array_unique($this->media_list);
2408c2e8227SGreg Roach			// Sort these using _WT_OBJE_SORT
2418c2e8227SGreg Roach			$wt_obje_sort = array();
2428c2e8227SGreg Roach			foreach ($controller->record->getFacts('_WT_OBJE_SORT') as $fact) {
2438c2e8227SGreg Roach				$wt_obje_sort[] = trim($fact->getValue(), '@');
2448c2e8227SGreg Roach			}
2458c2e8227SGreg Roach			usort($this->media_list, function (Media $x, Media $y) use ($wt_obje_sort) {
2468c2e8227SGreg Roach				return array_search($x->getXref(), $wt_obje_sort) - array_search($y->getXref(), $wt_obje_sort);
2478c2e8227SGreg Roach			});
2488c2e8227SGreg Roach		}
249cbc1590aSGreg Roach
2508c2e8227SGreg Roach		return $this->media_list;
2518c2e8227SGreg Roach	}
2528c2e8227SGreg Roach
25376692c8bSGreg Roach	/**
25476692c8bSGreg Roach	 * Can this tab load asynchronously?
25576692c8bSGreg Roach	 *
25676692c8bSGreg Roach	 * @return bool
25776692c8bSGreg Roach	 */
2588c2e8227SGreg Roach	public function canLoadAjax() {
2598c2e8227SGreg Roach		return !Auth::isSearchEngine(); // Search engines cannot use AJAX
2608c2e8227SGreg Roach	}
2618c2e8227SGreg Roach
26276692c8bSGreg Roach	/**
26376692c8bSGreg Roach	 * Any content (e.g. Javascript) that needs to be rendered before the tabs.
26476692c8bSGreg Roach	 *
26576692c8bSGreg Roach	 * This function is probably not needed, as there are better ways to achieve this.
26676692c8bSGreg Roach	 *
26776692c8bSGreg Roach	 * @return string
26876692c8bSGreg Roach	 */
2698c2e8227SGreg Roach	public function getPreLoadContent() {
2708c2e8227SGreg Roach		return '';
2718c2e8227SGreg Roach	}
2728c2e8227SGreg Roach}
273