summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGreg Roach <fisharebest@webtrees.net>2018-12-14 09:36:19 +0000
committerGreg Roach <fisharebest@webtrees.net>2018-12-14 09:36:19 +0000
commitc0dc1dc8776d0d9214741483e39305c5e08e2358 (patch)
tree1ab8045b0041bb90346dd2704208cffbbfbbd9be
parent1efebf18750c84c258e87e294e56bd7ef897b541 (diff)
downloadwebtrees-c0dc1dc8776d0d9214741483e39305c5e08e2358.tar.gz
webtrees-c0dc1dc8776d0d9214741483e39305c5e08e2358.tar.bz2
webtrees-c0dc1dc8776d0d9214741483e39305c5e08e2358.zip
Refactor clipboard functionality to a ClipboardService
-rw-r--r--app/Functions/FunctionsPrint.php81
-rw-r--r--app/Http/Controllers/EditGedcomRecordController.php48
-rw-r--r--app/Services/ClipboardService.php115
-rw-r--r--resources/views/edit/add-fact-row.phtml50
-rw-r--r--resources/views/edit/paste-fact-row.phtml33
-rwxr-xr-xthemes/clouds/css-2.0.0/style.css5
-rwxr-xr-xthemes/colors/css-2.0.0/style.css5
-rwxr-xr-xthemes/fab/css-2.0.0/style.css5
-rwxr-xr-xthemes/minimal/css-2.0.0/style.css5
-rwxr-xr-xthemes/webtrees/css-2.0.0/style.css5
-rwxr-xr-xthemes/xenea/css-2.0.0/style.css5
11 files changed, 227 insertions, 130 deletions
diff --git a/app/Functions/FunctionsPrint.php b/app/Functions/FunctionsPrint.php
index 6a2d7138b6..1e1c2aa3c9 100644
--- a/app/Functions/FunctionsPrint.php
+++ b/app/Functions/FunctionsPrint.php
@@ -32,6 +32,7 @@ use Fisharebest\Webtrees\I18N;
use Fisharebest\Webtrees\Individual;
use Fisharebest\Webtrees\Note;
use Fisharebest\Webtrees\Place;
+use Fisharebest\Webtrees\Services\ClipboardService;
use Fisharebest\Webtrees\Session;
use Fisharebest\Webtrees\Theme;
use Fisharebest\Webtrees\Tree;
@@ -479,42 +480,10 @@ class FunctionsPrint
*
* @return void
*/
- public static function printAddNewFact(GedcomRecord $record, $usedfacts, $type)
+ public static function printAddNewFact(GedcomRecord $record, $usedfacts, $type): void
{
$tree = $record->tree();
- // -- Add from clipboard
- if (is_array(Session::get('clipboard'))) {
- $newRow = true;
- foreach (array_reverse(Session::get('clipboard'), true) as $fact_id => $fact) {
- if ($fact['type'] == $type || $fact['type'] == 'all') {
- if ($newRow) {
- $newRow = false;
- echo '<tr><th scope="row">';
- echo I18N::translate('Add from clipboard'), '</th>';
- echo '<td><form name="newFromClipboard" onsubmit="return false;">';
- echo '<select id="newClipboardFact">';
- }
- echo '<option value="', e($fact_id), '">', GedcomTag::getLabel($fact['fact']);
- // TODO use the event class to store/parse the clipboard events
- if (preg_match('/^2 DATE (.+)/m', $fact['factrec'], $match)) {
- $tmp = new Date($match[1]);
- echo '; ', $tmp->minimumDate()->format('%Y');
- }
- if (preg_match('/^2 PLAC ([^,\n]+)/m', $fact['factrec'], $match)) {
- echo '; ', $match[1];
- }
- echo '</option>';
- }
- }
- if (!$newRow) {
- echo '</select>';
- /* I18N: A button label. */
- echo '&nbsp;&nbsp;<input type="button" value="', I18N::translate('add'), '" onclick="return paste_fact(\'' . e($tree->name()) . '\',\'' . e($record->xref()) . '\', \'#newClipboardFact\');"> ';
- echo '</form></td></tr>', "\n";
- }
- }
-
// -- Add from pick list
switch ($type) {
case 'INDI':
@@ -559,36 +528,20 @@ class FunctionsPrint
uasort($translated_addfacts, function (string $x, string $y): int {
return I18N::strcasecmp(I18N::translate($x), I18N::translate($y));
});
- echo '<tr><th scope="row">';
- echo I18N::translate('Fact or event');
- echo '</th>';
- echo '<td>';
- echo '<form onsubmit="if ($(&quot;#add-fact&quot;).val() === null) {event.preventDefault();}">';
- echo '<input type="hidden" name="route" value="add-fact">';
- echo '<input type="hidden" name="xref" value="' . e($record->xref()) . '">';
- echo '<input type="hidden" name="ged" value="' . e($tree->name()) . '">';
- echo '<select id="add-fact" name="fact">';
- echo '<option value="" disabled selected>' . I18N::translate('&lt;select&gt;') . '</option>';
- foreach ($translated_addfacts as $fact => $fact_name) {
- echo '<option value="', $fact, '">', $fact_name, '</option>';
- }
- if ($type == 'INDI' || $type == 'FAM') {
- echo '<option value="FACT">', I18N::translate('Custom fact'), '</option>';
- echo '<option value="EVEN">', I18N::translate('Custom event'), '</option>';
- }
- echo '</select>';
- /* I18N: A button label. */
- echo '<input type="submit" value="', I18N::translate('add'), '">';
- echo '</form>';
- echo '<span class="quickfacts">';
- foreach ($quickfacts as $fact) {
- echo '<a href="' . e(route('add-fact', [
- 'fact' => $fact,
- 'xref' => $record->xref(),
- 'ged' => $tree->name(),
- ])) . '">', GedcomTag::getLabel($fact), '</a>';
- }
- echo '</span>';
- echo '</td></tr>';
+
+ $clipboard_service = new ClipboardService();
+
+ $pastable_facts = $clipboard_service->pastableFacts($record);
+
+ echo view('edit/paste-fact-row', [
+ 'facts' => $pastable_facts,
+ 'record' => $record,
+ ]);
+
+ echo view('edit/add-fact-row', [
+ 'add_facts' => $translated_addfacts,
+ 'quick_facts' => $quickfacts,
+ 'record' => $record,
+ ]);
}
}
diff --git a/app/Http/Controllers/EditGedcomRecordController.php b/app/Http/Controllers/EditGedcomRecordController.php
index 040c413c2e..7c265e4716 100644
--- a/app/Http/Controllers/EditGedcomRecordController.php
+++ b/app/Http/Controllers/EditGedcomRecordController.php
@@ -27,7 +27,7 @@ use Fisharebest\Webtrees\I18N;
use Fisharebest\Webtrees\Individual;
use Fisharebest\Webtrees\Module;
use Fisharebest\Webtrees\Module\CensusAssistantModule;
-use Fisharebest\Webtrees\Session;
+use Fisharebest\Webtrees\Services\ClipboardService;
use Fisharebest\Webtrees\Tree;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
@@ -44,12 +44,13 @@ class EditGedcomRecordController extends AbstractEditController
/**
* Copy a fact to the clipboard.
*
- * @param Request $request
- * @param Tree $tree
+ * @param Request $request
+ * @param Tree $tree
+ * @param ClipboardService $clipboard_service
*
* @return Response
*/
- public function copyFact(Request $request, Tree $tree): Response
+ public function copyFact(Request $request, Tree $tree, ClipboardService $clipboard_service): Response
{
$xref = $request->get('xref', '');
$fact_id = $request->get('fact_id');
@@ -59,31 +60,9 @@ class EditGedcomRecordController extends AbstractEditController
$this->checkRecordAccess($record, true);
foreach ($record->facts() as $fact) {
- if ($fact->id() == $fact_id) {
- switch ($fact->getTag()) {
- case 'NOTE':
- case 'SOUR':
- case 'OBJE':
- $type = 'all'; // paste this anywhere
- break;
- default:
- $type = $record::RECORD_TYPE; // paste only to the same record type
- break;
- }
- $clipboard = Session::get('clipboard');
- if (!is_array($clipboard)) {
- $clipboard = [];
- }
- $clipboard[$fact_id] = [
- 'type' => $type,
- 'factrec' => $fact->gedcom(),
- 'fact' => $fact->getTag(),
- ];
-
- // The clipboard only holds 10 facts
- $clipboard = array_slice($clipboard, -10);
+ if ($fact->id() === $fact_id) {
+ $clipboard_service->copyFact($fact);
- Session::put('clipboard', $clipboard);
FlashMessages::addMessage(I18N::translate('The record has been copied to the clipboard.'));
break;
}
@@ -178,12 +157,13 @@ class EditGedcomRecordController extends AbstractEditController
/**
* Paste a fact from the clipboard into a record.
*
- * @param Request $request
- * @param Tree $tree
+ * @param Request $request
+ * @param Tree $tree
+ * @param ClipboardService $clipboard_service
*
* @return Response
*/
- public function pasteFact(Request $request, Tree $tree): Response
+ public function pasteFact(Request $request, Tree $tree, ClipboardService $clipboard_service): Response
{
$xref = $request->get('xref', '');
$fact_id = $request->get('fact_id');
@@ -192,11 +172,7 @@ class EditGedcomRecordController extends AbstractEditController
$this->checkRecordAccess($record, true);
- $clipboard = Session::get('clipboard');
-
- if (isset($clipboard[$fact_id])) {
- $record->createFact($clipboard[$fact_id]['factrec'], true);
- }
+ $clipboard_service->pasteFact($fact_id, $record);
return new Response();
}
diff --git a/app/Services/ClipboardService.php b/app/Services/ClipboardService.php
new file mode 100644
index 0000000000..afe4b98e9b
--- /dev/null
+++ b/app/Services/ClipboardService.php
@@ -0,0 +1,115 @@
+<?php
+/**
+ * webtrees: online genealogy
+ * Copyright (C) 2018 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\Services;
+
+use Fisharebest\Webtrees\Fact;
+use Fisharebest\Webtrees\GedcomRecord;
+use Fisharebest\Webtrees\Session;
+
+/**
+ * Copy and past facts between records.
+ */
+class ClipboardService
+{
+ // Maximum number of entries in the clipboard.
+ private const CLIPBOARD_SIZE = 10;
+
+ /**
+ * Copy a fact to the clipboard.
+ *
+ * @param Fact $fact
+ */
+ public function copyFact(Fact $fact): void {
+ $clipboard = Session::get('clipboard', []);
+
+ switch ($fact->getTag()) {
+ case 'NOTE':
+ case 'SOUR':
+ case 'OBJE':
+ // paste this anywhere
+ $type = 'all';
+ break;
+ default:
+ // paste only to the same record type
+ $type = $fact->record()::RECORD_TYPE;
+ break;
+ }
+
+ // If we are copying the same fact twice, make sure the new one is at the top.
+ $fact_id = $fact->id();
+
+ unset($clipboard[$fact_id]);
+
+ $clipboard[$fact_id] = [
+ 'type' => $type,
+ 'factrec' => $fact->gedcom(),
+ 'fact' => $fact->getTag(),
+ ];
+
+ // The clipboard only holds a limited number of facts.
+ $clipboard = array_slice($clipboard, -self::CLIPBOARD_SIZE);
+
+ Session::put('clipboard', $clipboard);
+ }
+
+ /**
+ * Copy a fact from the clipboard to a record.
+ *
+ * @param string $fact_id
+ * @param GedcomRecord $record
+ *
+ * @return bool
+ */
+ public function pasteFact(string $fact_id, GedcomRecord $record): bool {
+ $clipboard = Session::get('clipboard');
+
+ if (isset($clipboard[$fact_id])) {
+ $record->createFact($clipboard[$fact_id]['factrec'], true);
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Createa a list of facts that can be pasted into a given record
+ *
+ * @param GedcomRecord $gedcom_record
+ *
+ * @return Fact[]
+ */
+ public function pastableFacts(GedcomRecord $gedcom_record): array {
+ // The facts are stored in the session.
+ $clipboard = Session::get('clipboard', []);
+
+ // Put the most recently copied fact at the top of the list.
+ $clipboard = array_reverse($clipboard);
+
+ // Only include facts that can be pasted onto this record.
+ $clipboard = array_filter($clipboard, function(array $clipping) use ($gedcom_record): bool {
+ return $clipping['type'] == $gedcom_record::RECORD_TYPE || $clipping['type'] == 'all';
+ });
+
+ // Create facts for the record.
+ $facts = array_map(function(array $clipping) use ($gedcom_record): Fact {
+ return new Fact($clipping['factrec'], $gedcom_record, md5($clipping['factrec']));
+ }, $clipboard);
+
+ return $facts;
+ }
+}
diff --git a/resources/views/edit/add-fact-row.phtml b/resources/views/edit/add-fact-row.phtml
new file mode 100644
index 0000000000..4979054eef
--- /dev/null
+++ b/resources/views/edit/add-fact-row.phtml
@@ -0,0 +1,50 @@
+<?php use Fisharebest\Webtrees\GedcomTag; ?>
+<?php use Fisharebest\Webtrees\I18N; ?>
+
+<tr>
+ <th scope="row">
+ <?= I18N::translate('Fact or event') ?>
+ </th>
+ <td>
+ <form onsubmit="if ($('#add-fact').val() === null) {event.preventDefault();}">
+ <input type="hidden" name="route" value="add-fact">
+ <input type="hidden" name="xref" value="<?= e($record->xref()) ?>">
+ <input type="hidden" name="ged" value="<?= e($record->tree()->name()) ?>">
+ <div class="input-group">
+ <select class="form-control" id="add-fact" name="fact">
+ <option value="" disabled selected>
+ <?= I18N::translate('&lt;select&gt;') ?>
+ </option>
+ <?php foreach ($add_facts as $fact => $fact_name) : ?>
+ <option value="<?= $fact ?>"><?= $fact_name ?></option>
+ <?php endforeach ?>
+ <?php if ($record::RECORD_TYPE === 'INDI' || $record::RECORD_TYPE === 'FAM') : ?>
+ <option value="FACT">
+ <?= I18N::translate('Custom fact') ?>
+ </option>
+ <option value="EVEN">
+ <?= I18N::translate('Custom event') ?>
+ </option>
+ <?php endif ?>
+ </select>
+ <div class="input-group-append">
+ <button class="btn btn-light" type="submit">
+ <?= /* I18N: A button label. */ I18N::translate('add') ?>
+ </button>
+ </div>
+ </div>
+ </form>
+
+ <div class="wt-quick-facts">
+ <?php foreach ($quick_facts as $fact) : ?>
+ <a class="btn btn-link btn-sm wt-quick-fact" href="<?= e(route('add-fact', [
+ 'fact' => $fact,
+ 'xref' => $record->xref(),
+ 'ged' => $tree->name(),
+ ])) ?>">
+ <?= GedcomTag::getLabel($fact) ?>
+ </a>
+ <?php endforeach ?>
+ </div>
+ </td>
+</tr>
diff --git a/resources/views/edit/paste-fact-row.phtml b/resources/views/edit/paste-fact-row.phtml
new file mode 100644
index 0000000000..33521107fb
--- /dev/null
+++ b/resources/views/edit/paste-fact-row.phtml
@@ -0,0 +1,33 @@
+<?php use Fisharebest\Webtrees\I18N; ?>
+
+<?php if (!empty($facts)) : ?>
+<tr>
+ <th scope="row">
+ <?= I18N::translate('Add from clipboard') ?>
+ </th>
+ <td>
+ <form name="newFromClipboard" onsubmit="return false;">
+ <div class="input-group">
+ <select class="form-control" id="newClipboardFact">
+ <?php foreach ($facts as $fact) : ?>
+ <option value="<?= e($fact->id()) ?>">
+ <?= $fact->label() ?>
+ <?php if ($fact->date()->isOK()) : ?>
+ – <?= $fact->date()->minimumDate()->format('%Y') ?>
+ <?php endif ?>
+ <?php if (!$fact->place()->isEmpty()) : ?>
+ – <?= $fact->place()->getShortName() ?>
+ <?php endif ?>
+ </option>
+ <?php endforeach ?>
+ </select>
+ <div class="input-group-append">
+ <button class="btn btn-light" type="submit" onclick="return paste_fact('<?= e($tree->name()) ?>', '<?= e($record->xref()) ?>', '#newClipboardFact');">
+ <?= /* I18N: A button label. */ I18N::translate('add') ?>
+ </button>
+ </div>
+ </div>
+ </form>
+ </td>
+</tr>
+<?php endif ?>
diff --git a/themes/clouds/css-2.0.0/style.css b/themes/clouds/css-2.0.0/style.css
index 209e895195..fdfa133a1d 100755
--- a/themes/clouds/css-2.0.0/style.css
+++ b/themes/clouds/css-2.0.0/style.css
@@ -1249,11 +1249,6 @@ div.fact_SHARED_NOTE {
background-color: #fdd;
}
-.quickfacts a {
- padding: 0 3px;
- font-size: 9px;
-}
-
.tabs_table {
width: 99%;
}
diff --git a/themes/colors/css-2.0.0/style.css b/themes/colors/css-2.0.0/style.css
index fef9ccb729..8a5d945a61 100755
--- a/themes/colors/css-2.0.0/style.css
+++ b/themes/colors/css-2.0.0/style.css
@@ -1151,11 +1151,6 @@ div.fact_SHARED_NOTE {
background-color: #fdd;
}
-.quickfacts a {
- padding: 0 3px;
- font-size: 9px;
-}
-
.tabs_table {
width: 99%;
}
diff --git a/themes/fab/css-2.0.0/style.css b/themes/fab/css-2.0.0/style.css
index 555e409ba7..032aa5d24d 100755
--- a/themes/fab/css-2.0.0/style.css
+++ b/themes/fab/css-2.0.0/style.css
@@ -691,11 +691,6 @@ div.fact_SHARED_NOTE {
background-color: #fdd;
}
-.quickfacts a {
- padding: 0 3px;
- font-size: 9px;
-}
-
.tabs_table {
width: 99%;
}
diff --git a/themes/minimal/css-2.0.0/style.css b/themes/minimal/css-2.0.0/style.css
index 7a25c66942..f48d0366d3 100755
--- a/themes/minimal/css-2.0.0/style.css
+++ b/themes/minimal/css-2.0.0/style.css
@@ -623,11 +623,6 @@ table {
margin: 0 auto;
}
-.quickfacts a {
- font-size: .75rem;
- padding: 0 3px;
-}
-
#reportengine-page .report-type {
overflow: hidden;
margin: auto;
diff --git a/themes/webtrees/css-2.0.0/style.css b/themes/webtrees/css-2.0.0/style.css
index cd80275a41..c827cd707d 100755
--- a/themes/webtrees/css-2.0.0/style.css
+++ b/themes/webtrees/css-2.0.0/style.css
@@ -1154,11 +1154,6 @@ div.fact_SHARED_NOTE {
border-color: #ff2080;
}
-.quickfacts a {
- padding: 0 3px;
- font-size: 9px;
-}
-
.tabs_table {
width: 99%;
}
diff --git a/themes/xenea/css-2.0.0/style.css b/themes/xenea/css-2.0.0/style.css
index 770a0fbfb9..31ca8ffd0e 100755
--- a/themes/xenea/css-2.0.0/style.css
+++ b/themes/xenea/css-2.0.0/style.css
@@ -1136,11 +1136,6 @@ div.fact_SHARED_NOTE {
border-color: #ff2080;
}
-.quickfacts a {
- padding: 0 3px;
- font-size: 9px;
-}
-
.tabs_table {
width: 99%;
}