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\Services; 21 22use Fisharebest\Webtrees\Carbon; 23use Fisharebest\Webtrees\Functions\FunctionsImport; 24use Fisharebest\Webtrees\GedcomRecord; 25use Fisharebest\Webtrees\Tree; 26use Illuminate\Database\Capsule\Manager as DB; 27use Illuminate\Database\Query\Builder; 28use Illuminate\Database\Query\Expression; 29use InvalidArgumentException; 30use Psr\Http\Message\ServerRequestInterface; 31 32/** 33 * Manage pending changes 34 */ 35class PendingChangesService 36{ 37 /** 38 * Accept all changes to a tree. 39 * 40 * @param Tree $tree 41 * 42 * @return void 43 */ 44 public function acceptTree(Tree $tree): void 45 { 46 $changes = DB::table('change') 47 ->where('gedcom_id', '=', $tree->id()) 48 ->where('status', '=', 'pending') 49 ->orderBy('change_id') 50 ->get(); 51 52 foreach ($changes as $change) { 53 if ($change->new_gedcom === '') { 54 // delete 55 FunctionsImport::updateRecord($change->old_gedcom, $tree, true); 56 } else { 57 // add/update 58 FunctionsImport::updateRecord($change->new_gedcom, $tree, false); 59 } 60 61 DB::table('change') 62 ->where('change_id', '=', $change->change_id) 63 ->update(['status' => 'accepted']); 64 } 65 } 66 67 /** 68 * Accept all changes to a record. 69 * 70 * @param GedcomRecord $record 71 */ 72 public function acceptRecord(GedcomRecord $record): void 73 { 74 $changes = DB::table('change') 75 ->where('gedcom_id', '=', $record->tree()->id()) 76 ->where('xref', '=', $record->xref()) 77 ->where('status', '=', 'pending') 78 ->orderBy('change_id') 79 ->get(); 80 81 foreach ($changes as $change) { 82 if ($change->new_gedcom === '') { 83 // delete 84 FunctionsImport::updateRecord($change->old_gedcom, $record->tree(), true); 85 } else { 86 // add/update 87 FunctionsImport::updateRecord($change->new_gedcom, $record->tree(), false); 88 } 89 90 DB::table('change') 91 ->where('change_id', '=', $change->change_id) 92 ->update(['status' => 'accepted']); 93 } 94 } 95 96 /** 97 * Accept a change (and previous changes) to a record. 98 * 99 * @param GedcomRecord $record 100 * @param string $change_id 101 */ 102 public function acceptChange(GedcomRecord $record, string $change_id): void 103 { 104 $changes = DB::table('change') 105 ->where('gedcom_id', '=', $record->tree()->id()) 106 ->where('xref', '=', $record->xref()) 107 ->where('change_id', '<=', $change_id) 108 ->where('status', '=', 'pending') 109 ->orderBy('change_id') 110 ->get(); 111 112 foreach ($changes as $change) { 113 if ($change->new_gedcom === '') { 114 // delete 115 FunctionsImport::updateRecord($change->old_gedcom, $record->tree(), true); 116 } else { 117 // add/update 118 FunctionsImport::updateRecord($change->new_gedcom, $record->tree(), false); 119 } 120 121 DB::table('change') 122 ->where('change_id', '=', $change->change_id) 123 ->update(['status' => 'accepted']); 124 } 125 } 126 127 /** 128 * Reject all changes to a tree. 129 * 130 * @param Tree $tree 131 */ 132 public function rejectTree(Tree $tree): void 133 { 134 DB::table('change') 135 ->where('gedcom_id', '=', $tree->id()) 136 ->where('status', '=', 'pending') 137 ->update(['status' => 'rejected']); 138 } 139 140 /** 141 * Reject a change (subsequent changes) to a record. 142 * 143 * @param GedcomRecord $record 144 * @param string $change_id 145 */ 146 public function rejectChange(GedcomRecord $record, string $change_id): void 147 { 148 DB::table('change') 149 ->where('gedcom_id', '=', $record->tree()->id()) 150 ->where('xref', '=', $record->xref()) 151 ->where('change_id', '>=', $change_id) 152 ->where('status', '=', 'pending') 153 ->update(['status' => 'rejected']); 154 } 155 156 /** 157 * Reject all changes to a record. 158 * 159 * @param GedcomRecord $record 160 */ 161 public function rejectRecord(GedcomRecord $record): void 162 { 163 DB::table('change') 164 ->where('gedcom_id', '=', $record->tree()->id()) 165 ->where('xref', '=', $record->xref()) 166 ->where('status', '=', 'pending') 167 ->update(['status' => 'rejected']); 168 } 169 170 /** 171 * Generate a query for filtering the changes log. 172 * 173 * @param ServerRequestInterface $request 174 * 175 * @return Builder 176 */ 177 public function changesQuery(ServerRequestInterface $request): Builder 178 { 179 $tree = $request->getAttribute('tree'); 180 assert($tree instanceof Tree, new InvalidArgumentException()); 181 182 $from = $request->getQueryParams()['from'] ?? ''; 183 $to = $request->getQueryParams()['to'] ?? ''; 184 $type = $request->getQueryParams()['type'] ?? ''; 185 $oldged = $request->getQueryParams()['oldged'] ?? ''; 186 $newged = $request->getQueryParams()['newged'] ?? ''; 187 $xref = $request->getQueryParams()['xref'] ?? ''; 188 $username = $request->getQueryParams()['username'] ?? ''; 189 $search = $request->getQueryParams()['search'] ?? []; 190 $search = $search['value'] ?? ''; 191 192 $query = DB::table('change') 193 ->leftJoin('user', 'user.user_id', '=', 'change.user_id') 194 ->join('gedcom', 'gedcom.gedcom_id', '=', 'change.gedcom_id') 195 ->select(['change.*', new Expression("COALESCE(user_name, '<none>') AS user_name"), 'gedcom_name']) 196 ->where('gedcom_name', '=', $tree->name()); 197 198 if ($search !== '') { 199 $query->where(static function (Builder $query) use ($search): void { 200 $query 201 ->whereContains('old_gedcom', $search) 202 ->whereContains('new_gedcom', $search, 'or'); 203 }); 204 } 205 206 if ($from !== '') { 207 $query->where('change_time', '>=', $from); 208 } 209 210 if ($to !== '') { 211 // before end of the day 212 $query->where('change_time', '<', Carbon::make($to)->addDay()); 213 } 214 215 if ($type !== '') { 216 $query->where('status', '=', $type); 217 } 218 219 if ($oldged !== '') { 220 $query->whereContains('old_gedcom', $oldged); 221 } 222 if ($newged !== '') { 223 $query->whereContains('new_gedcom', $oldged); 224 } 225 226 if ($xref !== '') { 227 $query->where('xref', '=', $xref); 228 } 229 230 if ($username !== '') { 231 $query->whereContains('user_name', $username); 232 } 233 234 return $query; 235 } 236} 237