387 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			387 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
<?php
 | 
						|
namespace WapplerSystems\Meilisearch\Controller\Backend\Search;
 | 
						|
 | 
						|
/***************************************************************
 | 
						|
 *  Copyright notice
 | 
						|
 *
 | 
						|
 *  (c) 2010-2017 dkd Internet Service GmbH <meilisearchs-support@dkd.de>
 | 
						|
 *  All rights reserved
 | 
						|
 *
 | 
						|
 *  This script is part of the TYPO3 project. The TYPO3 project 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.
 | 
						|
 *
 | 
						|
 *  The GNU General Public License can be found at
 | 
						|
 *  http://www.gnu.org/copyleft/gpl.html.
 | 
						|
 *
 | 
						|
 *  This script 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.
 | 
						|
 *
 | 
						|
 *  This copyright notice MUST APPEAR in all copies of the script!
 | 
						|
 ***************************************************************/
 | 
						|
 | 
						|
use WapplerSystems\Meilisearch\Utility\ManagedResourcesUtility;
 | 
						|
use TYPO3\CMS\Backend\Template\ModuleTemplate;
 | 
						|
use TYPO3\CMS\Core\Messaging\FlashMessage;
 | 
						|
use TYPO3\CMS\Core\Utility\GeneralUtility;
 | 
						|
use TYPO3\CMS\Extbase\Mvc\View\ViewInterface;
 | 
						|
 | 
						|
/**
 | 
						|
 * Manage Synonyms and Stop words in Backend Module
 | 
						|
 * @property \TYPO3\CMS\Extbase\Mvc\Web\Response $response
 | 
						|
 */
 | 
						|
