xref: /webtrees/app/Module/UpcomingAnniversariesModule.php (revision e24053e5c68a36a62ca2714caf7fca093e7dc791)
18c2e8227SGreg Roach<?php
23976b470SGreg Roach
38c2e8227SGreg Roach/**
48c2e8227SGreg Roach * webtrees: online genealogy
58fcd0d32SGreg Roach * Copyright (C) 2019 webtrees development team
68c2e8227SGreg Roach * This program is free software: you can redistribute it and/or modify
78c2e8227SGreg Roach * it under the terms of the GNU General Public License as published by
88c2e8227SGreg Roach * the Free Software Foundation, either version 3 of the License, or
98c2e8227SGreg Roach * (at your option) any later version.
108c2e8227SGreg Roach * This program is distributed in the hope that it will be useful,
118c2e8227SGreg Roach * but WITHOUT ANY WARRANTY; without even the implied warranty of
128c2e8227SGreg Roach * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
138c2e8227SGreg Roach * GNU General Public License for more details.
148c2e8227SGreg Roach * You should have received a copy of the GNU General Public License
158c2e8227SGreg Roach * along with this program. If not, see <http://www.gnu.org/licenses/>.
168c2e8227SGreg Roach */
17fcfa147eSGreg Roach
18e7f56f2aSGreg Roachdeclare(strict_types=1);
19e7f56f2aSGreg Roach
2076692c8bSGreg Roachnamespace Fisharebest\Webtrees\Module;
2176692c8bSGreg Roach
224459dc9aSGreg Roachuse Fisharebest\Webtrees\Carbon;
238d0ebef0SGreg Roachuse Fisharebest\Webtrees\Gedcom;
2412664b30SGreg Roachuse Fisharebest\Webtrees\GedcomTag;
250e62c4b8SGreg Roachuse Fisharebest\Webtrees\I18N;
26f0a11419SGreg Roachuse Fisharebest\Webtrees\Services\CalendarService;
27e490cd80SGreg Roachuse Fisharebest\Webtrees\Tree;
281e7a7a28SGreg Roachuse Illuminate\Support\Str;
296ccdf4f0SGreg Roachuse Psr\Http\Message\ServerRequestInterface;
308c2e8227SGreg Roach
318c2e8227SGreg Roach/**
328c2e8227SGreg Roach * Class UpcomingAnniversariesModule
338c2e8227SGreg Roach */
3437eb8894SGreg Roachclass UpcomingAnniversariesModule extends AbstractModule implements ModuleBlockInterface
35c1010edaSGreg Roach{
3649a243cbSGreg Roach    use ModuleBlockTrait;
3749a243cbSGreg Roach
38c385536dSGreg Roach    // Default values for new blocks.
3916d6367aSGreg Roach    private const DEFAULT_DAYS   = '7';
4016d6367aSGreg Roach    private const DEFAULT_FILTER = '1';
4116d6367aSGreg Roach    private const DEFAULT_SORT   = 'alpha';
4216d6367aSGreg Roach    private const DEFAULT_STYLE  = 'table';
43c385536dSGreg Roach
44c385536dSGreg Roach    // Can show this number of days into the future.
4516d6367aSGreg Roach    private const MIN_DAYS = 1;
4616d6367aSGreg Roach    private const MAX_DAYS = 30;
47c385536dSGreg Roach
4812664b30SGreg Roach    // All standard GEDCOM 5.5.1 events except CENS, RESI and EVEN
4916d6367aSGreg Roach    private const ALL_EVENTS = [
5012664b30SGreg Roach        'ADOP',
5112664b30SGreg Roach        'ANUL',
5212664b30SGreg Roach        'BAPM',
5312664b30SGreg Roach        'BARM',
5412664b30SGreg Roach        'BASM',
5512664b30SGreg Roach        'BIRT',
5612664b30SGreg Roach        'BLES',
5712664b30SGreg Roach        'BURI',
5812664b30SGreg Roach        'CHR',
5912664b30SGreg Roach        'CHRA',
6012664b30SGreg Roach        'CONF',
6112664b30SGreg Roach        'CREM',
6212664b30SGreg Roach        'DEAT',
6312664b30SGreg Roach        'DIV',
6412664b30SGreg Roach        'DIVF',
6512664b30SGreg Roach        'EMIG',
6612664b30SGreg Roach        'ENGA',
6712664b30SGreg Roach        'FCOM',
6812664b30SGreg Roach        'GRAD',
6912664b30SGreg Roach        'IMMI',
7012664b30SGreg Roach        'MARB',
7112664b30SGreg Roach        'MARC',
7212664b30SGreg Roach        'MARL',
7312664b30SGreg Roach        'MARR',
7412664b30SGreg Roach        'MARS',
7512664b30SGreg Roach        'NATU',
7612664b30SGreg Roach        'ORDN',
7712664b30SGreg Roach        'PROB',
7812664b30SGreg Roach        'RETI',
7912664b30SGreg Roach        'WILL',
8012664b30SGreg Roach    ];
8112664b30SGreg Roach
8216d6367aSGreg Roach    private const DEFAULT_EVENTS = [
8312664b30SGreg Roach        'BIRT',
8412664b30SGreg Roach        'MARR',
8512664b30SGreg Roach        'DEAT',
8612664b30SGreg Roach    ];
8712664b30SGreg Roach
8876692c8bSGreg Roach    /**
890cfd6963SGreg Roach     * How should this module be identified in the control panel, etc.?
9076692c8bSGreg Roach     *
9176692c8bSGreg Roach     * @return string
9276692c8bSGreg Roach     */
9349a243cbSGreg Roach    public function title(): string
94c1010edaSGreg Roach    {
95bbb76c12SGreg Roach        /* I18N: Name of a module */
96bbb76c12SGreg Roach        return I18N::translate('Upcoming events');
978c2e8227SGreg Roach    }
988c2e8227SGreg Roach
9976692c8bSGreg Roach    /**
10076692c8bSGreg Roach     * A sentence describing what this module does.
10176692c8bSGreg Roach     *
10276692c8bSGreg Roach     * @return string
10376692c8bSGreg Roach     */
10449a243cbSGreg Roach    public function description(): string
105c1010edaSGreg Roach    {
106bbb76c12SGreg Roach        /* I18N: Description of the “Upcoming events” module */
107bbb76c12SGreg Roach        return I18N::translate('A list of the anniversaries that will occur in the near future.');
1088c2e8227SGreg Roach    }
1098c2e8227SGreg Roach
11076692c8bSGreg Roach    /**
11176692c8bSGreg Roach     * Generate the HTML content of this block.
11276692c8bSGreg Roach     *
113e490cd80SGreg Roach     * @param Tree     $tree
11476692c8bSGreg Roach     * @param int      $block_id
1153caaa4d2SGreg Roach     * @param string   $context
1163caaa4d2SGreg Roach     * @param string[] $config
11776692c8bSGreg Roach     *
11876692c8bSGreg Roach     * @return string
11976692c8bSGreg Roach     */
1203caaa4d2SGreg Roach    public function getBlock(Tree $tree, int $block_id, string $context, array $config = []): string
121c1010edaSGreg Roach    {
122f0a11419SGreg Roach        $calendar_service = new CalendarService();
123f0a11419SGreg Roach
12412664b30SGreg Roach        $default_events = implode(',', self::DEFAULT_EVENTS);
12512664b30SGreg Roach
12676f666f4SGreg Roach        $days      = (int) $this->getBlockSetting($block_id, 'days', self::DEFAULT_DAYS);
127c385536dSGreg Roach        $filter    = (bool) $this->getBlockSetting($block_id, 'filter', self::DEFAULT_FILTER);
128c385536dSGreg Roach        $infoStyle = $this->getBlockSetting($block_id, 'infoStyle', self::DEFAULT_STYLE);
129c385536dSGreg Roach        $sortStyle = $this->getBlockSetting($block_id, 'sortStyle', self::DEFAULT_SORT);
13012664b30SGreg Roach        $events    = $this->getBlockSetting($block_id, 'events', $default_events);
1318c2e8227SGreg Roach
1323caaa4d2SGreg Roach        extract($config, EXTR_OVERWRITE);
1338c2e8227SGreg Roach
13412664b30SGreg Roach        $event_array = explode(',', $events);
13512664b30SGreg Roach
13612664b30SGreg Roach        // If we are only showing living individuals, then we don't need to search for DEAT events.
13712664b30SGreg Roach        if ($filter) {
1388d0ebef0SGreg Roach            $event_array  = array_diff($event_array, Gedcom::DEATH_EVENTS);
13912664b30SGreg Roach        }
14012664b30SGreg Roach
14112664b30SGreg Roach        $events_filter = implode('|', $event_array);
14212664b30SGreg Roach
1434459dc9aSGreg Roach        $startjd = Carbon::now()->julianDay() + 1;
1444459dc9aSGreg Roach        $endjd   = Carbon::now()->julianDay() + $days;
14512664b30SGreg Roach
146f0a11419SGreg Roach        $facts = $calendar_service->getEventsList($startjd, $endjd, $events_filter, $filter, $sortStyle, $tree);
14712664b30SGreg Roach
148cd51dbdfSGreg Roach        if ($facts->isEmpty()) {
149d8189b6aSDavid Drury            if ($endjd == $startjd) {
150147e99aaSGreg Roach                $content = view('modules/upcoming_events/empty', [
151c1010edaSGreg Roach                    'message' => I18N::translate('No events exist for tomorrow.'),
1520280f44aSGreg Roach                ]);
153d8189b6aSDavid Drury            } else {
154bbb76c12SGreg Roach                /* I18N: translation for %s==1 is unused; it is translated separately as “tomorrow” */                $content = view('modules/upcoming_events/empty', [
155bbb76c12SGreg Roach                    'message' => I18N::plural('No events exist for the next %s day.', 'No events exist for the next %s days.', $endjd - $startjd + 1, I18N::number($endjd - $startjd + 1)),
1560280f44aSGreg Roach                ]);
1578c2e8227SGreg Roach            }
158147e99aaSGreg Roach        } elseif ($infoStyle === 'list') {
15948f08416SGreg Roach            $content = view('lists/anniversaries-list', [
160*e24053e5SGreg Roach                'id'    => $block_id,
161d8189b6aSDavid Drury                'facts' => $facts,
162*e24053e5SGreg Roach                'limit' => 10,
163147e99aaSGreg Roach            ]);
164147e99aaSGreg Roach        } else {
16548f08416SGreg Roach            $content = view('lists/anniversaries-table', [
166147e99aaSGreg Roach                'facts' => $facts,
167*e24053e5SGreg Roach                'limit' => 10,
168147e99aaSGreg Roach            ]);
1690280f44aSGreg Roach        }
1708c2e8227SGreg Roach
1713caaa4d2SGreg Roach        if ($context !== self::CONTEXT_EMBED) {
172147e99aaSGreg Roach            return view('modules/block-template', [
1731e7a7a28SGreg Roach                'block'      => Str::kebab($this->name()),
1749c6524dcSGreg Roach                'id'         => $block_id,
1753caaa4d2SGreg Roach                'config_url' => $this->configUrl($tree, $context, $block_id),
17649a243cbSGreg Roach                'title'      => $this->title(),
1779c6524dcSGreg Roach                'content'    => $content,
1789c6524dcSGreg Roach            ]);
1798c2e8227SGreg Roach        }
180b2ce94c6SRico Sonntag
181b2ce94c6SRico Sonntag        return $content;
1828c2e8227SGreg Roach    }
1838c2e8227SGreg Roach
1843caaa4d2SGreg Roach    /**
1853caaa4d2SGreg Roach     * Should this block load asynchronously using AJAX?
1863caaa4d2SGreg Roach     *
1873caaa4d2SGreg Roach     * Simple blocks are faster in-line, more complex ones can be loaded later.
1883caaa4d2SGreg Roach     *
1893caaa4d2SGreg Roach     * @return bool
1903caaa4d2SGreg Roach     */
191c1010edaSGreg Roach    public function loadAjax(): bool
192c1010edaSGreg Roach    {
1938c2e8227SGreg Roach        return true;
1948c2e8227SGreg Roach    }
1958c2e8227SGreg Roach
1963caaa4d2SGreg Roach    /**
1973caaa4d2SGreg Roach     * Can this block be shown on the user’s home page?
1983caaa4d2SGreg Roach     *
1993caaa4d2SGreg Roach     * @return bool
2003caaa4d2SGreg Roach     */
201c1010edaSGreg Roach    public function isUserBlock(): bool
202c1010edaSGreg Roach    {
2038c2e8227SGreg Roach        return true;
2048c2e8227SGreg Roach    }
2058c2e8227SGreg Roach
2063caaa4d2SGreg Roach    /**
2073caaa4d2SGreg Roach     * Can this block be shown on the tree’s home page?
2083caaa4d2SGreg Roach     *
2093caaa4d2SGreg Roach     * @return bool
2103caaa4d2SGreg Roach     */
21163276d8fSGreg Roach    public function isTreeBlock(): bool
212c1010edaSGreg Roach    {
2138c2e8227SGreg Roach        return true;
2148c2e8227SGreg Roach    }
2158c2e8227SGreg Roach
21676692c8bSGreg Roach    /**
217a45f9889SGreg Roach     * Update the configuration for a block.
218a45f9889SGreg Roach     *
2196ccdf4f0SGreg Roach     * @param ServerRequestInterface $request
220a45f9889SGreg Roach     * @param int     $block_id
221a45f9889SGreg Roach     *
222a45f9889SGreg Roach     * @return void
223a45f9889SGreg Roach     */
2246ccdf4f0SGreg Roach    public function saveBlockConfiguration(ServerRequestInterface $request, int $block_id): void
225a45f9889SGreg Roach    {
226b46c87bdSGreg Roach        $params = (array) $request->getParsedBody();
227c50a90beSGreg Roach
228c50a90beSGreg Roach        $this->setBlockSetting($block_id, 'days', $params['days']);
229c50a90beSGreg Roach        $this->setBlockSetting($block_id, 'filter', $params['filter']);
230c50a90beSGreg Roach        $this->setBlockSetting($block_id, 'infoStyle', $params['infoStyle']);
231c50a90beSGreg Roach        $this->setBlockSetting($block_id, 'sortStyle', $params['sortStyle']);
232c50a90beSGreg Roach        $this->setBlockSetting($block_id, 'events', implode(',', $params['events'] ?? []));
233a45f9889SGreg Roach    }
234a45f9889SGreg Roach
235a45f9889SGreg Roach    /**
23676692c8bSGreg Roach     * An HTML form to edit block settings
23776692c8bSGreg Roach     *
238e490cd80SGreg Roach     * @param Tree $tree
23976692c8bSGreg Roach     * @param int  $block_id
240a9430be8SGreg Roach     *
2413caaa4d2SGreg Roach     * @return string
24276692c8bSGreg Roach     */
2433caaa4d2SGreg Roach    public function editBlockConfiguration(Tree $tree, int $block_id): string
244c1010edaSGreg Roach    {
24512664b30SGreg Roach        $default_events = implode(',', self::DEFAULT_EVENTS);
24612664b30SGreg Roach
24776f666f4SGreg Roach        $days      = (int) $this->getBlockSetting($block_id, 'days', self::DEFAULT_DAYS);
248c385536dSGreg Roach        $filter    = $this->getBlockSetting($block_id, 'filter', self::DEFAULT_FILTER);
249c385536dSGreg Roach        $infoStyle = $this->getBlockSetting($block_id, 'infoStyle', self::DEFAULT_STYLE);
250c385536dSGreg Roach        $sortStyle = $this->getBlockSetting($block_id, 'sortStyle', self::DEFAULT_SORT);
25112664b30SGreg Roach        $events    = $this->getBlockSetting($block_id, 'events', $default_events);
2528c2e8227SGreg Roach
25312664b30SGreg Roach        $event_array = explode(',', $events);
25412664b30SGreg Roach
25512664b30SGreg Roach        $all_events = [];
25612664b30SGreg Roach        foreach (self::ALL_EVENTS as $event) {
25712664b30SGreg Roach            $all_events[$event] = GedcomTag::getLabel($event);
25812664b30SGreg Roach        }
25912664b30SGreg Roach
260c385536dSGreg Roach        $info_styles = [
261bbb76c12SGreg Roach            /* I18N: An option in a list-box */
262bbb76c12SGreg Roach            'list'  => I18N::translate('list'),
263bbb76c12SGreg Roach            /* I18N: An option in a list-box */
264bbb76c12SGreg Roach            'table' => I18N::translate('table'),
265c385536dSGreg Roach        ];
2668c2e8227SGreg Roach
267c385536dSGreg Roach        $sort_styles = [
268bbb76c12SGreg Roach            /* I18N: An option in a list-box */
269bbb76c12SGreg Roach            'alpha' => I18N::translate('sort by name'),
270bbb76c12SGreg Roach            /* I18N: An option in a list-box */
271bbb76c12SGreg Roach            'anniv' => I18N::translate('sort by date'),
272c385536dSGreg Roach        ];
2738c2e8227SGreg Roach
2743caaa4d2SGreg Roach        return view('modules/upcoming_events/config', [
275c385536dSGreg Roach            'all_events'  => $all_events,
276c385536dSGreg Roach            'days'        => $days,
277c385536dSGreg Roach            'event_array' => $event_array,
278c385536dSGreg Roach            'filter'      => $filter,
279c385536dSGreg Roach            'infoStyle'   => $infoStyle,
280c385536dSGreg Roach            'info_styles' => $info_styles,
281c385536dSGreg Roach            'max_days'    => self::MAX_DAYS,
282c385536dSGreg Roach            'sortStyle'   => $sortStyle,
283c385536dSGreg Roach            'sort_styles' => $sort_styles,
284c385536dSGreg Roach        ]);
2858c2e8227SGreg Roach    }
2868c2e8227SGreg Roach}
287