From 60957f53616e5275ce2ca521c08dfb1dead1ee1b Mon Sep 17 00:00:00 2001 From: Yuriy Bakhtin Date: Wed, 28 Aug 2024 17:47:22 +0300 Subject: [PATCH] Fix search reindexing after content deletion (#7187) * Fix search reindexing after content deletion * Refactor `ContentSearchService` * Update ZendLucenceDriver.php --------- Co-authored-by: Lucas Bartholemy --- CHANGELOG.md | 1 + protected/humhub/modules/content/Events.php | 11 +++++------ .../modules/content/commands/SearchController.php | 14 +++----------- protected/humhub/modules/content/config.php | 4 ++-- .../modules/content/jobs/SearchDeleteDocument.php | 6 +----- .../content/search/driver/AbstractDriver.php | 2 +- .../modules/content/search/driver/MysqlDriver.php | 7 +++---- .../content/search/driver/ZendLucenceDriver.php | 11 +++++------ .../content/services/ContentSearchService.php | 15 ++++++++++----- 9 files changed, 31 insertions(+), 40 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1397cebb8d..58c7457565 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ HumHub Changelog - Fix #7180: Fix active form on user edit form for correct working of widget inputs - Fix #7181: Fix duplicated label of checkbox profile field - Fix #7182: Fix initialization of several select2 inputs on the same page +- Fix #7187: Fix search reindexing after content deletion - Fix #7152: Fix search starting with special characters 1.16.1 (July 1, 2024) diff --git a/protected/humhub/modules/content/Events.php b/protected/humhub/modules/content/Events.php index 839800f5dd..1131c73713 100644 --- a/protected/humhub/modules/content/Events.php +++ b/protected/humhub/modules/content/Events.php @@ -11,7 +11,6 @@ namespace humhub\modules\content; use humhub\commands\CronController; use humhub\commands\IntegrityController; use humhub\components\Event; -use humhub\modules\content\components\ContentActiveRecord; use humhub\modules\content\models\Content; use humhub\modules\content\services\ContentSearchService; use humhub\modules\user\events\UserEvent; @@ -108,16 +107,16 @@ class Events extends BaseObject } /** - * After a components\ContentActiveRecord was deleted + * After a Content was deleted * * @param \yii\base\Event $event */ - public static function onContentActiveRecordDelete($event) + public static function onContentAfterDelete($event) { - /** @var ContentActiveRecord $record */ - $record = $event->sender; + /* @var Content $content */ + $content = $event->sender; - (new ContentSearchService($record->content))->delete(); + (new ContentSearchService($content))->delete(); } /** diff --git a/protected/humhub/modules/content/commands/SearchController.php b/protected/humhub/modules/content/commands/SearchController.php index 39167060aa..18c1e070e1 100644 --- a/protected/humhub/modules/content/commands/SearchController.php +++ b/protected/humhub/modules/content/commands/SearchController.php @@ -27,7 +27,7 @@ class SearchController extends Controller public function actionOptimize() { print "Optimizing search index: "; - $driver = $this->getSearchDriver(); + $driver = ContentSearchService::getDriver(); $driver->optimize(); print "OK!\n\n"; } @@ -37,7 +37,7 @@ class SearchController extends Controller */ public function actionRebuild() { - $driver = $this->getSearchDriver(); + $driver = ContentSearchService::getDriver(); $driver->purge(); foreach (Content::find()->each() as $content) { (new ContentSearchService($content))->update(false); @@ -67,7 +67,7 @@ class SearchController extends Controller */ public function actionFind($keyword) { - $driver = $this->getSearchDriver(); + $driver = ContentSearchService::getDriver(); $user = User::findOne(['id' => 1]); @@ -82,12 +82,4 @@ class SearchController extends Controller print "\t - " . $content->object_model . ' ' . $content->object_id . "\n"; } } - - private function getSearchDriver(): AbstractDriver - { - /** @var Module $module */ - $module = Yii::$app->getModule('content'); - - return $module->getSearchDriver(); - } } diff --git a/protected/humhub/modules/content/config.php b/protected/humhub/modules/content/config.php index d8afbfba4e..ef88656834 100644 --- a/protected/humhub/modules/content/config.php +++ b/protected/humhub/modules/content/config.php @@ -3,11 +3,11 @@ use humhub\commands\CronController; use humhub\modules\content\Events; use humhub\commands\IntegrityController; +use humhub\modules\content\models\Content; use humhub\modules\content\Module; use humhub\modules\content\widgets\WallEntryAddons; use humhub\modules\user\models\User; use humhub\modules\space\models\Space; -use humhub\modules\content\components\ContentActiveRecord; return [ 'id' => 'content', @@ -19,7 +19,7 @@ return [ ['class' => User::class, 'event' => User::EVENT_BEFORE_DELETE, 'callback' => [Events::class, 'onUserDelete']], ['class' => User::class, 'event' => User::EVENT_BEFORE_SOFT_DELETE, 'callback' => [Events::class, 'onUserSoftDelete']], ['class' => Space::class, 'event' => User::EVENT_BEFORE_DELETE, 'callback' => [Events::class, 'onSpaceDelete']], - ['class' => ContentActiveRecord::class, 'event' => ContentActiveRecord::EVENT_AFTER_DELETE, 'callback' => [Events::class, 'onContentActiveRecordDelete']], + ['class' => Content::class, 'event' => Content::EVENT_AFTER_DELETE, 'callback' => [Events::class, 'onContentAfterDelete']], ['class' => CronController::class, 'event' => CronController::EVENT_ON_DAILY_RUN, 'callback' => [Events::class, 'onCronDailyRun']], ['class' => CronController::class, 'event' => CronController::EVENT_BEFORE_ACTION, 'callback' => [Events::class, 'onCronBeforeAction']], ], diff --git a/protected/humhub/modules/content/jobs/SearchDeleteDocument.php b/protected/humhub/modules/content/jobs/SearchDeleteDocument.php index 23e8e72ed8..7d91bc6568 100644 --- a/protected/humhub/modules/content/jobs/SearchDeleteDocument.php +++ b/protected/humhub/modules/content/jobs/SearchDeleteDocument.php @@ -7,7 +7,6 @@ namespace humhub\modules\content\jobs; -use humhub\modules\content\models\Content; use humhub\modules\content\services\ContentSearchService; use humhub\modules\content\services\SearchJobService; use humhub\modules\queue\interfaces\ExclusiveJobInterface; @@ -31,10 +30,7 @@ class SearchDeleteDocument extends LongRunningActiveJob implements ExclusiveJobI public function run() { return $this->getService()->run(function () { - $content = Content::findOne(['id' => $this->contentId]); - if ($content) { - (new ContentSearchService($content))->delete(false); - } + ContentSearchService::deleteContentById($this->contentId, false); }); } diff --git a/protected/humhub/modules/content/search/driver/AbstractDriver.php b/protected/humhub/modules/content/search/driver/AbstractDriver.php index 3fe6002a84..ad92a20082 100644 --- a/protected/humhub/modules/content/search/driver/AbstractDriver.php +++ b/protected/humhub/modules/content/search/driver/AbstractDriver.php @@ -15,7 +15,7 @@ abstract class AbstractDriver extends Component abstract public function update(Content $content): void; - abstract public function delete(Content $content): void; + abstract public function delete(int $contentId): void; /** * Run search process diff --git a/protected/humhub/modules/content/search/driver/MysqlDriver.php b/protected/humhub/modules/content/search/driver/MysqlDriver.php index f399fe797e..a48b443aea 100644 --- a/protected/humhub/modules/content/search/driver/MysqlDriver.php +++ b/protected/humhub/modules/content/search/driver/MysqlDriver.php @@ -41,8 +41,7 @@ class MysqlDriver extends AbstractDriver public function update(Content $content): void { - - $this->delete($content); + $this->delete($content->id); $record = new ContentFulltext(); $record->content_id = $content->id; @@ -65,9 +64,9 @@ class MysqlDriver extends AbstractDriver $record->save(); } - public function delete(Content $content): void + public function delete(int $contentId): void { - ContentFulltext::deleteAll(['content_id' => $content->id]); + ContentFulltext::deleteAll(['content_id' => $contentId]); } /** diff --git a/protected/humhub/modules/content/search/driver/ZendLucenceDriver.php b/protected/humhub/modules/content/search/driver/ZendLucenceDriver.php index c6844efcaa..38b826f7d1 100644 --- a/protected/humhub/modules/content/search/driver/ZendLucenceDriver.php +++ b/protected/humhub/modules/content/search/driver/ZendLucenceDriver.php @@ -14,7 +14,6 @@ use humhub\modules\space\models\Space; use humhub\modules\user\helpers\AuthHelper; use humhub\modules\user\models\User; use Yii; -use yii\base\Exception; use yii\data\Pagination; use yii\helpers\FileHelper; use ZendSearch\Lucene\Analysis\Analyzer\Analyzer; @@ -100,9 +99,9 @@ class ZendLucenceDriver extends AbstractDriver ]; } - public function delete(Content $content): void + public function delete(int $contentId): void { - $query = new TermQuery(new Term($content->id, 'content_id')); + $query = new TermQuery(new Term($contentId, 'content_id')); foreach ($this->getIndex()->find($query) as $result) { try { $this->getIndex()->delete($result->id); @@ -145,13 +144,13 @@ class ZendLucenceDriver extends AbstractDriver } catch (\Exception $ex) { throw new \Exception('Could not get content id from Lucence search result'); } + $content = Content::findOne(['id' => $contentId]); if ($content !== null) { $resultSet->results[] = $content; } else { - throw new Exception('Could not load result! Content ID: ' . $contentId); - // ToDo: Delete Result - Yii::error("Could not load search result content: " . $contentId); + Yii::warning("Deleted non-existing content from search index. Content ID: ". $contentId, 'content'); + $this->delete($contentId); } } diff --git a/protected/humhub/modules/content/services/ContentSearchService.php b/protected/humhub/modules/content/services/ContentSearchService.php index ca50a6a99a..3048d98d0a 100644 --- a/protected/humhub/modules/content/services/ContentSearchService.php +++ b/protected/humhub/modules/content/services/ContentSearchService.php @@ -32,7 +32,7 @@ class ContentSearchService if ($asActiveJob) { Yii::$app->queue->push(new SearchUpdateDocument(['contentId' => $this->content->id])); } else { - $this->getSearchDriver()->update($this->content); + self::getDriver()->update($this->content); } } else { $this->delete($asActiveJob); @@ -40,11 +40,16 @@ class ContentSearchService } public function delete(bool $asActiveJob = true): void + { + self::deleteContentById($this->content->id, $asActiveJob); + } + + public static function deleteContentById(int $id, bool $asActiveJob = true): void { if ($asActiveJob) { - Yii::$app->queue->push(new SearchDeleteDocument(['contentId' => $this->content->id])); + Yii::$app->queue->push(new SearchDeleteDocument(['contentId' => $id])); } else { - $this->getSearchDriver()->delete($this->content); + self::getDriver()->delete($id); } } @@ -89,9 +94,9 @@ class ContentSearchService return true; } - private function getSearchDriver(): AbstractDriver + public static function getDriver(): AbstractDriver { - /** @var Module $module */ + /* @var Module $module */ $module = Yii::$app->getModule('content'); return $module->getSearchDriver(); }