diff --git a/phpmyfaq/admin/assets/src/api/faqs.js b/phpmyfaq/admin/assets/src/api/faqs.js index b0e72d86ca..3ba22b99da 100644 --- a/phpmyfaq/admin/assets/src/api/faqs.js +++ b/phpmyfaq/admin/assets/src/api/faqs.js @@ -94,3 +94,41 @@ export const deleteFaq = async (faqId, faqLanguage, token) => { throw error; } }; + +export const create = async (formData) => { + try { + const response = await fetch('./api/faq/create', { + method: 'POST', + headers: { + Accept: 'application/json, text/plain, */*', + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + data: formData, + }), + }); + + return await response.json(); + } catch (error) { + console.error(error); + } +}; + +export const update = async (formData) => { + try { + const response = await fetch('./api/faq/update', { + method: 'PUT', + headers: { + Accept: 'application/json, text/plain, */*', + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + data: formData, + }), + }); + + return await response.json(); + } catch (error) { + console.error(error); + } +}; diff --git a/phpmyfaq/admin/assets/src/content/editor.js b/phpmyfaq/admin/assets/src/content/editor.js index 4255475092..4cb669dfad 100644 --- a/phpmyfaq/admin/assets/src/content/editor.js +++ b/phpmyfaq/admin/assets/src/content/editor.js @@ -233,6 +233,11 @@ export const renderEditor = () => { image_dimensions: true, images_upload_url: '/admin/api/content/images', automatic_uploads: true, + setup: (editor) => { + editor.on('change', () => { + tinymce.triggerSave(); + }); + }, }); } }; diff --git a/phpmyfaq/admin/assets/src/content/faqs.editor.js b/phpmyfaq/admin/assets/src/content/faqs.editor.js new file mode 100644 index 0000000000..f8762b6251 --- /dev/null +++ b/phpmyfaq/admin/assets/src/content/faqs.editor.js @@ -0,0 +1,37 @@ +import { create, update } from '../api'; +import { serialize } from '../../../../assets/src/utils'; +import { pushErrorNotification, pushNotification } from '../utils'; + +export const handleSaveFaqData = () => { + const submitButton = document.getElementById('faqEditorSubmit'); + + if (submitButton) { + submitButton.addEventListener('click', async (event) => { + event.preventDefault(); + const form = document.getElementById('faqEditor'); + const formData = new FormData(form); + + const serializedData = serialize(formData); + + let response; + if (serializedData.faqId === '0') { + response = await create(serializedData); + } else { + response = await update(serializedData); + } + + if (response.success) { + const data = JSON.parse(response.data); + const faqId = document.getElementById('faqId'); + const revisionId = document.getElementById('revisionId'); + + faqId.value = data.id; + revisionId.value = data.revisionId; + + pushNotification(response.success); + } else { + pushErrorNotification(response.error); + } + }); + } +}; diff --git a/phpmyfaq/admin/assets/src/content/index.js b/phpmyfaq/admin/assets/src/content/index.js index a03a2c7190..05301f7e72 100644 --- a/phpmyfaq/admin/assets/src/content/index.js +++ b/phpmyfaq/admin/assets/src/content/index.js @@ -6,6 +6,7 @@ export * from './csvimport'; export * from './editor'; export * from './faqs'; export * from './faqs.autocomplete'; +export * from './faqs.editor'; export * from './glossary'; export * from './markdown'; export * from './media.browser'; diff --git a/phpmyfaq/admin/assets/src/index.js b/phpmyfaq/admin/assets/src/index.js index 48ad9c555a..6a2a1312c7 100644 --- a/phpmyfaq/admin/assets/src/index.js +++ b/phpmyfaq/admin/assets/src/index.js @@ -43,7 +43,11 @@ import { handleDeleteGlossary, handleAddGlossary, onOpenUpdateGlossaryModal, - handleUpdateGlossary, handleAddNews, handleNews, handleEditNews, + handleUpdateGlossary, + handleAddNews, + handleNews, + handleEditNews, + handleSaveFaqData, } from './content'; import { handleUserList, handleUsers } from './user'; import { handleGroups } from './group'; @@ -82,6 +86,7 @@ document.addEventListener('DOMContentLoaded', async () => { handleMarkdownForm(); handleAttachmentUploads(); handleFileFilter(); + handleSaveFaqData(); await handleFaqOverview(); // Content -> Comments diff --git a/phpmyfaq/admin/header.php b/phpmyfaq/admin/header.php index 8423dd38df..bc908a8863 100644 --- a/phpmyfaq/admin/header.php +++ b/phpmyfaq/admin/header.php @@ -187,7 +187,6 @@ case 'showcategory': case 'faqs-overview': case 'editentry': - case 'insertentry': case 'saveentry': case 'glossary': case 'saveglossary': diff --git a/phpmyfaq/admin/index.php b/phpmyfaq/admin/index.php index 02cce99963..7e1913597d 100755 --- a/phpmyfaq/admin/index.php +++ b/phpmyfaq/admin/index.php @@ -265,9 +265,6 @@ case 'editpreview': require 'record.edit.php'; break; - case 'insertentry': - require 'record.add.php'; - break; case 'saveentry': require 'record.save.php'; break; diff --git a/phpmyfaq/admin/record.add.php b/phpmyfaq/admin/record.add.php deleted file mode 100644 index 8efa708293..0000000000 --- a/phpmyfaq/admin/record.add.php +++ /dev/null @@ -1,283 +0,0 @@ - - * @copyright 2003-2024 phpMyFAQ Team - * @license https://www.mozilla.org/MPL/2.0/ Mozilla Public License Version 2.0 - * @link https://www.phpmyfaq.de - * @since 2003-02-23 - */ - -use phpMyFAQ\Administration\AdminLog; -use phpMyFAQ\Administration\Changelog; -use phpMyFAQ\Category; -use phpMyFAQ\Category\Permission; -use phpMyFAQ\Category\Relation; -use phpMyFAQ\Component\Alert; -use phpMyFAQ\Configuration; -use phpMyFAQ\Core\Exception; -use phpMyFAQ\Entity\FaqEntity; -use phpMyFAQ\Enums\PermissionType; -use phpMyFAQ\Faq\Permission; -use phpMyFAQ\Filter; -use phpMyFAQ\Helper\CategoryHelper; -use phpMyFAQ\Instance\Elasticsearch; -use phpMyFAQ\Link; -use phpMyFAQ\Notification; -use phpMyFAQ\Question; -use phpMyFAQ\Strings; -use phpMyFAQ\Tags; -use phpMyFAQ\Translation; -use phpMyFAQ\User\CurrentUser; -use phpMyFAQ\Visits; -use Symfony\Component\Mailer\Exception\TransportExceptionInterface; - -if (!defined('IS_VALID_PHPMYFAQ')) { - http_response_code(400); - exit(); -} - -$faqConfig = Configuration::getConfigurationInstance(); -$user = CurrentUser::getCurrentUser($faqConfig); - -if ($user->perm->hasPermission($user->getUserId(), PermissionType::FAQ_ADD->value)) { - $faqPermission = new Permission($faqConfig); - - // FAQ data - $dateStart = Filter::filterInput(INPUT_POST, 'dateStart', FILTER_SANITIZE_SPECIAL_CHARS); - $dateEnd = Filter::filterInput(INPUT_POST, 'dateEnd', FILTER_SANITIZE_SPECIAL_CHARS); - $question = Filter::filterInput(INPUT_POST, 'question', FILTER_SANITIZE_SPECIAL_CHARS); - $categories = Filter::filterInputArray( - INPUT_POST, - [ - 'rubrik' => [ - 'filter' => FILTER_VALIDATE_INT, - 'flags' => FILTER_REQUIRE_ARRAY, - ], - ] - ); - $recordLang = Filter::filterInput(INPUT_POST, 'lang', FILTER_SANITIZE_SPECIAL_CHARS); - $tags = Filter::filterInput(INPUT_POST, 'tags', FILTER_SANITIZE_SPECIAL_CHARS); - $active = Filter::filterInput(INPUT_POST, 'active', FILTER_SANITIZE_SPECIAL_CHARS); - $sticky = Filter::filterInput(INPUT_POST, 'sticky', FILTER_SANITIZE_SPECIAL_CHARS); - $content = Filter::filterInput(INPUT_POST, 'answer', FILTER_SANITIZE_SPECIAL_CHARS); - $keywords = Filter::filterInput(INPUT_POST, 'keywords', FILTER_SANITIZE_SPECIAL_CHARS); - $author = Filter::filterInput(INPUT_POST, 'author', FILTER_SANITIZE_SPECIAL_CHARS); - $email = Filter::filterInput(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL, ''); - $comment = Filter::filterInput(INPUT_POST, 'comment', FILTER_SANITIZE_SPECIAL_CHARS); - $recordId = Filter::filterInput(INPUT_POST, 'id', FILTER_VALIDATE_INT); - $solutionId = Filter::filterInput(INPUT_POST, 'solution_id', FILTER_VALIDATE_INT); - $revisionId = Filter::filterInput(INPUT_POST, 'revision_id', FILTER_VALIDATE_INT); - $changed = Filter::filterInput(INPUT_POST, 'changed', FILTER_SANITIZE_SPECIAL_CHARS); - $date = Filter::filterInput(INPUT_POST, 'date', FILTER_SANITIZE_SPECIAL_CHARS); - $notes = Filter::filterInput(INPUT_POST, 'notes', FILTER_SANITIZE_SPECIAL_CHARS); - - // Permissions - $permissions = $faqPermission->createPermissionArray(); - - if (!isset($categories['rubrik'])) { - $categories['rubrik'] = []; - } - - if (!is_null($question) && !is_null($categories['rubrik'])) { - // new entry - $logging = new AdminLog($faqConfig); - $logging->log($user, 'admin-save-new-faq'); - ?> -
-

- - -

-
- - setUser($currentAdminUser); - $category->setGroups($currentAdminGroups); - - $categoryPermission = new Permission($faqConfig); - $tagging = new Tags($faqConfig); - $notification = new Notification($faqConfig); - - $faqData = new FaqEntity(); - $faqData - ->setLanguage($recordLang) - ->setActive($active === 'yes') - ->setSticky(!is_null($sticky)) - ->setQuestion( - Filter::removeAttributes(html_entity_decode((string) $question, ENT_QUOTES | ENT_HTML5, 'UTF-8')) - ) - ->setAnswer( - Filter::removeAttributes(html_entity_decode((string) $content, ENT_QUOTES | ENT_HTML5, 'UTF-8')) - ) - ->setKeywords($keywords) - ->setAuthor($author) - ->setEmail($email) - ->setComment(!is_null($comment)) - ->setCreatedDate(new DateTime()) - ->setNotes(Filter::removeAttributes($notes)); - - // Add new record and get that ID - $recordId = $faq->create($faqData); - - if ($recordId) { - // Create ChangeLog entry - $changelog = new Changelog($faqConfig); - $changelog->add($recordId, $user->getUserId(), nl2br((string) $changed), $faqData->getLanguage()); - - // Create the visit entry - $visits = new Visits($faqConfig); - $visits->logViews($recordId); - - $categoryRelation = new Relation($faqConfig, $category); - $categoryRelation->add($categories['rubrik'], $recordId, $faqData->getLanguage()); - - // Insert the tags - if ($tags !== '') { - $tagging->create($recordId, explode(',', trim((string) $tags))); - } - - // Add user permissions - $faqPermission->add(Permission::USER, $recordId, $permissions['restricted_user']); - $categoryPermission->add(Permission::USER, $categories['rubrik'], $permissions['restricted_user']); - // Add group permission - if ($faqConfig->get('security.permLevel') !== 'basic') { - $faqPermission->add(Permission::GROUP, $recordId, $permissions['restricted_groups']); - $categoryPermission->add( - Permission::GROUP, - $categories['rubrik'], - $permissions['restricted_groups'] - ); - } - - // Open question answered - $questionObject = new Question($faqConfig); - $openQuestionId = Filter::filterInput(INPUT_POST, 'openQuestionId', FILTER_VALIDATE_INT); - if (0 !== $openQuestionId) { - if ($faqConfig->get('records.enableDeleteQuestion')) { // deletes question - $questionObject->delete($openQuestionId); - } else { // adds this faq record id to the related open question - $questionObject->updateQuestionAnswer($openQuestionId, $recordId, $categories['rubrik'][0]); - } - - $url = sprintf( - '%s?action=faq&cat=%d&id=%d&artlang=%s', - $faqConfig->getDefaultUrl(), - $categories['rubrik'][0], - $recordId, - $recordLang - ); - $oLink = new Link($url, $faqConfig); - - // notify the user who added the question - try { - $notifyEmail = Filter::filterInput(INPUT_POST, 'notifyEmail', FILTER_SANITIZE_EMAIL); - $notifyUser = Filter::filterInput(INPUT_POST, 'notifyUser', FILTER_SANITIZE_SPECIAL_CHARS); - $notification->sendOpenQuestionAnswered($notifyEmail, $notifyUser, $oLink->toString()); - } catch (Exception | TransportExceptionInterface $e) { - printf('

%s

', $e->getMessage()); - } - } - - // Let the admin and the category owners to be informed by email of this new entry - try { - $categoryHelper = new CategoryHelper(); - $categoryHelper - ->setCategory($category) - ->setConfiguration($faqConfig); - $moderators = $categoryHelper->getModerators($categories['rubrik']); - $notification->sendNewFaqAdded($moderators, $recordId, $recordLang); - } catch (Exception | TransportExceptionInterface $e) { - printf('

%s

', $e->getMessage()); - } - - // If Elasticsearch is enabled, index new FAQ document - if ($faqConfig->get('search.enableElasticsearch')) { - $esInstance = new Elasticsearch($faqConfig); - $esInstance->index( - [ - 'id' => $recordId, - 'lang' => $recordLang, - 'solution_id' => $solutionId, - 'question' => $faqData->getQuestion(), - 'answer' => $faqData->getAnswer(), - 'keywords' => $keywords, - 'category_id' => $categories['rubrik'][0] - ] - ); - } - - echo Alert::success('ad_entry_savedsuc'); - ?> -
-
- Saving ... -
-
- - getDb()->error()); - } - } else { - printf( - '
', - Translation::get('ad_entry_aor') - ); - echo Alert::danger('ad_entryins_fail'); - ?> -
- - - - - - - - $_categories) { - echo ' '; - } - } - ?> - - - - - - - - - - - - - -

