Enh: Added SearchAttributesEvent to improve content addon indexing (comment/file)

This commit is contained in:
Lucas Bartholemy 2017-09-11 08:15:58 +02:00
parent 43cb942423
commit e3fb211ec6
10 changed files with 151 additions and 35 deletions

View File

@ -23,8 +23,9 @@ Important note for LDAP users: There is a new setting "ID Attribute" which shoul
- Fix: trigger richtext `clear` when submitting comment.
- Fix: missing return in `FileContent::beforeValidate`
- Fix: Mentioning search with `-` not working
- Fix #2730 Mentioning search with `-` not working
- Fix File search with suffix not working
- Fix #2730: Mentioning search with `-` not working
- Fix: File search with suffix not working
- Enh: Added SearchAttributesEvent to improve content addon indexing (comment/file)
1.2.2 (August 2, 2017)
--------------------------------

View File

@ -9,13 +9,16 @@
namespace humhub\modules\comment;
use humhub\modules\comment\models\Comment;
use humhub\modules\search\events\SearchAttributesEvent;
use humhub\modules\search\engine\Search;
use yii\base\Event;
/**
* Events provides callbacks to handle events.
*
* @author luke
*/
class Events extends \yii\base\Object
class Events extends \yii\base\Component
{
/**
@ -42,8 +45,8 @@ class Events extends \yii\base\Object
foreach (Comment::findAll(['created_by' => $event->sender->id]) as $comment) {
$comment->delete();
}
return true;
return true;
}
/**
@ -85,7 +88,7 @@ class Events extends \yii\base\Object
if ($event->sender->object->content === null) {
return;
}
if (\Yii::$app->getModule('comment')->canComment($event->sender->object->content)) {
$event->sender->addWidget(widgets\CommentLink::className(), ['object' => $event->sender->object], ['sortOrder' => 10]);
}
@ -101,4 +104,28 @@ class Events extends \yii\base\Object
$event->sender->addWidget(widgets\Comments::className(), ['object' => $event->sender->object], ['sortOrder' => 20]);
}
/**
* Handles the SearchAttributesEvent and adds related comments
*
* @since 1.2.3
* @param SearchAttributesEvent $event
*/
public static function onSearchAttributes(SearchAttributesEvent $event)
{
if (!isset($event->attributes['comments'])) {
$event->attributes['comments'] = [];
}
foreach (Comment::findAll(['object_model' => $event->record->className(), 'object_id' => $event->record->id]) as $comment) {
/* @var $comment Comment */
$event->attributes['comments'][$comment->id] = [
'author' => ($comment->user !== null) ? $comment->user->displayName : '',
'message' => $comment->message
];
// Add comment related attributes (e.g. files)
Event::trigger(Search::class, Search::EVENT_SEARCH_ATTRIBUTES, new SearchAttributesEvent($event->attributes['comments'][$comment->id], $comment));
}
}
}

View File

@ -6,16 +6,18 @@ use humhub\modules\content\components\ContentActiveRecord;
use humhub\commands\IntegrityController;
use humhub\modules\content\widgets\WallEntryAddons;
use humhub\modules\content\widgets\WallEntryLinks;
use humhub\modules\search\engine\Search;
return [
'id' => 'comment',
'class' => \humhub\modules\comment\Module::className(),
'isCoreModule' => true,
'events' => [
['class' => User::className(), 'event' => User::EVENT_BEFORE_DELETE, 'callback' => [Events::className(), 'onUserDelete']],
['class' => ContentActiveRecord::className(), 'event' => ContentActiveRecord::EVENT_BEFORE_DELETE, 'callback' => [Events::className(), 'onContentDelete']],
['class' => IntegrityController::className(), 'event' => IntegrityController::EVENT_ON_RUN, 'callback' => [Events::className(), 'onIntegrityCheck']],
['class' => WallEntryLinks::className(), 'event' => WallEntryLinks::EVENT_INIT, 'callback' => [Events::className(), 'onWallEntryLinksInit']],
['class' => WallEntryAddons::className(), 'event' => WallEntryAddons::EVENT_INIT, 'callback' => [Events::className(), 'onWallEntryAddonInit']],
['class' => User::class, 'event' => User::EVENT_BEFORE_DELETE, 'callback' => [Events::class, 'onUserDelete']],
['class' => ContentActiveRecord::class, 'event' => ContentActiveRecord::EVENT_BEFORE_DELETE, 'callback' => [Events::class, 'onContentDelete']],
['class' => IntegrityController::class, 'event' => IntegrityController::EVENT_ON_RUN, 'callback' => [Events::class, 'onIntegrityCheck']],
['class' => WallEntryLinks::class, 'event' => WallEntryLinks::EVENT_INIT, 'callback' => [Events::class, 'onWallEntryLinksInit']],
['class' => WallEntryAddons::class, 'event' => WallEntryAddons::EVENT_INIT, 'callback' => [Events::class, 'onWallEntryAddonInit']],
['class' => Search::class, 'event' => Search::EVENT_SEARCH_ATTRIBUTES, 'callback' => [Events::class, 'onSearchAttributes']]
],
];
];

