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