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 * Empty the clipboard 84 * 85 * @return void 86 */ 87 public function emptyClipboard(): void 88 { 89 Session::put('clipboard', []); 90 } 91 92 /** 93 * Create a list of facts that can be pasted into a given record 94 * 95 * @param GedcomRecord $record 96 * 97 * @return Collection<Fact> 98 */ 99 public function pastableFacts(GedcomRecord $record): Collection 100 { 101 // The facts are stored in the session. 102 return (new Collection(Session::get('clipboard', [])[$record->tag()] ?? [])) 103 // Put the most recently copied fact at the top of the list. 104 ->reverse() 105 // Create facts for the record. 106 ->map(static function (string $clipping) use ($record): Fact { 107 return new Fact($clipping, $record, md5($clipping)); 108 }); 109 } 110 111 /** 112 * Find facts of a given type, from all records. 113 * 114 * @param GedcomRecord $record 115 * @param Collection $types 116 * 117 * @return Collection<Fact> 118 */ 119 public function pastableFactsOfType(GedcomRecord $record, Collection $types): Collection 120 { 121 // The facts are stored in the session. 122 return (new Collection(Session::get('clipboard', []))) 123 ->flatten(1) 124 ->reverse() 125 ->map(static function (string $clipping) use ($record): Fact { 126 return new Fact($clipping, $record, md5($clipping)); 127 }) 128 ->filter(static function (Fact $fact) use ($types): bool { 129 return $types->contains(explode(':', $fact->tag())[1]); 130 }); 131 } 132} 133