1<?php 2 3/** 4 * webtrees: online genealogy 5 * Copyright (C) 2023 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\Algorithm\MyersDiff; 23use Fisharebest\Webtrees\Family; 24use Fisharebest\Webtrees\Gedcom; 25use Fisharebest\Webtrees\GedcomRecord; 26use Fisharebest\Webtrees\Individual; 27use Fisharebest\Webtrees\Media; 28use Fisharebest\Webtrees\Note; 29use Fisharebest\Webtrees\Registry; 30use Fisharebest\Webtrees\Repository; 31use Fisharebest\Webtrees\Source; 32use Fisharebest\Webtrees\Submitter; 33use Fisharebest\Webtrees\Tree; 34 35use function e; 36use function explode; 37use function implode; 38use function preg_replace_callback; 39use function strip_tags; 40 41/** 42 * Bulk updates on genealogy data 43 */ 44class DataFixService 45{ 46 /** 47 * Since we know the type, this is quicker than calling Registry::gedcomRecordFactory()->make(). 48 */ 49 public function getRecordByType(string $xref, Tree $tree, string $type): GedcomRecord|null 50 { 51 switch ($type) { 52 case Family::RECORD_TYPE: 53 return Registry::familyFactory()->make($xref, $tree); 54 55 case Individual::RECORD_TYPE: 56 return Registry::individualFactory()->make($xref, $tree); 57 58 case Note::RECORD_TYPE: 59 return Registry::noteFactory()->make($xref, $tree); 60 61 case Media::RECORD_TYPE: 62 return Registry::mediaFactory()->make($xref, $tree); 63 64 case Repository::RECORD_TYPE: 65 return Registry::repositoryFactory()->make($xref, $tree); 66 67 case Source::RECORD_TYPE: 68 return Registry::sourceFactory()->make($xref, $tree); 69 70 case Submitter::RECORD_TYPE: 71 return Registry::submitterFactory()->make($xref, $tree); 72 73 default: 74 return Registry::gedcomRecordFactory()->make($xref, $tree); 75 } 76 } 77 78 /** 79 * Default preview generator. 80 * 81 * @param Tree $tree 82 * @param string $old_gedcom 83 * @param string $new_gedcom 84 * 85 * @return string 86 */ 87 public function gedcomDiff(Tree $tree, string $old_gedcom, string $new_gedcom): string 88 { 89 $old_lines = explode("\n", $old_gedcom); 90 $new_lines = explode("\n", $new_gedcom); 91 $algorithm = new MyersDiff(); 92 $differences = $algorithm->calculate($old_lines, $new_lines); 93 $diff_lines = []; 94 95 foreach ($differences as $difference) { 96 switch ($difference[1]) { 97 case MyersDiff::DELETE: 98 $diff_lines[] = '<del>' . e($difference[0]) . '</del><br>'; 99 break; 100 case MyersDiff::INSERT: 101 $diff_lines[] = '<ins>' . e($difference[0]) . '</ins><br>'; 102 break; 103 case MyersDiff::KEEP: 104 $diff_lines[] = e($difference[0]) . '<br>'; 105 break; 106 } 107 } 108 109 $html = implode('', $diff_lines); 110 111 $html = preg_replace_callback('/@(' . Gedcom::REGEX_XREF . ')@/', static function (array $match) use ($tree): string { 112 $record = Registry::gedcomRecordFactory()->make($match[0], $tree); 113 114 if ($record instanceof GedcomRecord) { 115 $title = strip_tags($record->fullName()); 116 $href = e($record->url()); 117 118 return '<a href="' . $href . '" title="' . $title . '">' . $match[0] . '</a>'; 119 } 120 121 return $match[0]; 122 }, $html); 123 124 return '<pre class="gedcom-data">' . $html . '</pre>'; 125 } 126} 127