View File

@ -210,4 +210,4 @@ class ContentAddonActiveRecord extends ActiveRecord implements ContentOwner
return $this->hasOne(\humhub\modules\user\models\User::className(), ['id' => 'created_by']);
}
}
}

View File

@ -138,12 +138,10 @@ class Content extends ContentDeprecated
*/
public function beforeSave($insert)
{
if ($this->object_model == "" || $this->object_id == "") {
throw new Exception("Could not save content with object_model or object_id!");
}
// Set some default values
if (!$this->archived) {
$this->archived = 0;

View File

@ -8,7 +8,10 @@
namespace humhub\modules\file;
use humhub\modules\search\engine\Search;
use humhub\modules\file\models\File;
use yii\base\Event;
use humhub\modules\search\events\SearchAttributesEvent;
/**
* Events provides callbacks to handle events.
@ -96,4 +99,27 @@ class Events extends \yii\base\Object
return true;
}
/**
* Handles the SearchAttributesEvent and adds related files
*
* @since 1.2.3
* @param SearchAttributesEvent $event
*/
public static function onSearchAttributes(SearchAttributesEvent $event)
{
if (!isset($event->attributes['files'])) {
$event->attributes['files'] = [];
}
foreach (File::findAll(['object_model' => $event->record->className(), 'object_id' => $event->record->id]) as $file) {
/* @var $file File */
$event->attributes['files'][$file->id] = [
'name' => $file->file_name
];
// Add comment related attributes
Event::trigger(Search::class, Search::EVENT_SEARCH_ATTRIBUTES, new SearchAttributesEvent($event->attributes['files'][$file->id], $file));
}
}
}

View File

@ -1,5 +1,6 @@
<?php
use humhub\modules\search\engine\Search;
use humhub\modules\content\widgets\WallEntryAddons;
use humhub\commands\CronController;
use humhub\commands\IntegrityController;
@ -11,12 +12,13 @@ return [
'id' => 'file',
'class' => \humhub\modules\file\Module::className(),
'isCoreModule' => true,
'events' => array(
array('class' => WallEntryAddons::className(), 'event' => WallEntryAddons::EVENT_INIT, 'callback' => array(Events::className(), 'onWallEntryAddonInit')),
array('class' => CronController::className(), 'event' => CronController::EVENT_ON_DAILY_RUN, 'callback' => array(Events::className(), 'onCronDailyRun')),
array('class' => IntegrityController::className(), 'event' => IntegrityController::EVENT_ON_RUN, 'callback' => array(Events::className(), 'onIntegrityCheck')),
array('class' => ActiveRecord::className(), 'event' => \humhub\components\ActiveRecord::EVENT_BEFORE_DELETE, 'callback' => array(Events::className(), 'onBeforeActiveRecordDelete')),
array('class' => User::className(), 'event' => User::EVENT_BEFORE_DELETE, 'callback' => array(Events::className(), 'onUserDelete')),
),
'events' => [
['class' => WallEntryAddons::class, 'event' => WallEntryAddons::EVENT_INIT, 'callback' => [Events::class, 'onWallEntryAddonInit']],
['class' => CronController::class, 'event' => CronController::EVENT_ON_DAILY_RUN, 'callback' => [Events::class, 'onCronDailyRun']],
['class' => IntegrityController::class, 'event' => IntegrityController::EVENT_ON_RUN, 'callback' => [Events::class, 'onIntegrityCheck']],
['class' => ActiveRecord::class, 'event' => ActiveRecord::EVENT_BEFORE_DELETE, 'callback' => [Events::class, 'onBeforeActiveRecordDelete']],
['class' => User::class, 'event' => User::EVENT_BEFORE_DELETE, 'callback' => [Events::class, 'onUserDelete']],
['class' => Search::class, 'event' => Search::EVENT_SEARCH_ATTRIBUTES, 'callback' => [Events::class, 'onSearchAttributes']]
],
];
?>

View File

@ -14,6 +14,7 @@ use humhub\modules\content\models\Content;
use humhub\modules\content\components\ContentActiveRecord;
use humhub\modules\user\models\User;
use humhub\modules\space\models\Space;
use humhub\modules\search\events\SearchAttributesEvent;
/**
* Description of HSearchComponent
@ -24,6 +25,7 @@ use humhub\modules\space\models\Space;
abstract class Search extends \yii\base\Component
{
const EVENT_SEARCH_ATTRIBUTES = 'search_attributes';
const EVENT_ON_REBUILD = 'onRebuild';
const DOCUMENT_TYPE_USER = 'user';
const DOCUMENT_TYPE_SPACE = 'space';
@ -166,4 +168,18 @@ abstract class Search extends \yii\base\Component
return $options;
}
/**
* Returns additional search attributes for the given object.
* This contains a list of comments, files and other content addons.
*
* @param Searchable $object
* @return array the additional search attributes
*/
protected function getAdditionalAttributes(Searchable $object)
{
$additionalAttributes = [];
$this->trigger(self::EVENT_SEARCH_ATTRIBUTES, new SearchAttributesEvent($additionalAttributes, $object));
return $additionalAttributes;
}
}