- -

-
- language = $faqData['lang']; $faq->getRecord($faqData['id'], $selectedRevisionId, true); $faqData = $faq->faqRecord; $faqData['tags'] = implode(', ', $tagging->getAllTagsById($faqData['id'])); @@ -383,13 +382,14 @@ class="form-select"> } ?> -
- - +
- @@ -816,7 +816,7 @@ class="form-check-input" checked>
- get('records.enableAutoRevisions')) : ?> + get('records.enableAutoRevisions')) : ?>
@@ -861,10 +861,10 @@ class="form-check-input"
-
diff --git a/phpmyfaq/admin/record.save.php b/phpmyfaq/admin/record.save.php deleted file mode 100644 index 8c77e00ef8..0000000000 --- a/phpmyfaq/admin/record.save.php +++ /dev/null @@ -1,226 +0,0 @@ - - * @copyright 2003-2024 phpMyFAQ Team - * @license https://www.mozilla.org/MPL/2.0/ Mozilla Public License Version 2.0 - * @link https://www.phpmyfaq.de - * @since 2003-02-23 - */ - -use phpMyFAQ\Administration\AdminLog; -use phpMyFAQ\Administration\Changelog; -use phpMyFAQ\Administration\Revision; -use phpMyFAQ\Category; -use phpMyFAQ\Category\Relation; -use phpMyFAQ\Component\Alert; -use phpMyFAQ\Configuration; -use phpMyFAQ\Entity\FaqEntity; -use phpMyFAQ\Enums\PermissionType; -use phpMyFAQ\Faq\Permission; -use phpMyFAQ\Filter; -use phpMyFAQ\Instance\Elasticsearch; -use phpMyFAQ\Tags; -use phpMyFAQ\Translation; -use phpMyFAQ\User\CurrentUser; -use phpMyFAQ\Visits; - -if (!defined('IS_VALID_PHPMYFAQ')) { - http_response_code(400); - exit(); -} - -$faqConfig = Configuration::getConfigurationInstance(); -$user = CurrentUser::getCurrentUser($faqConfig); - -$category = new Category($faqConfig, [], false); -$category->setUser($currentAdminUser); -$category->setGroups($currentAdminGroups); - -if ($user->perm->hasPermission($user->getUserId(), PermissionType::FAQ_EDIT->value)) { - // Get submit action - $submit = Filter::filterInputArray( - INPUT_POST, - [ - 'submit' => [ - 'filter' => FILTER_VALIDATE_INT, - 'flags' => FILTER_REQUIRE_ARRAY, - ], - ] - ); - - // FAQ data - $dateStart = Filter::filterInput(INPUT_POST, 'dateStart', FILTER_SANITIZE_SPECIAL_CHARS); - $dateEnd = Filter::filterInput(INPUT_POST, 'dateEnd', FILTER_SANITIZE_SPECIAL_CHARS); - $question = Filter::filterInput(INPUT_POST, 'question', FILTER_SANITIZE_SPECIAL_CHARS); - $categories = Filter::filterInputArray( - INPUT_POST, - [ - 'rubrik' => [ - 'filter' => FILTER_VALIDATE_INT, - 'flags' => FILTER_REQUIRE_ARRAY, - ], - ] - ); - $recordLang = Filter::filterInput(INPUT_POST, 'lang', FILTER_SANITIZE_SPECIAL_CHARS); - $tags = Filter::filterInput(INPUT_POST, 'tags', FILTER_SANITIZE_SPECIAL_CHARS); - $active = 'yes' == Filter::filterInput( - INPUT_POST, - 'active', - FILTER_SANITIZE_SPECIAL_CHARS - ) && $user->perm->hasPermission($user->getUserId(), 'approverec') ? 'yes' : 'no'; - $sticky = Filter::filterInput(INPUT_POST, 'sticky', FILTER_SANITIZE_SPECIAL_CHARS); - $content = Filter::filterInput(INPUT_POST, 'answer', FILTER_SANITIZE_SPECIAL_CHARS); - $keywords = Filter::filterInput(INPUT_POST, 'keywords', FILTER_SANITIZE_SPECIAL_CHARS); - $author = Filter::filterInput(INPUT_POST, 'author', FILTER_SANITIZE_SPECIAL_CHARS); - $email = Filter::filterInput(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL, ''); - $comment = Filter::filterInput(INPUT_POST, 'comment', FILTER_SANITIZE_SPECIAL_CHARS); - $recordId = Filter::filterInput(INPUT_POST, 'record_id', FILTER_VALIDATE_INT); - $solutionId = Filter::filterInput(INPUT_POST, 'solution_id', FILTER_VALIDATE_INT); - $revision = Filter::filterInput(INPUT_POST, 'revision', FILTER_SANITIZE_SPECIAL_CHARS); - $revisionId = Filter::filterInput(INPUT_POST, 'revision_id', FILTER_VALIDATE_INT); - $changed = Filter::filterInput(INPUT_POST, 'changed', FILTER_SANITIZE_SPECIAL_CHARS); - $date = Filter::filterInput(INPUT_POST, 'date', FILTER_SANITIZE_SPECIAL_CHARS); - $notes = Filter::filterInput(INPUT_POST, 'notes', FILTER_SANITIZE_SPECIAL_CHARS); - - // Permissions - $faqPermission = new Permission($faqConfig); - $permissions = $faqPermission->createPermissionArray(); - - if (!is_null($question) && !is_null($categories)) { - // Save entry - $logging = new AdminLog($faqConfig); - $logging->log($user, 'admin-save-existing-faq ' . $recordId); - if ($active === 'yes') { - $logging->log($user, 'admin-publish-existing-faq ' . $recordId); - } - ?> - -
-

