1<?php 2 3/** 4 * webtrees: online genealogy 5 * Copyright (C) 2019 webtrees development team 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation, either version 3 of the License, or 9 * (at your option) any later version. 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18declare(strict_types=1); 19 20namespace Fisharebest\Webtrees\Module; 21 22use Fisharebest\Webtrees\Carbon; 23use Fisharebest\Webtrees\Gedcom; 24use Fisharebest\Webtrees\GedcomTag; 25use Fisharebest\Webtrees\I18N; 26use Fisharebest\Webtrees\Services\CalendarService; 27use Fisharebest\Webtrees\Tree; 28use Illuminate\Support\Str; 29use Psr\Http\Message\ServerRequestInterface; 30 31/** 32 * Class OnThisDayModule 33 */ 34class OnThisDayModule extends AbstractModule implements ModuleBlockInterface 35{ 36 use ModuleBlockTrait; 37 38 // All standard GEDCOM 5.5.1 events except CENS, RESI and EVEN 39 private const ALL_EVENTS = [ 40 'ADOP', 41 'ANUL', 42 'BAPM', 43 'BARM', 44 'BASM', 45 'BIRT', 46 'BLES', 47 'BURI', 48 'CHR', 49 'CHRA', 50 'CONF', 51 'CREM', 52 'DEAT', 53 'DIV', 54 'DIVF', 55 'EMIG', 56 'ENGA', 57 'FCOM', 58 'GRAD', 59 'IMMI', 60 'MARB', 61 'MARC', 62 'MARL', 63 'MARR', 64 'MARS', 65 'NATU', 66 'ORDN', 67 'PROB', 68 'RETI', 69 'WILL', 70 ]; 71 72 private const DEFAULT_EVENTS = [ 73 'BIRT', 74 'MARR', 75 'DEAT', 76 ]; 77 78 /** 79 * How should this module be identified in the control panel, etc.? 80 * 81 * @return string 82 */ 83 public function title(): string 84 { 85 /* I18N: Name of a module */ 86 return I18N::translate('On this day'); 87 } 88 89 /** 90 * A sentence describing what this module does. 91 * 92 * @return string 93 */ 94 public function description(): string 95 { 96 /* I18N: Description of the “On this day” module */ 97 return I18N::translate('A list of the anniversaries that occur today.'); 98 } 99 100 /** 101 * Generate the HTML content of this block. 102 * 103 * @param Tree $tree 104 * @param int $block_id 105 * @param string $context 106 * @param string[] $config 107 * 108 * @return string 109 */ 110 public function getBlock(Tree $tree, int $block_id, string $context, array $config = []): string 111 { 112 $calendar_service = new CalendarService(); 113 114 $default_events = implode(',', self::DEFAULT_EVENTS); 115 116 $filter = (bool) $this->getBlockSetting($block_id, 'filter', '1'); 117 $infoStyle = $this->getBlockSetting($block_id, 'infoStyle', 'table'); 118 $sortStyle = $this->getBlockSetting($block_id, 'sortStyle', 'alpha'); 119 $events = $this->getBlockSetting($block_id, 'events', $default_events); 120 121 extract($config, EXTR_OVERWRITE); 122 123 $event_array = explode(',', $events); 124 125 // If we are only showing living individuals, then we don't need to search for DEAT events. 126 if ($filter) { 127 $event_array = array_diff($event_array, Gedcom::DEATH_EVENTS); 128 } 129 130 $events_filter = implode('|', $event_array); 131 132 $startjd = Carbon::now()->julianDay(); 133 $endjd = $startjd; 134 135 $facts = $calendar_service->getEventsList($startjd, $endjd, $events_filter, $filter, $sortStyle, $tree); 136 137 if ($facts === []) { 138 $content = view('modules/todays_events/empty'); 139 } elseif ($infoStyle === 'list') { 140 $content = view('lists/anniversaries-list', [ 141 'facts' => $facts, 142 ]); 143 } else { 144 $content = view('lists/anniversaries-table', [ 145 'facts' => $facts, 146 ]); 147 } 148 149 if ($context !== self::CONTEXT_EMBED) { 150 return view('modules/block-template', [ 151 'block' => Str::kebab($this->name()), 152 'id' => $block_id, 153 'config_url' => $this->configUrl($tree, $context, $block_id), 154 'title' => $this->title(), 155 'content' => $content, 156 ]); 157 } 158 159 return $content; 160 } 161 162 /** 163 * Should this block load asynchronously using AJAX? 164 * 165 * Simple blocks are faster in-line, more complex ones can be loaded later. 166 * 167 * @return bool 168 */ 169 public function loadAjax(): bool 170 { 171 return true; 172 } 173 174 /** 175 * Can this block be shown on the user’s home page? 176 * 177 * @return bool 178 */ 179 public function isUserBlock(): bool 180 { 181 return true; 182 } 183 184 /** 185 * Can this block be shown on the tree’s home page? 186 * 187 * @return bool 188 */ 189 public function isTreeBlock(): bool 190 { 191 return true; 192 } 193 194 /** 195 * Update the configuration for a block. 196 * 197 * @param ServerRequestInterface $request 198 * @param int $block_id 199 * 200 * @return void 201 */ 202 public function saveBlockConfiguration(ServerRequestInterface $request, int $block_id): void 203 { 204 $params = $request->getParsedBody(); 205 206 $this->setBlockSetting($block_id, 'filter', $params['filter']); 207 $this->setBlockSetting($block_id, 'infoStyle', $params['infoStyle']); 208 $this->setBlockSetting($block_id, 'sortStyle', $params['sortStyle']); 209 $this->setBlockSetting($block_id, 'events', implode(',', $params['events'] ?? [])); 210 } 211 212 /** 213 * An HTML form to edit block settings 214 * 215 * @param Tree $tree 216 * @param int $block_id 217 * 218 * @return string 219 */ 220 public function editBlockConfiguration(Tree $tree, int $block_id): string 221 { 222 $default_events = implode(',', self::DEFAULT_EVENTS); 223 224 $filter = $this->getBlockSetting($block_id, 'filter', '1'); 225 $infoStyle = $this->getBlockSetting($block_id, 'infoStyle', 'table'); 226 $sortStyle = $this->getBlockSetting($block_id, 'sortStyle', 'alpha'); 227 $events = $this->getBlockSetting($block_id, 'events', $default_events); 228 229 $event_array = explode(',', $events); 230 231 $all_events = []; 232 foreach (self::ALL_EVENTS as $event) { 233 $all_events[$event] = GedcomTag::getLabel($event); 234 } 235 236 $info_styles = [ 237 /* I18N: An option in a list-box */ 238 'list' => I18N::translate('list'), 239 /* I18N: An option in a list-box */ 240 'table' => I18N::translate('table'), 241 ]; 242 243 $sort_styles = [ 244 /* I18N: An option in a list-box */ 245 'alpha' => I18N::translate('sort by name'), 246 /* I18N: An option in a list-box */ 247 'anniv' => I18N::translate('sort by date'), 248 ]; 249 250 return view('modules/todays_events/config', [ 251 'all_events' => $all_events, 252 'event_array' => $event_array, 253 'filter' => $filter, 254 'infoStyle' => $infoStyle, 255 'info_styles' => $info_styles, 256 'sortStyle' => $sortStyle, 257 'sort_styles' => $sort_styles, 258 ]); 259 } 260} 261