View File

@ -2,7 +2,7 @@
/**
* @link https://www.humhub.org/
* @copyright Copyright (c) 2015 HumHub GmbH & Co. KG
* @copyright Copyright (c) 2017 HumHub GmbH & Co. KG
* @license https://www.humhub.com/licences
*/
@ -10,11 +10,11 @@ namespace humhub\modules\search\engine;
use Yii;
use humhub\modules\search\interfaces\Searchable;
use humhub\modules\content\components\ContentActiveRecord;
use humhub\modules\search\libs\SearchResult;
use humhub\modules\search\libs\SearchResultSet;
use humhub\modules\comment\models\Comment;
use humhub\modules\space\models\Space;
use ZendSearch\Lucene\Document\Field;
use yii\helpers\VarDumper;
/**
* ZendLucenceSearch Engine
@ -30,6 +30,9 @@ class ZendLuceneSearch extends Search
*/
public $index = null;
/**
* @inheritdoc
*/
public function add(Searchable $obj)
{
// Get Primary Key
@ -41,7 +44,7 @@ class ZendLuceneSearch extends Search
// Add Meta Data fields
foreach ($this->getMetaInfoArray($obj) as $fieldName => $fieldValue) {
$doc->addField(\ZendSearch\Lucene\Document\Field::keyword($fieldName, $fieldValue));
$doc->addField(Field::keyword($fieldName, $fieldValue));
}
// Add provided search infos
@ -50,19 +53,16 @@ class ZendLuceneSearch extends Search
$val = implode(" ", $val);
}
$doc->addField(\ZendSearch\Lucene\Document\Field::Text($key, $val, 'UTF-8'));
$doc->addField(Field::Text($key, $val, 'UTF-8'));
}
// Add comments - if record is content
if ($obj instanceof ContentActiveRecord) {
$comments = "";
foreach (Comment::findAll(['object_id' => $obj->getPrimaryKey(), 'object_model' => $obj->className()]) as $comment) {
$comments .= ' ' . $comment->user->displayName . ' ' . $comment->message;
foreach ($this->getAdditionalAttributes($obj) as $attrName => $attrValue) {
if (!empty($attrValue)) {
$doc->addField(Field::unStored($attrName, VarDumper::dumpAsString($attrValue), 'UTF-8'));
}
$doc->addField(\ZendSearch\Lucene\Document\Field::unStored('comments', $comments, 'UTF-8'));
}
if (\Yii::$app->request->isConsoleRequest) {
if (Yii::$app->request->isConsoleRequest) {
print ".";
}
@ -109,7 +109,7 @@ class ZendLuceneSearch extends Search
$options = $this->setDefaultFindOptions($options);
$index = $this->getIndex();
$keyword = str_replace(array('*', '?', '_', '$', '-', '.'), ' ', mb_strtolower($keyword, 'utf-8'));
$keyword = str_replace(array('*', '?', '_', '$', '-', '.'), ' ', mb_strtolower($keyword, 'utf-8'));
$query = $this->buildQuery($keyword, $options);
if ($query === null) {

View File

@ -0,0 +1,44 @@
<?php
/**
* @link https://www.humhub.org/
* @copyright Copyright (c) 2017 HumHub GmbH & Co. KG
* @license https://www.humhub.com/licences
*/
namespace humhub\modules\search\events;
/**
* This event is used to collect additional search attributes for a record.
*
* The event object holds an reference to the search index attributes.
* Modules like comments or files can add additional attributes to it.
*
* @author luke
* @since 1.2.3
*/
class SearchAttributesEvent extends \yii\base\Event
{
/**
* @var array Reference to the currently added search attributes
*/
public $attributes;
/**
* @var \humhub\modules\search\interfaces\Searchable the searchable record
*/
public $record;
/**
* @inheritdoc
*/
public function __construct(&$attributes, $record)
{
$this->attributes = &$attributes;
$this->record = $record;
$this->init();
}
}