- - - -

-
- - get('records.enableAutoRevisions')) { - $faqRevision = new Revision($faqConfig); - $faqRevision->create($recordId, $recordLang); - ++$revisionId; - } - - $faqData = new FaqEntity(); - $faqData - ->setId($recordId) - ->setLanguage($recordLang) - ->setRevisionId($revisionId) - ->setActive($active === 'yes') - ->setSticky(!is_null($sticky)) - ->setQuestion( - Filter::removeAttributes(html_entity_decode((string) $question, ENT_QUOTES | ENT_HTML5, 'UTF-8')) - ) - ->setAnswer( - Filter::removeAttributes(html_entity_decode((string) $content, ENT_QUOTES | ENT_HTML5, 'UTF-8')) - ) - ->setKeywords($keywords) - ->setAuthor($author) - ->setEmail($email) - ->setComment(!is_null($comment)) - ->setCreatedDate(new DateTime()) - ->setNotes(Filter::removeAttributes($notes)); - - // Create ChangeLog entry - $changelog = new Changelog($faqConfig); - $changelog->add($recordId, $user->getUserId(), (string) $changed, $recordLang, $revisionId); - - // Create the visit entry - $visits = new Visits($faqConfig); - $visits->logViews((int)$recordId); - - // save or update the FAQ record - if ($faq->hasTranslation($recordId, $recordLang)) { - $faq->update($faqData); - } else { - $recordId = $faq->create($faqData); - } - - if ($recordId) { - echo Alert::success('ad_entry_savedsuc'); - echo '
-
- Saving ... -
-
'; - } else { - echo Alert::danger('ad_entry_savedfail', $faqConfig->getDb()->error()); - } - - if (!isset($categories['rubrik'])) { - $categories['rubrik'] = []; - } - - $categoryRelation = new Relation($faqConfig, $category); - $categoryRelation->deleteByFaq($recordId, $recordLang); - $categoryRelation->add($categories['rubrik'], $recordId, $recordLang); - - // Insert the tags - if ($tags != '') { - $tagging->create($recordId, explode(',', trim((string) $tags))); - } else { - $tagging->deleteByRecordId($recordId); - } - - // Add user permissions - $faqPermission->delete(Permission::USER, $recordId); - $faqPermission->add(Permission::USER, $recordId, $permissions['restricted_user']); - // Add group permission - if ($faqConfig->get('security.permLevel') !== 'basic') { - $faqPermission->delete(Permission::GROUP, $recordId); - $faqPermission->add(Permission::GROUP, $recordId, $permissions['restricted_groups']); - } - - // If Elasticsearch is enabled, update an active or delete inactive FAQ document - if ($faqConfig->get('search.enableElasticsearch')) { - $esInstance = new Elasticsearch($faqConfig); - if ('yes' === $active) { - $esInstance->update( - [ - 'id' => $recordId, - 'lang' => $recordLang, - 'solution_id' => $solutionId, - 'question' => $faqData->getQuestion(), - 'answer' => $faqData->getAnswer(), - 'keywords' => $keywords, - 'category_id' => $categories['rubrik'][0] - ] - ); - } - } - - // All the other translations - $languages = Filter::filterInput(INPUT_POST, 'used_translated_languages', FILTER_SANITIZE_SPECIAL_CHARS); - ?> - - [FaqController::class, 'activate'], '_methods' => 'POST']) ); +$routes->add( + 'admin.api.faq.create', + new Route('/faq/create', ['_controller' => [FaqController::class, 'create'], '_methods' => 'POST']) +); + $routes->add( 'admin.api.faq.delete', new Route('/faq/delete', ['_controller' => [FaqController::class, 'delete'], '_methods' => 'DELETE']) ); +$routes->add( + 'admin.api.faq.update', + new Route('/faq/update', ['_controller' => [FaqController::class, 'update'], '_methods' => 'PUT']) +); + $routes->add( 'admin.api.faq.permissions', new Route('/faq/permissions/{faqId}', ['_controller' => [FaqController::class, 'listPermissions']]) diff --git a/phpmyfaq/src/phpMyFAQ/Administration/Revision.php b/phpmyfaq/src/phpMyFAQ/Administration/Revision.php index e8f38daf36..566cfff1ac 100644 --- a/phpmyfaq/src/phpMyFAQ/Administration/Revision.php +++ b/phpmyfaq/src/phpMyFAQ/Administration/Revision.php @@ -46,7 +46,7 @@ public function create(int $faqId, string $faqLanguage): bool %sfaqdata_revisions SELECT id, lang, solution_id, revision_id + 1, active, sticky, keywords, thema, content, author, email, - comment, updated, date_start, date_end, created, notes + comment, updated, date_start, date_end, created, notes, sticky_order FROM %sfaqdata WHERE diff --git a/phpmyfaq/src/phpMyFAQ/Application.php b/phpmyfaq/src/phpMyFAQ/Application.php index 78a8c8388e..d136e5934a 100644 --- a/phpmyfaq/src/phpMyFAQ/Application.php +++ b/phpmyfaq/src/phpMyFAQ/Application.php @@ -75,7 +75,7 @@ private function initializeTranslation(string $currentLanguage): void ->setCurrentLanguage($currentLanguage) ->setMultiByteLanguage(); } catch (Exception $exception) { - throw new Exception($exception->getMessage()); + throw new Exception('x' . $exception->getMessage()); } } @@ -101,14 +101,24 @@ private function handleRequest(RouteCollection $routeCollection): void } catch (UnauthorizedHttpException) { $response = new Response('Unauthorized', Response::HTTP_UNAUTHORIZED); } catch (BadRequestException $exception) { - $response = new Response($exception->getMessage(), Response::HTTP_BAD_REQUEST); + $response = new Response( + sprintf( + 'An error occurred: %s at line %d at %s
%s', + $exception->getMessage(), + $exception->getLine(), + $exception->getFile(), + implode('
', $exception->getTrace()) + ), + Response::HTTP_BAD_REQUEST + ); } catch (ErrorException | Exception $exception) { $response = new Response( sprintf( - 'An error occurred: %s at line %d at %s', + 'An error occurred: %s at line %d at %s
%s', $exception->getMessage(), $exception->getLine(), - $exception->getFile() + $exception->getFile(), + implode('
', $exception->getTrace()) ), Response::HTTP_INTERNAL_SERVER_ERROR ); diff --git a/phpmyfaq/src/phpMyFAQ/Controller/Administration/FaqController.php b/phpmyfaq/src/phpMyFAQ/Controller/Administration/FaqController.php index 5b1d58a3e5..2e39cf27f4 100644 --- a/phpmyfaq/src/phpMyFAQ/Controller/Administration/FaqController.php +++ b/phpmyfaq/src/phpMyFAQ/Controller/Administration/FaqController.php @@ -16,32 +16,377 @@ namespace phpMyFAQ\Controller\Administration; +use DateTime; use Exception; use phpMyFAQ\Administration\AdminLog; +use phpMyFAQ\Administration\Changelog; +use phpMyFAQ\Administration\Revision; use phpMyFAQ\Attachment\AttachmentException; use phpMyFAQ\Attachment\Filesystem\File\FileException; use phpMyFAQ\Category; +use phpMyFAQ\Category\Permission as CategoryPermission; +use phpMyFAQ\Category\Relation; use phpMyFAQ\Configuration; use phpMyFAQ\Controller\AbstractController; +use phpMyFAQ\Entity\FaqEntity; use phpMyFAQ\Enums\PermissionType; use phpMyFAQ\Faq; -use phpMyFAQ\Faq\Permission; +use phpMyFAQ\Faq\Permission as FaqPermission; use phpMyFAQ\Faq\Import; use phpMyFAQ\Filter; +use phpMyFAQ\Helper\CategoryHelper; use phpMyFAQ\Helper\SearchHelper; +use phpMyFAQ\Instance\Elasticsearch; use phpMyFAQ\Language; +use phpMyFAQ\Link; +use phpMyFAQ\Notification; +use phpMyFAQ\Question; use phpMyFAQ\Search; use phpMyFAQ\Search\SearchResultSet; use phpMyFAQ\Session\Token; +use phpMyFAQ\Tags; use phpMyFAQ\Translation; use phpMyFAQ\User\CurrentUser; +use phpMyFAQ\Visits; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Mailer\Exception\TransportExceptionInterface; use Symfony\Component\Routing\Annotation\Route; class FaqController extends AbstractController { + /** + * @throws \phpMyFAQ\Core\Exception + */ + #[Route('admin/api/faq/create')] + public function create(Request $request): JsonResponse + { + $this->userHasPermission(PermissionType::FAQ_ADD); + + $user = CurrentUser::getCurrentUser($this->configuration); + [ $currentUser, $currentGroups ] = CurrentUser::getCurrentUserGroupId($user); + + $faq = new Faq($this->configuration); + $faqPermission = new FaqPermission($this->configuration); + $categoryPermission = new CategoryPermission($this->configuration); + $tagging = new Tags($this->configuration); + $notification = new Notification($this->configuration); + $logging = new AdminLog($this->configuration); + $changelog = new Changelog($this->configuration); + $visits = new Visits($this->configuration); + + $category = new Category($this->configuration, [], false); + $category->setUser($currentUser); + $category->setGroups($currentGroups); + + $data = json_decode($request->getContent())->data; + + if (!Token::getInstance()->verifyToken('edit-faq', $data->{'pmf-csrf-token'})) { + return $this->json(['error' => Translation::get('err_NotAuth')], Response::HTTP_UNAUTHORIZED); + } + + // Collect FAQ data + $question = Filter::filterVar($data->question, FILTER_SANITIZE_SPECIAL_CHARS); + if (is_array($data->{'categories[]'})) { + $categories = Filter::filterArray($data->{'categories[]'}); + } else { + $categories = [Filter::filterVar($data->{'categories[]'}, FILTER_VALIDATE_INT)]; + } + + $recordLang = Filter::filterVar($data->lang, FILTER_SANITIZE_SPECIAL_CHARS); + $tags = Filter::filterVar($data->tags, FILTER_SANITIZE_SPECIAL_CHARS); + $active = Filter::filterVar($data->active, FILTER_SANITIZE_SPECIAL_CHARS); + $sticky = Filter::filterVar($data->sticky ?? false, FILTER_SANITIZE_SPECIAL_CHARS); + $content = Filter::filterVar($data->answer, FILTER_SANITIZE_SPECIAL_CHARS); + $keywords = Filter::filterVar($data->keywords, FILTER_SANITIZE_SPECIAL_CHARS); + $author = Filter::filterVar($data->author, FILTER_SANITIZE_SPECIAL_CHARS); + $email = Filter::filterVar($data->email, FILTER_VALIDATE_EMAIL, ''); + $comment = Filter::filterVar($data->comment ?? '', FILTER_SANITIZE_SPECIAL_CHARS); + $changed = Filter::filterVar($data->changed, FILTER_SANITIZE_SPECIAL_CHARS); + $notes = Filter::filterVar($data->notes, FILTER_SANITIZE_SPECIAL_CHARS); + + // Permissions + $permissions = $faqPermission->createPermissionArray(); + + $logging->log($user, 'admin-save-new-faq'); + + if (empty($question) && empty($answer)) { + return $this->json(['error' => Translation::get('msgNoQuestionAndAnswer')], Response::HTTP_CONFLICT); + } + + $faqData = new FaqEntity(); + $faqData + ->setLanguage($recordLang) + ->setActive($active === 'yes') + ->setSticky(!is_null($sticky)) + ->setQuestion( + Filter::removeAttributes(html_entity_decode((string) $question, ENT_QUOTES | ENT_HTML5, 'UTF-8')) + ) + ->setAnswer( + Filter::removeAttributes(html_entity_decode((string) $content, ENT_QUOTES | ENT_HTML5, 'UTF-8')) + ) + ->setKeywords($keywords) + ->setAuthor($author) + ->setEmail($email) + ->setComment(!is_null($comment)) + ->setCreatedDate(new DateTime()) + ->setNotes(Filter::removeAttributes($notes)); + + // Add new record and get that ID + $faqData = $faq->create($faqData); + + if ($faqData->getId()) { + // Create ChangeLog entry + $changelog->add($faqData->getId(), $user->getUserId(), nl2br((string) $changed), $faqData->getLanguage()); + + // Create the visit entry + $visits->logViews($faqData->getId()); + + $categoryRelation = new Relation($this->configuration, $category); + $categoryRelation->add($categories, $faqData->getId(), $faqData->getLanguage()); + + // Insert the tags + if ($tags !== '') { + $tagging->create($faqData->getId(), explode(',', trim((string) $tags))); + } + + // Add user permissions + $faqPermission->add(FaqPermission::USER, $faqData->getId(), $permissions['restricted_user']); + $categoryPermission->add(CategoryPermission::USER, $categories, $permissions['restricted_user']); + // Add group permission + if ($this->configuration->get('security.permLevel') !== 'basic') { + $faqPermission->add(FaqPermission::GROUP, $faqData->getId(), $permissions['restricted_groups']); + $categoryPermission->add( + CategoryPermission::GROUP, + $categories, + $permissions['restricted_groups'] + ); + } + + // Open question answered + $questionObject = new Question($this->configuration); + $openQuestionId = Filter::filterVar($data->openQuestionId, FILTER_VALIDATE_INT); + if (0 !== $openQuestionId) { + if ($this->configuration->get('records.enableDeleteQuestion')) { // deletes question + $questionObject->delete($openQuestionId); + } else { // adds this faq record id to the related open question + $questionObject->updateQuestionAnswer($openQuestionId, $faqData->getId(), $categories[0]); + } + + $url = sprintf( + '%s?action=faq&cat=%d&id=%d&artlang=%s', + $this->configuration->getDefaultUrl(), + $categories[0], + $faqData->getId(), + $recordLang + ); + $oLink = new Link($url, $this->configuration); + + // notify the user who added the question + try { + $notifyEmail = Filter::filterVar($data->notifyEmail, FILTER_SANITIZE_EMAIL); + $notifyUser = Filter::filterVar($data->notifyUser, FILTER_SANITIZE_SPECIAL_CHARS); + $notification->sendOpenQuestionAnswered($notifyEmail, $notifyUser, $oLink->toString()); + } catch (Exception | TransportExceptionInterface $e) { + return $this->json(['error' => $e->getMessage()], Response::HTTP_BAD_REQUEST); + } + } + + // Let the admin and the category owners to be informed by email of this new entry + try { + $categoryHelper = new CategoryHelper(); + $categoryHelper + ->setCategory($category) + ->setConfiguration($this->configuration); + $moderators = $categoryHelper->getModerators($categories); + $notification->sendNewFaqAdded($moderators, $faqData->getId(), $recordLang); + } catch (Exception | TransportExceptionInterface $e) { + return $this->json(['error' => $e->getMessage()], Response::HTTP_BAD_REQUEST); + } + + // If Elasticsearch is enabled, index new FAQ document + if ($this->configuration->get('search.enableElasticsearch')) { + $esInstance = new Elasticsearch($this->configuration); + $esInstance->index( + [ + 'id' => $faqData->getId(), + 'lang' => $faqData->getLanguage(), + 'solution_id' => $faqData->getSolutionId(), + 'question' => $faqData->getQuestion(), + 'answer' => $faqData->getAnswer(), + 'keywords' => $faqData->getKeywords(), + 'category_id' => $categories[0] + ] + ); + } + + return $this->json( + [ + 'success' => Translation::get('ad_entry_savedsuc'), + 'data' => $faqData->getJson(), + ], + Response::HTTP_OK + ); + } else { + return $this->json(['error' => Translation::get('ad_entry_savedfail')], Response::HTTP_BAD_REQUEST); + } + } + + /** + * @throws \phpMyFAQ\Core\Exception + */ + #[Route('admin/api/faq/update')] + public function update(Request $request): JsonResponse + { + $this->userHasPermission(PermissionType::FAQ_EDIT); + + $user = CurrentUser::getCurrentUser($this->configuration); + [ $currentUser, $currentGroups ] = CurrentUser::getCurrentUserGroupId($user); + + $faq = new Faq($this->configuration); + $faqPermission = new FaqPermission($this->configuration); + $tagging = new Tags($this->configuration); + $logging = new AdminLog($this->configuration); + $changelog = new Changelog($this->configuration); + $visits = new Visits($this->configuration); + + $category = new Category($this->configuration, [], false); + $category->setUser($currentUser); + $category->setGroups($currentGroups); + + $data = json_decode($request->getContent())->data; + + if (!Token::getInstance()->verifyToken('edit-faq', $data->{'pmf-csrf-token'})) { + return $this->json(['error' => Translation::get('err_NotAuth')], Response::HTTP_UNAUTHORIZED); + } + + // Collect FAQ data + $faqId = Filter::filterVar($data->faqId, FILTER_VALIDATE_INT); + $solutionId = Filter::filterVar($data->solutionId, FILTER_VALIDATE_INT); + $revisionId = Filter::filterVar($data->revisionId, FILTER_VALIDATE_INT); + $question = Filter::filterVar($data->question, FILTER_SANITIZE_SPECIAL_CHARS); + if (is_array($data->{'categories[]'})) { + $categories = Filter::filterArray($data->{'categories[]'}); + } else { + $categories = [Filter::filterVar($data->{'categories[]'}, FILTER_VALIDATE_INT)]; + } + $faqLang = Filter::filterVar($data->lang, FILTER_SANITIZE_SPECIAL_CHARS); + $tags = Filter::filterVar($data->tags, FILTER_SANITIZE_SPECIAL_CHARS); + $active = Filter::filterVar($data->active, FILTER_SANITIZE_SPECIAL_CHARS); + $sticky = Filter::filterVar($data->sticky ?? false, FILTER_SANITIZE_SPECIAL_CHARS); + $content = Filter::filterVar($data->answer, FILTER_SANITIZE_SPECIAL_CHARS); + $keywords = Filter::filterVar($data->keywords, FILTER_SANITIZE_SPECIAL_CHARS); + $author = Filter::filterVar($data->author, FILTER_SANITIZE_SPECIAL_CHARS); + $email = Filter::filterVar($data->email, FILTER_VALIDATE_EMAIL, ''); + $comment = Filter::filterVar($data->comment ?? '', FILTER_SANITIZE_SPECIAL_CHARS); + $changed = Filter::filterVar($data->changed, FILTER_SANITIZE_SPECIAL_CHARS); + $notes = Filter::filterVar($data->notes, FILTER_SANITIZE_SPECIAL_CHARS); + $revision = Filter::filterVar($data->revision ?? 'no', FILTER_SANITIZE_SPECIAL_CHARS); + + if (empty($question) && empty($answer)) { + return $this->json(['error' => Translation::get('msgNoQuestionAndAnswer')], Response::HTTP_CONFLICT); + } + + // Permissions + $permissions = $faqPermission->createPermissionArray(); + + $logging->log($user, 'admin-save-existing-faq ' . $faqId); + if ($active === 'yes') { + $logging->log($user, 'admin-publish-existing-faq ' . $faqId); + } + + if ('yes' === $revision || $this->configuration->get('records.enableAutoRevisions')) { + $faqRevision = new Revision($this->configuration); + $faqRevision->create($faqId, $faqLang); + ++$revisionId; + } + + $faqData = new FaqEntity(); + $faqData + ->setId($faqId) + ->setLanguage($faqLang) + ->setRevisionId($revisionId) + ->setSolutionId($solutionId) + ->setActive($active === 'yes') + ->setSticky(!is_null($sticky)) + ->setQuestion( + Filter::removeAttributes(html_entity_decode((string) $question, ENT_QUOTES | ENT_HTML5, 'UTF-8')) + ) + ->setAnswer( + Filter::removeAttributes(html_entity_decode((string) $content, ENT_QUOTES | ENT_HTML5, 'UTF-8')) + ) + ->setKeywords($keywords) + ->setAuthor($author) + ->setEmail($email) + ->setComment(!is_null($comment)) + ->setCreatedDate(new DateTime()) + ->setNotes(Filter::removeAttributes($notes)); + + // Create ChangeLog entry + $changelog->add($faqData->getId(), $user->getUserId(), (string) $changed, $faqData->getLanguage(), $revisionId); + + // Create the visit entry + $visits->logViews($faqData->getId()); + + // save or update the FAQ record + if ($faq->hasTranslation($faqData->getId(), $faqData->getLanguage())) { + $faqData = $faq->update($faqData); + } else { + $faqData = $faq->create($faqData); + } + + if (!isset($categories)) { + $categories = []; + } + + $categoryRelation = new Relation($this->configuration, $category); + $categoryRelation->deleteByFaq($faqData->getId(), $faqData->getLanguage()); + $categoryRelation->add($categories, $faqData->getId(), $faqData->getLanguage()); + + // Insert the tags + if ($tags !== '') { + $tagging->create($faqData->getId(), explode(',', trim((string) $tags))); + } else { + $tagging->deleteByRecordId($faqData->getId()); + } + + // Add user permissions + $faqPermission->delete(FaqPermission::USER, $faqData->getId()); + $faqPermission->add(FaqPermission::USER, $faqData->getId(), $permissions['restricted_user']); + // Add group permission + if ($this->configuration->get('security.permLevel') !== 'basic') { + $faqPermission->delete(FaqPermission::GROUP, $faqData->getId()); + $faqPermission->add(FaqPermission::GROUP, $faqData->getId(), $permissions['restricted_groups']); + } + + // If Elasticsearch is enabled, update an active or delete inactive FAQ document + if ($this->configuration->get('search.enableElasticsearch')) { + $esInstance = new Elasticsearch($this->configuration); + if ('yes' === $active) { + $esInstance->update( + [ + 'id' => $faqData->getId(), + 'lang' => $faqData->getLanguage(), + 'solution_id' => $faqData->getSolutionId(), + 'question' => $faqData->getQuestion(), + 'answer' => $faqData->getAnswer(), + 'keywords' => $faqData->getKeywords(), + 'category_id' => $categories[0] + ] + ); + } + } + + return $this->json( + [ + 'success' => Translation::get('ad_entry_savedsuc'), + 'data' => $faqData->getJson(), + ], + Response::HTTP_OK + ); + } + /** * @throws Exception */ @@ -52,12 +397,12 @@ public function listPermissions(Request $request): JsonResponse $faqId = Filter::filterVar($request->get('faqId'), FILTER_VALIDATE_INT); - $faqPermission = new Permission(Configuration::getConfigurationInstance()); + $faqPermission = new FaqPermission(Configuration::getConfigurationInstance()); return $this->json( [ - 'user' => $faqPermission->get(Permission::USER, $faqId), - 'group' => $faqPermission->get(Permission::GROUP, $faqId), + 'user' => $faqPermission->get(FaqPermission::USER, $faqId), + 'group' => $faqPermission->get(FaqPermission::GROUP, $faqId), ], Response::HTTP_OK ); @@ -212,7 +557,7 @@ public function search(Request $request): JsonResponse return $this->json(['error' => Translation::get('err_NotAuth')], Response::HTTP_UNAUTHORIZED); } - $faqPermission = new Permission($configuration); + $faqPermission = new FaqPermission($configuration); $faqSearch = new Search($configuration); $faqSearch->setCategory(new Category($configuration)); diff --git a/phpmyfaq/src/phpMyFAQ/Entity/FaqEntity.php b/phpmyfaq/src/phpMyFAQ/Entity/FaqEntity.php index 2fcd75c0cd..3f2492365a 100644 --- a/phpmyfaq/src/phpMyFAQ/Entity/FaqEntity.php +++ b/phpmyfaq/src/phpMyFAQ/Entity/FaqEntity.php @@ -261,4 +261,9 @@ public function setUpdatedDate(DateTime $updatedDate): FaqEntity $this->updatedDate = $updatedDate; return $this; } + + public function getJson(): string + { + return json_encode(get_object_vars($this)); + } } diff --git a/phpmyfaq/src/phpMyFAQ/Faq.php b/phpmyfaq/src/phpMyFAQ/Faq.php index 0d039ff74d..ea6b41c118 100755 --- a/phpmyfaq/src/phpMyFAQ/Faq.php +++ b/phpmyfaq/src/phpMyFAQ/Faq.php @@ -844,12 +844,15 @@ public function getRecordsByIds(array $faqIds): array /** * Creates a new FAQ. */ - public function create(FaqEntity $faqEntity): int + public function create(FaqEntity $faqEntity): FaqEntity { if (is_null($faqEntity->getId())) { $faqEntity->setId($this->configuration->getDb()->nextId(Database::getTablePrefix() . 'faqdata', 'id')); } + $faqEntity->setSolutionId($this->getNextSolutionId()); + $faqEntity->setRevisionId(0); + $query = sprintf( "INSERT INTO %sfaqdata (id, lang, solution_id, revision_id, active, sticky, keywords, thema, content, author, email, comment, @@ -859,8 +862,8 @@ public function create(FaqEntity $faqEntity): int Database::getTablePrefix(), $faqEntity->getId(), $this->configuration->getDb()->escape($faqEntity->getLanguage()), - $this->getNextSolutionId(), - 0, + $faqEntity->getSolutionId(), + $faqEntity->getRevisionId(), $faqEntity->isActive() ? 'yes' : 'no', $faqEntity->isSticky() ? 1 : 0, $this->configuration->getDb()->escape($faqEntity->getKeywords()), @@ -878,7 +881,7 @@ public function create(FaqEntity $faqEntity): int $this->configuration->getDb()->query($query); - return $faqEntity->getId(); + return $faqEntity; } /** @@ -903,7 +906,7 @@ public function getNextSolutionId(): int return $latestId + PMF_SOLUTION_ID_INCREMENT_VALUE; } - public function update(FaqEntity $faqEntity): bool + public function update(FaqEntity $faqEntity): FaqEntity { $query = sprintf( "UPDATE @@ -944,7 +947,9 @@ public function update(FaqEntity $faqEntity): bool $this->configuration->getDb()->escape($faqEntity->getLanguage()) ); - return (bool) $this->configuration->getDb()->query($query); + $this->configuration->getDb()->query($query); + + return $faqEntity; } /** diff --git a/phpmyfaq/src/phpMyFAQ/Faq/Permission.php b/phpmyfaq/src/phpMyFAQ/Faq/Permission.php index 9691e72f2f..2741f84790 100644 --- a/phpmyfaq/src/phpMyFAQ/Faq/Permission.php +++ b/phpmyfaq/src/phpMyFAQ/Faq/Permission.php @@ -19,6 +19,7 @@ use phpMyFAQ\Configuration; use phpMyFAQ\Database; use phpMyFAQ\Filter; +use Symfony\Component\HttpFoundation\Request; /** * Class FaqPermission @@ -132,31 +133,27 @@ public function createPermissionArray(): array { $permissions = []; - if ('all' === Filter::filterInput(INPUT_POST, 'userpermission', FILTER_SANITIZE_SPECIAL_CHARS)) { + $data = json_decode(Request::createFromGlobals()->getContent())->data; + + if ('all' === Filter::filterVar($data->userpermission, FILTER_SANITIZE_SPECIAL_CHARS)) { $permissions += [ 'restricted_user' => [-1], ]; } else { $permissions += [ 'restricted_user' => [ - Filter::filterInput(INPUT_POST, 'restricted_users', FILTER_VALIDATE_INT), + Filter::filterVar($data->restricted_users, FILTER_VALIDATE_INT), ], ]; } - if ('all' === Filter::filterInput(INPUT_POST, 'grouppermission', FILTER_SANITIZE_SPECIAL_CHARS)) { + if ('all' === Filter::filterVar($data->grouppermission, FILTER_SANITIZE_SPECIAL_CHARS)) { $permissions += [ 'restricted_groups' => [-1], ]; } else { - $permissions += Filter::filterInputArray( - INPUT_POST, - [ - 'restricted_groups' => [ - 'filter' => FILTER_VALIDATE_INT, - 'flags' => FILTER_REQUIRE_ARRAY, - ], - ] + $permissions += Filter::filterArray( + $data->restricted_groups ); } diff --git a/phpmyfaq/src/phpMyFAQ/User/CurrentUser.php b/phpmyfaq/src/phpMyFAQ/User/CurrentUser.php index 82bb1e546d..9ae0e6ea85 100644 --- a/phpmyfaq/src/phpMyFAQ/User/CurrentUser.php +++ b/phpmyfaq/src/phpMyFAQ/User/CurrentUser.php @@ -448,7 +448,7 @@ public static function getCurrentUser(Configuration $configuration): CurrentUser * Returns the current user ID and group IDs as an array, default values are -1 * * @param CurrentUser|null $user - * @return array + * @return array{0: int, 1: int[]} */ public static function getCurrentUserGroupId(CurrentUser $user = null): array { diff --git a/phpmyfaq/translations/language_de.php b/phpmyfaq/translations/language_de.php index 6d0fb940fc..1e6e16ab0f 100755 --- a/phpmyfaq/translations/language_de.php +++ b/phpmyfaq/translations/language_de.php @@ -1420,4 +1420,7 @@ // added v4.0.0-alpha.2 - 2024-04-21 by Jan $PMF_LANG['msgDeleteNews'] = 'News löschen'; +// added v4.0.0-alpha.2 - 2024-04-30 by Thorsten +$PMF_LANG['msgNoQuestionAndAnswer'] = 'Keine Frage und Antwort gefunden.'; + return $PMF_LANG; diff --git a/phpmyfaq/translations/language_en.php b/phpmyfaq/translations/language_en.php index 84eff2fb5e..e9ef8f0b91 100644 --- a/phpmyfaq/translations/language_en.php +++ b/phpmyfaq/translations/language_en.php @@ -1440,4 +1440,7 @@ // added v4.0.0-alpha.2 - 2024-04-21 by Jan $PMF_LANG['msgDeleteNews'] = 'Delete news'; +// added v4.0.0-alpha.2 - 2024-04-30 by Thorsten +$PMF_LANG['msgNoQuestionAndAnswer'] = 'No question and answer found.'; + return $PMF_LANG; diff --git a/tests/phpMyFAQ/FaqTest.php b/tests/phpMyFAQ/FaqTest.php index 805a9e09e4..109fbfdefd 100644 --- a/tests/phpMyFAQ/FaqTest.php +++ b/tests/phpMyFAQ/FaqTest.php @@ -77,7 +77,7 @@ public function testCreate(): void $result = $this->faq->create($faqEntity); // Assert that the method returns an integer - $this->assertIsInt($result); + $this->assertIsInt($result->getId()); $this->assertGreaterThan(0, $result); } @@ -94,7 +94,7 @@ public function testGetNextSolutionId(): void public function testUpdate(): void { $faqEntity = $this->getFaqEntity(); - $faqEntity->setId($this->faq->create($faqEntity)); + $faqEntity->setId($this->faq->create($faqEntity)->getId()); $faqEntity->setRevisionId(0); $faqEntity->setQuestion('Updated question'); @@ -102,7 +102,7 @@ public function testUpdate(): void $result = $this->faq->update($faqEntity); - $this->assertTrue($result); + $this->assertInstanceOf(FaqEntity::class, $result); } /** @@ -112,7 +112,7 @@ public function testUpdate(): void public function testDeleteRecord(): void { $faqEntity = $this->getFaqEntity(); - $faqEntity->setId($this->faq->create($faqEntity)); + $faqEntity->setId($this->faq->create($faqEntity)->getId()); $result = $this->faq->deleteRecord($faqEntity->getId(), $faqEntity->getLanguage()); @@ -122,7 +122,7 @@ public function testDeleteRecord(): void public function testGetSolutionIdFromId(): void { $faqEntity = $this->getFaqEntity(); - $faqEntity->setId($this->faq->create($faqEntity)); + $faqEntity->setId($this->faq->create($faqEntity)->getId()); $this->assertIsInt($this->faq->getSolutionIdFromId($faqEntity->getId(), $faqEntity->getLanguage())); $this->assertGreaterThan(0, $this->faq->getSolutionIdFromId($faqEntity->getId(), $faqEntity->getLanguage())); @@ -131,7 +131,7 @@ public function testGetSolutionIdFromId(): void public function testHasTranslation(): void { $faqEntity = $this->getFaqEntity(); - $faqEntity->setId($this->faq->create($faqEntity)); + $faqEntity->setId($this->faq->create($faqEntity)->getId()); $this->assertTrue($this->faq->hasTranslation($faqEntity->getId(), $faqEntity->getLanguage())); $this->assertFalse($this->faq->hasTranslation($faqEntity->getId(), 'de')); @@ -140,7 +140,7 @@ public function testHasTranslation(): void public function testIsActive(): void { $faqEntity = $this->getFaqEntity(); - $faqEntity->setId($this->faq->create($faqEntity)); + $faqEntity->setId($this->faq->create($faqEntity)->getId()); $this->assertTrue($this->faq->isActive($faqEntity->getId(), $faqEntity->getLanguage())); }