1<?php 2 3/** 4 * webtrees: online genealogy 5 * Copyright (C) 2020 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\Webtrees\Carbon; 23use Fisharebest\Webtrees\Factory; 24use Fisharebest\Webtrees\Family; 25use Fisharebest\Webtrees\Gedcom; 26use Fisharebest\Webtrees\Header; 27use Fisharebest\Webtrees\Http\ViewResponseTrait; 28use Fisharebest\Webtrees\I18N; 29use Fisharebest\Webtrees\Individual; 30use Fisharebest\Webtrees\Location; 31use Fisharebest\Webtrees\Media; 32use Fisharebest\Webtrees\Note; 33use Fisharebest\Webtrees\Repository; 34use Fisharebest\Webtrees\Services\TreeService; 35use Fisharebest\Webtrees\Source; 36use Fisharebest\Webtrees\Submission; 37use Fisharebest\Webtrees\Submitter; 38use Fisharebest\Webtrees\Tree; 39use Illuminate\Database\Capsule\Manager as DB; 40use Psr\Http\Message\ResponseInterface; 41use Psr\Http\Message\ServerRequestInterface; 42use Psr\Http\Server\RequestHandlerInterface; 43 44use function assert; 45use function key; 46use function preg_match; 47use function reset; 48use function route; 49 50/** 51 * Show all pending changes. 52 */ 53class PendingChanges implements RequestHandlerInterface 54{ 55 use ViewResponseTrait; 56 57 /** @var TreeService */ 58 private $tree_service; 59 60 /** 61 * @param TreeService $tree_service 62 */ 63 public function __construct(TreeService $tree_service) 64 { 65 $this->tree_service = $tree_service; 66 } 67 68 /** 69 * @param ServerRequestInterface $request 70 * 71 * @return ResponseInterface 72 */ 73 public function handle(ServerRequestInterface $request): ResponseInterface 74 { 75 $tree = $request->getAttribute('tree'); 76 assert($tree instanceof Tree); 77 78 $url = $request->getQueryParams()['url'] ?? route(TreePage::class, ['tree' => $tree->name()]); 79 80 $rows = DB::table('change') 81 ->join('user', 'user.user_id', '=', 'change.user_id') 82 ->join('gedcom', 'gedcom.gedcom_id', '=', 'change.gedcom_id') 83 ->where('status', '=', 'pending') 84 ->orderBy('change.gedcom_id') 85 ->orderBy('change.xref') 86 ->orderBy('change.change_id') 87 ->select(['change.*', 'user.user_name', 'user.real_name', 'gedcom_name']) 88 ->get(); 89 90 $changes = []; 91 foreach ($rows as $row) { 92 $row->change_time = Carbon::make($row->change_time); 93 94 $change_tree = $this->tree_service->all()->get($row->gedcom_name); 95 96 preg_match('/^0 (?:@' . Gedcom::REGEX_XREF . '@ )?(' . Gedcom::REGEX_TAG . ')/', $row->old_gedcom . $row->new_gedcom, $match); 97 98 switch ($match[1]) { 99 case Individual::RECORD_TYPE: 100 $row->record = Factory::individual()->new($row->xref, $row->old_gedcom, $row->new_gedcom, $change_tree); 101 break; 102 case Family::RECORD_TYPE: 103 $row->record = Factory::family()->new($row->xref, $row->old_gedcom, $row->new_gedcom, $change_tree); 104 break; 105 case Source::RECORD_TYPE: 106 $row->record = Factory::source()->new($row->xref, $row->old_gedcom, $row->new_gedcom, $change_tree); 107 break; 108 case Repository::RECORD_TYPE: 109 $row->record = Factory::repository()->new($row->xref, $row->old_gedcom, $row->new_gedcom, $change_tree); 110 break; 111 case Media::RECORD_TYPE: 112 $row->record = Factory::media()->new($row->xref, $row->old_gedcom, $row->new_gedcom, $change_tree); 113 break; 114 case Note::RECORD_TYPE: 115 $row->record = Factory::note()->new($row->xref, $row->old_gedcom, $row->new_gedcom, $change_tree); 116 break; 117 case Submitter::RECORD_TYPE: 118 $row->record = Factory::submitter()->new($row->xref, $row->old_gedcom, $row->new_gedcom, $change_tree); 119 break; 120 case Submission::RECORD_TYPE: 121 $row->record = Factory::submission()->new($row->xref, $row->old_gedcom, $row->new_gedcom, $change_tree); 122 break; 123 case Location::RECORD_TYPE: 124 $row->record = Factory::location()->new($row->xref, $row->old_gedcom, $row->new_gedcom, $change_tree); 125 break; 126 case Header::RECORD_TYPE: 127 $row->record = Factory::header()->new($row->xref, $row->old_gedcom, $row->new_gedcom, $change_tree); 128 break; 129 default: 130 $row->record = Factory::gedcomRecord()->new($row->xref, $row->old_gedcom, $row->new_gedcom, $change_tree); 131 break; 132 } 133 134 $changes[$row->gedcom_name][$row->xref][] = $row; 135 } 136 137 $title = I18N::translate('Pending changes'); 138 139 // If the current tree has changes, activate that tab. Otherwise activate the first tab. 140 if (($changes[$tree->id()] ?? []) === []) { 141 reset($changes); 142 $active_tree_name = key($changes); 143 } else { 144 $active_tree_name = $tree->name(); 145 } 146 147 return $this->viewResponse('pending-changes-page', [ 148 'active_tree_name' => $active_tree_name, 149 'changes' => $changes, 150 'title' => $title, 151 'tree' => $tree, 152 'trees' => $this->tree_service->all(), 153 'url' => $url, 154 ]); 155 } 156} 157