class CoreOptimizationModuleController extends AbstractModuleController
 | 
						|
{
 | 
						|
    /**
 | 
						|
     * Set up the doc header properly here
 | 
						|
     *
 | 
						|
     * @param ViewInterface $view
 | 
						|
     * @return void
 | 
						|
     */
 | 
						|
    protected function initializeView(ViewInterface $view)
 | 
						|
    {
 | 
						|
        parent::initializeView($view);
 | 
						|
 | 
						|
        $this->generateCoreSelectorMenuUsingPageTree();
 | 
						|
        /* @var ModuleTemplate $module */ // holds the state of chosen tab
 | 
						|
        $module = $this->objectManager->get(ModuleTemplate::class);
 | 
						|
        $coreOptimizationTabs = $module->getDynamicTabMenu([], 'coreOptimization');
 | 
						|
        $this->view->assign('tabs', $coreOptimizationTabs);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Gets synonyms and stopwords for the currently selected core
 | 
						|
     *
 | 
						|
     * @return void
 | 
						|
     */
 | 
						|
    public function indexAction()
 | 
						|
    {
 | 
						|
        if ($this->selectedMeilisearchCoreConnection === null) {
 | 
						|
            $this->view->assign('can_not_proceed', true);
 | 
						|
            return;
 | 
						|
        }
 | 
						|
 | 
						|
        $synonyms = [];
 | 
						|
        $coreAdmin = $this->selectedMeilisearchCoreConnection->getAdminService();
 | 
						|
        $rawSynonyms = $coreAdmin->getSynonyms();
 | 
						|
        foreach ($rawSynonyms as $baseWord => $synonymList) {
 | 
						|
            $synonyms[$baseWord] = implode(', ', $synonymList);
 | 
						|
        }
 | 
						|
 | 
						|
        $stopWords = $coreAdmin->getStopWords();
 | 
						|
        $this->view->assignMultiple([
 | 
						|
            'synonyms' => $synonyms,
 | 
						|
            'stopWords' => implode(PHP_EOL, $stopWords),
 | 
						|
            'stopWordsCount' => count($stopWords)
 | 
						|
        ]);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Add synonyms to selected core
 | 
						|
     *
 | 
						|
     * @param string $baseWord
 | 
						|
     * @param string $synonyms
 | 
						|
     * @param bool $overrideExisting
 | 
						|
     * @return void
 | 
						|
     */
 | 
						|
    public function addSynonymsAction(string $baseWord, string $synonyms, $overrideExisting)
 | 
						|
    {
 | 
						|
        if (empty($baseWord) || empty($synonyms)) {
 | 
						|
            $this->addFlashMessage(
 | 
						|
                'Please provide a base word and synonyms.',
 | 
						|
                'Missing parameter',
 | 
						|
                FlashMessage::ERROR
 | 
						|
            );
 | 
						|
        } else {
 | 
						|
            $baseWord = mb_strtolower($baseWord);
 | 
						|
            $synonyms = mb_strtolower($synonyms);
 | 
						|
 | 
						|
            $coreAdmin = $this->selectedMeilisearchCoreConnection->getAdminService();
 | 
						|
            if ($overrideExisting && $coreAdmin->getSynonyms($baseWord)) {
 | 
						|
                $coreAdmin->deleteSynonym($baseWord);
 | 
						|
            }
 | 
						|
            $coreAdmin->addSynonym($baseWord, GeneralUtility::trimExplode(',', $synonyms, true));
 | 
						|
            $coreAdmin->reloadCore();
 | 
						|
 | 
						|
            $this->addFlashMessage(
 | 
						|
                '"' . $synonyms . '" added as synonyms for base word "' . $baseWord . '"'
 | 
						|
            );
 | 
						|
        }
 | 
						|
 | 
						|
        $this->redirect('index');
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param string $fileFormat
 | 
						|
     * @return void
 | 
						|
     */
 | 
						|
    public function exportStopWordsAction($fileFormat = 'txt')
 | 
						|
    {
 | 
						|
        $coreAdmin = $this->selectedMeilisearchCoreConnection->getAdminService();
 | 
						|
        $this->exportFile(
 | 
						|
            implode(PHP_EOL, $coreAdmin->getStopWords()),
 | 
						|
            'stopwords',
 | 
						|
            $fileFormat
 | 
						|
        );
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Exports synonyms to a download file.
 | 
						|
     *
 | 
						|
     * @param string $fileFormat
 | 
						|
     * @return string
 | 
						|
     */
 | 
						|
    public function exportSynonymsAction($fileFormat = 'txt')
 | 
						|
    {
 | 
						|
        $coreAdmin = $this->selectedMeilisearchCoreConnection->getAdminService();
 | 
						|
        $synonyms = $coreAdmin->getSynonyms();
 | 
						|
        return $this->exportFile(ManagedResourcesUtility::exportSynonymsToTxt($synonyms), 'synonyms', $fileFormat);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param array $synonymFileUpload
 | 
						|
     * @param bool $overrideExisting
 | 
						|
     * @param bool $deleteSynonymsBefore
 | 
						|
     * @return void
 | 
						|
     */
 | 
						|
    public function importSynonymListAction(array $synonymFileUpload, $overrideExisting, $deleteSynonymsBefore)
 | 
						|
    {
 | 
						|
        if ($deleteSynonymsBefore) {
 | 
						|
            $this->deleteAllSynonyms();
 | 
						|
        }
 | 
						|
 | 
						|
        $fileLines = ManagedResourcesUtility::importSynonymsFromPlainTextContents($synonymFileUpload);
 | 
						|
        $synonymCount = 0;
 | 
						|
 | 
						|
        $coreAdmin = $this->selectedMeilisearchCoreConnection->getAdminService();
 | 
						|
        foreach ($fileLines as $baseWord => $synonyms) {
 | 
						|
            if (!isset($baseWord) || empty($synonyms)) {
 | 
						|
                continue;
 | 
						|
            }
 | 
						|
            $this->deleteExistingSynonym($overrideExisting, $deleteSynonymsBefore, $baseWord);
 | 
						|
            $coreAdmin->addSynonym($baseWord, $synonyms);
 | 
						|
            $synonymCount++;
 | 
						|
        }
 | 
						|
 | 
						|
        $coreAdmin->reloadCore();
 | 
						|
        $this->addFlashMessage(
 | 
						|
            $synonymCount . ' synonyms imported.'
 | 
						|
        );
 | 
						|
        $this->redirect('index');
 | 
						|
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param array $stopwordsFileUpload
 | 
						|
     * @param bool $replaceStopwords
 | 
						|
     * @return void
 | 
						|
     */
 | 
						|
    public function importStopWordListAction(array $stopwordsFileUpload, $replaceStopwords)
 | 
						|
    {
 | 
						|
        $this->saveStopWordsAction(
 | 
						|
            ManagedResourcesUtility::importStopwordsFromPlainTextContents($stopwordsFileUpload),
 | 
						|
            $replaceStopwords
 | 
						|
        );
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Delete complete synonym list
 | 
						|
     *
 | 
						|
     * @return void
 | 
						|
     */
 | 
						|
    public function deleteAllSynonymsAction()
 | 
						|
    {
 | 
						|
        $allSynonymsCouldBeDeleted = $this->deleteAllSynonyms();
 | 
						|
 | 
						|
        $coreAdmin = $this->selectedMeilisearchCoreConnection->getAdminService();
 | 
						|
        $reloadResponse = $coreAdmin->reloadCore();
 | 
						|
 | 
						|
        if ($allSynonymsCouldBeDeleted
 | 
						|
            && $reloadResponse->getHttpStatus() == 200
 | 
						|
        ) {
 | 
						|
            $this->addFlashMessage(
 | 
						|
                'All synonym removed.'
 | 
						|
            );
 | 
						|
        } else {
 | 
						|
            $this->addFlashMessage(
 | 
						|
                'Failed to remove all synonyms.',
 | 
						|
                'An error occurred',
 | 
						|
                FlashMessage::ERROR
 | 
						|
            );
 | 
						|
        }
 | 
						|
        $this->redirect('index');
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Deletes a synonym mapping by its base word.
 | 
						|
     *
 | 
						|
     * @param string $baseWord Synonym mapping base word
 | 
						|
     */
 | 
						|
    public function deleteSynonymsAction($baseWord)
 | 
						|
    {
 | 
						|
        $coreAdmin = $this->selectedMeilisearchCoreConnection->getAdminService();
 | 
						|
        $deleteResponse = $coreAdmin->deleteSynonym($baseWord);
 | 
						|
        $reloadResponse = $coreAdmin->reloadCore();
 | 
						|
 | 
						|
        if ($deleteResponse->getHttpStatus() == 200
 | 
						|
            && $reloadResponse->getHttpStatus() == 200
 | 
						|
        ) {
 | 
						|
            $this->addFlashMessage(
 | 
						|
                'Synonym removed.'
 | 
						|
            );
 | 
						|
        } else {
 | 
						|
            $this->addFlashMessage(
 | 
						|
                'Failed to remove synonym.',
 | 
						|
                'An error occurred',
 | 
						|
                FlashMessage::ERROR
 | 
						|
            );
 | 
						|
        }
 | 
						|
 | 
						|
        $this->redirect('index');
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Saves the edited stop word list to Meilisearch
 | 
						|
     *
 | 
						|
     * @param string $stopWords
 | 
						|
     * @param bool $replaceStopwords
 | 
						|
     * @return void
 | 
						|
     */
 | 
						|
    public function saveStopWordsAction(string $stopWords, $replaceStopwords = true)
 | 
						|
    {
 | 
						|
        // lowercase stopword before saving because terms get lowercased before stopword filtering
 | 
						|
        $newStopWords = mb_strtolower($stopWords);
 | 
						|
        $newStopWords = GeneralUtility::trimExplode("\n", $newStopWords, true);
 | 
						|
 | 
						|
        $coreAdmin = $this->selectedMeilisearchCoreConnection->getAdminService();
 | 
						|
        $oldStopWords = $coreAdmin->getStopWords();
 | 
						|
 | 
						|
        if ($replaceStopwords) {
 | 
						|
            $removedStopWords = array_diff($oldStopWords, $newStopWords);
 | 
						|
            $wordsRemoved = $this->removeStopsWordsFromIndex($removedStopWords);
 | 
						|
        } else {
 | 
						|
            $wordsRemoved = true;
 | 
						|
        }
 | 
						|
 | 
						|
        $wordsAdded = true;
 | 
						|
        $addedStopWords = array_diff($newStopWords, $oldStopWords);
 | 
						|
        if (!empty($addedStopWords)) {
 | 
						|
            $wordsAddedResponse = $coreAdmin->addStopWords($addedStopWords);
 | 
						|
            $wordsAdded = ($wordsAddedResponse->getHttpStatus() == 200);
 | 
						|
        }
 | 
						|
 | 
						|
        $reloadResponse = $coreAdmin->reloadCore();
 | 
						|
        if ($wordsRemoved && $wordsAdded && $reloadResponse->getHttpStatus() == 200) {
 | 
						|
            $this->addFlashMessage(
 | 
						|
                'Stop Words Updated.'
 | 
						|
            );
 | 
						|
        }
 | 
						|
 | 
						|
        $this->redirect('index');
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param string $content
 | 
						|
     * @param string $type
 | 
						|
     * @param string $fileExtension
 | 
						|
     * @return string
 | 
						|
     */
 | 
						|
    protected function exportFile($content, $type = 'synonyms', $fileExtension = 'txt') : string
 | 
						|
    {
 | 
						|
        $coreAdmin = $this->selectedMeilisearchCoreConnection->getAdminService();
 | 
						|
 | 
						|
        $this->response->setHeader('Content-type', 'text/plain', true);
 | 
						|
        $this->response->setHeader('Cache-control', 'public', true);
 | 
						|
        $this->response->setHeader('Content-Description', 'File transfer', true);
 | 
						|
        $this->response->setHeader(
 | 
						|
            'Content-disposition',
 | 
						|
            'attachment; filename =' . $type . '_' .
 | 
						|
            $coreAdmin->getPrimaryEndpoint()->getCore() . '.' . $fileExtension,
 | 
						|
            true
 | 
						|
        );
 | 
						|
 | 
						|
        $this->response->setContent($content);
 | 
						|
        $this->sendFileResponse();
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * This method send the headers and content and does an exit, since without the exit TYPO3 produces and error.
 | 
						|
     * @return void
 | 
						|
     */
 | 
						|
    protected function sendFileResponse()
 | 
						|
    {
 | 
						|
        $this->response->sendHeaders();
 | 
						|
        $this->response->send();
 | 
						|
        $this->response->shutdown();
 | 
						|
 | 
						|
        exit();
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Delete complete synonym list form meilisearch
 | 
						|
     *
 | 
						|
     * @return bool
 | 
						|
     */
 | 
						|
    protected function deleteAllSynonyms() : bool
 | 
						|
    {
 | 
						|
        $coreAdmin = $this->selectedMeilisearchCoreConnection->getAdminService();
 | 
						|
        $synonyms = $coreAdmin->getSynonyms();
 | 
						|
        $allSynonymsCouldBeDeleted = true;
 | 
						|
 | 
						|
        foreach ($synonyms as $baseWord => $synonym) {
 | 
						|
            $deleteResponse = $coreAdmin->deleteSynonym($baseWord);
 | 
						|
            $allSynonymsCouldBeDeleted = $allSynonymsCouldBeDeleted && $deleteResponse->getHttpStatus() == 200;
 | 
						|
        }
 | 
						|
 | 
						|
        return $allSynonymsCouldBeDeleted;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @param $stopwordsToRemove
 | 
						|
     * @return bool
 | 
						|
     */
 | 
						|
    protected function removeStopsWordsFromIndex($stopwordsToRemove) : bool
 | 
						|
    {
 | 
						|
        $wordsRemoved = true;
 | 
						|
        $coreAdmin = $this->selectedMeilisearchCoreConnection->getAdminService();
 | 
						|
 | 
						|
        foreach ($stopwordsToRemove as $word) {
 | 
						|
            $response = $coreAdmin->deleteStopWord($word);
 | 
						|
            if ($response->getHttpStatus() != 200) {
 | 
						|
                $wordsRemoved = false;
 | 
						|
                $this->addFlashMessage(
 | 
						|
                    'Failed to remove stop word "' . $word . '".',
 | 
						|
                    'An error occurred',
 | 
						|
                    FlashMessage::ERROR
 | 
						|
                );
 | 
						|
                break;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        return $wordsRemoved;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Delete synonym entry if selceted before
 | 
						|
     * @param bool $overrideExisting
 | 
						|
     * @param bool $deleteSynonymsBefore
 | 
						|
     * @param string $baseWord
 | 
						|
     */
 | 
						|
    protected function deleteExistingSynonym($overrideExisting, $deleteSynonymsBefore, $baseWord)
 | 
						|
    {
 | 
						|
        $coreAdmin = $this->selectedMeilisearchCoreConnection->getAdminService();
 | 
						|
 | 
						|
        if (!$deleteSynonymsBefore &&
 | 
						|
            $overrideExisting &&
 | 
						|
            $coreAdmin->getSynonyms($baseWord)
 | 
						|
        ) {
 | 
						|
            $coreAdmin->deleteSynonym($baseWord);
 | 
						|
        }
 | 
						|
 | 
						|
    }
 | 
						|
}
 |