summaryrefslogtreecommitdiff
path: root/app/Http/RequestHandlers
diff options
context:
space:
mode:
Diffstat (limited to 'app/Http/RequestHandlers')
-rw-r--r--app/Http/RequestHandlers/PendingChanges.php146
-rw-r--r--app/Http/RequestHandlers/PendingChangesAcceptChange.php69
-rw-r--r--app/Http/RequestHandlers/PendingChangesAcceptRecord.php78
-rw-r--r--app/Http/RequestHandlers/PendingChangesAcceptTree.php66
-rw-r--r--app/Http/RequestHandlers/PendingChangesLogAction.php66
-rw-r--r--app/Http/RequestHandlers/PendingChangesLogData.php135
-rw-r--r--app/Http/RequestHandlers/PendingChangesLogDelete.php58
-rw-r--r--app/Http/RequestHandlers/PendingChangesLogDownload.php75
-rw-r--r--app/Http/RequestHandlers/PendingChangesLogPage.php133
-rw-r--r--app/Http/RequestHandlers/PendingChangesRejectChange.php69
-rw-r--r--app/Http/RequestHandlers/PendingChangesRejectRecord.php73
-rw-r--r--app/Http/RequestHandlers/PendingChangesRejectTree.php67
12 files changed, 1035 insertions, 0 deletions
diff --git a/app/Http/RequestHandlers/PendingChanges.php b/app/Http/RequestHandlers/PendingChanges.php
new file mode 100644
index 0000000000..94bfec4349
--- /dev/null
+++ b/app/Http/RequestHandlers/PendingChanges.php
@@ -0,0 +1,146 @@
+<?php
+
+/**
+ * webtrees: online genealogy
+ * Copyright (C) 2019 webtrees development team
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+declare(strict_types=1);
+
+namespace Fisharebest\Webtrees\Http\RequestHandlers;
+
+use Fisharebest\Webtrees\Carbon;
+use Fisharebest\Webtrees\Family;
+use Fisharebest\Webtrees\Gedcom;
+use Fisharebest\Webtrees\GedcomRecord;
+use Fisharebest\Webtrees\Http\ViewResponseTrait;
+use Fisharebest\Webtrees\I18N;
+use Fisharebest\Webtrees\Individual;
+use Fisharebest\Webtrees\Media;
+use Fisharebest\Webtrees\Note;
+use Fisharebest\Webtrees\Repository;
+use Fisharebest\Webtrees\Services\PendingChangesService;
+use Fisharebest\Webtrees\Services\TreeService;
+use Fisharebest\Webtrees\Source;
+use Fisharebest\Webtrees\Tree;
+use Illuminate\Database\Capsule\Manager as DB;
+use InvalidArgumentException;
+use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\ServerRequestInterface;
+use Psr\Http\Server\RequestHandlerInterface;
+
+use function assert;
+use function key;
+use function preg_match;
+use function reset;
+use function route;
+
+/**
+ * Show all pending changes.
+ */
+class PendingChanges implements RequestHandlerInterface
+{
+ use ViewResponseTrait;
+
+ /** @var PendingChangesService */
+ private $pending_changes_service;
+
+ /** @var TreeService */
+ private $tree_service;
+
+ /**
+ * @param PendingChangesService $pending_changes_service
+ * @param TreeService $tree_service
+ */
+ public function __construct(PendingChangesService $pending_changes_service, TreeService $tree_service)
+ {
+ $this->pending_changes_service = $pending_changes_service;
+ $this->tree_service = $tree_service;
+ }
+
+ /**
+ * @param ServerRequestInterface $request
+ *
+ * @return ResponseInterface
+ */
+ public function handle(ServerRequestInterface $request): ResponseInterface
+ {
+ $tree = $request->getAttribute('tree');
+ assert($tree instanceof Tree, new InvalidArgumentException());
+
+ $url = $request->getQueryParams()['url'] ?? route('tree-page', ['tree' => $tree->name()]);
+
+ $rows = DB::table('change')
+ ->join('user', 'user.user_id', '=', 'change.user_id')
+ ->join('gedcom', 'gedcom.gedcom_id', '=', 'change.gedcom_id')
+ ->where('status', '=', 'pending')
+ ->orderBy('change.gedcom_id')
+ ->orderBy('change.xref')
+ ->orderBy('change.change_id')
+ ->select(['change.*', 'user.user_name', 'user.real_name', 'gedcom_name'])
+ ->get();
+
+ $changes = [];
+ foreach ($rows as $row) {
+ $row->change_time = Carbon::make($row->change_time);
+
+ $change_tree = $this->tree_service->all()->get($row->gedcom_name);
+
+ preg_match('/^0 (?:@' . Gedcom::REGEX_XREF . '@ )?(' . Gedcom::REGEX_TAG . ')/', $row->old_gedcom . $row->new_gedcom, $match);
+
+ switch ($match[1]) {
+ case 'INDI':
+ $row->record = new Individual($row->xref, $row->old_gedcom, $row->new_gedcom, $change_tree);
+ break;
+ case 'FAM':
+ $row->record = new Family($row->xref, $row->old_gedcom, $row->new_gedcom, $change_tree);
+ break;
+ case 'SOUR':
+ $row->record = new Source($row->xref, $row->old_gedcom, $row->new_gedcom, $change_tree);
+ break;
+ case 'REPO':
+ $row->record = new Repository($row->xref, $row->old_gedcom, $row->new_gedcom, $change_tree);
+ break;
+ case 'OBJE':
+ $row->record = new Media($row->xref, $row->old_gedcom, $row->new_gedcom, $change_tree);
+ break;
+ case 'NOTE':
+ $row->record = new Note($row->xref, $row->old_gedcom, $row->new_gedcom, $change_tree);
+ break;
+ default:
+ $row->record = new GedcomRecord($row->xref, $row->old_gedcom, $row->new_gedcom, $change_tree);
+ break;
+ }
+
+ $changes[$row->gedcom_id][$row->xref][] = $row;
+ }
+
+ $title = I18N::translate('Pending changes');
+
+ // If the current tree has changes, activate that tab. Otherwise activate the first tab.
+ if (($changes[$tree->id()] ?? []) === []) {
+ reset($changes);
+ $active_tree_id = key($changes);
+ } else {
+ $active_tree_id = $tree->id();
+ }
+
+ return $this->viewResponse('pending-changes-page', [
+ 'active_tree_id' => $active_tree_id,
+ 'changes' => $changes,
+ 'title' => $title,
+ 'tree' => $tree,
+ 'url' => $url,
+ ]);
+ }
+}
diff --git a/app/Http/RequestHandlers/PendingChangesAcceptChange.php b/app/Http/RequestHandlers/PendingChangesAcceptChange.php
new file mode 100644
index 0000000000..4130482850
--- /dev/null
+++ b/app/Http/RequestHandlers/PendingChangesAcceptChange.php
@@ -0,0 +1,69 @@
+<?php
+
+/**
+ * webtrees: online genealogy
+ * Copyright (C) 2019 webtrees development team
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+declare(strict_types=1);
+
+namespace Fisharebest\Webtrees\Http\RequestHandlers;
+
+use Fisharebest\Webtrees\GedcomRecord;
+use Fisharebest\Webtrees\Services\PendingChangesService;
+use Fisharebest\Webtrees\Tree;
+use InvalidArgumentException;
+use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\ServerRequestInterface;
+use Psr\Http\Server\RequestHandlerInterface;
+
+use function assert;
+use function response;
+
+/**
+ * Accept pending changes for a record.
+ */
+class PendingChangesAcceptChange implements RequestHandlerInterface
+{
+ /** @var PendingChangesService */
+ private $pending_changes_service;
+
+ /**
+ * @param PendingChangesService $pending_changes_service
+ */
+ public function __construct(PendingChangesService $pending_changes_service)
+ {
+ $this->pending_changes_service = $pending_changes_service;
+ }
+
+ /**
+ * @param ServerRequestInterface $request
+ *
+ * @return ResponseInterface
+ */
+ public function handle(ServerRequestInterface $request): ResponseInterface
+ {
+ $tree = $request->getAttribute('tree');
+ assert($tree instanceof Tree, new InvalidArgumentException());
+
+ $xref = $request->getAttribute('xref');
+ $record = GedcomRecord::getInstance($xref, $tree);
+ $change = $request->getAttribute('change');
+
+ if ($record instanceof GedcomRecord) {
+ $this->pending_changes_service->acceptChange($record, $change);
+ }
+
+ return response();
+ }
+}
diff --git a/app/Http/RequestHandlers/PendingChangesAcceptRecord.php b/app/Http/RequestHandlers/PendingChangesAcceptRecord.php
new file mode 100644
index 0000000000..645e08cecb
--- /dev/null
+++ b/app/Http/RequestHandlers/PendingChangesAcceptRecord.php
@@ -0,0 +1,78 @@
+<?php
+
+/**
+ * webtrees: online genealogy
+ * Copyright (C) 2019 webtrees development team
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+declare(strict_types=1);
+
+namespace Fisharebest\Webtrees\Http\RequestHandlers;
+
+use Fisharebest\Webtrees\FlashMessages;
+use Fisharebest\Webtrees\GedcomRecord;
+use Fisharebest\Webtrees\I18N;
+use Fisharebest\Webtrees\Services\PendingChangesService;
+use Fisharebest\Webtrees\Tree;
+use InvalidArgumentException;
+use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\ServerRequestInterface;
+use Psr\Http\Server\RequestHandlerInterface;
+
+use function assert;
+use function response;
+
+/**
+ * Accept pending changes for a record.
+ */
+class PendingChangesAcceptRecord implements RequestHandlerInterface
+{
+ /** @var PendingChangesService */
+ private $pending_changes_service;
+
+ /**
+ * @param PendingChangesService $pending_changes_service
+ */
+ public function __construct(PendingChangesService $pending_changes_service)
+ {
+ $this->pending_changes_service = $pending_changes_service;
+ }
+
+ /**
+ * @param ServerRequestInterface $request
+ *
+ * @return ResponseInterface
+ */
+ public function handle(ServerRequestInterface $request): ResponseInterface
+ {
+ $tree = $request->getAttribute('tree');
+ assert($tree instanceof Tree, new InvalidArgumentException());
+
+ $xref = $request->getAttribute('xref') ?? '';
+ $record = GedcomRecord::getInstance($xref, $tree);
+
+ if ($record) {
+ if ($record->isPendingDeletion()) {
+ /* I18N: %s is the name of a genealogy record */
+ FlashMessages::addMessage(I18N::translate('“%s” has been deleted.', $record->fullName()));
+ } else {
+ /* I18N: %s is the name of a genealogy record */
+ FlashMessages::addMessage(I18N::translate('The changes to “%s” have been accepted.', $record->fullName()));
+ }
+
+ $this->pending_changes_service->acceptRecord($record);
+ }
+
+ return response();
+ }
+}
diff --git a/app/Http/RequestHandlers/PendingChangesAcceptTree.php b/app/Http/RequestHandlers/PendingChangesAcceptTree.php
new file mode 100644
index 0000000000..18d505941e
--- /dev/null
+++ b/app/Http/RequestHandlers/PendingChangesAcceptTree.php
@@ -0,0 +1,66 @@
+<?php
+
+/**
+ * webtrees: online genealogy
+ * Copyright (C) 2019 webtrees development team
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+declare(strict_types=1);
+
+namespace Fisharebest\Webtrees\Http\RequestHandlers;
+
+use Fisharebest\Webtrees\FlashMessages;
+use Fisharebest\Webtrees\I18N;
+use Fisharebest\Webtrees\Services\PendingChangesService;
+use Fisharebest\Webtrees\Tree;
+use InvalidArgumentException;
+use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\ServerRequestInterface;
+use Psr\Http\Server\RequestHandlerInterface;
+
+use function assert;
+use function e;
+use function response;
+
+/**
+ * Accept pending changes for a tree.
+ */
+class PendingChangesAcceptTree implements RequestHandlerInterface
+{
+ /** @var PendingChangesService */
+ private $pending_changes_service;
+
+ /**
+ * @param PendingChangesService $pending_changes_service
+ */
+ public function __construct(PendingChangesService $pending_changes_service)
+ {
+ $this->pending_changes_service = $pending_changes_service;
+ }
+
+ /**
+ * @param ServerRequestInterface $request
+ *
+ * @return ResponseInterface
+ */
+ public function handle(ServerRequestInterface $request): ResponseInterface
+ {
+ $tree = $request->getAttribute('tree');
+ assert($tree instanceof Tree, new InvalidArgumentException());
+
+ $this->pending_changes_service->acceptTree($tree);
+
+ FlashMessages::addMessage(I18N::translate('The changes to “%s” have been accepted.', e($tree->title())));
+ return response();
+ }
+}
diff --git a/app/Http/RequestHandlers/PendingChangesLogAction.php b/app/Http/RequestHandlers/PendingChangesLogAction.php
new file mode 100644
index 0000000000..c2ddd37389
--- /dev/null
+++ b/app/Http/RequestHandlers/PendingChangesLogAction.php
@@ -0,0 +1,66 @@
+<?php
+
+/**
+ * webtrees: online genealogy
+ * Copyright (C) 2019 webtrees development team
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+declare(strict_types=1);
+
+namespace Fisharebest\Webtrees\Http\RequestHandlers;
+
+use Fisharebest\Webtrees\Services\PendingChangesService;
+use Fisharebest\Webtrees\Tree;
+use InvalidArgumentException;
+use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\ServerRequestInterface;
+use Psr\Http\Server\RequestHandlerInterface;
+
+use function assert;
+use function response;
+
+/**
+ * Show pending changes.
+ */
+class PendingChangesLogAction implements RequestHandlerInterface
+{
+ /** @var PendingChangesService */
+ private $pending_changes_service;
+
+ /**
+ * @param PendingChangesService $pending_changes_service
+ */
+ public function __construct(PendingChangesService $pending_changes_service)
+ {
+ $this->pending_changes_service = $pending_changes_service;
+ }
+
+ /**
+ * @param ServerRequestInterface $request
+ *
+ * @return ResponseInterface
+ */
+ public function handle(ServerRequestInterface $request): ResponseInterface
+ {
+ return redirect(route(PendingChangesLogPage::class, [
+ 'tree' => $request->getParsedBody()['tree'],
+ 'from' => $request->getParsedBody()['from'] ?? '',
+ 'to' => $request->getParsedBody()['to'] ?? '',
+ 'type' => $request->getParsedBody()['type'] ?? '',
+ 'oldged' => $request->getParsedBody()['oldged'] ?? '',
+ 'newged' => $request->getParsedBody()['newged'] ?? '',
+ 'xref' => $request->getParsedBody()['xref'] ?? '',
+ 'username' => $request->getParsedBody()['username'] ?? '',
+ ]));
+ }
+}
diff --git a/app/Http/RequestHandlers/PendingChangesLogData.php b/app/Http/RequestHandlers/PendingChangesLogData.php
new file mode 100644
index 0000000000..a4af95c3b3
--- /dev/null
+++ b/app/Http/RequestHandlers/PendingChangesLogData.php
@@ -0,0 +1,135 @@
+<?php
+
+/**
+ * webtrees: online genealogy
+ * Copyright (C) 2019 webtrees development team
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+declare(strict_types=1);
+
+namespace Fisharebest\Webtrees\Http\RequestHandlers;
+
+use Fisharebest\Algorithm\MyersDiff;
+use Fisharebest\Webtrees\Carbon;
+use Fisharebest\Webtrees\Gedcom;
+use Fisharebest\Webtrees\GedcomRecord;
+use Fisharebest\Webtrees\I18N;
+use Fisharebest\Webtrees\Services\DatatablesService;
+use Fisharebest\Webtrees\Services\PendingChangesService;
+use Fisharebest\Webtrees\Services\TreeService;
+use Fisharebest\Webtrees\Tree;
+use InvalidArgumentException;
+use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\ServerRequestInterface;
+use Psr\Http\Server\RequestHandlerInterface;
+use stdClass;
+
+use function e;
+use function explode;
+use function implode;
+use function preg_replace_callback;
+
+/**
+ * Find pending changes.
+ */
+class PendingChangesLogData implements RequestHandlerInterface
+{
+ /** @var DatatablesService */
+ private $datatables_service;
+
+ /** @var MyersDiff */
+ private $myers_diff;
+
+ /** @var PendingChangesService */
+ private $pending_changes_service;
+
+ /** @var TreeService */
+ private $tree_service;
+
+ /**
+ * @param DatatablesService $datatables_service
+ * @param MyersDiff $myers_diff
+ * @param PendingChangesService $pending_changes_service
+ * @param TreeService $tree_service
+ */
+ public function __construct(
+ DatatablesService $datatables_service,
+ MyersDiff $myers_diff,
+ PendingChangesService $pending_changes_service,
+ TreeService $tree_service
+ ) {
+ $this->datatables_service = $datatables_service;
+ $this->myers_diff = $myers_diff;
+ $this->pending_changes_service = $pending_changes_service;
+ $this->tree_service = $tree_service;
+ }
+
+ /**
+ * @param ServerRequestInterface $request
+ *
+ * @return ResponseInterface
+ */
+ public function handle(ServerRequestInterface $request): ResponseInterface
+ {
+ $tree = $request->getAttribute('tree');
+ assert($tree instanceof Tree, new InvalidArgumentException());
+
+ $query = $this->pending_changes_service->changesQuery($request);
+
+ $callback = function (stdClass $row) use ($tree): array {
+ $old_lines = explode("\n", $row->old_gedcom);
+ $new_lines = explode("\n", $row->new_gedcom);
+
+ $differences = $this->myers_diff->calculate($old_lines, $new_lines);
+ $diff_lines = [];
+
+ foreach ($differences as $difference) {
+ switch ($difference[1]) {
+ case MyersDiff::DELETE:
+ $diff_lines[] = '<del>' . $difference[0] . '</del>';
+ break;
+ case MyersDiff::INSERT:
+ $diff_lines[] = '<ins>' . $difference[0] . '</ins>';
+ break;
+ default:
+ $diff_lines[] = $difference[0];
+ }
+ }
+
+ // Only convert valid xrefs to links
+ $record = GedcomRecord::getInstance($row->xref, $tree);
+
+ return [
+ $row->change_id,
+ Carbon::make($row->change_time)->local()->format('Y-m-d H:i:s'),
+ I18N::translate($row->status),
+ $record ? '<a href="' . e($record->url()) . '">' . $record->xref() . '</a>' : $row->xref,
+ '<div class="gedcom-data" dir="ltr">' .
+ preg_replace_callback(
+ '/@(' . Gedcom::REGEX_XREF . ')@/',
+ static function (array $match) use ($tree): string {
+ $record = GedcomRecord::getInstance($match[1], $tree);
+
+ return $record ? '<a href="' . e($record->url()) . '">' . $match[0] . '</a>' : $match[0];
+ },
+ implode("\n", $diff_lines)
+ ) .
+ '</div>',
+ $row->user_name,
+ $row->gedcom_name,
+ ];
+ };
+
+ return $this->datatables_service->handle($request, $query, [], [], $callback);
+ }
+}
diff --git a/app/Http/RequestHandlers/PendingChangesLogDelete.php b/app/Http/RequestHandlers/PendingChangesLogDelete.php
new file mode 100644
index 0000000000..d8c72fe91c
--- /dev/null
+++ b/app/Http/RequestHandlers/PendingChangesLogDelete.php
@@ -0,0 +1,58 @@
+<?php
+
+/**
+ * webtrees: online genealogy
+ * Copyright (C) 2019 webtrees development team
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+declare(strict_types=1);
+
+namespace Fisharebest\Webtrees\Http\RequestHandlers;
+
+use Fisharebest\Webtrees\Services\PendingChangesService;
+use Fisharebest\Webtrees\Tree;
+use InvalidArgumentException;
+use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\ServerRequestInterface;
+use Psr\Http\Server\RequestHandlerInterface;
+
+use function response;
+
+/**
+ * Delete pending changes.
+ */
+class PendingChangesLogDelete implements RequestHandlerInterface
+{
+ /** @var PendingChangesService */
+ private $pending_changes_service;
+
+ /**
+ * @param PendingChangesService $pending_changes_service
+ */
+ public function __construct(PendingChangesService $pending_changes_service)
+ {
+ $this->pending_changes_service = $pending_changes_service;
+ }
+
+ /**
+ * @param ServerRequestInterface $request
+ *
+ * @return ResponseInterface
+ */
+ public function handle(ServerRequestInterface $request): ResponseInterface
+ {
+ $this->pending_changes_service->changesQuery($request)->delete();
+
+ return response();
+ }
+}
diff --git a/app/Http/RequestHandlers/PendingChangesLogDownload.php b/app/Http/RequestHandlers/PendingChangesLogDownload.php
new file mode 100644
index 0000000000..de5a3afb6b
--- /dev/null
+++ b/app/Http/RequestHandlers/PendingChangesLogDownload.php
@@ -0,0 +1,75 @@
+<?php
+
+/**
+ * webtrees: online genealogy
+ * Copyright (C) 2019 webtrees development team
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+declare(strict_types=1);
+
+namespace Fisharebest\Webtrees\Http\RequestHandlers;
+
+use Fig\Http\Message\StatusCodeInterface;
+use Fisharebest\Webtrees\Services\PendingChangesService;
+use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\ServerRequestInterface;
+use Psr\Http\Server\RequestHandlerInterface;
+use stdClass;
+
+use function response;
+
+/**
+ * Download pending changes.
+ */
+class PendingChangesLogDownload implements RequestHandlerInterface
+{
+ /** @var PendingChangesService */
+ private $pending_changes_service;
+
+ /**
+ * @param PendingChangesService $pending_changes_service
+ */
+ public function __construct(PendingChangesService $pending_changes_service)
+ {
+ $this->pending_changes_service = $pending_changes_service;
+ }
+
+ /**
+ * @param ServerRequestInterface $request
+ *
+ * @return ResponseInterface
+ */
+ public function handle(ServerRequestInterface $request): ResponseInterface
+ {
+ $content = $this->pending_changes_service->changesQuery($request)
+ ->get()
+ ->map(static function (stdClass $row): string {
+ // Convert to CSV
+ return implode(',', [
+ '"' . $row->change_time . '"',
+ '"' . $row->status . '"',
+ '"' . $row->xref . '"',
+ '"' . str_replace('"', '""', $row->old_gedcom) . '"',
+ '"' . str_replace('"', '""', $row->new_gedcom) . '"',
+ '"' . str_replace('"', '""', $row->user_name) . '"',
+ '"' . str_replace('"', '""', $row->gedcom_name) . '"',
+ ]);
+ })
+ ->implode("\n");
+
+ return response($content, StatusCodeInterface::STATUS_OK, [
+ 'Content-Type' => 'text/csv; charset=utf-8',
+ 'Content-Disposition' => 'attachment; filename="changes.csv"',
+ ]);
+ }
+}
diff --git a/app/Http/RequestHandlers/PendingChangesLogPage.php b/app/Http/RequestHandlers/PendingChangesLogPage.php
new file mode 100644
index 0000000000..76c887f289
--- /dev/null
+++ b/app/Http/RequestHandlers/PendingChangesLogPage.php
@@ -0,0 +1,133 @@
+<?php
+
+/**
+ * webtrees: online genealogy
+ * Copyright (C) 2019 webtrees development team
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+declare(strict_types=1);
+
+namespace Fisharebest\Webtrees\Http\RequestHandlers;
+
+use Fisharebest\Webtrees\Carbon;
+use Fisharebest\Webtrees\Http\ViewResponseTrait;
+use Fisharebest\Webtrees\I18N;
+use Fisharebest\Webtrees\Services\TreeService;
+use Fisharebest\Webtrees\Services\UserService;
+use Fisharebest\Webtrees\Tree;
+use Illuminate\Database\Capsule\Manager as DB;
+use InvalidArgumentException;
+use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\ServerRequestInterface;
+use Psr\Http\Server\RequestHandlerInterface;
+
+use function array_key_exists;
+use function reset;
+
+/**
+ * Show pending changes.
+ */
+class PendingChangesLogPage implements RequestHandlerInterface
+{
+ use ViewResponseTrait;
+
+ /** @var TreeService */
+ private $tree_service;
+
+ /** @var UserService */
+ private $user_service;
+
+ /**
+ * @param TreeService $tree_service
+ * @param UserService $user_service
+ */
+ public function __construct(TreeService $tree_service, UserService $user_service)
+ {
+ $this->tree_service = $tree_service;
+ $this->user_service = $user_service;
+ }
+
+ /**
+ * @param ServerRequestInterface $request
+ *
+ * @return ResponseInterface
+ */
+ public function handle(ServerRequestInterface $request): ResponseInterface
+ {
+ $this->layout = 'layouts/administration';
+
+ $tree = $request->getAttribute('tree');
+ assert($tree instanceof Tree, new InvalidArgumentException());
+
+ $trees = $this->tree_service->titles();
+
+ $users = ['' => ''];
+ foreach ($this->user_service->all() as $user) {
+ $user_name = $user->userName();
+ $users[$user_name] = $user_name;
+ }
+
+ // First and last change in the database.
+ $earliest = DB::table('change')->min('change_time');
+ $latest = DB::table('change')->max('change_time');
+
+ $earliest = $earliest !== null ? Carbon::make($earliest) : Carbon::now();
+ $latest = $latest !== null ? Carbon::make($latest) : Carbon::now();
+
+ $earliest = $earliest->toDateString();
+ $latest = $latest->toDateString();
+
+ $from = $request->getQueryParams()['from'] ?? $earliest;
+ $to = $request->getQueryParams()['to'] ?? $latest;
+ $type = $request->getQueryParams()['type'] ?? '';
+ $oldged = $request->getQueryParams()['oldged'] ?? '';
+ $newged = $request->getQueryParams()['newged'] ?? '';
+ $xref = $request->getQueryParams()['xref'] ?? '';
+ $username = $request->getQueryParams()['username'] ?? '';
+
+ return $this->viewResponse('admin/changes-log', [
+ 'earliest' => $earliest,
+ 'from' => $from,
+ 'latest' => $latest,
+ 'newged' => $newged,
+ 'oldged' => $oldged,
+ 'statuses' => $this->changeStatuses(),
+ 'title' => I18N::translate('Changes log'),
+ 'to' => $to,
+ 'tree' => $tree,
+ 'trees' => $trees,
+ 'type' => $type,
+ 'username' => $username,
+ 'users' => $users,
+ 'xref' => $xref,
+ ]);
+ }
+
+ /**
+ * Labels for the various statuses.
+ *
+ * @return array
+ */
+ private function changeStatuses(): array
+ {
+ return [
+ '' => '',
+ /* I18N: the status of an edit accepted/rejected/pending */
+ 'accepted' => I18N::translate('accepted'),
+ /* I18N: the status of an edit accepted/rejected/pending */
+ 'rejected' => I18N::translate('rejected'),
+ /* I18N: the status of an edit accepted/rejected/pending */
+ 'pending' => I18N::translate('pending'),
+ ];
+ }
+}
diff --git a/app/Http/RequestHandlers/PendingChangesRejectChange.php b/app/Http/RequestHandlers/PendingChangesRejectChange.php
new file mode 100644
index 0000000000..07a146016c
--- /dev/null
+++ b/app/Http/RequestHandlers/PendingChangesRejectChange.php
@@ -0,0 +1,69 @@
+<?php
+
+/**
+ * webtrees: online genealogy
+ * Copyright (C) 2019 webtrees development team
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+declare(strict_types=1);
+
+namespace Fisharebest\Webtrees\Http\RequestHandlers;
+
+use Fisharebest\Webtrees\GedcomRecord;
+use Fisharebest\Webtrees\Services\PendingChangesService;
+use Fisharebest\Webtrees\Tree;
+use InvalidArgumentException;
+use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\ServerRequestInterface;
+use Psr\Http\Server\RequestHandlerInterface;
+
+use function assert;
+use function response;
+
+/**
+ * Reject a pending change for a record.
+ */
+class PendingChangesRejectChange implements RequestHandlerInterface
+{
+ /** @var PendingChangesService */
+ private $pending_changes_service;
+
+ /**
+ * @param PendingChangesService $pending_changes_service
+ */
+ public function __construct(PendingChangesService $pending_changes_service)
+ {
+ $this->pending_changes_service = $pending_changes_service;
+ }
+
+ /**
+ * @param ServerRequestInterface $request
+ *
+ * @return ResponseInterface
+ */
+ public function handle(ServerRequestInterface $request): ResponseInterface
+ {
+ $tree = $request->getAttribute('tree');
+ assert($tree instanceof Tree, new InvalidArgumentException());
+
+ $xref = $request->getAttribute('xref');
+ $record = GedcomRecord::getInstance($xref, $tree);
+ $change = $request->getAttribute('change');
+
+ if ($record instanceof GedcomRecord) {
+ $this->pending_changes_service->rejectChange($record, $change);
+ }
+
+ return response();
+ }
+}
diff --git a/app/Http/RequestHandlers/PendingChangesRejectRecord.php b/app/Http/RequestHandlers/PendingChangesRejectRecord.php
new file mode 100644
index 0000000000..0f4f6e1ac4
--- /dev/null
+++ b/app/Http/RequestHandlers/PendingChangesRejectRecord.php
@@ -0,0 +1,73 @@
+<?php
+
+/**
+ * webtrees: online genealogy
+ * Copyright (C) 2019 webtrees development team
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+declare(strict_types=1);
+
+namespace Fisharebest\Webtrees\Http\RequestHandlers;
+
+use Fisharebest\Webtrees\FlashMessages;
+use Fisharebest\Webtrees\GedcomRecord;
+use Fisharebest\Webtrees\I18N;
+use Fisharebest\Webtrees\Services\PendingChangesService;
+use Fisharebest\Webtrees\Tree;
+use InvalidArgumentException;
+use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\ServerRequestInterface;
+use Psr\Http\Server\RequestHandlerInterface;
+
+use function assert;
+use function response;
+
+/**
+ * Reject pending changes for a record.
+ */
+class PendingChangesRejectRecord implements RequestHandlerInterface
+{
+ /** @var PendingChangesService */
+ private $pending_changes_service;
+
+ /**
+ * @param PendingChangesService $pending_changes_service
+ */
+ public function __construct(PendingChangesService $pending_changes_service)
+ {
+ $this->pending_changes_service = $pending_changes_service;
+ }
+
+ /**
+ * @param ServerRequestInterface $request
+ *
+ * @return ResponseInterface
+ */
+ public function handle(ServerRequestInterface $request): ResponseInterface
+ {
+ $tree = $request->getAttribute('tree');
+ assert($tree instanceof Tree, new InvalidArgumentException());
+
+ $xref = $request->getAttribute('xref') ?? '';
+ $record = GedcomRecord::getInstance($xref, $tree);
+
+ if ($record instanceof GedcomRecord) {
+ $this->pending_changes_service->rejectRecord($record);
+
+ /* I18N: %s is the name of a genealogy record */
+ FlashMessages::addMessage(I18N::translate('The changes to “%s” have been rejected.', $record->fullName()));
+ }
+
+ return response();
+ }
+}
diff --git a/app/Http/RequestHandlers/PendingChangesRejectTree.php b/app/Http/RequestHandlers/PendingChangesRejectTree.php
new file mode 100644
index 0000000000..4089661a0b
--- /dev/null
+++ b/app/Http/RequestHandlers/PendingChangesRejectTree.php
@@ -0,0 +1,67 @@
+<?php
+
+/**
+ * webtrees: online genealogy
+ * Copyright (C) 2019 webtrees development team
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+declare(strict_types=1);
+
+namespace Fisharebest\Webtrees\Http\RequestHandlers;
+
+use Fisharebest\Webtrees\FlashMessages;
+use Fisharebest\Webtrees\I18N;
+use Fisharebest\Webtrees\Services\PendingChangesService;
+use Fisharebest\Webtrees\Tree;
+use InvalidArgumentException;
+use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\ServerRequestInterface;
+use Psr\Http\Server\RequestHandlerInterface;
+
+use function assert;
+use function e;
+use function response;
+
+/**
+ * Reject pending changes for a tree.
+ */
+class PendingChangesRejectTree implements RequestHandlerInterface
+{
+ /** @var PendingChangesService */
+ private $pending_changes_service;
+
+ /**
+ * @param PendingChangesService $pending_changes_service
+ */
+ public function __construct(PendingChangesService $pending_changes_service)
+ {
+ $this->pending_changes_service = $pending_changes_service;
+ }
+
+ /**
+ * @param ServerRequestInterface $request
+ *
+ * @return ResponseInterface
+ */
+ public function handle(ServerRequestInterface $request): ResponseInterface
+ {
+ $tree = $request->getAttribute('tree');
+ assert($tree instanceof Tree, new InvalidArgumentException());
+
+ $this->pending_changes_service->rejectTree($tree);
+
+ FlashMessages::addMessage(I18N::translate('The changes to “%s” have been rejected.', e($tree->title())));
+
+ return response();
+ }
+}