1<?php 2 3/** 4 * webtrees: online genealogy 5 * Copyright (C) 2021 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 <https://www.gnu.org/licenses/>. 16 */ 17 18declare(strict_types=1); 19 20namespace Fisharebest\Webtrees\Services; 21 22use Fisharebest\Webtrees\Fact; 23use Fisharebest\Webtrees\GedcomRecord; 24use Fisharebest\Webtrees\Session; 25use Illuminate\Support\Collection; 26 27use function explode; 28 29/** 30 * Copy and past facts between records. 31 */ 32class ClipboardService 33{ 34 // Maximum number of entries in the clipboard. 35 private const CLIPBOARD_SIZE = 10; 36 37 /** 38 * Copy a fact to the clipboard. 39 * 40 * @param Fact $fact 41 */ 42 public function copyFact(Fact $fact): void 43 { 44 $clipboard = Session::get('clipboard', []); 45 $record_type = $fact->record()->tag(); 46 $fact_id = $fact->id(); 47 48 // If we are copying the same fact twice, make sure the new one is at the end. 49 unset($clipboard[$record_type][$fact_id]); 50 51 $clipboard[$record_type][$fact_id] = $fact->gedcom(); 52 53 // The clipboard only holds a limited number of facts. 54 $clipboard[$record_type] = array_slice($clipboard[$record_type], -self::CLIPBOARD_SIZE); 55 56 Session::put('clipboard', $clipboard); 57 } 58 59 /** 60 * Copy a fact from the clipboard to a record. 61 * 62 * @param string $fact_id 63 * @param GedcomRecord $record 64 * 65 * @return bool 66 */ 67 public function pasteFact(string $fact_id, GedcomRecord $record): bool 68 { 69 $clipboard = Session::get('clipboard'); 70 71 $record_type = $record->tag(); 72 73 if (isset($clipboard[$record_type][$fact_id])) { 74 $record->createFact($clipboard[$record_type][$fact_id], true); 75 76 return true; 77 } 78 79 return false; 80 } 81 82 /** 83 * Create a list of facts that can be pasted into a given record 84 * 85 * @param GedcomRecord $record 86 * 87 * @return Collection<Fact> 88 */ 89 public function pastableFacts(GedcomRecord $record): Collection 90 { 91 // The facts are stored in the session. 92 return (new Collection(Session::get('clipboard', [])[$record->tag()] ?? [])) 93 // Put the most recently copied fact at the top of the list. 94 ->reverse() 95 // Create facts for the record. 96 ->map(static function (string $clipping) use ($record): Fact { 97 return new Fact($clipping, $record, md5($clipping)); 98 }); 99 } 100 101 /** 102 * Find facts of a given type, from all records. 103 * 104 * @param GedcomRecord $record 105 * @param Collection $types 106 * 107 * @return Collection<Fact> 108 */ 109 public function pastableFactsOfType(GedcomRecord $record, Collection $types): Collection 110 { 111 // The facts are stored in the session. 112 return (new Collection(Session::get('clipboard', []))) 113 ->flatten(1) 114 ->reverse() 115 ->map(static function (string $clipping) use ($record): Fact { 116 return new Fact($clipping, $record, md5($clipping)); 117 }) 118 ->filter(static function (Fact $fact) use ($types): bool { 119 return $types->contains(explode(':', $fact->tag())[1]); 120 }); 121 } 122} 123