- Fix: Source serialization of Notification ActiveJob

- Enh: Added 'requireSource' & 'requireOriginator' flags in SocialActivities
This commit is contained in:
Lucas Bartholemy 2018-07-30 13:08:03 +02:00
parent 7b981d6caa
commit 73f04d0e24
8 changed files with 140 additions and 36 deletions

View File

@ -8,6 +8,7 @@
namespace humhub\components; namespace humhub\components;
use humhub\components\behaviors\PolymorphicRelation;
use humhub\libs\Helpers; use humhub\libs\Helpers;
use humhub\modules\content\models\Content; use humhub\modules\content\models\Content;
use Yii; use Yii;
@ -43,6 +44,12 @@ abstract class SocialActivity extends \yii\base\BaseObject implements rendering\
*/ */
public $originator; public $originator;
/**
* @var bool ensure originator existence
* @since 1.3
*/
public $requireOriginator = true;
/** /**
* The source instance which created this activity * The source instance which created this activity
* *
@ -50,6 +57,12 @@ abstract class SocialActivity extends \yii\base\BaseObject implements rendering\
*/ */
public $source; public $source;
/**
* @var bool ensure source existence
* @since 1.3
*/
public $requireSource = true;
/** /**
* @var string the module id which this activity belongs to (required) * @var string the module id which this activity belongs to (required)
*/ */
@ -362,6 +375,23 @@ abstract class SocialActivity extends \yii\base\BaseObject implements rendering\
return RichText::preview($content->getContentDescription(), $maxLength); return RichText::preview($content->getContentDescription(), $maxLength);
} }
/**
* Validates the existence of required attributes
*
* @return bool
*/
public function validate() {
if (empty($this->source) && $this->requireSource) {
return false;
}
if (empty($this->originator) && $this->requireOriginator) {
return false;
}
return true;
}
/** /**
* Serializes the $source and $originator fields. * Serializes the $source and $originator fields.
* *
@ -372,8 +402,17 @@ abstract class SocialActivity extends \yii\base\BaseObject implements rendering\
*/ */
public function serialize() public function serialize()
{ {
$sourceClass = null;
$sourcePk = null;
if ($this->source) {
$sourceClass = get_class($this->source);
$sourcePk = $this->source->getPrimaryKey();
}
return serialize([ return serialize([
'source' => $this->source, 'sourceClass' => $sourceClass,
'sourcePk' => $sourcePk,
'originator_id' => $this->originator->id 'originator_id' => $this->originator->id
]); ]);
} }
@ -389,9 +428,25 @@ abstract class SocialActivity extends \yii\base\BaseObject implements rendering\
{ {
$this->init(); $this->init();
$unserializedArr = unserialize($serialized); $unserializedArr = unserialize($serialized);
if(isset($unserializedArr['originator_id'])) { if(isset($unserializedArr['originator_id'])) {
$this->from(User::findOne(['id' => $unserializedArr['originator_id']])); $user = User::findOne(['id' => $unserializedArr['originator_id']]);
if ($user !== null) {
$this->from($user);
}
} }
$this->about($unserializedArr['source']);
// Temporary for 1.3.0-beta.2 to 1.3.0-beta.3 updates with existing queue record
if (isset($unserializedArr['source'])) {
$this->about($unserializedArr['source']);
}
if (!empty($unserializedArr['sourceClass']) && !empty($unserializedArr['sourcePk'])) {
$source = PolymorphicRelation::loadActiveRecord($unserializedArr['sourceClass'], $unserializedArr['sourcePk']);
if ($source !== null) {
$this->about($source);
}
}
} }
} }

View File

