xref: /webtrees/app/Services/ClipboardService.php (revision 8fcd0d32e56ee262912bbdb593202cfd1cbc1615)
1c0dc1dc8SGreg Roach<?php
2c0dc1dc8SGreg Roach/**
3c0dc1dc8SGreg Roach * webtrees: online genealogy
4*8fcd0d32SGreg Roach * Copyright (C) 2019 webtrees development team
5c0dc1dc8SGreg Roach * This program is free software: you can redistribute it and/or modify
6c0dc1dc8SGreg Roach * it under the terms of the GNU General Public License as published by
7c0dc1dc8SGreg Roach * the Free Software Foundation, either version 3 of the License, or
8c0dc1dc8SGreg Roach * (at your option) any later version.
9c0dc1dc8SGreg Roach * This program is distributed in the hope that it will be useful,
10c0dc1dc8SGreg Roach * but WITHOUT ANY WARRANTY; without even the implied warranty of
11c0dc1dc8SGreg Roach * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12c0dc1dc8SGreg Roach * GNU General Public License for more details.
13c0dc1dc8SGreg Roach * You should have received a copy of the GNU General Public License
14c0dc1dc8SGreg Roach * along with this program. If not, see <http://www.gnu.org/licenses/>.
15c0dc1dc8SGreg Roach */
16c0dc1dc8SGreg Roachdeclare(strict_types=1);
17c0dc1dc8SGreg Roach
18c0dc1dc8SGreg Roachnamespace Fisharebest\Webtrees\Services;
19c0dc1dc8SGreg Roach
20c0dc1dc8SGreg Roachuse Fisharebest\Webtrees\Fact;
21c0dc1dc8SGreg Roachuse Fisharebest\Webtrees\GedcomRecord;
22c0dc1dc8SGreg Roachuse Fisharebest\Webtrees\Session;
23c0dc1dc8SGreg Roach
24c0dc1dc8SGreg Roach/**
25c0dc1dc8SGreg Roach * Copy and past facts between records.
26c0dc1dc8SGreg Roach */
27c0dc1dc8SGreg Roachclass ClipboardService
28c0dc1dc8SGreg Roach{
29c0dc1dc8SGreg Roach    // Maximum number of entries in the clipboard.
30c0dc1dc8SGreg Roach    private const CLIPBOARD_SIZE = 10;
31c0dc1dc8SGreg Roach
32b8361dd5SGreg Roach    // Some facts can be copied to multiple types of record.
33b8361dd5SGreg Roach    // Others can only be copied to the same type.
34b8361dd5SGreg Roach    // NOTE: just because GEDCOM permits these, it doesn't mean that they are advisable.
35b8361dd5SGreg Roach    private const DESTINATION_TYPES = [
36b8361dd5SGreg Roach        'CENS' => ['FAM', 'INDI'],
37b8361dd5SGreg Roach        'RESI' => ['FAM', 'INDI'],
38b8361dd5SGreg Roach        'NOTE' => ['FAM', 'INDI', 'OBJE', 'REPO', 'SOUR'],
39b8361dd5SGreg Roach        'OBJE' => ['FAM', 'INDI', 'NOTE', 'SOUR'],
40b8361dd5SGreg Roach        'SOUR' => ['FAM', 'INDI', 'NOTE', 'OBJE'],
41b8361dd5SGreg Roach    ];
42b8361dd5SGreg Roach
43c0dc1dc8SGreg Roach    /**
44c0dc1dc8SGreg Roach     * Copy a fact to the clipboard.
45c0dc1dc8SGreg Roach     *
46c0dc1dc8SGreg Roach     * @param Fact $fact
47c0dc1dc8SGreg Roach     */
4852a04bc1SGreg Roach    public function copyFact(Fact $fact): void
4952a04bc1SGreg Roach    {
50c0dc1dc8SGreg Roach        $clipboard = Session::get('clipboard', []);
51c0dc1dc8SGreg Roach
52b8361dd5SGreg Roach        $fact_type   = $fact->getTag();
53b8361dd5SGreg Roach        $record_type = $fact->record()::RECORD_TYPE;
54c0dc1dc8SGreg Roach
55b8361dd5SGreg Roach        $destination_types = self::DESTINATION_TYPES[$fact_type] ?? [$record_type];
56b8361dd5SGreg Roach
57c0dc1dc8SGreg Roach        $fact_id = $fact->id();
58c0dc1dc8SGreg Roach
59b8361dd5SGreg Roach        foreach ($destination_types as $destination_type) {
60b8361dd5SGreg Roach            // If we are copying the same fact twice, make sure the new one is at the end.
61b8361dd5SGreg Roach            unset($clipboard[$destination_type][$fact_id]);
62c0dc1dc8SGreg Roach
63b8361dd5SGreg Roach            $clipboard[$destination_type][$fact_id] = [
64c0dc1dc8SGreg Roach                'factrec' => $fact->gedcom(),
65c0dc1dc8SGreg Roach                'fact'    => $fact->getTag(),
66c0dc1dc8SGreg Roach            ];
67c0dc1dc8SGreg Roach
68c0dc1dc8SGreg Roach            // The clipboard only holds a limited number of facts.
69b8361dd5SGreg Roach            $clipboard[$destination_type] = array_slice($clipboard[$destination_type], -self::CLIPBOARD_SIZE);
70b8361dd5SGreg Roach        }
71c0dc1dc8SGreg Roach
72c0dc1dc8SGreg Roach        Session::put('clipboard', $clipboard);
73c0dc1dc8SGreg Roach    }
74c0dc1dc8SGreg Roach
75c0dc1dc8SGreg Roach    /**
76c0dc1dc8SGreg Roach     * Copy a fact from the clipboard to a record.
77c0dc1dc8SGreg Roach     *
78c0dc1dc8SGreg Roach     * @param string       $fact_id
79c0dc1dc8SGreg Roach     * @param GedcomRecord $record
80c0dc1dc8SGreg Roach     *
81c0dc1dc8SGreg Roach     * @return bool
82c0dc1dc8SGreg Roach     */
8352a04bc1SGreg Roach    public function pasteFact(string $fact_id, GedcomRecord $record): bool
8452a04bc1SGreg Roach    {
85c0dc1dc8SGreg Roach        $clipboard = Session::get('clipboard');
86c0dc1dc8SGreg Roach
87b8361dd5SGreg Roach        $record_type = $record::RECORD_TYPE;
88b8361dd5SGreg Roach
89b8361dd5SGreg Roach        if (isset($clipboard[$record_type][$fact_id])) {
90b8361dd5SGreg Roach            $record->createFact($clipboard[$record_type][$fact_id]['factrec'], true);
91b8361dd5SGreg Roach
92c0dc1dc8SGreg Roach            return true;
93c0dc1dc8SGreg Roach        }
94c0dc1dc8SGreg Roach
95c0dc1dc8SGreg Roach        return false;
96c0dc1dc8SGreg Roach    }
97c0dc1dc8SGreg Roach
98c0dc1dc8SGreg Roach    /**
99c0dc1dc8SGreg Roach     * Createa a list of facts that can be pasted into a given record
100c0dc1dc8SGreg Roach     *
101b8361dd5SGreg Roach     * @param GedcomRecord $record
102c0dc1dc8SGreg Roach     *
103c0dc1dc8SGreg Roach     * @return Fact[]
104c0dc1dc8SGreg Roach     */
10552a04bc1SGreg Roach    public function pastableFacts(GedcomRecord $record): array
10652a04bc1SGreg Roach    {
107c0dc1dc8SGreg Roach        // The facts are stored in the session.
108c0dc1dc8SGreg Roach        $clipboard = Session::get('clipboard', []);
109c0dc1dc8SGreg Roach
110c0dc1dc8SGreg Roach        // Put the most recently copied fact at the top of the list.
111b8361dd5SGreg Roach        $clipboard = array_reverse($clipboard[$record::RECORD_TYPE] ?? []);
112c0dc1dc8SGreg Roach
113c0dc1dc8SGreg Roach        // Create facts for the record.
114b8361dd5SGreg Roach        $facts = array_map(function (array $clipping) use ($record): Fact {
115b8361dd5SGreg Roach            return new Fact($clipping['factrec'], $record, md5($clipping['factrec']));
116c0dc1dc8SGreg Roach        }, $clipboard);
117c0dc1dc8SGreg Roach
118c0dc1dc8SGreg Roach        return $facts;
119c0dc1dc8SGreg Roach    }
120c0dc1dc8SGreg Roach}
121