Page MenuHomePhabricator

No OneTemporary

diff --git a/bin/classes/ping/core/_recipes/notificationemail.php b/bin/classes/ping/core/_recipes/notificationemail.php
index 6c33d04..1efeb55 100644
--- a/bin/classes/ping/core/_recipes/notificationemail.php
+++ b/bin/classes/ping/core/_recipes/notificationemail.php
@@ -1,61 +1,69 @@
<?php
use spitfire\exceptions\FileNotFoundException;
use settings\NotificationModel as NotificationSetting;
/*
* The MIT License
*
* Copyright 2019 César de la Cal Bretschneider <cesar@magic3w.com>.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/*
* After a new activity is pushed to the database, the system should decide whether
* it needs to send a email to the user immediately, later (as a digest) or not at all.
*/
$core->activity->push->after()->do(function ($parameter) {
//TODO This code deserves to go, it's broken
$sso = new \auth\SSOCache(\spitfire\core\Environment::get('SSO'));
$email = new \EmailSender($sso);
$target = $parameter->target;
$src = $parameter->src;
$url = $parameter->url;
$content = $parameter->content;
$type = $parameter->type;
+ /**
+ * If the notification is silent, we do not send an email to the user, that
+ * would be kind of double tapping.
+ */
+ if ($parameter->silent) {
+ return;
+ }
+
if ((!$target instanceof UserModel) || $target->notify($type, NotificationSetting::NOTIFY_EMAIL)) {
//TODO This code deserves to go, it's broken
$email->push($target->_id, $src, $content, $url);
}
elseif ($target->notify($type, NotificationSetting::NOTIFY_DIGEST)) {
/*
* The user chose to receive digests of their notifications. Defer the sending
* of the email to a later point in time.
*/
$r = db()->table('email\digestqueue')->newRecord();
$r->user = $target;
$r->type = $type;
$r->notification = db()->table('notification')->get('_id', $parameter->id)->first();
$r->store();
}
});
\ No newline at end of file
diff --git a/bin/controllers/activity.php b/bin/controllers/activity.php
index c3d3e04..ceb0171 100644
--- a/bin/controllers/activity.php
+++ b/bin/controllers/activity.php
@@ -1,125 +1,132 @@
<?php
use spitfire\exceptions\PublicException;
/**
* Activity refers to anything that happens on the network ping is directly connected
* to. This means that, unlike pings or authors, the activity is not able to be
* federated. The server can determine to push activity to the user if there's an
* event on the federated network that is considered worthy of attention.
*
* Whenever a user receives activity, they will be notified about it. Either via
* email or push notification.
*
* @author César de la Cal Bretschneider <cesar@magic3w.com>
*/
class ActivityController extends AppController
{
public function index() {
/*
* A user can only get their activity feed when they are logged into the
* application.
*/
if (!$this->user) {
$this->response->setBody('Redirect...')->getHeaders()->redirect(url('account', 'login'));
return;
}
if (isset($_GET['until'])) {
$notifications = db()->table('notification')->get('target__id', $this->user->id)->addRestriction('_id', $_GET['until'], '<')->setOrder('_id', 'DESC')->range(0, 20);
} else {
$notifications = db()->table('notification')->get('target__id', $this->user->id)->setOrder('_id', 'DESC')->range(0, 20);
}
$user = db()->table('user')->get('_id', $this->user->id)->fetch();
$user->lastSeenActivity = time();
$user->store();
$this->view->set('notifications', $notifications);
}
/**
*
* @validate GET#signature (required)
* @validate POST#target (required)
* @validate POST#content(required string length[1, 250])
* @validate POST#url(required string url)
* @request-method POST
*/
public function push() {
#Validate the app
if (!$this->sso->authApp($_GET['signature'])) {
throw new PublicException('Invalid signature', 403);
}
#Read POST data
$srcid = $_POST['src'];
$tgtid = (array)$_POST['target'];
$content = str_replace("\r", '', $_POST['content']);
$url = $_POST['url'];
$type = _def($_POST['type'], 0);
#There needs to be a src user. That means that somebody is originating the
#notification. There has to be one, and no more than one.
try {
$src = AuthorModel::get(db()->table('user')->get('_id', $srcid)->fetch()? : UserModel::makeFromSSO($this->sso->getUser($srcid)));
}
catch (\Exception$e) {
trigger_error(sprintf('User with id %s was not found', $srcid), E_USER_NOTICE);
$src = null;
}
$targets = collect($tgtid)->filter(function ($tgtid) use ($src, $content, $url) {
#In the event the user is not registered, and the application is notifying
#a guest with just an email address.
if (filter_var($tgtid, FILTER_VALIDATE_EMAIL)) {
$email = new \EmailSender($this->sso);
$email->push($tgtid, $src, $content, $url);
return false;
}
return true;
})
->each(function ($tgtid) use ($srcid) {
#If sourceID and target are identical, we skip the sending of the notification
#This requires the application to check whether the user is visiting his own profile
if ($srcid == $tgtid) { return null; }
#If there is no user specified we do skip them
try { return db()->table('user')->get('_id', $tgtid)->fetch()? : UserModel::makeFromSSO($this->sso->getUser($tgtid)); }
catch (\Exception$e) { return null; }
})->filter()->toArray();
#It could happen that the target is established as an email and therefore
#receives notifications directly as emails
foreach ($targets as $target) {
#Make it a record
$notification = db()->table('notification')->newRecord();
$notification->src = $src;
$notification->target = $target;
$notification->content = $content;
$notification->url = $url;
$notification->type = $type;
+ /*
+ * Only JSON requests can explicitly set the silent variable to false,
+ * the HTML requests will have to ommit the flag if they wis to set it
+ * to false.
+ */
+ $notification->silent = isset($_POST['silent'])? $_POST['silent'] !== false : false;
+
$this->core->activity->push->do(function ($notification) {
$notification->store();
}, $notification);
}
#This happens if the user defined no targets (this would imply that the ping
#they sent out was public.
if (empty($tgtid)) {
throw new PublicException('Notifications require a target', 400);
}
}
}
\ No newline at end of file
diff --git a/bin/models/notification.php b/bin/models/notification.php
index 73e764e..d4036aa 100644
--- a/bin/models/notification.php
+++ b/bin/models/notification.php
@@ -1,45 +1,60 @@
<?php
class NotificationModel extends spitfire\Model
{
const TYPE_OTHER = 0;
const TYPE_FOLLOW = 1;
const TYPE_LIKE = 2;
const TYPE_SHARE = 3;
const TYPE_COMMENT = 4;
const TYPE_ALERT = 5;
const TYPE_PAYMENT = 6;
const TYPE_MENTION = 7;
const TYPE_MESSAGE = 8;
public function definitions(\spitfire\storage\database\Schema $schema) {
$schema->src = new Reference('author'); # User originating the action
$schema->target = new Reference('user'); # If a notification is not a broadcast
$schema->content = new StringField(255); # A ping can contain up to 255 characters
$schema->url = new StringField(255); # Source URL for the notification
$schema->created = new IntegerField(true);
$schema->type = new IntegerField(true);
+ /*
+ * Silent notifications allow an application to notify a user without sending
+ * any email or push notification through other channels. This is usually done
+ * because the application sending the notification wishes to further customize
+ * the email or push notification.
+ *
+ * For example, in a ticketing system that wishes to notify a user that a
+ * response was sent will usually include the message in the email and allow
+ * the user to respond to the mail.
+ *
+ * To do so, it needs to set ping to not send an email to prevent the emails
+ * from being duplicated.
+ */
+ $schema->silent = new BooleanField();
+
$schema->type->setNullable(false);
}
public function onbeforesave() {
if (!$this->created) { $this->created = time(); }
}
public static function getTypesAvailable() {
return [
'other' => self::TYPE_OTHER,
'follow' => self::TYPE_FOLLOW,
'like' => self::TYPE_LIKE,
'share' => self::TYPE_SHARE,
'comment' => self::TYPE_COMMENT,
'alert' => self::TYPE_ALERT,
'payment' => self::TYPE_PAYMENT,
'mention' => self::TYPE_MENTION,
'message' => self::TYPE_MESSAGE
];
}
}

File Metadata

Mime Type
text/x-diff
Expires
Apr 13 2021, 11:45 AM (9 w, 10 h ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
4498
Default Alt Text
(9 KB)

Event Timeline