@ -8,9 +8,13 @@
namespace humhub\components\behaviors; namespace humhub\components\behaviors;
use Exception;
use ReflectionClass;
use ReflectionException;
use Yii; use Yii;
use yii\base\Behavior; use yii\base\Behavior;
use yii\db\Exception; use yii\db\ActiveRecord;
use yii\db\BaseActiveRecord;
/** /**
* PolymorphicRelations behavior provides simple support for polymorphic relations in ActiveRecords. * PolymorphicRelations behavior provides simple support for polymorphic relations in ActiveRecords.
@ -51,34 +55,14 @@ class PolymorphicRelation extends Behavior
return $this->_cached; return $this->_cached;
} }
$object = static::loadActiveRecord(
$this->owner->getAttribute($this->classAttribute),
$this->owner->getAttribute($this->pkAttribute)
);
$className = $this->owner->getAttribute($this->classAttribute); if ($object !== null && $this->validateUnderlyingObjectType($object)) {
$this->_cached = $object;
if ($className == "") { return $object;
return null;
}
if (!class_exists($className)) {
Yii::error("Underlying object class " . $className . " not found!");
return null;
}
if (!method_exists($className, 'tableName')) {
// Avoids failures when running integrity checks etc.
return null;
}
try {
$tableName = $className::tableName();
$object = $className::find()->where([$tableName . '.id' => $this->owner->getAttribute($this->pkAttribute)])->one();
if ($object !== null && $this->validateUnderlyingObjectType($object)) {
$this->_cached = $object;
return $object;
}
} catch (\Exception $e) {
// Avoid failures when running integrity checks etc.
Yii::error($e);
} }
return null; return null;
@ -127,7 +111,44 @@ class PolymorphicRelation extends Behavior
} }
Yii::error('Got invalid underlying object type! (' . $object->className() . ')'); Yii::error('Got invalid underlying object type! (' . $object->className() . ')');
return false; return false;
} }
/**
* Loads an active record based on classname and primary key.
*
* @param $className
* @param $primaryKey
* @return null|ActiveRecord
*/
public static function loadActiveRecord($className, $primaryKey)
{
try {
$class = new ReflectionClass($className);
} catch (ReflectionException $e) {
Yii::error('Could not load polymorphic relation! Class (' . $e->getMessage() . ')');
return null;
}
if (!$class->isSubclassOf(BaseActiveRecord::class)) {
Yii::error('Could not load polymorphic relation! Class (Class is no ActiveRecord: ' . $className . ')');
return null;
}
try {
$primaryKeyNames = $className::primaryKey();
if (count($primaryKey) !== 1) {
Yii::error('Could not load polymorphic relation! Only one primary key is supported!');
return null;
}
return $className::findOne([$primaryKeyNames[0] => $primaryKey]);
} catch (Exception $ex) {
Yii::error('Could not load polymorphic relation! Error: "' . $ex->getMessage());
}
return null;
}
} }

View File

@ -21,6 +21,9 @@ HumHub Change Log
- Fix #2700: Prevent GroupManager access to system admin group management - Fix #2700: Prevent GroupManager access to system admin group management
- Enh: Styled user deletion view - Enh: Styled user deletion view
- Fixed: Space and User Admin Filterbar padding - Fixed: Space and User Admin Filterbar padding
- Fix: Source serialization of Notification ActiveJob
- Enh: Added 'requireSource' & 'requireOriginator' flags in SocialActivities
1.3.0-beta.2 (July 18, 2018) 1.3.0-beta.2 (July 18, 2018)
----------------------------- -----------------------------

View File

@ -33,6 +33,11 @@ Added new user status (User::SOFT_DELETED). You can find more information here:
Moved all form and field related widgets from `humhub\widgets` to `humhub\modules\ui\form\widgets` namespace. Moved all form and field related widgets from `humhub\widgets` to `humhub\modules\ui\form\widgets` namespace.
There is a compatibility layer for the 1.3 release. There is a compatibility layer for the 1.3 release.
### Social Activities (Notification & Activities)
- Added new 'requireOriginator' flag with default to true
- Added new 'requireSoruce' flag with default to true
### Deprecations ### Deprecations
- `humhub\components\Theme.php` -> `humhub\modules\ui\view\components\Theme` - `humhub\components\Theme.php` -> `humhub\modules\ui\view\components\Theme`

View File

@ -29,6 +29,16 @@ class NewVersionAvailable extends BaseNotification
*/ */
public $moduleId = 'admin'; public $moduleId = 'admin';
/**
* @inheritdoc
*/
public $requireOriginator = false;
/**
* @inheritdoc
*/
public $requireSource = false;
/** /**
* @inheritdoc * @inheritdoc
*/ */

View File

@ -117,7 +117,7 @@ class NewComment extends \humhub\modules\notification\components\BaseNotificatio
private function getGroupTitle() private function getGroupTitle()
{ {
$user = $this->record->user; $user = $this->record->user;
$contentRecord = $this->getCommentedRecord(); $contentRecord = $this->getCommentedRecord();
$contentInfo = $this->getContentInfo($this->getCommentedRecord()); $contentInfo = $this->getContentInfo($this->getCommentedRecord());

View File

@ -218,6 +218,10 @@ abstract class BaseNotification extends SocialActivity
*/ */
public function saveRecord(User $user) public function saveRecord(User $user)
{ {
if (!$this->validate()) {
return false;
}
$notification = new Notification([ $notification = new Notification([
'user_id' => $user->id, 'user_id' => $user->id,
'class' => static::class, 'class' => static::class,
@ -240,9 +244,12 @@ abstract class BaseNotification extends SocialActivity
static::class . ' ' . static::class . ' ' .
print_r($notification->getErrors(), true) print_r($notification->getErrors(), true)
); );
return false;
} }
$this->record = $notification; $this->record = $notification;
return true;
} }
/** /**

View File

@ -73,9 +73,12 @@ class NotificationManager
continue; continue;
} }
$notification->saveRecord($user); if ($notification->saveRecord($user)) {
foreach ($this->getTargets($user) as $target) { foreach ($this->getTargets($user) as $target) {
$target->send($notification, $user); $target->send($notification, $user);
}
} else {
Yii::debug('Could not store notification '.get_class($notification). ' for user '. $user->id);
} }
$processed[] = $user->id; $processed[] = $user->id;