...
 
Commits (2)
......@@ -47,36 +47,71 @@ class referrals implements Interfaces\Api
$response['referrals'] = Factory::exportable(array_values($referrals->toArray()));
$response['load-next'] = (string) $referrals->getPagingToken();
$tempProspect = (object) [
"guid" => "988145006634078224",
"verified" => true,
"username" => "oldprospector",
"name" => "oldprospector",
"icontime" => "1560987887"
];
$tempRef = (object) [
'referrer_guid' => '987892327202689039',
'state' => 'complete',
'score' => 10,
'register_timestamp' => "1560857128000",
'join_timestamp' => "1560867128000",
'prospect' => $tempProspect
];
array_push($response['referrals'], $tempRef);
// $tempProspect = (object) [
// "guid" => "988145006634078224",
// "verified" => true,
// "username" => "oldprospector",
// "name" => "oldprospector",
// "icontime" => "1560987887"
// ];
// $tempRef = (object) [
// 'referrer_guid' => '987892327202689039',
// 'state' => 'complete',
// 'register_timestamp' => "1560857128000",
// 'join_timestamp' => "1560867128000",
// 'prospect' => $tempProspect
// ];
// array_push($response['referrals'], $tempRef);
return Factory::response($response);
}
// Not implemented - new referrals are added in Core/Events/Hooks/Register.php (when prospect registers for Minds)
// Not implemented
// Note: New referrals are added when prospect registers for Minds (in `Core/Events/Hooks/Register.php`)
public function post($pages)
{
}
// Not implemented - referrals are updated in ReferralDelegate.php (when prospect joins rewards)
// Notify a prospect to urge them to join the rewards program
// Note: referrals are updated when prospect joins rewards (in `Core/Rewards/Delegates/ReferralDelegate.php`)
public function put($pages)
{
$referrer_guid = Core\Session::getLoggedInUser()->guid;
if (!$referrer_guid) {
return Factory::response([
'status' => 'error',
'message' => 'You must be logged in to trigger a notification',
]);
}
if (!isset($pages[0])) {
return Factory::response([
'status' => 'error',
'message' => 'Prospect guid is required to trigger a notification',
]);
}
$prospect_guid = $pages[0];
$referral = new Referral;
$referral->setReferrerGuid($referrer_guid)
->setProspectGuid($prospect_guid)
->setPingTimestamp(time());
$manager = Di::_()->get('Referrals\Manager');
if(!$manager->ping($referral)){
return Factory::response([
'status' => 'error',
'done' => false,
]);
}
return Factory::response([
'status' => 'success',
'done' => true,
]);
}
// Not implemented
......
This diff is collapsed.
......@@ -100,8 +100,9 @@ class Manager
'friends',
'welcome_chat',
'welcome_discover',
'referral_ping',
'referral_pending',
'referral_complete'
'referral_complete',
];
break;
case "groups":
......@@ -189,6 +190,7 @@ class Manager
case 'friends':
case 'welcome_chat':
case 'welcome_discover':
case 'referral_ping':
case 'referral_pending':
case 'referral_complete':
return 'subscriptions';
......
......@@ -27,6 +27,7 @@ class PushSettings
'boost_completed' => true,
'group_invite' => true,
'messenger_invite' => true,
'referral_ping' => true,
'referral_pending' => true,
'referral_complete' => true,
];
......
......@@ -1420,6 +1420,7 @@ CREATE TABLE minds.referrals (
prospect_guid bigint,
register_timestamp timestamp,
join_timestamp timestamp,
ping_timestamp timestamp,
PRIMARY KEY (referrer_guid, prospect_guid)
) WITH CLUSTERING ORDER BY (prospect_guid DESC);
......
......@@ -23,11 +23,11 @@ class NotificationDelegate
}
/**
* Sends a notification to referrer
* Sends a notification to referrer on prospect state change
* @param Referral $referral
* @return void
*/
public function send(Referral $referral)
public function notifyReferrer(Referral $referral)
{
$entityGuid = $referral->getProspectGuid();
$entity = $this->entitiesBuilder->single($entityGuid);
......@@ -38,8 +38,6 @@ class NotificationDelegate
$notification_view = 'referral_complete';
}
$notification_view = 'referral_complete';
$this->dispatcher->trigger('notification', 'all', [
'to' => [$referral->getReferrerGuid()],
'entity' => $entity,
......@@ -48,4 +46,24 @@ class NotificationDelegate
'params' => [],
]);
}
/**
* Sends a notification to pending referral prospect to suggest they join rewards program
* @param Referral $referral
* @return void
*/
public function notifyProspect(Referral $referral)
{
$entityGuid = $referral->getReferrerGuid();
$entity = $this->entitiesBuilder->single($entityGuid);
$this->dispatcher->trigger('notification', 'all', [
'to' => [$referral->getProspectGuid()],
'entity' => $entity,
'from' => $referral->getReferrerGuid(),
'notification_view' => 'referral_ping',
'params' => [],
]);
}
}
\ No newline at end of file
......@@ -55,7 +55,7 @@ class Manager
/**
* Create referral for pending prospect who registered for Minds
* @param ReferrerGuid $referrerGuid
* @param Referral $referral
* @return bool
*/
public function add($referral)
......@@ -63,22 +63,39 @@ class Manager
$this->repository->add($referral);
// Send a notification to the referrer
$this->notificationDelegate->send($referral);
$this->notificationDelegate->notifyReferrer($referral);
return true;
}
/**
* Update referral for completed prospect who has joined rewards program
* @param ProspectGuid $prospectGuid
* @param Referral $referral
* @return bool
*/
public function update($referral)
{
// Update the join timestamp
$this->repository->update($referral);
// Send a notification to the referrer
$this->notificationDelegate->send($referral);
$this->notificationDelegate->notifyReferrer($referral);
return true;
}
/**
* Send a notification to pending prospect to suggest they join rewards program
* @param Referral $referral
* @return bool
*/
public function ping($referral)
{
// Update the ping timestamp
$this->repository->ping($referral);
// Send a ping notification to the prospect
$this->notificationDelegate->notifyProspect($referral);
return true;
}
......
<?php
/**
* Referrals module.
* Referrals module
*/
namespace Minds\Core\Referrals;
......
......@@ -13,10 +13,14 @@ use Minds\Traits\MagicAttributes;
* @method long getReferrerGuid()
* @method Referral setProspectGuid()
* @method long getProspectGuid()
* @method Referral setProspect()
* @method User getProspect()
* @method Referral setRegisterTimestamp(int $ts)
* @method int getRegisterTimestamp
* @method Referral setJoinTimestamp(int $ts)
* @method int getJoinTimestamp
* @method Referral setPingTimestamp(int $ts)
* @method int getPingTimestamp
*/
class Referral
......@@ -38,18 +42,41 @@ class Referral
/** @var int $joinTimestamp */
private $joinTimestamp;
/** @var int $pingTimestamp */
private $pingTimestamp;
/**
* Return the state
* @return string
*/
public function getState()
{
// the referral goes from pending to complete when the prospect joins rewards
if ($this->joinTimestamp) {
return 'complete';
}
return 'pending';
}
/**
* Return whether 7 days has passed since last ping
* @return bool
*/
public function getPingable()
{
// determines duration a referrer must wait before re-pinging
$waitTime= 1000*60*60*24*7; // 7 days
$now = time();
$elapsedTime = $now - $this->pingTimestamp;
// referrer can't send another ping notification until a week has gone by
if ($this->pingTimestamp && $elapsedTime < $waitTime ) {
return false;
}
return true;
}
/**
* Export
* @return array
......@@ -58,11 +85,12 @@ class Referral
{
return [
'referrer_guid' => $this->referrerGuid,
// 'prospect_guid' => $this->prospectGuid,
'prospect' => $this->prospect ? $this->prospect->export() : null,
'state' => $this->getState(),
'register_timestamp' => $this->registerTimestamp,
'join_timestamp' => $this->joinTimestamp,
'ping_timestamp' => $this->pingTimestamp,
'pingable' => $this->getPingable(),
];
}
}
......@@ -65,7 +65,8 @@ class Repository
$referral->setProspectGuid((string) $row['prospect_guid'])
->setReferrerGuid((string) $row['referrer_guid'])
->setRegisterTimestamp((string) $row['register_timestamp'])
->setJoinTimestamp((string) $row['join_timestamp']);
->setJoinTimestamp((string) $row['join_timestamp'])
->setPingTimestamp((string) $row['ping_timestamp']);
$response[] = $referral;
}
......@@ -74,7 +75,6 @@ class Repository
$response->setLastPage($rows->isLastPage());
} catch (\Exception $e) {
// return false;
$response = $e;
return $response;
}
......@@ -127,12 +127,20 @@ class Repository
}
/**
* Update a referral
* Update a referral when the prospect joins rewards program
* @param Referral $referral
* @return bool
*/
public function update(Referral $referral)
{
if (!$referral->getReferrerGuid()) {
throw new \Exception('Referrer GUID is required');
}
if (!$referral->getProspectGuid()) {
throw new \Exception('Prospect GUID is required');
}
if (!$referral->getJoinTimestamp()) {
throw new \Exception('Join timestamp is required');
}
......@@ -157,6 +165,46 @@ class Repository
return true;
}
/**
* Update referral when prospect is notified by the referrer to urge them to join rewards
* @param Referral $referral
* @return bool
*/
public function ping(Referral $referral)
{
if (!$referral->getReferrerGuid()) {
throw new \Exception('Referrer GUID is required');
}
if (!$referral->getProspectGuid()) {
throw new \Exception('Prospect GUID is required');
}
if (!$referral->getPingTimestamp()) {
throw new \Exception('Ping timestamp is required');
}
$template = "UPDATE referrals SET ping_timestamp = ? WHERE referrer_guid = ? AND prospect_guid = ?";
$values = [
new Cassandra\Timestamp($referral->getPingTimestamp()),
new Cassandra\Bigint($referral->getReferrerGuid()),
new Cassandra\Bigint($referral->getProspectGuid()),
];
$query = new Prepared\Custom();
$query->query($template, $values);
try {
$success = $this->client->request($query);
} catch (\Exception $e) {
return false;
}
return true;
}
/**
* void
*/
......
......@@ -9,7 +9,7 @@ class ContributionValues
'reminds' => 4,
'votes' => 1,
'subscribers' => 4,
'referrals' => 10,
'referrals' => 50,
'checkin' => 2,
'jury_duty' => 25,
];
......
......@@ -42,7 +42,7 @@ class Join
/** @var OfacBlacklist */
private $ofacBlacklist;
/** @var TestnetBalance */
private $testnetBalance;
......@@ -138,12 +138,10 @@ class Join
public function confirm()
{
// || this->config->get('development_mode')
if ($this->user->getPhoneNumberHash()) {
return false; //already joined
}
if ($this->twofactor->verifyCode($this->secret, $this->code, 8)) {
$hash = hash('sha256', $this->number . $this->config->get('phone_number_hash_salt'));
$this->user->setPhoneNumberHash($hash);
......@@ -159,24 +157,31 @@ class Join
->setAction('joined')
->push();
//////////////////////////////////////////////
// TODOOJM confirm that this should still be removed
$this->testnetBalance->setUser($this->user);
$testnetBalanceVal = BigNumber::_($this->testnetBalance->get());
if ($testnetBalanceVal->lt(0)) {
if ($testnetBalanceVal->lt(0)) {
return false; //balance negative
}
$transactions = Di::_()->get('Blockchain\Wallets\OffChain\Transactions');
$transactions
->setUser($this->user)
->setType('joined')
->setAmount((string) $testnetBalanceVal);
->setAmount((string) $testnetBalanceVal); // replace 1 token (one with 80 zeros) 1 * 10 to the power of 18
//////////////////////////////////////////////
$transaction = $transactions->create();
}
// validate referral and give referral prospect a token
if ($this->user->referrer && $this->user->guid != $this->user->referrer) {
$this->validator->setHash($hash);
$this->validator->setHash($hash);
if ($this->validator->validate()) {
$event = new Core\Analytics\Metrics\Event();
......@@ -189,9 +194,29 @@ class Join
->setAction('referral')
->push();
// OJMQ: instead of giving the prospect a token, isn't it better to give them +50 score too?
// TODO: get the prospect's hash and push an equivalent event for them??
// OR make a new Event.action type 'referred'? (OR alter the existing referral event)
// OJM: maybe something like this
// $event->setUserGuid((string) $this->user->referrer)
// ->setUserPhoneNumberHash($hash)
// ->setEntityGuid((string) $this->user->guid)
// ->push();
$this->referralDelegate->onReferral($this->user);
// OJM: this is what would be used if the prospect would get a token instead of +50
// // give the referral prospect a token
// $transactions = Di::_()->get('Blockchain\Wallets\OffChain\Transactions');
// $transactions
// ->setUser($this->user)
// ->setType('joined')
// ->setAmount((string) $testnetBalanceVal);
// // replace $testnetBalanceVal with 1 token (one with 80 zeros) 1 * 10 to the power of 18
$this->referralDelegate->onReferral($this->user);
}
}
} else {
......