.
*/
namespace Fisharebest\Webtrees\Theme;
use Fisharebest\Webtrees\Auth;
use Fisharebest\Webtrees\Controller\PageController;
use Fisharebest\Webtrees\Database;
use Fisharebest\Webtrees\Fact;
use Fisharebest\Webtrees\Filter;
use Fisharebest\Webtrees\FlashMessages;
use Fisharebest\Webtrees\Functions\Functions;
use Fisharebest\Webtrees\GedcomRecord;
use Fisharebest\Webtrees\GedcomTag;
use Fisharebest\Webtrees\HitCounter;
use Fisharebest\Webtrees\I18N;
use Fisharebest\Webtrees\Individual;
use Fisharebest\Webtrees\Menu;
use Fisharebest\Webtrees\Module;
use Fisharebest\Webtrees\Module\AncestorsChartModule;
use Fisharebest\Webtrees\Module\CompactTreeChartModule;
use Fisharebest\Webtrees\Module\DescendancyChartModule;
use Fisharebest\Webtrees\Module\FamilyBookChartModule;
use Fisharebest\Webtrees\Module\FamilyTreeFavoritesModule;
use Fisharebest\Webtrees\Module\FanChartModule;
use Fisharebest\Webtrees\Module\GoogleMapsModule;
use Fisharebest\Webtrees\Module\HourglassChartModule;
use Fisharebest\Webtrees\Module\InteractiveTreeModule;
use Fisharebest\Webtrees\Module\LifespansChartModule;
use Fisharebest\Webtrees\Module\PedigreeChartModule;
use Fisharebest\Webtrees\Module\RelationshipsChartModule;
use Fisharebest\Webtrees\Module\StatisticsChartModule;
use Fisharebest\Webtrees\Module\TimelineChartModule;
use Fisharebest\Webtrees\Module\UserFavoritesModule;
use Fisharebest\Webtrees\Site;
use Fisharebest\Webtrees\Theme;
use Fisharebest\Webtrees\Tree;
use Fisharebest\Webtrees\User;
/**
* Common functions for all themes.
*/
abstract class AbstractTheme {
/** @var Tree The current tree */
protected $tree;
/** @var string An escaped version of the "ged=XXX" URL parameter */
protected $tree_url;
/** @var int The number of times this page has been shown */
protected $page_views;
/**
* Custom themes should place their initialization code in the function hookAfterInit(), not in
* the constructor, as all themes get constructed - whether they are used or not.
*/
final public function __construct() {
}
/**
* Create accessibility links for the header.
*
* "Skip to content" allows keyboard only users to navigate over the headers without
* pressing TAB many times.
*
* @return string
*/
protected function accessibilityLinks() {
return
'
';
}
/**
* Create scripts for analytics and tracking.
*
* @return string
*/
protected function analytics() {
if ($this->themeId() === '_administration' || !empty($_SERVER['HTTP_DNT'])) {
return '';
} else {
return
$this->analyticsBingWebmaster(
Site::getPreference('BING_WEBMASTER_ID')
) .
$this->analyticsGoogleWebmaster(
Site::getPreference('GOOGLE_WEBMASTER_ID')
) .
$this->analyticsGoogleTracker(
Site::getPreference('GOOGLE_ANALYTICS_ID')
) .
$this->analyticsPiwikTracker(
Site::getPreference('PIWIK_URL'),
Site::getPreference('PIWIK_SITE_ID')
) .
$this->analyticsStatcounterTracker(
Site::getPreference('STATCOUNTER_PROJECT_ID'),
Site::getPreference('STATCOUNTER_SECURITY_ID')
);
}
}
/**
* Create the verification code for Google Webmaster Tools.
*
* @param string $verification_id
*
* @return string
*/
protected function analyticsBingWebmaster($verification_id) {
// Only need to add this to the home page.
if (WT_SCRIPT_NAME === 'index.php' && $verification_id) {
return '';
} else {
return '';
}
}
/**
* Create the verification code for Google Webmaster Tools.
*
* @param string $verification_id
*
* @return string
*/
protected function analyticsGoogleWebmaster($verification_id) {
// Only need to add this to the home page.
if (WT_SCRIPT_NAME === 'index.php' && $verification_id) {
return '';
} else {
return '';
}
}
/**
* Create the tracking code for Google Analytics.
*
* See https://developers.google.com/analytics/devguides/collection/analyticsjs/advanced
*
* @param string $analytics_id
*
* @return string
*/
protected function analyticsGoogleTracker($analytics_id) {
if ($analytics_id) {
// Add extra dimensions (i.e. filtering categories)
$dimensions = (object) array(
'dimension1' => $this->tree ? $this->tree->getName() : '-',
'dimension2' => $this->tree ? Auth::accessLevel($this->tree) : '-',
);
return
'' .
'';
} else {
return '';
}
}
/**
* Create the tracking code for Piwik Analytics.
*
* @param string $url - The domain/path to Piwik
* @param string $site_id - The Piwik site identifier
*
* @return string
*/
protected function analyticsPiwikTracker($url, $site_id) {
$url = preg_replace(array('/^https?:\/\//', '/\/$/'), '', $url);
if ($url && $site_id) {
return
'';
} else {
return '';
}
}
/**
* Create the tracking code for Statcounter.
*
* @param string $project_id - The statcounter project ID
* @param string $security_id - The statcounter security ID
*
* @return string
*/
protected function analyticsStatcounterTracker($project_id, $security_id) {
if ($project_id && $security_id) {
return
'';
} else {
return '';
}
}
/**
* Create the top of the .
*
* @return string
*/
public function bodyHeader() {
return
'' .
'' .
$this->headerContent() .
$this->primaryMenuContainer($this->primaryMenu()) .
'' .
'' .
$this->flashMessagesContainer(FlashMessages::getMessages());
}
/**
* Create the top of the (for popup windows).
*
* @return string
*/
public function bodyHeaderPopupWindow() {
return
'' .
'' .
$this->flashMessagesContainer(FlashMessages::getMessages());
}
/**
* Create a contact link for a user.
*
* @param User $user
*
* @return string
*/
public function contactLink(User $user) {
$method = $user->getPreference('contactmethod');
switch ($method) {
case 'none':
return '';
case 'mailto':
return '' . $user->getRealNameHtml() . '';
default:
return "" . $user->getRealNameHtml() . '';
}
}
/**
* Create contact link for both technical and genealogy support.
*
* @param User $user
*
* @return string
*/
protected function contactLinkEverything(User $user) {
return I18N::translate('For technical support or genealogy questions contact %s.', $this->contactLink($user));
}
/**
* Create contact link for genealogy support.
*
* @param User $user
*
* @return string
*/
protected function contactLinkGenealogy(User $user) {
return I18N::translate('For help with genealogy questions contact %s.', $this->contactLink($user));
}
/**
* Create contact link for technical support.
*
* @param User $user
*
* @return string
*/
protected function contactLinkTechnical(User $user) {
return I18N::translate('For technical support and information contact %s.', $this->contactLink($user));
}
/**
* Create contact links for the page footer.
*
* @return string
*/
protected function contactLinks() {
$contact_user = User::find($this->tree->getPreference('CONTACT_USER_ID'));
$webmaster_user = User::find($this->tree->getPreference('WEBMASTER_USER_ID'));
if ($contact_user && $contact_user === $webmaster_user) {
return $this->contactLinkEverything($contact_user);
} elseif ($contact_user && $webmaster_user) {
return $this->contactLinkGenealogy($contact_user) . ' ' . $this->contactLinkTechnical($webmaster_user);
} elseif ($contact_user) {
return $this->contactLinkGenealogy($contact_user);
} elseif ($webmaster_user) {
return $this->contactLinkTechnical($webmaster_user);
} else {
return '';
}
}
/**
* Create a cookie warning.
*
* @return string
*/
public function cookieWarning() {
if (
empty($_SERVER['HTTP_DNT']) &&
empty($_COOKIE['cookie']) &&
(Site::getPreference('GOOGLE_ANALYTICS_ID') || Site::getPreference('PIWIK_SITE_ID') || Site::getPreference('STATCOUNTER_PROJECT_ID'))
) {
return
'
' .
I18N::translate('Cookies') . ' - ' .
I18N::translate('This website uses cookies to learn about visitor behaviour.') . ' ' .
'' .
'
';
} else {
return '';
}
}
/**
* Create the tag.
*
* @return string
*/
public function doctype() {
return '';
}
/**
* HTML link to a "favorites icon".
*
* @return string
*/
protected function favicon() {
return
'' .
'' .
'';
}
/**
* Add markup to a flash message.
*
* @param \stdClass $message
*
* @return string
*/
protected function flashMessageContainer(\stdClass $message) {
return $this->htmlAlert($message->text, $message->status, true);
}
/**
* Create a container for messages that are "flashed" to the session
* on one request, and displayed on another. If there are many messages,
* the container may need a max-height and scroll-bar.
*
* @param \stdClass[] $messages
*
* @return string
*/
protected function flashMessagesContainer(array $messages) {
$html = '';
foreach ($messages as $message) {
$html .= $this->flashMessageContainer($message);
}
if ($html) {
return '
' . $html . '
';
} else {
return '';
}
}
/**
* Close the main content and create the ';
}
/**
* Close the main content.
* Note that popup windows are deprecated
*
* @return string
*/
public function footerContainerPopupWindow() {
return '';
}
/**
* Create the contents of the