xref: /webtrees/app/Services/ClipboardService.php (revision c0dc1dc8776d0d9214741483e39305c5e08e2358)
1<?php
2/**
3 * webtrees: online genealogy
4 * Copyright (C) 2018 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\Services;
19
20use Fisharebest\Webtrees\Fact;
21use Fisharebest\Webtrees\GedcomRecord;
22use Fisharebest\Webtrees\Session;
23
24/**
25 * Copy and past facts between records.
26 */
27class ClipboardService
28{
29    // Maximum number of entries in the clipboard.
30    private const CLIPBOARD_SIZE = 10;
31
32    /**
33     * Copy a fact to the clipboard.
34     *
35     * @param Fact $fact
36     */
37    public function copyFact(Fact $fact): void {
38        $clipboard = Session::get('clipboard', []);
39
40        switch ($fact->getTag()) {
41            case 'NOTE':
42            case 'SOUR':
43            case 'OBJE':
44                // paste this anywhere
45                $type = 'all';
46                break;
47            default:
48                // paste only to the same record type
49                $type = $fact->record()::RECORD_TYPE;
50                break;
51        }
52
53        // If we are copying the same fact twice, make sure the new one is at the top.
54        $fact_id = $fact->id();
55
56        unset($clipboard[$fact_id]);
57
58        $clipboard[$fact_id] = [
59            'type'    => $type,
60            'factrec' => $fact->gedcom(),
61            'fact'    => $fact->getTag(),
62        ];
63
64        // The clipboard only holds a limited number of facts.
65        $clipboard = array_slice($clipboard, -self::CLIPBOARD_SIZE);
66
67        Session::put('clipboard', $clipboard);
68    }
69
70    /**
71     * Copy a fact from the clipboard to a record.
72     *
73     * @param string       $fact_id
74     * @param GedcomRecord $record
75     *
76     * @return bool
77     */
78    public function pasteFact(string $fact_id, GedcomRecord $record): bool {
79        $clipboard = Session::get('clipboard');
80
81        if (isset($clipboard[$fact_id])) {
82            $record->createFact($clipboard[$fact_id]['factrec'], true);
83            return true;
84        }
85
86        return false;
87    }
88
89    /**
90     * Createa a list of facts that can be pasted into a given record
91     *
92     * @param GedcomRecord $gedcom_record
93     *
94     * @return Fact[]
95     */
96    public function pastableFacts(GedcomRecord $gedcom_record): array {
97        // The facts are stored in the session.
98        $clipboard = Session::get('clipboard', []);
99
100        // Put the most recently copied fact at the top of the list.
101        $clipboard = array_reverse($clipboard);
102
103        // Only include facts that can be pasted onto this record.
104        $clipboard = array_filter($clipboard, function(array $clipping) use ($gedcom_record): bool {
105            return $clipping['type'] == $gedcom_record::RECORD_TYPE || $clipping['type'] == 'all';
106        });
107
108        // Create facts for the record.
109        $facts = array_map(function(array $clipping) use ($gedcom_record): Fact {
110            return new Fact($clipping['factrec'], $gedcom_record, md5($clipping['factrec']));
111        }, $clipboard);
112
113        return $facts;
114    }
115}
116