From c3a39628cebf3089b4afc335e303eb318308a429 Mon Sep 17 00:00:00 2001 From: Marcel Werk Date: Mon, 13 Apr 2020 13:34:34 +0200 Subject: [PATCH] Avoid potential race condition when saving search keywords --- .../keyword/SearchKeywordAction.class.php | 17 +++++++++++ .../files/lib/form/SearchForm.class.php | 5 +++- .../search/SearchKeywordManager.class.php | 29 +++---------------- 3 files changed, 25 insertions(+), 26 deletions(-) diff --git a/wcfsetup/install/files/lib/data/search/keyword/SearchKeywordAction.class.php b/wcfsetup/install/files/lib/data/search/keyword/SearchKeywordAction.class.php index 6c0d883493..dfb4d332d3 100644 --- a/wcfsetup/install/files/lib/data/search/keyword/SearchKeywordAction.class.php +++ b/wcfsetup/install/files/lib/data/search/keyword/SearchKeywordAction.class.php @@ -56,4 +56,21 @@ class SearchKeywordAction extends AbstractDatabaseObjectAction implements ISearc return $list; } + + /** + * Inserts a new keyword if it does not already exist, or updates it if it does. + */ + public function upsert() { + $sql = "INSERT INTO wcf".WCF_N."_search_keyword + (keyword, searches, lastSearchTime) + VALUES (?, ?, ?) + ON DUPLICATE KEY UPDATE searches = searches + VALUES(searches), + lastSearchTime = VALUES(lastSearchTime)"; + $statement = WCF::getDB()->prepareStatement($sql); + $statement->execute([ + mb_substr($this->parameters['data']['keyword'], 0, 191), + ($this->parameters['data']['searches'] ?? 1), + ($this->parameters['data']['lastSearchTime'] ?? TIME_NOW), + ]); + } } diff --git a/wcfsetup/install/files/lib/form/SearchForm.class.php b/wcfsetup/install/files/lib/form/SearchForm.class.php index 62b6c12853..a9f84e9b65 100644 --- a/wcfsetup/install/files/lib/form/SearchForm.class.php +++ b/wcfsetup/install/files/lib/form/SearchForm.class.php @@ -1,5 +1,6 @@ query)) { - SearchKeywordManager::getInstance()->add($this->query); + (new SearchKeywordAction([], 'upsert', ['data' => [ + 'keyword' => $this->query, + ]]))->executeAction(); } $this->saved(); diff --git a/wcfsetup/install/files/lib/system/search/SearchKeywordManager.class.php b/wcfsetup/install/files/lib/system/search/SearchKeywordManager.class.php index 0a795953bd..380e772aac 100644 --- a/wcfsetup/install/files/lib/system/search/SearchKeywordManager.class.php +++ b/wcfsetup/install/files/lib/system/search/SearchKeywordManager.class.php @@ -1,9 +1,7 @@ * @package WoltLabSuite\Core\System\Search + * @deprecated 5.2 */ class SearchKeywordManager extends SingletonFactory { /** @@ -20,28 +19,8 @@ class SearchKeywordManager extends SingletonFactory { * @param string $keyword */ public function add($keyword) { - $keyword = mb_substr($keyword, 0, 191); - - // search existing entry - $sql = "SELECT * - FROM wcf".WCF_N."_search_keyword - WHERE keyword = ?"; - $statement = WCF::getDB()->prepareStatement($sql); - $statement->execute([$keyword]); - if (($object = $statement->fetchObject(SearchKeyword::class)) !== null) { - $action = new SearchKeywordAction([$object], 'update', ['data' => [ - 'searches' => $object->searches + 1, - 'lastSearchTime' => TIME_NOW - ]]); - $action->executeAction(); - } - else { - $action = new SearchKeywordAction([], 'create', ['data' => [ - 'keyword' => $keyword, - 'searches' => 1, - 'lastSearchTime' => TIME_NOW - ]]); - $action->executeAction(); - } + (new SearchKeywordAction([], 'upsert', ['data' => [ + 'keyword' => $keyword, + ]]))->executeAction(); } } -- 2.20.1