diff options
| author | Greg Roach <fisharebest@webtrees.net> | 2019-01-25 14:59:31 +0000 |
|---|---|---|
| committer | Greg Roach <fisharebest@webtrees.net> | 2019-01-25 19:09:59 +0000 |
| commit | 37eb8894d5d4381f3fd9b791a53a32f0012b32ec (patch) | |
| tree | 383982de09bcf286033b61de69829608866fafeb | |
| parent | f0393844a7bf8df7dfbdb5cceafe26a558c04601 (diff) | |
| download | webtrees-37eb8894d5d4381f3fd9b791a53a32f0012b32ec.tar.gz webtrees-37eb8894d5d4381f3fd9b791a53a32f0012b32ec.tar.bz2 webtrees-37eb8894d5d4381f3fd9b791a53a32f0012b32ec.zip | |
Convert tracking and analytics functions into modules
119 files changed, 1075 insertions, 491 deletions
diff --git a/app/Http/Controllers/AbstractBaseController.php b/app/Http/Controllers/AbstractBaseController.php index 8a3e3b2ece..46a2a12e89 100644 --- a/app/Http/Controllers/AbstractBaseController.php +++ b/app/Http/Controllers/AbstractBaseController.php @@ -17,33 +17,7 @@ declare(strict_types=1); namespace Fisharebest\Webtrees\Http\Controllers; -use Fisharebest\Webtrees\Exceptions\FamilyAccessDeniedException; -use Fisharebest\Webtrees\Exceptions\FamilyNotFoundException; -use Fisharebest\Webtrees\Exceptions\IndividualAccessDeniedException; -use Fisharebest\Webtrees\Exceptions\IndividualNotFoundException; -use Fisharebest\Webtrees\Exceptions\MediaAccessDeniedException; -use Fisharebest\Webtrees\Exceptions\MediaNotFoundException; -use Fisharebest\Webtrees\Exceptions\NoteAccessDeniedException; -use Fisharebest\Webtrees\Exceptions\NoteNotFoundException; -use Fisharebest\Webtrees\Exceptions\RecordAccessDeniedException; -use Fisharebest\Webtrees\Exceptions\RecordNotFoundException; -use Fisharebest\Webtrees\Exceptions\RepositoryAccessDeniedException; -use Fisharebest\Webtrees\Exceptions\RepositoryNotFoundException; -use Fisharebest\Webtrees\Exceptions\SourceAccessDeniedException; -use Fisharebest\Webtrees\Exceptions\SourceNotFoundException; -use Fisharebest\Webtrees\Family; -use Fisharebest\Webtrees\GedcomRecord; -use Fisharebest\Webtrees\I18N; -use Fisharebest\Webtrees\Individual; -use Fisharebest\Webtrees\Media; -use Fisharebest\Webtrees\Module; -use Fisharebest\Webtrees\Module\ModuleChartInterface; -use Fisharebest\Webtrees\Note; -use Fisharebest\Webtrees\Repository; -use Fisharebest\Webtrees\Source; -use Fisharebest\Webtrees\Tree; use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; /** * Common functions for all controllers diff --git a/app/Http/Controllers/Admin/AbstractAdminController.php b/app/Http/Controllers/Admin/AbstractAdminController.php new file mode 100644 index 0000000000..013f89cf9f --- /dev/null +++ b/app/Http/Controllers/Admin/AbstractAdminController.php @@ -0,0 +1,29 @@ +<?php +/** + * webtrees: online genealogy + * Copyright (C) 2019 webtrees development team + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +declare(strict_types=1); + +namespace Fisharebest\Webtrees\Http\Controllers\Admin; + +use Fisharebest\Webtrees\Http\Controllers\AbstractBaseController; + +/** + * Common functions for admin controllers. + */ +abstract class AbstractAdminController extends AbstractBaseController +{ + /** @var string */ + protected $layout = 'layouts/administration'; +} diff --git a/app/Http/Controllers/Admin/AnalyticsController.php b/app/Http/Controllers/Admin/AnalyticsController.php new file mode 100644 index 0000000000..f60feed569 --- /dev/null +++ b/app/Http/Controllers/Admin/AnalyticsController.php @@ -0,0 +1,91 @@ +<?php +/** + * webtrees: online genealogy + * Copyright (C) 2019 webtrees development team + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +declare(strict_types=1); + +namespace Fisharebest\Webtrees\Http\Controllers\Admin; + +use Fisharebest\Webtrees\FlashMessages; +use Fisharebest\Webtrees\I18N; +use Fisharebest\Webtrees\Module; +use Fisharebest\Webtrees\Module\ModuleAnalyticsInterface; +use Illuminate\Support\Collection; +use Symfony\Component\HttpFoundation\RedirectResponse; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; + +/** + * Controller for configuring the tracking and analytics modules. + */ +class AnalyticsController extends AbstractAdminController +{ + /** + * @return Response + */ + public function list(): Response + { + /* I18N: e.g. http://www.google.com/analytics */ + $title = I18N::translate('Tracking and analytics'); + + return $this->viewResponse('admin/analytics/index', [ + 'modules' => Module::findByInterface(ModuleAnalyticsInterface::class), + 'title' => $title, + ]); + } + + /** + * @param Request $request + * + * @return Response + */ + public function edit(Request $request): Response + { + $module_name = $request->get('module'); + $module = Module::findByName($module_name); + + if ($module instanceof ModuleAnalyticsInterface) { + return $this->viewResponse('admin/analytics/edit', [ + 'module_name' => $module_name, + 'form_fields' => $module->analyticsFormFields(), + 'preview' => $module->analyticsSnippet($module->analyticsParameters()), + 'title' => $module->title(), + ]); + } + + return new RedirectResponse(route('analytics')); + } + + /** + * @param Request $request + * + * @return RedirectResponse + */ + public function save(Request $request): RedirectResponse + { + $module_name = $request->get('module', ''); + + $module = Module::findByName($module_name); + + if ($module instanceof ModuleAnalyticsInterface) { + foreach (array_keys($module->analyticsParameters()) as $setting_name) { + $module->setPreference($setting_name, $request->get($setting_name, '')); + } + + FlashMessages::addMessage(I18N::translate('The preferences for the module “%s” have been updated.', $module->title()), 'success'); + } + + return new RedirectResponse(route('analytics')); + } +} diff --git a/app/Http/Controllers/AdminSiteController.php b/app/Http/Controllers/AdminSiteController.php index ea4c72ab7c..44ab3a89bb 100644 --- a/app/Http/Controllers/AdminSiteController.php +++ b/app/Http/Controllers/AdminSiteController.php @@ -46,40 +46,6 @@ class AdminSiteController extends AbstractBaseController protected $layout = 'layouts/administration'; /** - * @return Response - */ - public function analyticsForm(): Response - { - /* I18N: e.g. http://www.google.com/analytics */ - $title = I18N::translate('Tracking and analytics'); - - return $this->viewResponse('admin/site-analytics', [ - 'title' => $title, - ]); - } - - /** - * @param Request $request - * - * @return RedirectResponse - */ - public function analyticsSave(Request $request): RedirectResponse - { - Site::setPreference('BING_WEBMASTER_ID', $request->get('BING_WEBMASTER_ID')); - Site::setPreference('GOOGLE_WEBMASTER_ID', $request->get('GOOGLE_WEBMASTER_ID')); - Site::setPreference('GOOGLE_ANALYTICS_ID', $request->get('GOOGLE_ANALYTICS_ID')); - Site::setPreference('PIWIK_URL', $request->get('PIWIK_URL')); - Site::setPreference('PIWIK_SITE_ID', $request->get('PIWIK_SITE_ID')); - Site::setPreference('STATCOUNTER_PROJECT_ID', $request->get('STATCOUNTER_PROJECT_ID')); - Site::setPreference('STATCOUNTER_SECURITY_ID', $request->get('STATCOUNTER_SECURITY_ID')); - - FlashMessages::addMessage(I18N::translate('The website preferences have been updated.'), 'success'); - $url = route('admin-control-panel'); - - return new RedirectResponse($url); - } - - /** * Show old user files in the data folder. * * @param Filesystem $filesystem diff --git a/app/Module.php b/app/Module.php index 20bcda9964..c0877ce531 100644 --- a/app/Module.php +++ b/app/Module.php @@ -18,6 +18,10 @@ declare(strict_types=1); namespace Fisharebest\Webtrees; use Closure; +use Fisharebest\Webtrees\Module\BingWebmasterToolsModule; +use Fisharebest\Webtrees\Module\GoogleAnalyticsModule; +use Fisharebest\Webtrees\Module\GoogleWebmasterToolsModule; +use Fisharebest\Webtrees\Module\MatomoAnalyticsModule; use Fisharebest\Webtrees\Module\ModuleBlockInterface; use Fisharebest\Webtrees\Module\ModuleChartInterface; use Fisharebest\Webtrees\Module\ModuleInterface; @@ -25,6 +29,7 @@ use Fisharebest\Webtrees\Module\ModuleMenuInterface; use Fisharebest\Webtrees\Module\ModuleReportInterface; use Fisharebest\Webtrees\Module\ModuleSidebarInterface; use Fisharebest\Webtrees\Module\ModuleTabInterface; +use Fisharebest\Webtrees\Module\StatcounterModule; use Illuminate\Database\Capsule\Manager as DB; use Illuminate\Support\Collection; use Illuminate\Support\Str; @@ -126,16 +131,75 @@ class Module ]; /** - * All modules. + * All core modules in the system. * - * @return Collection|ModuleInterface[] + * @return Collection */ - public static function all(): Collection + private static function coreModules(): Collection + { + // Array keys are module names, and should match module names from earlier versions of webtrees. + $modules = new Collection([ + 'bing-webmaster-tools' => BingWebmasterToolsModule::class, + 'google-analytics' => GoogleAnalyticsModule::class, + 'google-webmaster-tools' => GoogleWebmasterToolsModule::class, + 'matomo-analytics' => MatomoAnalyticsModule::class, + 'statcounter' => StatcounterModule::class, + ]); + + return $modules->map(function (string $class, string $name): ModuleInterface { + $module = app()->make($class); + + $module->setName($name); + + return $module; + }); + } + + /** + * All custom modules in the system. Custom modules are defined in modules_v4/ + * + * @return Collection + */ + private static function customModules(): Collection { $pattern = WT_ROOT . Webtrees::MODULES_PATH . '*/module.php'; $filenames = glob($pattern); - return app('cache.array')->rememberForever('all_modules', function () use ($filenames): Collection { + return (new Collection($filenames)) + ->filter(function (string $filename): bool { + // Special characters will break PHP variable names. + // This also allows us to ignore modules called "foo.example" and "foo.disable" + return !Str::contains(basename(dirname($filename)), ['.', ' ', '[', ']']); + }) + ->map(function (string $filename): ?ModuleInterface { + try { + $module = self::load($filename); + + if ($module instanceof ModuleInterface) { + $module_name = 'custom-' . basename(dirname($filename)); + + $module->setName($module_name); + } + + return $module; + } catch (Throwable $ex) { + $message = '<pre>' . e($ex->getMessage()) . "\n" . e($ex->getTraceAsString()) . '</pre>'; + FlashMessages::addMessage($message, 'danger'); + + return null; + } + }) + ->filter(); + } + + /** + * All modules. + * + * @return Collection|ModuleInterface[] + */ + public static function all(): Collection + { + return app('cache.array')->rememberForever('all_modules', function (): Collection { // Modules have a default status, order etc. // We can override these from database settings. $module_info = DB::table('module') @@ -144,49 +208,31 @@ class Module return [$row->module_name => $row]; }); - return (new Collection($filenames)) - ->filter(function (string $filename): bool { - // Module names with dots break things. - return !Str::contains(basename(dirname($filename)), '.'); - }) - ->map(function (string $filename) use ($module_info): ?ModuleInterface { - try { - $module_name = basename(dirname($filename)); - $module = self::load($filename); + return self::coreModules() + ->merge(self::customModules()) + ->map(function (ModuleInterface $module) use ($module_info): ModuleInterface { + $info = $module_info->get($module->name()); - if ($module instanceof ModuleInterface) { - $module->setName($module_name); - } - - $info = $module_info->get($module_name); - - if ($info instanceof stdClass) { - $module->setEnabled($info->status === 'enabled'); - - if ($module instanceof ModuleMenuInterface && $info->menu_order !== null) { - $module->setMenuOrder((int) $info->menu_order); - } - - if ($module instanceof ModuleSidebarInterface && $info->sidebar_order !== null) { - $module->setSidebarOrder((int) $info->sidebar_order); - } + if ($info instanceof stdClass) { + $module->setEnabled($info->status === 'enabled'); - if ($module instanceof ModuleTabInterface && $info->tab_order !== null) { - $module->setTabOrder((int) $info->tab_order); - } - } else { - DB::table('module')->insert(['module_name' => $module_name]); + if ($module instanceof ModuleMenuInterface && $info->menu_order !== null) { + $module->setMenuOrder((int) $info->menu_order); } - return $module; - } catch (Throwable $ex) { - $message = '<pre>' . e($ex->getMessage()) . "\n" . e($ex->getTraceAsString()) . '</pre>'; - FlashMessages::addMessage($message, 'danger'); + if ($module instanceof ModuleSidebarInterface && $info->sidebar_order !== null) { + $module->setSidebarOrder((int) $info->sidebar_order); + } - return null; + if ($module instanceof ModuleTabInterface && $info->tab_order !== null) { + $module->setTabOrder((int) $info->tab_order); + } + } else { + DB::table('module')->insert(['module_name' => $module->name()]); } + + return $module; }) - ->filter() ->sort(self::moduleSorter()); }); } @@ -263,7 +309,7 @@ class Module public static function findByComponent(string $component, Tree $tree, User $user): Collection { $interface = self::COMPONENTS[$component]; - + return self::findByInterface($interface) ->filter(function (ModuleInterface $module) use ($component, $tree, $user): bool { return $module->accessLevel($tree, $component) >= Auth::accessLevel($tree, $user); diff --git a/app/Module/AbstractModule.php b/app/Module/AbstractModule.php index 1a2016cc65..35b08009d9 100644 --- a/app/Module/AbstractModule.php +++ b/app/Module/AbstractModule.php @@ -117,13 +117,11 @@ abstract class AbstractModule implements ModuleInterface * * @param string $name * - * @return ModuleInterface + * @return void */ - final public function setName(string $name): ModuleInterface + final public function setName(string $name): void { $this->name = $name; - - return $this; } /** @@ -168,7 +166,7 @@ abstract class AbstractModule implements ModuleInterface * * @return string */ - final public function getPreference($setting_name, $default = ''): string + final public function getPreference(string $setting_name, string $default = ''): string { return DB::table('module_setting') ->where('module_name', '=', $this->name()) @@ -187,7 +185,7 @@ abstract class AbstractModule implements ModuleInterface * * @return $this */ - final public function setPreference($setting_name, $setting_value): self + final public function setPreference(string $setting_name, string $setting_value): void { DB::table('module_setting')->updateOrInsert([ 'module_name' => $this->name(), @@ -195,8 +193,6 @@ abstract class AbstractModule implements ModuleInterface ], [ 'setting_value' => $setting_value, ]); - - return $this; } /** diff --git a/app/Module/AhnentafelReportModule.php b/app/Module/AhnentafelReportModule.php index 3d0274210f..2e9407da6b 100644 --- a/app/Module/AhnentafelReportModule.php +++ b/app/Module/AhnentafelReportModule.php @@ -24,7 +24,7 @@ use Fisharebest\Webtrees\Menu; /** * Class AhnentafelReportModule */ -class AhnentafelReportModule extends AbstractModule implements ModuleInterface, ModuleReportInterface +class AhnentafelReportModule extends AbstractModule implements ModuleReportInterface { use ModuleReportTrait; diff --git a/app/Module/AlbumModule.php b/app/Module/AlbumModule.php index f0881c4ed3..4bdb03f068 100644 --- a/app/Module/AlbumModule.php +++ b/app/Module/AlbumModule.php @@ -25,7 +25,7 @@ use Fisharebest\Webtrees\Media; /** * Class AlbumModule */ -class AlbumModule extends AbstractModule implements ModuleInterface, ModuleTabInterface +class AlbumModule extends AbstractModule implements ModuleTabInterface { use ModuleTabTrait; diff --git a/app/Module/AncestorsChartModule.php b/app/Module/AncestorsChartModule.php index 451027226e..1304f48976 100644 --- a/app/Module/AncestorsChartModule.php +++ b/app/Module/AncestorsChartModule.php @@ -35,7 +35,7 @@ use Symfony\Component\HttpFoundation\Response; /** * Class AncestorsChartModule */ -class AncestorsChartModule extends AbstractModule implements ModuleInterface, ModuleChartInterface +class AncestorsChartModule extends AbstractModule implements ModuleChartInterface { use ModuleChartTrait; diff --git a/app/Module/BatchUpdateModule.php b/app/Module/BatchUpdateModule.php index fac4a66a66..7a5c3cf0ba 100644 --- a/app/Module/BatchUpdateModule.php +++ b/app/Module/BatchUpdateModule.php @@ -40,7 +40,7 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; /** * Class BatchUpdateModule */ -class BatchUpdateModule extends AbstractModule implements ModuleInterface, ModuleConfigInterface +class BatchUpdateModule extends AbstractModule implements ModuleConfigInterface { use ModuleConfigTrait; diff --git a/app/Module/BingWebmasterToolsModule.php b/app/Module/BingWebmasterToolsModule.php new file mode 100644 index 0000000000..0067b9e3ec --- /dev/null +++ b/app/Module/BingWebmasterToolsModule.php @@ -0,0 +1,79 @@ +<?php +/** + * webtrees: online genealogy + * Copyright (C) 2019 webtrees development team + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +declare(strict_types=1); + +namespace Fisharebest\Webtrees\Module; + +/** + * Class BingWebmasterToolsModule - add support for Bing webmaster tools + */ +class BingWebmasterToolsModule extends AbstractModule implements ModuleAnalyticsInterface +{ + use ModuleAnalyticsTrait; + + /** + * How should this module be labelled on tabs, menus, etc.? + * + * @return string + */ + public function title(): string { + return 'Bing™ webmaster tools'; + } + + /** + * Form fields to edit the parameters. + * + * @return string + */ + public function analyticsFormFields(): string + { + return view('admin/analytics/bing-webmaster-form', $this->analyticsParameters()); + } + + /** + * Home page for the service. + * + * @return string + */ + public function analyticsHomePageUrl(): string + { + return 'https://www.bing.com/toolbox/webmaster'; + } + + /** + * The parameters that need to be embedded in the snippet. + * + * @return string[] + */ + public function analyticsParameters(): array + { + return [ + 'BING_WEBMASTER_ID' => $this->getPreference('BING_WEBMASTER_ID') + ]; + } + + /** + * Embed placeholders in the snippet. + * + * @param string[] $parameters + * + * @return string + */ + public function analyticsSnippet(array $parameters): string + { + return view('admin/analytics/bing-webmaster-snippet', $parameters); + } +} diff --git a/app/Module/BirthDeathMarriageReportModule.php b/app/Module/BirthDeathMarriageReportModule.php index a0b559073b..3826d4b53f 100644 --- a/app/Module/BirthDeathMarriageReportModule.php +++ b/app/Module/BirthDeathMarriageReportModule.php @@ -24,7 +24,7 @@ use Fisharebest\Webtrees\Menu; /** * Class BirthDeathMarriageReportModule */ -class BirthDeathMarriageReportModule extends AbstractModule implements ModuleInterface, ModuleReportInterface +class BirthDeathMarriageReportModule extends AbstractModule implements ModuleReportInterface { use ModuleReportTrait; diff --git a/app/Module/BirthReportModule.php b/app/Module/BirthReportModule.php index 5eaf0f39da..c584be8c01 100644 --- a/app/Module/BirthReportModule.php +++ b/app/Module/BirthReportModule.php @@ -24,7 +24,7 @@ use Fisharebest\Webtrees\Menu; /** * Class BirthReportModule */ -class BirthReportModule extends AbstractModule implements ModuleInterface, ModuleReportInterface +class BirthReportModule extends AbstractModule implements ModuleReportInterface { use ModuleReportTrait; diff --git a/app/Module/CalendarMenuModule.php b/app/Module/CalendarMenuModule.php index c5ef709ea5..da2f070f65 100644 --- a/app/Module/CalendarMenuModule.php +++ b/app/Module/CalendarMenuModule.php @@ -24,7 +24,7 @@ use Fisharebest\Webtrees\Tree; /** * Class CalendarMenuModule - provide a menu option for the calendar */ -class CalendarMenuModule extends AbstractModule implements ModuleInterface, ModuleMenuInterface +class CalendarMenuModule extends AbstractModule implements ModuleMenuInterface { use ModuleMenuTrait; diff --git a/app/Module/CemeteryReportModule.php b/app/Module/CemeteryReportModule.php index 172088b60a..7e9f5bd11e 100644 --- a/app/Module/CemeteryReportModule.php +++ b/app/Module/CemeteryReportModule.php @@ -24,7 +24,7 @@ use Fisharebest\Webtrees\Menu; /** * Class CemeteryReportModule */ -class CemeteryReportModule extends AbstractModule implements ModuleInterface, ModuleReportInterface +class CemeteryReportModule extends AbstractModule implements ModuleReportInterface { use ModuleReportTrait; diff --git a/app/Module/ChangeReportModule.php b/app/Module/ChangeReportModule.php index 9f61978707..1c506a2a5d 100644 --- a/app/Module/ChangeReportModule.php +++ b/app/Module/ChangeReportModule.php @@ -25,7 +25,7 @@ use Fisharebest\Webtrees\Menu; /** * Class ChangeReportModule */ -class ChangeReportModule extends AbstractModule implements ModuleInterface, ModuleReportInterface +class ChangeReportModule extends AbstractModule implements ModuleReportInterface { use ModuleReportTrait; diff --git a/app/Module/ChartsBlockModule.php b/app/Module/ChartsBlockModule.php index e28c4c482c..cd076423c1 100644 --- a/app/Module/ChartsBlockModule.php +++ b/app/Module/ChartsBlockModule.php @@ -28,7 +28,7 @@ use Symfony\Component\HttpFoundation\Request; /** * Class ChartsBlockModule */ -class ChartsBlockModule extends AbstractModule implements ModuleInterface, ModuleBlockInterface +class ChartsBlockModule extends AbstractModule implements ModuleBlockInterface { use ModuleBlockTrait; diff --git a/app/Module/ChartsMenuModule.php b/app/Module/ChartsMenuModule.php index a6d459b5e1..a20a67e568 100644 --- a/app/Module/ChartsMenuModule.php +++ b/app/Module/ChartsMenuModule.php @@ -28,7 +28,7 @@ use Symfony\Component\HttpFoundation\Request; /** * Class ChartsMenuModule - provide a menu option for the charts */ -class ChartsMenuModule extends AbstractModule implements ModuleInterface, ModuleMenuInterface +class ChartsMenuModule extends AbstractModule implements ModuleMenuInterface { use ModuleMenuTrait; diff --git a/app/Module/ClippingsCartModule.php b/app/Module/ClippingsCartModule.php index b35b4438a2..0fd035411d 100644 --- a/app/Module/ClippingsCartModule.php +++ b/app/Module/ClippingsCartModule.php @@ -50,7 +50,7 @@ use Symfony\Component\HttpFoundation\ResponseHeaderBag; /** * Class ClippingsCartModule */ -class ClippingsCartModule extends AbstractModule implements ModuleInterface, ModuleMenuInterface +class ClippingsCartModule extends AbstractModule implements ModuleMenuInterface { use ModuleMenuTrait; diff --git a/app/Module/CompactTreeChartModule.php b/app/Module/CompactTreeChartModule.php index 8bd7138d61..9e6d550890 100644 --- a/app/Module/CompactTreeChartModule.php +++ b/app/Module/CompactTreeChartModule.php @@ -29,7 +29,7 @@ use Symfony\Component\HttpFoundation\Response; /** * Class CompactTreeChartModule */ -class CompactTreeChartModule extends AbstractModule implements ModuleInterface, ModuleChartInterface +class CompactTreeChartModule extends AbstractModule implements ModuleChartInterface { use ModuleChartTrait; diff --git a/app/Module/DeathReportModule.php b/app/Module/DeathReportModule.php index 7c92e48f74..9d656df191 100644 --- a/app/Module/DeathReportModule.php +++ b/app/Module/DeathReportModule.php @@ -24,7 +24,7 @@ use Fisharebest\Webtrees\Menu; /** * Class DeathReportModule */ -class DeathReportModule extends AbstractModule implements ModuleInterface, ModuleReportInterface +class DeathReportModule extends AbstractModule implements ModuleReportInterface { use ModuleReportTrait; diff --git a/app/Module/DescendancyChartModule.php b/app/Module/DescendancyChartModule.php index e0dd6ff876..9ac313723f 100644 --- a/app/Module/DescendancyChartModule.php +++ b/app/Module/DescendancyChartModule.php @@ -38,7 +38,7 @@ use Symfony\Component\HttpFoundation\Response; /** * Class DescendancyChartModule */ -class DescendancyChartModule extends AbstractModule implements ModuleInterface, ModuleChartInterface +class DescendancyChartModule extends AbstractModule implements ModuleChartInterface { use ModuleChartTrait; diff --git a/app/Module/DescendancyModule.php b/app/Module/DescendancyModule.php index c7754608ac..1b12e1fd37 100644 --- a/app/Module/DescendancyModule.php +++ b/app/Module/DescendancyModule.php @@ -29,7 +29,7 @@ use Symfony\Component\HttpFoundation\Response; /** * Class DescendancyModule */ -class DescendancyModule extends AbstractModule implements ModuleInterface, ModuleSidebarInterface +class DescendancyModule extends AbstractModule implements ModuleSidebarInterface { use ModuleSidebarTrait; diff --git a/app/Module/DescendancyReportModule.php b/app/Module/DescendancyReportModule.php index b02bca6ed1..e386e04cf6 100644 --- a/app/Module/DescendancyReportModule.php +++ b/app/Module/DescendancyReportModule.php @@ -24,7 +24,7 @@ use Fisharebest\Webtrees\Menu; /** * Class DescendancyReportModule */ -class DescendancyReportModule extends AbstractModule implements ModuleInterface, ModuleReportInterface +class DescendancyReportModule extends AbstractModule implements ModuleReportInterface { use ModuleReportTrait; diff --git a/app/Module/ExtraInformationModule.php b/app/Module/ExtraInformationModule.php index 1dce10c6c4..110fc46c84 100644 --- a/app/Module/ExtraInformationModule.php +++ b/app/Module/ExtraInformationModule.php @@ -26,7 +26,7 @@ use Fisharebest\Webtrees\Individual; * Class ExtraInformationModule * A sidebar to show non-genealogy information about an individual */ -class ExtraInformationModule extends AbstractModule implements ModuleInterface, ModuleSidebarInterface +class ExtraInformationModule extends AbstractModule implements ModuleSidebarInterface { use ModuleSidebarTrait; diff --git a/app/Module/FactSourcesReportModule.php b/app/Module/FactSourcesReportModule.php index 699855b8f2..9b43b2b1b9 100644 --- a/app/Module/FactSourcesReportModule.php +++ b/app/Module/FactSourcesReportModule.php @@ -25,7 +25,7 @@ use Fisharebest\Webtrees\Menu; /** * Class FactSourcesReportModule */ -class FactSourcesReportModule extends AbstractModule implements ModuleInterface, ModuleReportInterface +class FactSourcesReportModule extends AbstractModule implements ModuleReportInterface { use ModuleReportTrait; diff --git a/app/Module/FamilyBookChartModule.php b/app/Module/FamilyBookChartModule.php index 073adf323e..4a9e73eaee 100644 --- a/app/Module/FamilyBookChartModule.php +++ b/app/Module/FamilyBookChartModule.php @@ -31,7 +31,7 @@ use Symfony\Component\HttpFoundation\Response; /** * Class FamilyBookChartModule */ -class FamilyBookChartModule extends AbstractModule implements ModuleInterface, ModuleChartInterface +class FamilyBookChartModule extends AbstractModule implements ModuleChartInterface { use ModuleChartTrait; diff --git a/app/Module/FamilyGroupReportModule.php b/app/Module/FamilyGroupReportModule.php index 6149d8fa84..962502abc8 100644 --- a/app/Module/FamilyGroupReportModule.php +++ b/app/Module/FamilyGroupReportModule.php @@ -24,7 +24,7 @@ use Fisharebest\Webtrees\Menu; /** * Class FamilyGroupReportModule */ -class FamilyGroupReportModule extends AbstractModule implements ModuleInterface, ModuleReportInterface +class FamilyGroupReportModule extends AbstractModule implements ModuleReportInterface { use ModuleReportTrait; diff --git a/app/Module/FamilyNavigatorModule.php b/app/Module/FamilyNavigatorModule.php index 2ac182fb1d..b691539462 100644 --- a/app/Module/FamilyNavigatorModule.php +++ b/app/Module/FamilyNavigatorModule.php @@ -23,7 +23,7 @@ use Fisharebest\Webtrees\Individual; /** * Class FamilyNavigatorModule */ -class FamilyNavigatorModule extends AbstractModule implements ModuleInterface, ModuleSidebarInterface +class FamilyNavigatorModule extends AbstractModule implements ModuleSidebarInterface { use ModuleSidebarTrait; diff --git a/app/Module/FamilyTreeFavoritesModule.php b/app/Module/FamilyTreeFavoritesModule.php index 53404c8455..5138178311 100644 --- a/app/Module/FamilyTreeFavoritesModule.php +++ b/app/Module/FamilyTreeFavoritesModule.php @@ -30,7 +30,7 @@ use Symfony\Component\HttpFoundation\Request; /** * Class FamilyTreeFavoritesModule */ -class FamilyTreeFavoritesModule extends AbstractModule implements ModuleInterface, ModuleBlockInterface +class FamilyTreeFavoritesModule extends AbstractModule implements ModuleBlockInterface { use ModuleBlockTrait; diff --git a/app/Module/FamilyTreeNewsModule.php b/app/Module/FamilyTreeNewsModule.php index 8e610a833e..396d9c79a0 100644 --- a/app/Module/FamilyTreeNewsModule.php +++ b/app/Module/FamilyTreeNewsModule.php @@ -29,7 +29,7 @@ use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; /** * Class FamilyTreeNewsModule */ -class FamilyTreeNewsModule extends AbstractModule implements ModuleInterface, ModuleBlockInterface +class FamilyTreeNewsModule extends AbstractModule implements ModuleBlockInterface { use ModuleBlockTrait; diff --git a/app/Module/FamilyTreeStatisticsModule.php b/app/Module/FamilyTreeStatisticsModule.php index 61bef1b007..d5053bd319 100644 --- a/app/Module/FamilyTreeStatisticsModule.php +++ b/app/Module/FamilyTreeStatisticsModule.php @@ -28,7 +28,7 @@ use Symfony\Component\HttpFoundation\Request; /** * Class FamilyTreeStatisticsModule */ -class FamilyTreeStatisticsModule extends AbstractModule implements ModuleInterface, ModuleBlockInterface +class FamilyTreeStatisticsModule extends AbstractModule implements ModuleBlockInterface { use ModuleBlockTrait; diff --git a/app/Module/FanChartModule.php b/app/Module/FanChartModule.php index a5fc062cee..7e377b0c44 100644 --- a/app/Module/FanChartModule.php +++ b/app/Module/FanChartModule.php @@ -30,7 +30,7 @@ use Symfony\Component\HttpFoundation\Response; /** * Class FanChartModule */ -class FanChartModule extends AbstractModule implements ModuleInterface, ModuleChartInterface +class FanChartModule extends AbstractModule implements ModuleChartInterface { use ModuleChartTrait; diff --git a/app/Module/FrequentlyAskedQuestionsModule.php b/app/Module/FrequentlyAskedQuestionsModule.php index 0b5240c35f..e67a47194b 100644 --- a/app/Module/FrequentlyAskedQuestionsModule.php +++ b/app/Module/FrequentlyAskedQuestionsModule.php @@ -31,7 +31,7 @@ use Symfony\Component\HttpFoundation\Response; /** * Class FrequentlyAskedQuestionsModule */ -class FrequentlyAskedQuestionsModule extends AbstractModule implements ModuleInterface, ModuleConfigInterface, ModuleMenuInterface +class FrequentlyAskedQuestionsModule extends AbstractModule implements ModuleConfigInterface, ModuleMenuInterface { use ModuleConfigTrait; use ModuleMenuTrait; diff --git a/app/Module/GoogleAnalyticsModule.php b/app/Module/GoogleAnalyticsModule.php new file mode 100644 index 0000000000..3fd7afb0d3 --- /dev/null +++ b/app/Module/GoogleAnalyticsModule.php @@ -0,0 +1,92 @@ +<?php +/** + * webtrees: online genealogy + * Copyright (C) 2019 webtrees development team + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +declare(strict_types=1); + +namespace Fisharebest\Webtrees\Module; + +use Fisharebest\Webtrees\Auth; +use Fisharebest\Webtrees\Tree; +use Fisharebest\Webtrees\User; + +/** + * Class GoogleAnalyticsModule - add support for Google analytics. + */ +class GoogleAnalyticsModule extends AbstractModule implements ModuleAnalyticsInterface +{ + use ModuleAnalyticsTrait; + + /** + * How should this module be labelled on tabs, menus, etc.? + * + * @return string + */ + public function title(): string { + return 'Google™ analytics'; + } + + /** + * Form fields to edit the parameters. + * + * @return string + */ + public function analyticsFormFields(): string + { + return view('admin/analytics/google-analytics-form', $this->analyticsParameters()); + } + + /** + * Home page for the service. + * + * @return string + */ + public function analyticsHomePageUrl(): string + { + return 'https://www.google.com/analytics'; + } + + /** + * The parameters that need to be embedded in the snippet. + * + * @return string[] + */ + public function analyticsParameters(): array + { + return [ + 'GOOGLE_WEBMASTER_ID' => $this->getPreference('GOOGLE_WEBMASTER_ID') + ]; + } + + /** + * Embed placeholders in the snippet. + * + * @param string[] $parameters + * + * @return string + */ + public function analyticsSnippet(array $parameters): string + { + // Add extra dimensions (i.e. filtering categories) + $tree = app()->make(Tree::class); + $user = app()->make(User::class); + + $parameters['dimensions'] = (object) [ + 'dimension1' => $tree instanceof Tree ? $tree->name() : '-', + 'dimension2' => $tree instanceof Tree ? Auth::accessLevel($tree, $user) : '-', + ]; + + return view('admin/analytics/google-analytics-snippet', $parameters); + } +} diff --git a/app/Module/GoogleWebmasterToolsModule.php b/app/Module/GoogleWebmasterToolsModule.php new file mode 100644 index 0000000000..5ab78db990 --- /dev/null +++ b/app/Module/GoogleWebmasterToolsModule.php @@ -0,0 +1,79 @@ +<?php +/** + * webtrees: online genealogy + * Copyright (C) 2019 webtrees development team + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +declare(strict_types=1); + +namespace Fisharebest\Webtrees\Module; + +/** + * Class GoogleWebmasterToolsModule - add support for Google webmaster tools. + */ +class GoogleWebmasterToolsModule extends AbstractModule implements ModuleAnalyticsInterface +{ + use ModuleAnalyticsTrait; + + /** + * How should this module be labelled on tabs, menus, etc.? + * + * @return string + */ + public function title(): string { + return 'Google™ webmaster tools'; + } + + /** + * Form fields to edit the parameters. + * + * @return string + */ + public function analyticsFormFields(): string + { + return view('admin/analytics/google-webmaster-form', $this->analyticsParameters()); + } + + /** + * Home page for the service. + * + * @return string + */ + public function analyticsHomePageUrl(): string + { + return 'https://www.google.com/webmasters'; + } + + /** + * The parameters that need to be embedded in the snippet. + * + * @return string[] + */ + public function analyticsParameters(): array + { + return [ + 'GOOGLE_WEBMASTER_ID' => $this->getPreference('GOOGLE_WEBMASTER_ID') + ]; + } + + /** + * Embed placeholders in the snippet. + * + * @param string[] $parameters + * + * @return string + */ + public function analyticsSnippet(array $parameters): string + { + return view('admin/analytics/google-webmaster-snippet', $parameters); + } +} diff --git a/app/Module/HourglassChartModule.php b/app/Module/HourglassChartModule.php index 7f2ccb4f76..153b6a12e2 100644 --- a/app/Module/HourglassChartModule.php +++ b/app/Module/HourglassChartModule.php @@ -31,7 +31,7 @@ use Symfony\Component\HttpFoundation\Response; /** * Class HourglassChartModule */ -class HourglassChartModule extends AbstractModule implements ModuleInterface, ModuleChartInterface +class HourglassChartModule extends AbstractModule implements ModuleChartInterface { use ModuleChartTrait; diff --git a/app/Module/HtmlBlockModule.php b/app/Module/HtmlBlockModule.php index 3ff4c727a2..6ce1e8fecb 100644 --- a/app/Module/HtmlBlockModule.php +++ b/app/Module/HtmlBlockModule.php @@ -27,7 +27,7 @@ use Symfony\Component\HttpFoundation\Request; /** * Class HtmlBlockModule */ -class HtmlBlockModule extends AbstractModule implements ModuleInterface, ModuleBlockInterface +class HtmlBlockModule extends AbstractModule implements ModuleBlockInterface { use ModuleBlockTrait; diff --git a/app/Module/IndividualFactsTabModule.php b/app/Module/IndividualFactsTabModule.php index 74ab353f50..a5a9b66a34 100644 --- a/app/Module/IndividualFactsTabModule.php +++ b/app/Module/IndividualFactsTabModule.php @@ -31,7 +31,7 @@ use Fisharebest\Webtrees\Site; /** * Class IndividualFactsTabModule */ -class IndividualFactsTabModule extends AbstractModule implements ModuleInterface, ModuleTabInterface +class IndividualFactsTabModule extends AbstractModule implements ModuleTabInterface { use ModuleTabTrait; diff --git a/app/Module/IndividualFamiliesReportModule.php b/app/Module/IndividualFamiliesReportModule.php index 21dfb36bf9..693fff1f9e 100644 --- a/app/Module/IndividualFamiliesReportModule.php +++ b/app/Module/IndividualFamiliesReportModule.php @@ -25,7 +25,7 @@ use Fisharebest\Webtrees\Menu; /** * Class IndividualFamiliesReportModule */ -class IndividualFamiliesReportModule extends AbstractModule implements ModuleInterface, ModuleReportInterface +class IndividualFamiliesReportModule extends AbstractModule implements ModuleReportInterface { use ModuleReportTrait; diff --git a/app/Module/IndividualReportModule.php b/app/Module/IndividualReportModule.php index 1b116a73d4..5558658658 100644 --- a/app/Module/IndividualReportModule.php +++ b/app/Module/IndividualReportModule.php @@ -24,7 +24,7 @@ use Fisharebest\Webtrees\Menu; /** * Class IndividualReportModule */ -class IndividualReportModule extends AbstractModule implements ModuleInterface, ModuleReportInterface +class IndividualReportModule extends AbstractModule implements ModuleReportInterface { use ModuleReportTrait; diff --git a/app/Module/InteractiveTreeModule.php b/app/Module/InteractiveTreeModule.php index 4125810478..8622f51139 100644 --- a/app/Module/InteractiveTreeModule.php +++ b/app/Module/InteractiveTreeModule.php @@ -34,7 +34,7 @@ use Symfony\Component\HttpFoundation\Response; * Class InteractiveTreeModule * Tip : you could change the number of generations loaded before ajax calls both in individual page and in treeview page to optimize speed and server load */ -class InteractiveTreeModule extends AbstractModule implements ModuleInterface, ModuleChartInterface, ModuleTabInterface +class InteractiveTreeModule extends AbstractModule implements ModuleChartInterface, ModuleTabInterface { use ModuleChartTrait; use ModuleTabTrait; diff --git a/app/Module/LifespansChartModule.php b/app/Module/LifespansChartModule.php index 114777e3c1..978118ca95 100644 --- a/app/Module/LifespansChartModule.php +++ b/app/Module/LifespansChartModule.php @@ -33,7 +33,7 @@ use Symfony\Component\HttpFoundation\Response; /** * Class LifespansChartModule */ -class LifespansChartModule extends AbstractModule implements ModuleInterface, ModuleChartInterface +class LifespansChartModule extends AbstractModule implements ModuleChartInterface { use ModuleChartTrait; diff --git a/app/Module/ListsMenuModule.php b/app/Module/ListsMenuModule.php index cb65f1a278..4e0a9ceacd 100644 --- a/app/Module/ListsMenuModule.php +++ b/app/Module/ListsMenuModule.php @@ -25,7 +25,7 @@ use Illuminate\Database\Capsule\Manager as DB; /** * Class ListsMenuModule - provide a menu option for the lists */ -class ListsMenuModule extends AbstractModule implements ModuleInterface, ModuleMenuInterface +class ListsMenuModule extends AbstractModule implements ModuleMenuInterface { use ModuleMenuTrait; diff --git a/app/Module/LoggedInUsersModule.php b/app/Module/LoggedInUsersModule.php index c0b6c6938f..37a665f83a 100644 --- a/app/Module/LoggedInUsersModule.php +++ b/app/Module/LoggedInUsersModule.php @@ -27,7 +27,7 @@ use Symfony\Component\HttpFoundation\Request; /** * Class LoggedInUsersModule */ -class LoggedInUsersModule extends AbstractModule implements ModuleInterface, ModuleBlockInterface +class LoggedInUsersModule extends AbstractModule implements ModuleBlockInterface { use ModuleBlockTrait; diff --git a/app/Module/LoginBlockModule.php b/app/Module/LoginBlockModule.php index 2ead102e5a..3f1859a275 100644 --- a/app/Module/LoginBlockModule.php +++ b/app/Module/LoginBlockModule.php @@ -26,7 +26,7 @@ use Symfony\Component\HttpFoundation\Request; /** * Class LoginBlockModule */ -class LoginBlockModule extends AbstractModule implements ModuleInterface, ModuleBlockInterface +class LoginBlockModule extends AbstractModule implements ModuleBlockInterface { use ModuleBlockTrait; diff --git a/app/Module/MarriageReportModule.php b/app/Module/MarriageReportModule.php index 9b55f41f20..3f8e9e3a18 100644 --- a/app/Module/MarriageReportModule.php +++ b/app/Module/MarriageReportModule.php @@ -24,7 +24,7 @@ use Fisharebest\Webtrees\Menu; /** * Class MarriageReportModule */ -class MarriageReportModule extends AbstractModule implements ModuleInterface, ModuleReportInterface +class MarriageReportModule extends AbstractModule implements ModuleReportInterface { use ModuleReportTrait; diff --git a/app/Module/MatomoAnalyticsModule.php b/app/Module/MatomoAnalyticsModule.php new file mode 100644 index 0000000000..57dd7d0b52 --- /dev/null +++ b/app/Module/MatomoAnalyticsModule.php @@ -0,0 +1,80 @@ +<?php +/** + * webtrees: online genealogy + * Copyright (C) 2019 webtrees development team + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +declare(strict_types=1); + +namespace Fisharebest\Webtrees\Module; + +/** + * Class MatomoAnalyticsModule - add support for Matomo analytics. + */ +class MatomoAnalyticsModule extends AbstractModule implements ModuleAnalyticsInterface +{ + use ModuleAnalyticsTrait; + + /** + * How should this module be labelled on tabs, menus, etc.? + * + * @return string + */ + public function title(): string + { + return 'Matomo™ / Piwik™ analytics'; + } + + /** + * Form fields to edit the parameters. + * + * @return string + */ + public function analyticsFormFields(): string + { + return view('admin/analytics/matomo-analytics-form', $this->analyticsParameters()); + } + + /** + * Home page for the service. + * + * @return string + */ + public function analyticsHomePageUrl(): string + { + return 'https://matomo.org'; + } + + /** + * The parameters that need to be embedded in the snippet. + * + * @return string[] + */ + public function analyticsParameters(): array + { + return [ + 'MATOMO_WEBMASTER_ID' => $this->getPreference('MATOMO_WEBMASTER_ID'), + ]; + } + + /** + * Embed placeholders in the snippet. + * + * @param string[] $parameters + * + * @return string + */ + public function analyticsSnippet(array $parameters): string + { + return view('admin/analytics/matomo-analytics-snippet', $parameters); + } +} diff --git a/app/Module/MediaTabModule.php b/app/Module/MediaTabModule.php index f86aaf6f00..28173e715d 100644 --- a/app/Module/MediaTabModule.php +++ b/app/Module/MediaTabModule.php @@ -26,7 +26,7 @@ use Fisharebest\Webtrees\Individual; /** * Class MediaTabModule */ -class MediaTabModule extends AbstractModule implements ModuleInterface, ModuleTabInterface +class MediaTabModule extends AbstractModule implements ModuleTabInterface { use ModuleTabTrait; diff --git a/app/Module/MissingFactsReportModule.php b/app/Module/MissingFactsReportModule.php index b70c3be6a8..cd608bd75f 100644 --- a/app/Module/MissingFactsReportModule.php +++ b/app/Module/MissingFactsReportModule.php @@ -25,7 +25,7 @@ use Fisharebest\Webtrees\Menu; /** * Class MissingFactsReportModule */ -class MissingFactsReportModule extends AbstractModule implements ModuleInterface, ModuleReportInterface +class MissingFactsReportModule extends AbstractModule implements ModuleReportInterface { use ModuleReportTrait; diff --git a/app/Module/ModuleAnalyticsInterface.php b/app/Module/ModuleAnalyticsInterface.php new file mode 100644 index 0000000000..dbd16cb11b --- /dev/null +++ b/app/Module/ModuleAnalyticsInterface.php @@ -0,0 +1,63 @@ +<?php +/** + * webtrees: online genealogy + * Copyright (C) 2019 webtrees development team + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +declare(strict_types=1); + +namespace Fisharebest\Webtrees\Module; + +use Symfony\Component\HttpFoundation\Request; + +/** + * Interface ModuleAnalyticsInterface - Classes and libraries for module system + */ +interface ModuleAnalyticsInterface extends ModuleInterface +{ + /** + * Should we add this tracker? + * + * @return bool + */ + public function analyticsCanShow(): bool; + + /** + * Form fields to edit the parameters. + * + * @return string + */ + public function analyticsFormFields(): string; + + /** + * Home page for the service. + * + * @return string + */ + public function analyticsHomePageUrl(): string; + + /** + * The parameters that need to be embedded in the snippet. + * + * @return string[] + */ + public function analyticsParameters(): array; + + /** + * Embed placeholders in the snippet. + * + * @param string[] $parameters + * + * @return string + */ + public function analyticsSnippet(array $parameters): string; +} diff --git a/app/Module/ModuleAnalyticsTrait.php b/app/Module/ModuleAnalyticsTrait.php new file mode 100644 index 0000000000..d10afae301 --- /dev/null +++ b/app/Module/ModuleAnalyticsTrait.php @@ -0,0 +1,95 @@ +<?php +/** + * webtrees: online genealogy + * Copyright (C) 2019 webtrees development team + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +declare(strict_types=1); + +namespace Fisharebest\Webtrees\Module; + +use Fisharebest\Webtrees\I18N; +use Illuminate\Support\Collection; + +/** + * Trait ModuleAnalyticsTrait - default implementation of ModuleAnalyticsInterface + */ +trait ModuleAnalyticsTrait +{ + /** + * Should we add this tracker? + * + * @return bool + */ + public function analyticsCanShow(): bool + { + foreach ($this->analyticsParameters() as $parameter) { + if ($parameter === '') { + return false; + } + } + + return true; + } + + /** + * A sentence describing what this module does. + * + * @return string + */ + public function description(): string + { + return I18N::translate('Tracking and analytics'); + } + + /** + * Form fields to edit the parameters. + * + * @return string + */ + public function analyticsFormFields(): string + { + return ''; + } + + /** + * Home page for the service. + * + * @return string + */ + public function analyticsHomePageURL(): string + { + return ''; + } + + /** + * The parameters that need to be embedded in the snippet. + * + * @return string[] + */ + public function analyticsParameters(): array + { + return []; + } + + /** + * Embed placeholders in the snippet. + * + * @param string[] $parameters + * + * @return string + */ + public function analyticsSnippet(array $parameters): string + { + return ''; + } +} diff --git a/app/Module/ModuleBlockInterface.php b/app/Module/ModuleBlockInterface.php index 773264ca18..73ccce4588 100644 --- a/app/Module/ModuleBlockInterface.php +++ b/app/Module/ModuleBlockInterface.php @@ -23,7 +23,7 @@ use Symfony\Component\HttpFoundation\Request; /** * Interface ModuleBlockInterface - Classes and libraries for module system */ -interface ModuleBlockInterface +interface ModuleBlockInterface extends ModuleInterface { /** * Generate the HTML content of this block. diff --git a/app/Module/ModuleChartInterface.php b/app/Module/ModuleChartInterface.php index 4b8352fd06..4caec641f6 100644 --- a/app/Module/ModuleChartInterface.php +++ b/app/Module/ModuleChartInterface.php @@ -23,7 +23,7 @@ use Fisharebest\Webtrees\Menu; /** * Interface ModuleChartInterface - Classes and libraries for module system */ -interface ModuleChartInterface +interface ModuleChartInterface extends ModuleInterface { /** * A menu item for this chart for an individual box in a chart. diff --git a/app/Module/ModuleChartTrait.php b/app/Module/ModuleChartTrait.php index 949e7a1f14..43312f0ff9 100644 --- a/app/Module/ModuleChartTrait.php +++ b/app/Module/ModuleChartTrait.php @@ -26,11 +26,6 @@ use Fisharebest\Webtrees\Menu; trait ModuleChartTrait { /** - * @return string - */ - abstract public function name(): string; - - /** * A menu item for this chart for an individual box in a chart. * * @param Individual $individual diff --git a/app/Module/ModuleConfigInterface.php b/app/Module/ModuleConfigInterface.php index d252ae3b1c..c02512a7b0 100644 --- a/app/Module/ModuleConfigInterface.php +++ b/app/Module/ModuleConfigInterface.php @@ -20,7 +20,7 @@ namespace Fisharebest\Webtrees\Module; /** * Interface ModuleConfigInterface - Classes and libraries for module system */ -interface ModuleConfigInterface +interface ModuleConfigInterface extends ModuleInterface { /** * The URL to a page where the user can modify the configuration of this module. diff --git a/app/Module/ModuleConfigTrait.php b/app/Module/ModuleConfigTrait.php index fa04af13f1..108aac42c7 100644 --- a/app/Module/ModuleConfigTrait.php +++ b/app/Module/ModuleConfigTrait.php @@ -23,11 +23,6 @@ namespace Fisharebest\Webtrees\Module; trait ModuleConfigTrait { /** - * @return string - */ - abstract public function name(): string; - - /** * The URL to a page where the user can modify the configuration of this module. * * @return string diff --git a/app/Module/ModuleCustomInterface.php b/app/Module/ModuleCustomInterface.php index dbfa4a1c8d..7129ca3b63 100644 --- a/app/Module/ModuleCustomInterface.php +++ b/app/Module/ModuleCustomInterface.php @@ -20,7 +20,7 @@ namespace Fisharebest\Webtrees\Module; /** * Interface ModuleCustomInterface - Classes and libraries for module system */ -interface ModuleCustomInterface +interface ModuleCustomInterface extends ModuleInterface { /** * The person or organisation who created this module. diff --git a/app/Module/ModuleInterface.php b/app/Module/ModuleInterface.php index 64856b02cb..0fafe6d184 100644 --- a/app/Module/ModuleInterface.php +++ b/app/Module/ModuleInterface.php @@ -29,9 +29,9 @@ interface ModuleInterface * * @param string $name * - * @return self + * @return void */ - public function setName(string $name): self; + public function setName(string $name): void; /** * A unique internal name for this module (based on the installation folder). @@ -79,4 +79,27 @@ interface ModuleInterface * @return int */ public function accessLevel(Tree $tree, string $component): int; + + /** + * Get a module setting. Return a default if the setting is not set. + * + * @param string $setting_name + * @param string $default + * + * @return string + */ + public function getPreference(string $setting_name, string $default = ''): string; + + /** + * Set a module setting. + * + * Since module settings are NOT NULL, setting a value to NULL will cause + * it to be deleted. + * + * @param string $setting_name + * @param string $setting_value + * + * @return $this + */ + public function setPreference(string $setting_name, string $setting_value): void; } diff --git a/app/Module/ModuleMenuInterface.php b/app/Module/ModuleMenuInterface.php index 6e01da1f7d..03f21e461a 100644 --- a/app/Module/ModuleMenuInterface.php +++ b/app/Module/ModuleMenuInterface.php @@ -23,7 +23,7 @@ use Fisharebest\Webtrees\Tree; /** * Interface ModuleMenuInterface - Classes and libraries for module system */ -interface ModuleMenuInterface +interface ModuleMenuInterface extends ModuleInterface { /** * Users change change the order of menus using the control panel. diff --git a/app/Module/ModuleReportInterface.php b/app/Module/ModuleReportInterface.php index 1aa3fd7563..e5a9910780 100644 --- a/app/Module/ModuleReportInterface.php +++ b/app/Module/ModuleReportInterface.php @@ -23,7 +23,7 @@ use Fisharebest\Webtrees\Menu; /** * Interface ModuleReportInterface - Classes and libraries for module system */ -interface ModuleReportInterface +interface ModuleReportInterface extends ModuleInterface { /** * Return a menu item for this report. diff --git a/app/Module/ModuleSidebarInterface.php b/app/Module/ModuleSidebarInterface.php index f28ce02717..91c8528b97 100644 --- a/app/Module/ModuleSidebarInterface.php +++ b/app/Module/ModuleSidebarInterface.php @@ -22,7 +22,7 @@ use Fisharebest\Webtrees\Individual; /** * Interface ModuleSidebarInterface - Classes and libraries for module system */ -interface ModuleSidebarInterface +interface ModuleSidebarInterface extends ModuleInterface { /** * Users change change the order of sidebars using the control panel. diff --git a/app/Module/ModuleTabInterface.php b/app/Module/ModuleTabInterface.php index f9b67d5d72..3f92e6a503 100644 --- a/app/Module/ModuleTabInterface.php +++ b/app/Module/ModuleTabInterface.php @@ -22,7 +22,7 @@ use Fisharebest\Webtrees\Individual; /** * Interface ModuleTabInterface - Classes and libraries for module system */ -interface ModuleTabInterface +interface ModuleTabInterface extends ModuleInterface { /** * Users change change the order of tabs using the control panel. diff --git a/app/Module/ModuleThemeInterface.php b/app/Module/ModuleThemeInterface.php index 4e2b484b9c..9c25e2c31b 100644 --- a/app/Module/ModuleThemeInterface.php +++ b/app/Module/ModuleThemeInterface.php @@ -22,6 +22,6 @@ namespace Fisharebest\Webtrees\Module; * * This class is not currently used */ -interface ModuleThemeInterface +interface ModuleThemeInterface extends ModuleInterface { } diff --git a/app/Module/NotesTabModule.php b/app/Module/NotesTabModule.php index 49303e1839..8a9c2b4a3f 100644 --- a/app/Module/NotesTabModule.php +++ b/app/Module/NotesTabModule.php @@ -25,7 +25,7 @@ use Fisharebest\Webtrees\Individual; /** * Class NotesTabModule */ -class NotesTabModule extends AbstractModule implements ModuleInterface, ModuleTabInterface +class NotesTabModule extends AbstractModule implements ModuleTabInterface { use ModuleTabTrait; diff --git a/app/Module/OccupationReportModule.php b/app/Module/OccupationReportModule.php index 75192eeef9..2fe4cff4ef 100644 --- a/app/Module/OccupationReportModule.php +++ b/app/Module/OccupationReportModule.php @@ -25,7 +25,7 @@ use Fisharebest\Webtrees\Menu; /** * Class OccupationReportModule */ -class OccupationReportModule extends AbstractModule implements ModuleInterface, ModuleReportInterface +class OccupationReportModule extends AbstractModule implements ModuleReportInterface { use ModuleReportTrait; diff --git a/app/Module/OnThisDayModule.php b/app/Module/OnThisDayModule.php index 2fa940d90c..2babd43952 100644 --- a/app/Module/OnThisDayModule.php +++ b/app/Module/OnThisDayModule.php @@ -28,7 +28,7 @@ use Symfony\Component\HttpFoundation\Request; /** * Class OnThisDayModule */ -class OnThisDayModule extends AbstractModule implements ModuleInterface, ModuleBlockInterface +class OnThisDayModule extends AbstractModule implements ModuleBlockInterface { use ModuleBlockTrait; diff --git a/app/Module/PedigreeChartModule.php b/app/Module/PedigreeChartModule.php index 6a60b77516..76bd3865c1 100644 --- a/app/Module/PedigreeChartModule.php +++ b/app/Module/PedigreeChartModule.php @@ -32,7 +32,7 @@ use Symfony\Component\HttpFoundation\Response; /** * Class PedigreeChartModule */ -class PedigreeChartModule extends AbstractModule implements ModuleInterface, ModuleChartInterface +class PedigreeChartModule extends AbstractModule implements ModuleChartInterface { use ModuleChartTrait; diff --git a/app/Module/PedigreeMapModule.php b/app/Module/PedigreeMapModule.php index 9f2d69dce6..4d3b4744f0 100644 --- a/app/Module/PedigreeMapModule.php +++ b/app/Module/PedigreeMapModule.php @@ -35,7 +35,7 @@ use Symfony\Component\HttpFoundation\Response; /** * Class PedigreeMapModule */ -class PedigreeMapModule extends AbstractModule implements ModuleInterface, ModuleChartInterface +class PedigreeMapModule extends AbstractModule implements ModuleChartInterface { use ModuleChartTrait; diff --git a/app/Module/PedigreeReportModule.php b/app/Module/PedigreeReportModule.php index fa421691ef..ceb8d62a60 100644 --- a/app/Module/PedigreeReportModule.php +++ b/app/Module/PedigreeReportModule.php @@ -24,7 +24,7 @@ use Fisharebest\Webtrees\Menu; /** * Class PedigreeReportModule */ -class PedigreeReportModule extends AbstractModule implements ModuleInterface, ModuleReportInterface +class PedigreeReportModule extends AbstractModule implements ModuleReportInterface { use ModuleReportTrait; diff --git a/app/Module/PlacesModule.php b/app/Module/PlacesModule.php index f170f5d23f..4d18d0b781 100644 --- a/app/Module/PlacesModule.php +++ b/app/Module/PlacesModule.php @@ -31,7 +31,7 @@ use Symfony\Component\HttpFoundation\Request; /** * Class PlacesMapModule */ -class PlacesModule extends AbstractModule implements ModuleInterface, ModuleTabInterface +class PlacesModule extends AbstractModule implements ModuleTabInterface { use ModuleTabTrait; diff --git a/app/Module/RecentChangesModule.php b/app/Module/RecentChangesModule.php index 794061ed38..9ed1b792aa 100644 --- a/app/Module/RecentChangesModule.php +++ b/app/Module/RecentChangesModule.php @@ -28,7 +28,7 @@ use Symfony\Component\HttpFoundation\Request; /** * Class RecentChangesModule */ -class RecentChangesModule extends AbstractModule implements ModuleInterface, ModuleBlockInterface +class RecentChangesModule extends AbstractModule implements ModuleBlockInterface { use ModuleBlockTrait; diff --git a/app/Module/RelatedIndividualsReportModule.php b/app/Module/RelatedIndividualsReportModule.php index 4d2e74be28..83152d5ad5 100644 --- a/app/Module/RelatedIndividualsReportModule.php +++ b/app/Module/RelatedIndividualsReportModule.php @@ -24,7 +24,7 @@ use Fisharebest\Webtrees\Menu; /** * Class RelatedIndividualsReportModule */ -class RelatedIndividualsReportModule extends AbstractModule implements ModuleInterface, ModuleReportInterface +class RelatedIndividualsReportModule extends AbstractModule implements ModuleReportInterface { use ModuleReportTrait; diff --git a/app/Module/RelationshipsChartModule.php b/app/Module/RelationshipsChartModule.php index 31ec030a51..a0bec9ea38 100644 --- a/app/Module/RelationshipsChartModule.php +++ b/app/Module/RelationshipsChartModule.php @@ -38,7 +38,7 @@ use Symfony\Component\HttpFoundation\Response; /** * Class RelationshipsChartModule */ -class RelationshipsChartModule extends AbstractModule implements ModuleInterface, ModuleChartInterface, ModuleConfigInterface +class RelationshipsChartModule extends AbstractModule implements ModuleChartInterface, ModuleConfigInterface { use ModuleChartTrait; use ModuleConfigTrait; diff --git a/app/Module/RelativesTabModule.php b/app/Module/RelativesTabModule.php index 508dafcaf0..f2bc84542a 100644 --- a/app/Module/RelativesTabModule.php +++ b/app/Module/RelativesTabModule.php @@ -24,7 +24,7 @@ use Fisharebest\Webtrees\Individual; /** * Class RelativesTabModule */ -class RelativesTabModule extends AbstractModule implements ModuleInterface, ModuleTabInterface +class RelativesTabModule extends AbstractModule implements ModuleTabInterface { use ModuleTabTrait; diff --git a/app/Module/ReportsMenuModule.php b/app/Module/ReportsMenuModule.php index b8c34f0fc5..4d37f81802 100644 --- a/app/Module/ReportsMenuModule.php +++ b/app/Module/ReportsMenuModule.php @@ -28,7 +28,7 @@ use Symfony\Component\HttpFoundation\Request; /** * Class ReportsMenuModule - provide a menu option for the reports */ -class ReportsMenuModule extends AbstractModule implements ModuleInterface, ModuleMenuInterface +class ReportsMenuModule extends AbstractModule implements ModuleMenuInterface { use ModuleMenuTrait; diff --git a/app/Module/ResearchTaskModule.php b/app/Module/ResearchTaskModule.php index 70f53e270c..92f54fe5d8 100644 --- a/app/Module/ResearchTaskModule.php +++ b/app/Module/ResearchTaskModule.php @@ -31,7 +31,7 @@ use Symfony\Component\HttpFoundation\Request; /** * Class ResearchTaskModule */ -class ResearchTaskModule extends AbstractModule implements ModuleInterface, ModuleBlockInterface +class ResearchTaskModule extends AbstractModule implements ModuleBlockInterface { use ModuleBlockTrait; diff --git a/app/Module/ReviewChangesModule.php b/app/Module/ReviewChangesModule.php index ac83ee5e58..9fea8c1e1e 100644 --- a/app/Module/ReviewChangesModule.php +++ b/app/Module/ReviewChangesModule.php @@ -31,7 +31,7 @@ use Symfony\Component\HttpFoundation\Request; /** * Class ReviewChangesModule */ -class ReviewChangesModule extends AbstractModule implements ModuleInterface, ModuleBlockInterface +class ReviewChangesModule extends AbstractModule implements ModuleBlockInterface { use ModuleBlockTrait; diff --git a/app/Module/SearchMenuModule.php b/app/Module/SearchMenuModule.php index f3b19d012e..3a49d5a327 100644 --- a/app/Module/SearchMenuModule.php +++ b/app/Module/SearchMenuModule.php @@ -25,7 +25,7 @@ use Fisharebest\Webtrees\Tree; /** * Class SearchMenuModule - provide a menu option for the search options */ -class SearchMenuModule extends AbstractModule implements ModuleInterface, ModuleMenuInterface +class SearchMenuModule extends AbstractModule implements ModuleMenuInterface { use ModuleMenuTrait; diff --git a/app/Module/SiteMapModule.php b/app/Module/SiteMapModule.php index 3a45442464..7d8fe291bf 100644 --- a/app/Module/SiteMapModule.php +++ b/app/Module/SiteMapModule.php @@ -38,7 +38,7 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; /** * Class SiteMapModule */ -class SiteMapModule extends AbstractModule implements ModuleInterface, ModuleConfigInterface +class SiteMapModule extends AbstractModule implements ModuleConfigInterface { use ModuleConfigTrait; diff --git a/app/Module/SlideShowModule.php b/app/Module/SlideShowModule.php index ea13e01325..251176e1b9 100644 --- a/app/Module/SlideShowModule.php +++ b/app/Module/SlideShowModule.php @@ -30,7 +30,7 @@ use Symfony\Component\HttpFoundation\Request; /** * Class SlideShowModule */ -class SlideShowModule extends AbstractModule implements ModuleInterface, ModuleBlockInterface +class SlideShowModule extends AbstractModule implements ModuleBlockInterface { use ModuleBlockTrait; diff --git a/app/Module/SourcesTabModule.php b/app/Module/SourcesTabModule.php index ca104a5483..474fc1edc9 100644 --- a/app/Module/SourcesTabModule.php +++ b/app/Module/SourcesTabModule.php @@ -25,7 +25,7 @@ use Fisharebest\Webtrees\Individual; /** * Class SourcesTabModule */ -class SourcesTabModule extends AbstractModule implements ModuleInterface, ModuleTabInterface +class SourcesTabModule extends AbstractModule implements ModuleTabInterface { use ModuleTabTrait; diff --git a/app/Module/StatcounterModule.php b/app/Module/StatcounterModule.php new file mode 100644 index 0000000000..f39d7869ef --- /dev/null +++ b/app/Module/StatcounterModule.php @@ -0,0 +1,81 @@ +<?php +/** + * webtrees: online genealogy + * Copyright (C) 2019 webtrees development team + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +declare(strict_types=1); + +namespace Fisharebest\Webtrees\Module; + +/** + * Class StatcounterModule - add support for statcounter. + */ +class StatcounterModule extends AbstractModule implements ModuleAnalyticsInterface +{ + use ModuleAnalyticsTrait; + + /** + * How should this module be labelled on tabs, menus, etc.? + * + * @return string + */ + public function title(): string + { + return 'Statcounter™'; + } + + /** + * Form fields to edit the parameters. + * + * @return string + */ + public function analyticsFormFields(): string + { + return view('admin/analytics/statcounter-form', $this->analyticsParameters()); + } + + /** + * Home page for the service. + * + * @return string + */ + public function analyticsHomePageUrl(): string + { + return 'https://statcounter.com'; + } + + /** + * The parameters that need to be embedded in the snippet. + * + * @return string[] + */ + public function analyticsParameters(): array + { + return [ + 'STATCOUNTER_PROJECT_ID' => $this->getPreference('STATCOUNTER_PROJECT_ID'), + 'STATCOUNTER_SECURITY_ID' => $this->getPreference('STATCOUNTER_SECURITY_ID'), + ]; + } + + /** + * Embed placeholders in the snippet. + * + * @param string[] $parameters + * + * @return string + */ + public function analyticsSnippet(array $parameters): string + { + return view('admin/analytics/statcounter-snippet', $parameters); + } +} diff --git a/app/Module/StatisticsChartModule.php b/app/Module/StatisticsChartModule.php index c3a1dbfca0..33ccf025cf 100644 --- a/app/Module/StatisticsChartModule.php +++ b/app/Module/StatisticsChartModule.php @@ -31,7 +31,7 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; /** * Class StatisticsChartModule */ -class StatisticsChartModule extends AbstractModule implements ModuleInterface, ModuleChartInterface +class StatisticsChartModule extends AbstractModule implements ModuleChartInterface { use ModuleChartTrait; diff --git a/app/Module/StoriesModule.php b/app/Module/StoriesModule.php index 686aa561b9..5c830bb4a7 100644 --- a/app/Module/StoriesModule.php +++ b/app/Module/StoriesModule.php @@ -31,7 +31,7 @@ use Symfony\Component\HttpFoundation\Response; /** * Class StoriesModule */ -class StoriesModule extends AbstractModule implements ModuleInterface, ModuleConfigInterface, ModuleMenuInterface, ModuleTabInterface +class StoriesModule extends AbstractModule implements ModuleConfigInterface, ModuleMenuInterface, ModuleTabInterface { use ModuleTabTrait; use ModuleConfigTrait; diff --git a/app/Module/ThemeSelectModule.php b/app/Module/ThemeSelectModule.php index 3973d27d04..de9ef813bd 100644 --- a/app/Module/ThemeSelectModule.php +++ b/app/Module/ThemeSelectModule.php @@ -25,7 +25,7 @@ use Symfony\Component\HttpFoundation\Request; /** * Class ThemeSelectModule */ -class ThemeSelectModule extends AbstractModule implements ModuleInterface, ModuleBlockInterface +class ThemeSelectModule extends AbstractModule implements ModuleBlockInterface { use ModuleBlockTrait; diff --git a/app/Module/TimelineChartModule.php b/app/Module/TimelineChartModule.php index 84c9477156..0f8d989425 100644 --- a/app/Module/TimelineChartModule.php +++ b/app/Module/TimelineChartModule.php @@ -30,7 +30,7 @@ use Symfony\Component\HttpFoundation\Response; /** * Class TimelineChartModule */ -class TimelineChartModule extends AbstractModule implements ModuleInterface, ModuleChartInterface +class TimelineChartModule extends AbstractModule implements ModuleChartInterface { use ModuleChartTrait; diff --git a/app/Module/TopGivenNamesModule.php b/app/Module/TopGivenNamesModule.php index d2e8f93d5a..117f8cfa76 100644 --- a/app/Module/TopGivenNamesModule.php +++ b/app/Module/TopGivenNamesModule.php @@ -26,7 +26,7 @@ use Symfony\Component\HttpFoundation\Request; /** * Class TopGivenNamesModule */ -class TopGivenNamesModule extends AbstractModule implements ModuleInterface, ModuleBlockInterface +class TopGivenNamesModule extends AbstractModule implements ModuleBlockInterface { use ModuleBlockTrait; diff --git a/app/Module/TopPageViewsModule.php b/app/Module/TopPageViewsModule.php index 918847f1bf..22ed835d2e 100644 --- a/app/Module/TopPageViewsModule.php +++ b/app/Module/TopPageViewsModule.php @@ -27,7 +27,7 @@ use Symfony\Component\HttpFoundation\Request; /** * Class TopPageViewsModule */ -class TopPageViewsModule extends AbstractModule implements ModuleInterface, ModuleBlockInterface +class TopPageViewsModule extends AbstractModule implements ModuleBlockInterface { use ModuleBlockTrait; diff --git a/app/Module/TopSurnamesModule.php b/app/Module/TopSurnamesModule.php index fcf1acf8cc..b88e184cc2 100644 --- a/app/Module/TopSurnamesModule.php +++ b/app/Module/TopSurnamesModule.php @@ -27,7 +27,7 @@ use Symfony\Component\HttpFoundation\Request; /** * Class TopSurnamesModule */ -class TopSurnamesModule extends AbstractModule implements ModuleInterface, ModuleBlockInterface +class TopSurnamesModule extends AbstractModule implements ModuleBlockInterface { use ModuleBlockTrait; diff --git a/app/Module/TreesMenuModule.php b/app/Module/TreesMenuModule.php index 1cc9ce1c06..c0d9ce6311 100644 --- a/app/Module/TreesMenuModule.php +++ b/app/Module/TreesMenuModule.php @@ -25,7 +25,7 @@ use Fisharebest\Webtrees\Tree; /** * Class TreesMenuModule - provide a menu option for the trees options */ -class TreesMenuModule extends AbstractModule implements ModuleInterface, ModuleMenuInterface +class TreesMenuModule extends AbstractModule implements ModuleMenuInterface { use ModuleMenuTrait; diff --git a/app/Module/UpcomingAnniversariesModule.php b/app/Module/UpcomingAnniversariesModule.php index e7529e314f..89a0e144b2 100644 --- a/app/Module/UpcomingAnniversariesModule.php +++ b/app/Module/UpcomingAnniversariesModule.php @@ -28,7 +28,7 @@ use Symfony\Component\HttpFoundation\Request; /** * Class UpcomingAnniversariesModule */ -class UpcomingAnniversariesModule extends AbstractModule implements ModuleInterface, ModuleBlockInterface +class UpcomingAnniversariesModule extends AbstractModule implements ModuleBlockInterface { use ModuleBlockTrait; diff --git a/app/Module/UserFavoritesModule.php b/app/Module/UserFavoritesModule.php index c670427e59..abaf28c432 100644 --- a/app/Module/UserFavoritesModule.php +++ b/app/Module/UserFavoritesModule.php @@ -30,7 +30,7 @@ use Symfony\Component\HttpFoundation\Request; /** * Class UserFavoritesModule */ -class UserFavoritesModule extends AbstractModule implements ModuleInterface, ModuleBlockInterface +class UserFavoritesModule extends AbstractModule implements ModuleBlockInterface { use ModuleBlockTrait; diff --git a/app/Module/UserJournalModule.php b/app/Module/UserJournalModule.php index 2b22ad8eaf..d4af94cf02 100644 --- a/app/Module/UserJournalModule.php +++ b/app/Module/UserJournalModule.php @@ -29,7 +29,7 @@ use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; /** * Class UserJournalModule */ -class UserJournalModule extends AbstractModule implements ModuleInterface, ModuleBlockInterface +class UserJournalModule extends AbstractModule implements ModuleBlockInterface { use ModuleBlockTrait; diff --git a/app/Module/UserMessagesModule.php b/app/Module/UserMessagesModule.php index 88d747aad3..276ed8c6e5 100644 --- a/app/Module/UserMessagesModule.php +++ b/app/Module/UserMessagesModule.php @@ -31,7 +31,7 @@ use Symfony\Component\HttpFoundation\Response; /** * Class UserMessagesModule */ -class UserMessagesModule extends AbstractModule implements ModuleInterface, ModuleBlockInterface +class UserMessagesModule extends AbstractModule implements ModuleBlockInterface { use ModuleBlockTrait; diff --git a/app/Module/UserWelcomeModule.php b/app/Module/UserWelcomeModule.php index b9a0ebb392..0f0aa614c1 100644 --- a/app/Module/UserWelcomeModule.php +++ b/app/Module/UserWelcomeModule.php @@ -27,7 +27,7 @@ use Symfony\Component\HttpFoundation\Request; /** * Class UserWelcomeModule */ -class UserWelcomeModule extends AbstractModule implements ModuleInterface, ModuleBlockInterface +class UserWelcomeModule extends AbstractModule implements ModuleBlockInterface { use ModuleBlockTrait; diff --git a/app/Module/WelcomeBlockModule.php b/app/Module/WelcomeBlockModule.php index e83aeda920..c4bace206a 100644 --- a/app/Module/WelcomeBlockModule.php +++ b/app/Module/WelcomeBlockModule.php @@ -27,7 +27,7 @@ use Symfony\Component\HttpFoundation\Request; /** * Class WelcomeBlockModule */ -class WelcomeBlockModule extends AbstractModule implements ModuleInterface, ModuleBlockInterface +class WelcomeBlockModule extends AbstractModule implements ModuleBlockInterface { use ModuleBlockTrait; diff --git a/app/Module/YahrzeitModule.php b/app/Module/YahrzeitModule.php index 9777aa9a8d..81f03d7034 100644 --- a/app/Module/YahrzeitModule.php +++ b/app/Module/YahrzeitModule.php @@ -30,7 +30,7 @@ use Symfony\Component\HttpFoundation\Request; /** * Class YahrzeitModule */ -class YahrzeitModule extends AbstractModule implements ModuleInterface, ModuleBlockInterface +class YahrzeitModule extends AbstractModule implements ModuleBlockInterface { use ModuleBlockTrait; diff --git a/app/Theme/AbstractTheme.php b/app/Theme/AbstractTheme.php index de71a0e7c3..de3f0c2d0d 100644 --- a/app/Theme/AbstractTheme.php +++ b/app/Theme/AbstractTheme.php @@ -90,144 +90,6 @@ abstract class AbstractTheme } /** - * Create scripts for analytics and tracking. - * - * @return string - */ - public function analytics() - { - if (!empty($_SERVER['HTTP_DNT'])) { - return ''; - } - - 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 - */ - public function analyticsBingWebmaster($verification_id): string - { - return '<meta name="msvalidate.01" content="' . $verification_id . '">'; - } - - /** - * Create the verification code for Google Webmaster Tools. - * - * @param string $verification_id - * - * @return string - */ - public function analyticsGoogleWebmaster($verification_id): string - { - return '<meta name="google-site-verification" content="' . $verification_id . '">'; - } - - /** - * Create the tracking code for Google Analytics. - * See https://developers.google.com/analytics/devguides/collection/analyticsjs/advanced - * - * @param string $analytics_id - * - * @return string - */ - public function analyticsGoogleTracker($analytics_id) - { - if ($analytics_id) { - // Add extra dimensions (i.e. filtering categories) - $dimensions = (object) [ - 'dimension1' => $this->tree ? $this->tree->name() : '-', - 'dimension2' => $this->tree ? Auth::accessLevel($this->tree) : '-', - ]; - - return - '<script async src="https://www.google-analytics.com/analytics.js"></script>' . - '<script>' . - 'window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga.l=+new Date;' . - 'ga("create","' . $analytics_id . '","auto");' . - 'ga("send", "pageview", ' . json_encode($dimensions) . ');' . - '</script>'; - } - - 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 - */ - public function analyticsPiwikTracker($url, $site_id) - { - $url = preg_replace([ - '/^https?:\/\//', - '/\/$/', - ], '', $url); - - if ($url && $site_id) { - return - '<script>' . - 'var _paq=_paq||[];' . - '(function(){var u=(("https:"==document.location.protocol)?"https://' . $url . '/":"http://' . $url . '/");' . - '_paq.push(["setSiteId",' . $site_id . ']);' . - '_paq.push(["setTrackerUrl",u+"piwik.php"]);' . - '_paq.push(["trackPageView"]);' . - '_paq.push(["enableLinkTracking"]);' . - 'var d=document,g=d.createElement("script"),s=d.getElementsByTagName("script")[0];g.defer=true;g.async=true;g.src=u+"piwik.js";' . - 's.parentNode.insertBefore(g,s);})();' . - '</script>'; - } - - 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 - */ - public function analyticsStatcounterTracker($project_id, $security_id) - { - if ($project_id && $security_id) { - return - '<script>' . - 'var sc_project=' . (int) $project_id . ',sc_invisible=1,sc_security="' . $security_id . - '",scJsHost = (("https:"===document.location.protocol)?"https://secure.":"http://www.");' . - 'document.write("<sc"+"ript src=\'"+scJsHost+"statcounter.com/counter/counter.js\'></"+"script>");' . - '</script>'; - } - - return ''; - } - - /** * Where are our CSS, JS and other assets? * * @deprecated - use the constant directly diff --git a/app/Theme/ThemeInterface.php b/app/Theme/ThemeInterface.php index afe9d1ea80..fd6d1469d0 100644 --- a/app/Theme/ThemeInterface.php +++ b/app/Theme/ThemeInterface.php @@ -30,13 +30,6 @@ use Symfony\Component\HttpFoundation\Request; interface ThemeInterface { /** - * Create scripts for analytics and tracking. - * - * @return string - */ - public function analytics(); - - /** * Create a contact link for a user. * * @param User $user diff --git a/modules_v4/custom.example/module.php b/modules_v4/custom.example/module.php index 4af36139c2..b74740d4ab 100644 --- a/modules_v4/custom.example/module.php +++ b/modules_v4/custom.example/module.php @@ -36,7 +36,7 @@ use Fisharebest\Webtrees\Module\ModuleInterface; * We return an anonymouse class here. This prevents conflict with existing * class names. */ -return new class extends AbstractModule implements ModuleInterface, ModuleCustomInterface { +return new class extends AbstractModule implements ModuleCustomInterface { // We implement ModuleCustomInterface, so we must also use the corresponding trait. use ModuleCustomTrait; diff --git a/resources/views/admin/analytics/bing-webmaster-form.phtml b/resources/views/admin/analytics/bing-webmaster-form.phtml new file mode 100644 index 0000000000..e483ede59a --- /dev/null +++ b/resources/views/admin/analytics/bing-webmaster-form.phtml @@ -0,0 +1,12 @@ +<?php use Fisharebest\Webtrees\I18N; ?> + +<div class="row form-group"> + <label for="BING_WEBMASTER_ID" class="col-sm-3 col-form-label"> + <?= I18N::translate('Site verification code') ?> + </label> + + <div class="col-sm-9"> + <input type="text" class="form-control" id="BING_WEBMASTER_ID" name="BING_WEBMASTER_ID" value="<?= e($BING_WEBMASTER_ID ?? '') ?>" maxlength="255" pattern="[0-9a-zA-Z+=/_:.!-]*"> + </div> +</div> + diff --git a/resources/views/admin/analytics/bing-webmaster-snippet.phtml b/resources/views/admin/analytics/bing-webmaster-snippet.phtml new file mode 100644 index 0000000000..f78fb17c81 --- /dev/null +++ b/resources/views/admin/analytics/bing-webmaster-snippet.phtml @@ -0,0 +1 @@ +<meta name="msvalidate.01" content="<?= e($BING_WEBMASTER_ID ?? '') ?>"> diff --git a/resources/views/admin/analytics/edit.phtml b/resources/views/admin/analytics/edit.phtml new file mode 100644 index 0000000000..ce9879b5c1 --- /dev/null +++ b/resources/views/admin/analytics/edit.phtml @@ -0,0 +1,35 @@ +<?php use Fisharebest\Webtrees\I18N; ?> + +<?= view('components/breadcrumbs', ['links' => [route('admin-control-panel') => I18N::translate('Control panel'), route('analytics') => I18N::translate('Tracking and analytics'), $title]]) ?> + +<h1><?= $title ?></h1> + +<form method="post" class="form-horizontal"> + <?= csrf_field() ?> + <?= $form_fields ?> + + <div class="row form-group"> + <div class="col-sm-3"> + <?= I18N::translate('Preview') ?> + </div> + + <div class="col-sm-9"> + <pre><code><?= e($preview) ?></code></pre> + </div> + </div> + + + <div class="row form-group"> + <div class="offset-sm-3 col-sm-9"> + <button type="submit" class="btn btn-primary"> + <?= view('icons/save') ?> + <?= I18N::translate('save') ?> + </button> + + <a href="<?= e(route('analytics')) ?>" class="btn btn-secondary"> + <?= view('icons/cancel') ?> + <?= I18N::translate('cancel') ?> + </a> + </div> + </div> +</form> diff --git a/resources/views/admin/analytics/google-analytics-form.phtml b/resources/views/admin/analytics/google-analytics-form.phtml new file mode 100644 index 0000000000..a246214c5c --- /dev/null +++ b/resources/views/admin/analytics/google-analytics-form.phtml @@ -0,0 +1,11 @@ +<?php use Fisharebest\Webtrees\I18N; ?> + +<div class="row form-group"> + <label for="GOOGLE_ANALYTICS_ID" class="col-sm-3 col-form-label"> + <?= /* I18N: A configuration setting */ I18N::translate('Site identification code') ?> + <span class="sr-only">Google Analytics</span> + </label> + <div class="col-sm-9"> + <input type="text" class="form-control" id="GOOGLE_ANALYTICS_ID" name="GOOGLE_ANALYTICS_ID" value="<?= e($GOOGLE_ANALYTICS_ID ?? '') ?>" placeholder="UA-12345-6" maxlength="255" pattern="UA-[0-9]+-[0-9]+"> + </div> +</div> diff --git a/resources/views/admin/analytics/google-analytics-snippet.phtml b/resources/views/admin/analytics/google-analytics-snippet.phtml new file mode 100644 index 0000000000..e55b77b528 --- /dev/null +++ b/resources/views/admin/analytics/google-analytics-snippet.phtml @@ -0,0 +1,7 @@ +<script async src="https://www.google-analytics.com/analytics.js"></script> +<script> + window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)}; + ga.l=+new Date; + ga("create", "<?= e($GOOGLE_ANALYTICS_ID ?? '') ?>", "auto"); + ga("send", "pageview", <?= json_encode($dimensions) ?>); +</script> diff --git a/resources/views/admin/analytics/google-webmaster-form.phtml b/resources/views/admin/analytics/google-webmaster-form.phtml new file mode 100644 index 0000000000..4e3a7bd731 --- /dev/null +++ b/resources/views/admin/analytics/google-webmaster-form.phtml @@ -0,0 +1,12 @@ +<?php use Fisharebest\Webtrees\I18N; ?> + +<div class="row form-group"> + <label for="GOOGLE_WEBMASTER_ID" class="col-sm-3 col-form-label"> + <?= /* I18N: A configuration setting */ I18N::translate('Site verification code') ?> + <span class="sr-only">Google Webmaster Tools</span> + </label> + <div class="col-sm-9"> + <input type="text" class="form-control" id="GOOGLE_WEBMASTER_ID" name="GOOGLE_WEBMASTER_ID" value="<?= e($GOOGLE_WEBMASTER_ID ?? '') ?>" maxlength="255" pattern="[0-9a-zA-Z+=/_:.!-]*"> + </div> +</div> + diff --git a/resources/views/admin/analytics/google-webmaster-snippet.phtml b/resources/views/admin/analytics/google-webmaster-snippet.phtml new file mode 100644 index 0000000000..8728d9ada4 --- /dev/null +++ b/resources/views/admin/analytics/google-webmaster-snippet.phtml @@ -0,0 +1 @@ +<meta name="google-site-verification" content="<?= e($GOOGLE_WEBMASTER_ID ?? '') ?>"> diff --git a/resources/views/admin/analytics/index.phtml b/resources/views/admin/analytics/index.phtml new file mode 100644 index 0000000000..1e31c27075 --- /dev/null +++ b/resources/views/admin/analytics/index.phtml @@ -0,0 +1,36 @@ +<?php use Fisharebest\Webtrees\I18N; ?> +<?php use Fisharebest\Webtrees\Site; ?> + +<?= view('components/breadcrumbs', ['links' => [route('admin-control-panel') => I18N::translate('Control panel'), $title]]) ?> + +<h1><?= $title ?></h1> + +<p> + <?= I18N::translate('If you use one of the following tracking and analytics services, webtrees can add the tracking codes automatically.') ?> +</p> + +<p> + <?= I18N::translate('Tracking and analytics are not added to the control panel.') ?> +</p> + +<p> + <?= I18N::translate('Site verification codes do not work when webtrees is installed in a subfolder.') ?> +</p> + +<?php foreach ($modules as $module) : ?> + <h2> + <?= e($module->title()) ?> + </h2> + + <p> + <a class="btn btn-link" href="<?= e(route('analytics-edit', ['module' => $module->name()])) ?>"> + <?= view('icons/preferences') ?> + <?= I18N::translate('Preferences') ?> + </a> + + <a class="btn btn-link" href="<?= e($module->analyticsHomePageUrl()) ?>"> + <?= view('icons/information') ?> + <?= e($module->analyticsHomePageUrl()) ?> + </a> + </p> +<?php endforeach ?> diff --git a/resources/views/admin/analytics/matomo-analytics-form.phtml b/resources/views/admin/analytics/matomo-analytics-form.phtml new file mode 100644 index 0000000000..dcd4edfe92 --- /dev/null +++ b/resources/views/admin/analytics/matomo-analytics-form.phtml @@ -0,0 +1,21 @@ +<?php use Fisharebest\Webtrees\I18N; ?> + +<div class="row form-group"> + <label for="PIWIK_SITE_ID" class="col-sm-3 col-form-label"> + <?= /* I18N: A configuration setting */ I18N::translate('Site identification code') ?> + </label> + <div class="col-sm-9"> + <input type="text" class="form-control" id="PIWIK_SITE_ID" name="PIWIK_SITE_ID" value="<?= e($PIWIK_SITE_ID ?? '') ?>" maxlength="255" pattern="[0-9]+"> + </div> +</div> + +<!-- PIWIK_URL --> +<div class="row form-group"> + <label for="PIWIK_URL" class="col-sm-3 col-form-label"> + <?= /* I18N: A configuration setting */ I18N::translate('URL') ?> + </label> + <div class="col-sm-9"> + <input type="text" class="form-control" id="PIWIK_URL" name="PIWIK_URL" value="<?= e($PIWIK_URL ?? '') ?>" placeholder="//example.com/piwik/" maxlength="255"> + </div> +</div> + diff --git a/resources/views/admin/analytics/matomo-analytics-snippet.phtml b/resources/views/admin/analytics/matomo-analytics-snippet.phtml new file mode 100644 index 0000000000..c81a17f402 --- /dev/null +++ b/resources/views/admin/analytics/matomo-analytics-snippet.phtml @@ -0,0 +1,12 @@ +<script type="text/javascript"> + var _paq = window._paq || []; + _paq.push(['trackPageView']); + _paq.push(['enableLinkTracking']); + (function() { + var u=<?= json_encode($PIWIK_URL ?? '') ?>; + _paq.push(['setTrackerUrl', u+'piwik.php']); + _paq.push(['setSiteId', <?= json_encode($PIWIK_SITE_ID ?? '') ?>]); + var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0]; + g.type='text/javascript'; g.async=true; g.defer=true; g.src=u+'piwik.js'; s.parentNode.insertBefore(g,s); + })(); +</script> diff --git a/resources/views/admin/analytics/statcounter-form.phtml b/resources/views/admin/analytics/statcounter-form.phtml new file mode 100644 index 0000000000..23a38294b0 --- /dev/null +++ b/resources/views/admin/analytics/statcounter-form.phtml @@ -0,0 +1,20 @@ +<?php use Fisharebest\Webtrees\I18N; ?> + +<div class="row form-group"> + <label for="STATCOUNTER_PROJECT_ID" class="col-sm-3 col-form-label"> + <?= /* I18N: A configuration setting */ I18N::translate('Site identification code') ?> + </label> + <div class="col-sm-9"> + <input type="text" class="form-control" id="STATCOUNTER_PROJECT_ID" name="STATCOUNTER_PROJECT_ID" value="<?= e($STATCOUNTER_PROJECT_ID ?? '') ?>" maxlength="255" pattern="[0-9]+"> + </div> +</div> + +<!-- STATCOUNTER_SECURITY_ID --> +<div class="row form-group"> + <label for="STATCOUNTER_SECURITY_ID" class="col-sm-3 col-form-label"> + <?= /* I18N: A configuration setting */ I18N::translate('Security code') ?> + </label> + <div class="col-sm-9"> + <input type="text" class="form-control" id="STATCOUNTER_SECURITY_ID" name="STATCOUNTER_SECURITY_ID" value="<?= e($STATCOUNTER_SECURITY_ID ?? '') ?>" maxlength="255" pattern="[0-9a-zA-Z]+"> + </div> +</div> diff --git a/resources/views/admin/analytics/statcounter-snippet.phtml b/resources/views/admin/analytics/statcounter-snippet.phtml new file mode 100644 index 0000000000..13dfa49009 --- /dev/null +++ b/resources/views/admin/analytics/statcounter-snippet.phtml @@ -0,0 +1,9 @@ +<script> + var sc_project=<?= json_encode((int) ($STATCOUNTER_PROJECT_ID ?? '')) ?>; + var sc_invisible=1; + var sc_security=<?= json_encode($STATCOUNTER_SECURITY_ID ?? '') ?>; + var sc_https=1; + var scJsHost = (("https:" == document.location.protocol) ? "https://secure." : "http://www."); + document.write("<sc"+"ript type='text/javascript' async src='" + scJsHost + "statcounter.com/counter/counter_xhtml.js'></"+"script>"); +</script> + diff --git a/resources/views/admin/control-panel.phtml b/resources/views/admin/control-panel.phtml index 6f2277a342..b575b41729 100644 --- a/resources/views/admin/control-panel.phtml +++ b/resources/views/admin/control-panel.phtml @@ -64,8 +64,8 @@ </a> </li> <li> - <span class="fa-li"><?= view('icons/preferences') ?></span> - <a href="<?= e(route('admin-site-analytics')) ?>"> + <span class="fa-li"><?= view('icons/wizard') ?></span> + <a href="<?= e(route('analytics')) ?>"> <?= I18N::translate('Tracking and analytics') ?> </a> </li> diff --git a/resources/views/admin/site-analytics.phtml b/resources/views/admin/site-analytics.phtml deleted file mode 100644 index 3a6b4ab472..0000000000 --- a/resources/views/admin/site-analytics.phtml +++ /dev/null @@ -1,136 +0,0 @@ -<?php use Fisharebest\Webtrees\I18N; ?> -<?php use Fisharebest\Webtrees\Site; ?> - -<?= view('components/breadcrumbs', ['links' => [route('admin-control-panel') => I18N::translate('Control panel'), $title]]) ?> - -<h1><?= $title ?></h1> - -<form method="post" class="form-horizontal"> - <?= csrf_field() ?> - - <p> - <?= I18N::translate('If you use one of the following tracking and analytics services, webtrees can add the tracking codes automatically.') ?> - </p> - - <h2><a href="https://www.bing.com/toolbox/webmaster/">Bing Webmaster Tools</a></h2> - - <!-- BING_WEBMASTER_ID --> - <div class="row form-group"> - <label for="BING_WEBMASTER_ID" class="col-sm-3 col-form-label"> - <?= /* I18N: A configuration setting */ I18N::translate('Site verification code') ?> - <span class="sr-only">Google Webmaster Tools</span> - </label> - <div class="col-sm-9"> - <input - type="text" class="form-control" - id="BING_WEBMASTER_ID" name="BING_WEBMASTER_ID" <?= dirname(parse_url(WT_BASE_URL, PHP_URL_PATH)) === '/' ? '' : 'disabled' ?> - value="<?= e(Site::getPreference('BING_WEBMASTER_ID')) ?>" - maxlength="255" pattern="[0-9a-zA-Z+=/_:.!-]*" - > - <p class="small text-muted"> - <?= /* I18N: Help text for the "Site verification code for Google Webmaster Tools" site configuration setting */ I18N::translate('Site verification codes do not work when webtrees is installed in a subfolder.') ?> - </p> - </div> - </div> - - <h2><a href="https://www.google.com/webmasters/">Google Webmaster Tools</a></h2> - - <!-- GOOGLE_WEBMASTER_ID --> - <div class="row form-group"> - <label for="GOOGLE_WEBMASTER_ID" class="col-sm-3 col-form-label"> - <?= /* I18N: A configuration setting */ I18N::translate('Site verification code') ?> - <span class="sr-only">Google Webmaster Tools</span> - </label> - <div class="col-sm-9"> - <input - type="text" class="form-control" - id="GOOGLE_WEBMASTER_ID" name="GOOGLE_WEBMASTER_ID" <?= dirname(parse_url(WT_BASE_URL, PHP_URL_PATH)) === '/' ? '' : 'disabled' ?> - value="<?= e(Site::getPreference('GOOGLE_WEBMASTER_ID')) ?>" - maxlength="255" pattern="[0-9a-zA-Z+=/_:.!-]*" - > - <p class="small text-muted"> - <?= /* I18N: Help text for the "Site verification code for Google Webmaster Tools" site configuration setting */ I18N::translate('Site verification codes do not work when webtrees is installed in a subfolder.') ?> - </p> - </div> - </div> - - <h2><a href="https://www.google.com/analytics/">Google Analytics</a></h2> - - <!-- GOOGLE_ANALYTICS_ID --> - <div class="row form-group"> - <label for="GOOGLE_ANALYTICS_ID" class="col-sm-3 col-form-label"> - <?= /* I18N: A configuration setting */ I18N::translate('Site identification code') ?> - <span class="sr-only">Google Analytics</span> - </label> - <div class="col-sm-9"> - <input type="text" class="form-control" id="GOOGLE_ANALYTICS_ID" name="GOOGLE_ANALYTICS_ID" value="<?= e(Site::getPreference('GOOGLE_ANALYTICS_ID')) ?>" placeholder="UA-12345-6" maxlength="255" pattern="UA-[0-9]+-[0-9]+"> - <p class="small text-muted"> - <?= I18N::translate('Tracking and analytics are not added to the control panel.') ?> - </p> - </div> - </div> - - <h2><a href="https://piwik.org/">Piwik</a></h2> - - <!-- PIWIK_SITE_ID --> - <div class="row form-group"> - <label for="PIWIK_SITE_ID" class="col-sm-3 col-form-label"> - <?= /* I18N: A configuration setting */ I18N::translate('Site identification code') ?> - </label> - <div class="col-sm-9"> - <input type="text" class="form-control" id="PIWIK_SITE_ID" name="PIWIK_SITE_ID" value="<?= e(Site::getPreference('PIWIK_SITE_ID')) ?>" maxlength="255" pattern="[0-9]+"> - </div> - </div> - - <!-- PIWIK_URL --> - <div class="row form-group"> - <label for="PIWIK_URL" class="col-sm-3 col-form-label"> - <?= /* I18N: A configuration setting */ I18N::translate('URL') ?> - </label> - <div class="col-sm-9"> - <input type="text" class="form-control" id="PIWIK_URL" name="PIWIK_URL" value="<?= e(Site::getPreference('PIWIK_URL')) ?>" placeholder="example.com/piwik" maxlength="255"> - <p class="small text-muted"> - <?= I18N::translate('Tracking and analytics are not added to the control panel.') ?> - </p> - </div> - </div> - - <h2><a href="https://statcounter.com/">StatCounter</a></h2> - - <!-- STATCOUNTER_PROJECT_ID --> - <div class="row form-group"> - <label for="STATCOUNTER_PROJECT_ID" class="col-sm-3 col-form-label"> - <?= /* I18N: A configuration setting */ I18N::translate('Site identification code') ?> - </label> - <div class="col-sm-9"> - <input type="text" class="form-control" id="STATCOUNTER_PROJECT_ID" name="STATCOUNTER_PROJECT_ID" value="<?= e(Site::getPreference('STATCOUNTER_PROJECT_ID')) ?>" maxlength="255" pattern="[0-9]+"> - </div> - </div> - - <!-- STATCOUNTER_SECURITY_ID --> - <div class="row form-group"> - <label for="STATCOUNTER_SECURITY_ID" class="col-sm-3 col-form-label"> - <?= /* I18N: A configuration setting */ I18N::translate('Security code') ?> - </label> - <div class="col-sm-9"> - <input type="text" class="form-control" id="STATCOUNTER_SECURITY_ID" name="STATCOUNTER_SECURITY_ID" value="<?= e(Site::getPreference('STATCOUNTER_SECURITY_ID')) ?>" maxlength="255" pattern="[0-9a-zA-Z]+"> - <p class="small text-muted"> - <?= I18N::translate('Tracking and analytics are not added to the control panel.') ?> - </p> - </div> - </div> - - <div class="row form-group"> - <div class="offset-sm-3 col-sm-9"> - <button type="submit" class="btn btn-primary"> - <?= view('icons/save') ?> - <?= I18N::translate('save') ?> - </button> - - <a href="<?= e(route('admin-control-panel')) ?>" class="btn btn-secondary"> - <?= view('icons/cancel') ?> - <?= I18N::translate('cancel') ?> - </a> - </div> - </div> -</form> diff --git a/resources/views/icons/help.phtml b/resources/views/icons/help.phtml index 3d2e8cd1ca..cab0e99de6 100644 --- a/resources/views/icons/help.phtml +++ b/resources/views/icons/help.phtml @@ -1 +1 @@ -<i class="fas fa-info-circle fa-fw wt-icon-help" aria-hidden="true"></i> +<i class="fas fa-question-circle fa-fw wt-icon-help" aria-hidden="true"></i> diff --git a/resources/views/icons/information.phtml b/resources/views/icons/information.phtml new file mode 100644 index 0000000000..9152155dc8 --- /dev/null +++ b/resources/views/icons/information.phtml @@ -0,0 +1 @@ +<i class="fas fa-info-circle fa-fw wt-icon-information" aria-hidden="true"></i> diff --git a/resources/views/layouts/default.phtml b/resources/views/layouts/default.phtml index e4c018135c..236c6f3358 100644 --- a/resources/views/layouts/default.phtml +++ b/resources/views/layouts/default.phtml @@ -2,6 +2,8 @@ <?php use Fisharebest\Webtrees\DebugBar; ?> <?php use Fisharebest\Webtrees\FlashMessages; ?> <?php use Fisharebest\Webtrees\I18N; ?> +<?php use Fisharebest\Webtrees\Module; ?> +<?php use Fisharebest\Webtrees\Module\ModuleAnalyticsInterface; ?> <?php use Fisharebest\Webtrees\Theme; ?> <?php use Fisharebest\Webtrees\View; ?> <?php use Fisharebest\Webtrees\Webtrees; ?> @@ -41,7 +43,7 @@ <?= View::stack('styles') ?> - <?= Theme::theme()->analytics() ?> + <?= Module::findByInterface(ModuleAnalyticsInterface::class)->filter(function (ModuleAnalyticsInterface $module): bool { return $module->analyticsCanShow(); })->map(function (ModuleAnalyticsInterface $module): string { return $module->analyticsSnippet($module->analyticsParameters()); })->implode('') ?> <?= DebugBar::renderHead() ?> </head> diff --git a/routes/web.php b/routes/web.php index 9f62f447c3..44acaba735 100644 --- a/routes/web.php +++ b/routes/web.php @@ -24,6 +24,9 @@ $routes = []; // Admin routes. if (Auth::isAdmin()) { $routes += [ + 'GET:analytics' => 'Admin\\AnalyticsController@list', + 'GET:analytics-edit' => 'Admin\\AnalyticsController@edit', + 'POST:analytics-edit' => 'Admin\\AnalyticsController@save', 'GET:admin-blocks' => 'AdminController@blocks', 'GET:admin-charts' => 'AdminController@charts', 'GET:admin-control-panel' => 'AdminController@controlPanel', @@ -56,8 +59,6 @@ if (Auth::isAdmin()) { 'POST:admin-site-registration' => 'AdminSiteController@registrationSave', 'GET:admin-site-languages' => 'AdminSiteController@languagesForm', 'POST:admin-site-languages' => 'AdminSiteController@languagesSave', - 'GET:admin-site-analytics' => 'AdminSiteController@analyticsForm', - 'POST:admin-site-analytics' => 'AdminSiteController@analyticsSave', 'GET:admin-site-logs' => 'AdminSiteController@logs', 'GET:admin-site-logs-data' => 'AdminSiteController@logsData', 'POST:admin-site-logs-delete' => 'AdminSiteController@logsDelete', |
