public function save($Data, $Preference = false, $Options = [])
{
trace('ActivityModel->save()');
$Activity = $Data;
$this->_touch($Activity);
if ($Activity['ActivityUserID'] == $Activity['NotifyUserID'] && !val('Force', $Options)) {
trace('Skipping activity because it would notify the user of something they did.');
return null;
// don't notify users of something they did.
}
// Check the user's preference.
if ($Preference) {
list($Popup, $Email) = self::notificationPreference($Preference, $Activity['NotifyUserID'], 'both');
if ($Popup && !$Activity['Notified']) {
$Activity['Notified'] = self::SENT_PENDING;
}
if ($Email && !$Activity['Emailed']) {
$Activity['Emailed'] = self::SENT_PENDING;
}
if (!$Activity['Notified'] && !$Activity['Emailed'] && !val('Force', $Options)) {
trace("Skipping activity because the user has no preference set.");
return null;
}
}
$ActivityType = self::getActivityType($Activity['ActivityType']);
$ActivityTypeID = val('ActivityTypeID', $ActivityType);
if (!$ActivityTypeID) {
trace("There is no {$ActivityType} activity type.", TRACE_WARNING);
$ActivityType = self::getActivityType('Default');
$ActivityTypeID = val('ActivityTypeID', $ActivityType);
}
$Activity['ActivityTypeID'] = $ActivityTypeID;
$NotificationInc = 0;
if ($Activity['NotifyUserID'] > 0 && $Activity['Notified']) {
$NotificationInc = 1;
}
// Check to see if we are sharing this activity with another one.
if ($CommentActivityID = val('CommentActivityID', $Activity['Data'])) {
$CommentActivity = $this->getID($CommentActivityID);
$Activity['Data']['CommentNotifyUserID'] = $CommentActivity['NotifyUserID'];
}
// Make sure this activity isn't a duplicate.
if (val('CheckRecord', $Options)) {
// Check to see if this record already notified so we don't notify multiple times.
$Where = arrayTranslate($Activity, ['NotifyUserID', 'RecordType', 'RecordID']);
$Where['DateUpdated >'] = Gdn_Format::toDateTime(strtotime('-2 days'));
// index hint
$CheckActivity = $this->SQL->getWhere('Activity', $Where)->firstRow();
if ($CheckActivity) {
return false;
}
}
// Check to share the activity.
if (val('Share', $Options)) {
$this->share($Activity);
}
// Group he activity.
if ($GroupBy = val('GroupBy', $Options)) {
$GroupBy = (array) $GroupBy;
$Where = [];
foreach ($GroupBy as $ColumnName) {
$Where[$ColumnName] = $Activity[$ColumnName];
}
$Where['NotifyUserID'] = $Activity['NotifyUserID'];
// Make sure to only group activities by day.
$Where['DateInserted >'] = Gdn_Format::toDateTime(strtotime('-1 day'));
// See if there is another activity to group these into.
$GroupActivity = $this->SQL->getWhere('Activity', $Where)->firstRow(DATASET_TYPE_ARRAY);
if ($GroupActivity) {
$GroupActivity['Data'] = dbdecode($GroupActivity['Data']);
$Activity = $this->mergeActivities($GroupActivity, $Activity);
$NotificationInc = 0;
}
}
$Delete = false;
if ($Activity['Emailed'] == self::SENT_PENDING) {
$this->email($Activity);
$Delete = val('_Delete', $Activity);
}
$ActivityData = $Activity['Data'];
if (isset($Activity['Data']) && is_array($Activity['Data'])) {
$Activity['Data'] = dbencode($Activity['Data']);
}
$this->defineSchema();
$Activity = $this->filterSchema($Activity);
$ActivityID = val('ActivityID', $Activity);
if (!$ActivityID) {
if (!$Delete) {
$this->addInsertFields($Activity);
touchValue('DateUpdated', $Activity, $Activity['DateInserted']);
$this->EventArguments['Activity'] =& $Activity;
$this->EventArguments['ActivityID'] = null;
$Handled = false;
$this->EventArguments['Handled'] =& $Handled;
$this->fireEvent('BeforeSave');
if (count($this->validationResults()) > 0) {
return false;
}
if ($Handled) {
// A plugin handled this activity so don't save it.
return $Activity;
}
if (val('CheckSpam', $Options)) {
// Check for spam
$Spam = SpamModel::isSpam('Activity', $Activity);
if ($Spam) {
return SPAM;
}
// Check for approval
$ApprovalRequired = checkRestriction('Vanilla.Approval.Require');
if ($ApprovalRequired && !val('Verified', Gdn::session()->User)) {
LogModel::insert('Pending', 'Activity', $Activity);
return UNAPPROVED;
}
}
$ActivityID = $this->SQL->insert('Activity', $Activity);
$Activity['ActivityID'] = $ActivityID;
$this->prune();
}
} else {
$Activity['DateUpdated'] = Gdn_Format::toDateTime();
unset($Activity['ActivityID']);
$this->EventArguments['Activity'] =& $Activity;
$this->EventArguments['ActivityID'] = $ActivityID;
$this->fireEvent('BeforeSave');
if (count($this->validationResults()) > 0) {
return false;
}
$this->SQL->put('Activity', $Activity, ['ActivityID' => $ActivityID]);
$Activity['ActivityID'] = $ActivityID;
}
$Activity['Data'] = $ActivityData;
if (isset($CommentActivity)) {
$CommentActivity['Data']['SharedActivityID'] = $Activity['ActivityID'];
$CommentActivity['Data']['SharedNotifyUserID'] = $Activity['NotifyUserID'];
$this->setField($CommentActivity['ActivityID'], 'Data', $CommentActivity['Data']);
}
if ($NotificationInc > 0) {
$CountNotifications = Gdn::userModel()->getID($Activity['NotifyUserID'])->CountNotifications + $NotificationInc;
Gdn::userModel()->setField($Activity['NotifyUserID'], 'CountNotifications', $CountNotifications);
}
// If this is a wall post then we need to notify on that.
if (val('Name', $ActivityType) == 'WallPost' && $Activity['NotifyUserID'] == self::NOTIFY_PUBLIC) {
$this->notifyWallPost($Activity);
}
return $Activity;
}