Skip to content

Commit

Permalink
fix: fixed various issues with autosave, closes #1703
Browse files Browse the repository at this point in the history
  • Loading branch information
thorsten committed Apr 12, 2020
1 parent a0c56d9 commit 42df685
Show file tree
Hide file tree
Showing 8 changed files with 175 additions and 166 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"homepage": "https://www.phpmyfaq.de/",
"scripts": {
"build": "webpack",
"watch": "webpack --watch"
"build:watch": "webpack --watch"
},
"dependencies": {
"bootstrap": "^4.2.1",
Expand Down
89 changes: 45 additions & 44 deletions phpmyfaq/admin/ajax.autosave.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
]
]
);
$record_lang = Filter::filterInput(INPUT_POST, 'lang', FILTER_SANITIZE_STRING);
$recordLang = Filter::filterInput(INPUT_POST, 'lang', FILTER_SANITIZE_STRING);
$tags = Filter::filterInput(INPUT_POST, 'tags', FILTER_SANITIZE_STRING);
$active = Filter::filterInput(INPUT_POST, 'active', FILTER_SANITIZE_STRING);
$sticky = Filter::filterInput(INPUT_POST, 'sticky', FILTER_SANITIZE_STRING);
Expand All @@ -62,17 +62,17 @@
$author = Filter::filterInput(INPUT_POST, 'author', FILTER_SANITIZE_STRING);
$email = Filter::filterInput(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);
$comment = Filter::filterInput(INPUT_POST, 'comment', FILTER_SANITIZE_STRING);
$record_id = Filter::filterInput(INPUT_POST, 'record_id', FILTER_VALIDATE_INT);
$solution_id = Filter::filterInput(INPUT_POST, 'solution_id', FILTER_VALIDATE_INT);
$revision_id = Filter::filterInput(INPUT_POST, 'revision_id', FILTER_VALIDATE_INT);
$changed = Filter::filterInput(INPUT_POST, 'changed', FILTER_SANITIZE_STRING);
$recordId = Filter::filterInput(INPUT_POST, 'recordId', FILTER_VALIDATE_INT);
$solutionId = Filter::filterInput(INPUT_POST, 'solutionId', FILTER_VALIDATE_INT);
$revisionId = Filter::filterInput(INPUT_POST, 'revisionId', FILTER_VALIDATE_INT);
$changed = '';

$user_permission = Filter::filterInput(INPUT_POST, 'userpermission', FILTER_SANITIZE_STRING);
$restricted_users = ('all' == $user_permission) ? -1 : Filter::filterInput(INPUT_POST, 'restricted_users',
FILTER_VALIDATE_INT);
$restrictedUsers = ('all' == $user_permission) ? -1 : Filter::filterInput(INPUT_POST, 'restrictedUsers',
FILTER_VALIDATE_INT);
$group_permission = Filter::filterInput(INPUT_POST, 'grouppermission', FILTER_SANITIZE_STRING);
$restricted_groups = ('all' == $group_permission) ? -1 : Filter::filterInput(INPUT_POST, 'restricted_groups',
FILTER_VALIDATE_INT);
$restrictedGroups = ('all' == $group_permission) ? -1 : Filter::filterInput(INPUT_POST, 'restrictedGroups',
FILTER_VALIDATE_INT);

if (!is_null($question) && !is_null($categories)) {
$tagging = new Tags($faqConfig);
Expand All @@ -85,9 +85,9 @@
}

$recordData = [
'id' => $record_id,
'lang' => $record_lang,
'revision_id' => $revision_id,
'id' => $recordId,
'lang' => $recordLang,
'revisionId' => $revisionId,
'active' => $active,
'sticky' => (!is_null($sticky) ? 1 : 0),
'thema' => html_entity_decode($question),
Expand All @@ -101,75 +101,76 @@
'dateEnd' => (empty($dateEnd) ? '99991231235959' : str_replace('-', '', $dateEnd) . '235959'),
'linkState' => '',
'linkDateCheck' => 0,
'notes' => ''
];

