1<?php 2 3/** 4 * webtrees: online genealogy 5 * Copyright (C) 2019 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 <http://www.gnu.org/licenses/>. 16 */ 17 18declare(strict_types=1); 19 20namespace Fisharebest\Webtrees\Http\RequestHandlers; 21 22use Fisharebest\Algorithm\MyersDiff; 23use Fisharebest\Webtrees\Carbon; 24use Fisharebest\Webtrees\Gedcom; 25use Fisharebest\Webtrees\GedcomRecord; 26use Fisharebest\Webtrees\I18N; 27use Fisharebest\Webtrees\Services\DatatablesService; 28use Fisharebest\Webtrees\Services\PendingChangesService; 29use Fisharebest\Webtrees\Services\TreeService; 30use Fisharebest\Webtrees\Tree; 31use InvalidArgumentException; 32use Psr\Http\Message\ResponseInterface; 33use Psr\Http\Message\ServerRequestInterface; 34use Psr\Http\Server\RequestHandlerInterface; 35use stdClass; 36 37use function e; 38use function explode; 39use function implode; 40use function preg_replace_callback; 41 42/** 43 * Find pending changes. 44 */ 45class PendingChangesLogData implements RequestHandlerInterface 46{ 47 /** @var DatatablesService */ 48 private $datatables_service; 49 50 /** @var MyersDiff */ 51 private $myers_diff; 52 53 /** @var PendingChangesService */ 54 private $pending_changes_service; 55 56 /** @var TreeService */ 57 private $tree_service; 58 59 /** 60 * @param DatatablesService $datatables_service 61 * @param MyersDiff $myers_diff 62 * @param PendingChangesService $pending_changes_service 63 * @param TreeService $tree_service 64 */ 65 public function __construct( 66 DatatablesService $datatables_service, 67 MyersDiff $myers_diff, 68 PendingChangesService $pending_changes_service, 69 TreeService $tree_service 70 ) { 71 $this->datatables_service = $datatables_service; 72 $this->myers_diff = $myers_diff; 73 $this->pending_changes_service = $pending_changes_service; 74 $this->tree_service = $tree_service; 75 } 76 77 /** 78 * @param ServerRequestInterface $request 79 * 80 * @return ResponseInterface 81 */ 82 public function handle(ServerRequestInterface $request): ResponseInterface 83 { 84 $tree = $request->getAttribute('tree'); 85 assert($tree instanceof Tree, new InvalidArgumentException()); 86 87 $query = $this->pending_changes_service->changesQuery($request); 88 89 $callback = function (stdClass $row) use ($tree): array { 90 $old_lines = explode("\n", $row->old_gedcom); 91 $new_lines = explode("\n", $row->new_gedcom); 92 93 $differences = $this->myers_diff->calculate($old_lines, $new_lines); 94 $diff_lines = []; 95 96 foreach ($differences as $difference) { 97 switch ($difference[1]) { 98 case MyersDiff::DELETE: 99 $diff_lines[] = '<del>' . $difference[0] . '</del>'; 100 break; 101 case MyersDiff::INSERT: 102 $diff_lines[] = '<ins>' . $difference[0] . '</ins>'; 103 break; 104 default: 105 $diff_lines[] = $difference[0]; 106 } 107 } 108 109 // Only convert valid xrefs to links 110 $record = GedcomRecord::getInstance($row->xref, $tree); 111 112 return [ 113 $row->change_id, 114 Carbon::make($row->change_time)->local()->format('Y-m-d H:i:s'), 115 I18N::translate($row->status), 116 $record ? '<a href="' . e($record->url()) . '">' . $record->xref() . '</a>' : $row->xref, 117 '<div class="gedcom-data" dir="ltr">' . 118 preg_replace_callback( 119 '/@(' . Gedcom::REGEX_XREF . ')@/', 120 static function (array $match) use ($tree): string { 121 $record = GedcomRecord::getInstance($match[1], $tree); 122 123 return $record ? '<a href="' . e($record->url()) . '">' . $match[0] . '</a>' : $match[0]; 124 }, 125 implode("\n", $diff_lines) 126 ) . 127 '</div>', 128 $row->user_name, 129 $row->gedcom_name, 130 ]; 131 }; 132 133 return $this->datatables_service->handle($request, $query, [], [], $callback); 134 } 135} 136