if ('saveentry' == $do || $record_id) {
if ('saveentry' == $do || $recordId) {
/* Create a revision anyway, it's autosaving */
$faq->addNewRevision($record_id, $record_lang);
++$revision_id;
$faq->addNewRevision($recordId, $recordLang);
++$revisionId;

$changelog = new Changelog($faqConfig);
$changelog->addEntry($record_id, $user->getUserId(), nl2br($changed), $record_lang, $revision_id);
$changelog->addEntry($recordId, $user->getUserId(), nl2br($changed), $recordLang, $revisionId);

$visits = new Visits($faqConfig);
$visits->logViews($record_id);
$visits->logViews($recordId);

if ($faq->hasTranslation($record_id, $record_lang)) {
if ($faq->hasTranslation($recordId, $recordLang)) {
$faq->updateRecord($recordData);
} else {
$record_id = $faq->addRecord($recordData, false);
$recordId = $faq->addRecord($recordData, false);
}

$faq->deleteCategoryRelations($record_id, $record_lang);
$faq->addCategoryRelations($categories['rubrik'], $record_id, $record_lang);
$faq->deleteCategoryRelations($recordId, $recordLang);
$faq->addCategoryRelations($categories['rubrik'], $recordId, $recordLang);

if ($tags != '') {
$tagging->saveTags($record_id, explode(',', $tags));
$tagging->saveTags($recordId, explode(',', $tags));
} else {
$tagging->deleteTagsFromRecordId($record_id);
$tagging->deleteTagsFromRecordId($recordId);
}

$faq->deletePermission('user', $record_id);
$faq->addPermission('user', $record_id, $restricted_users);
$faq->deletePermission('user', $recordId);
$faq->addPermission('user', $recordId, [$restrictedUsers]);
$category->deletePermission('user', $categories['rubrik']);
$category->addPermission('user', $categories['rubrik'], $restricted_users);
$category->addPermission('user', $categories['rubrik'], [$restrictedUsers]);
if ($faqConfig->get('security.permLevel') !== 'basic') {
$faq->deletePermission('group', $record_id);
$faq->addPermission('group', $record_id, $restricted_groups);
$faq->deletePermission('group', $recordId);
$faq->addPermission('group', $recordId, [$restrictedGroups]);
$category->deletePermission('group', $categories['rubrik']);
$category->addPermission('group', $categories['rubrik'], $restricted_groups);
$category->addPermission('group', $categories['rubrik'], [$restrictedGroups]);
}
} elseif ('insertentry' == $do) {
unset($recordData['id']);
unset($recordData['revision_id']);
$revision_id = 1;
$record_id = $faq->addRecord($recordData);
if ($record_id) {
unset($recordData['revisionId']);
$revisionId = 1;
$recordId = $faq->addRecord($recordData);
if ($recordId) {
$changelog = new Changelog($faqConfig);
$changelog->addEntry($record_id, $user->getUserId(), nl2br($changed), $recordData['lang']);
$changelog->addEntry($recordId, $user->getUserId(), nl2br($changed), $recordData['lang']);
$visits = new Visits($faqConfig);
$visits->add($record_id);
$visits->add($recordId);

$faq->addCategoryRelations($categories['rubrik'], $record_id, $recordData['lang']);
$faq->addCategoryRelations($categories['rubrik'], $recordId, $recordData['lang']);

if ($tags != '') {
$tagging->saveTags($record_id, explode(',', $tags));
$tagging->saveTags($recordId, explode(',', $tags));
}

$faq->addPermission('user', $record_id, $restricted_users);
$category->addPermission('user', $categories['rubrik'], $restricted_users);
$faq->addPermission('user', $recordId, [$restrictedUsers]);
$category->addPermission('user', $categories['rubrik'], [$restrictedUsers]);

if ($faqConfig->get('security.permLevel') !== 'basic') {
$faq->addPermission('group', $record_id, $restricted_groups);
$category->addPermission('group', $categories['rubrik'], $restricted_groups);
$faq->addPermission('group', $recordId, [$restrictedGroups]);
$category->addPermission('group', $categories['rubrik'], [$restrictedGroups]);
}
}
}

$out = [
'msg' => sprintf('Item auto-saved at revision %d', $revision_id),
'revision_id' => $revision_id,
'record_id' => $record_id,
'msg' => sprintf('Item auto-saved at revision %d', $revisionId),
'revisionId' => $revisionId,
'recordId' => $recordId,
];

$http->sendJsonWithHeaders($out);
Expand Down
112 changes: 112 additions & 0 deletions phpmyfaq/admin/assets/js/autosave.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
/**
* Auto Save functionality JavaScript part
*
* This Source Code Form is subject to the terms of the Mozilla Public License,
* v. 2.0. If a copy of the MPL was not distributed with this file, You can
* obtain one at http://mozilla.org/MPL/2.0/.
*
* @package phpMyFAQ
* @author Anatoliy Belsky <ab@php.net>
* @copyright 2012-2020 phpMyFAQ Team
* @license http://www.mozilla.org/MPL/2.0/ Mozilla Public License Version 2.0
* @link https://www.phpmyfaq.de
* @since 2012-07-07
*/

/*global document: false, window: false, $: false */

document.addEventListener('DOMContentLoaded', () => {
'use strict';

const autoSaveInterval = document.querySelector('meta[name="phpmyfaq-config-autosave-seconds"]').content;

$(window).on('unload', () => {
if (typeof window.tinyMCE !== 'undefined' && window.tinyMCE.activeEditor !== null) {
if (window.tinyMCE.activeEditor.isDirty()) {
// @todo should be translated
const confirmed = window.confirm('Do you want to save the article before navigating away?');

if (confirmed) {
faqAutoSave();
}
}
}
});

if (typeof window.tinyMCE !== 'undefined' && typeof autoSaveInterval !== 'undefined') {
setInterval(() => {
faqAutoSave();
}, autoSaveInterval * 1000);
}

/**
* Post auto save data via AJAX.
*
* @return void
*/
function faqAutoSave() {
const activeEditor = window.tinyMCE.activeEditor;
if (activeEditor.isDirty()) {
const formData = {};
const category = document.getElementById('phpmyfaq-categories');
const languages = document.getElementById('lang');

formData.revision_id = $('#revisionId').attr('value');
formData.record_id = $('#recordId').attr('value');
formData.csrf = $('[name="csrf"]').attr('value');
formData.openQuestionId = $('#openQuestionId').attr('value');
formData.question = document.getElementById('question').value;
formData.answer = activeEditor.getContent();
formData.keywords = $('#keywords').attr('value');
formData.rubrik = Array.from(category.options)
.filter(o => o.selected)
.map(o => o.value);
formData.tags = $('#tags').attr('value');
formData.author = $('#author').attr('value');
formData.email = $('#email').attr('value');
formData.lang = languages.options[languages.selectedIndex].value;
formData.solution_id = $('#solutionId').attr('value');
formData.active = $('input:checked[name="active"]').attr('value');
formData.sticky = $('#sticky').attr('value');
formData.comment = $('#comment').attr('value');
formData.grouppermission = $('[name="grouppermission"]').attr('value');
formData.userpermission = $('[name="userpermission"]').attr('value');
formData.restricted_users = $('[name="restricted_users"]').attr('value');
formData.dateActualize = $('#dateActualize').attr('value');
formData.dateKeep = $('#dateKeep').attr('value');
formData.dateCustomize = $('#dateCustomize').attr('value');
formData.date = $('#date').attr('value');

$.ajax({
url: faqAutoSaveAction(),
type: 'POST',
data: formData,
success: data => {
const response = $.parseJSON(data);

$('#pmf-admin-saving-data-indicator').html(response.msg);

activeEditor.isNotDirty = true;

$('#recordId').attr('value', response.record_id);
$('#revisionId').attr('value', response.revision_id);
// @todo check update more places on the page according to the new saved data
},
});
}
}

/**
* Produce AJAX autosave action.
*
* @return string
*/
function faqAutoSaveAction() {
let action,
queryFunction = $('#faqEditor').attr('action');

action = '?action=ajax&ajax=autosave&' + queryFunction.substr(1).replace(/action=/, 'do=');

return action;
}
});
8 changes: 4 additions & 4 deletions phpmyfaq/admin/header.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
$exportsPage = false;
$backupPage = false;
$configurationPage = false;
$edAutoSave = (('editentry' === $action) && $faqConfig->get('records.autosaveActive'));
$editorAutoSave = (('editentry' === $action) && $faqConfig->get('records.autosaveActive'));

$adminHelper = new AdministrationHelper();
$adminHelper->setUser($user);
Expand Down Expand Up @@ -234,6 +234,7 @@
<meta name="copyright" content="(c) 2001-<?= date('Y') ?> phpMyFAQ Team">
<meta name="publisher" content="phpMyFAQ Team">
<meta name="robots" content="<?= $faqConfig->get('seo.metaTagsAdmin') ?>">
<meta name="phpmyfaq-config-autosave-seconds" content="<?= $faqConfig->get('records.autosaveSecs') ?>">

<link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet" type="text/css">
<link rel="stylesheet" href="../assets/dist/admin-styles.css">
Expand All @@ -244,9 +245,8 @@
<script src="assets/js/sidebar.js"></script>
<script src="assets/js/editor/tinymce.min.js?<?= time(); ?>"></script>

<?php if ($edAutoSave): ?>
<script>let pmfAutosaveInterval = <?= $faqConfig->get('records.autosaveSecs') ?>;</script>
<script src="../assets/src/autosave.js" async></script>
<?php if ($editorAutoSave): ?>
<script src="assets/js/autosave.js" async></script>
<?php endif; ?>

<link rel="shortcut icon" href="../assets/themes/<?= Template::getTplSetName(); ?>/img/favicon.ico">
Expand Down

0 comments on commit 42df685

Please sign in to comment.