...
 
Commits (11)
......@@ -6,6 +6,7 @@ use Minds\Interfaces;
use Minds\Helpers;
use Minds\Core\Security;
use Minds\Core\Session;
use Minds\Core\Di\Di;
/**
* API Factory
......
......@@ -29,6 +29,14 @@ class Analytics extends Cli\Controller implements Interfaces\CliControllerInterf
$this->out('Prints the counts of a user');
$this->out('--from={timestamp in milliseconds} the day to start count. Default is yesterday');
$this->out('--guid={user guid} REQUIRED the user to aggregate');
case 'addActivityDay':
$this->out('Add an activity day for user');
$this->out('--user_guid={user guid} The user to add for');
$this->out('--timestamp={timestamp in seconds} Timestamp of the interval start');
case 'deleteActivityDay':
$this->out('Delete an activity day for user');
$this->out('--user_guid={user guid} The user to add for');
$this->out('--timestamp={timestamp in seconds} Timestamp of the interval start');
// no break
default:
$this->out('Syntax usage: cli analytics <type>');
......@@ -168,18 +176,39 @@ class Analytics extends Cli\Controller implements Interfaces\CliControllerInterf
$this->out('Done');
}
public function fakeActivity()
public function addActivityDay()
{
$user_guid = $this->getOpt('user_guid');
$timestamp = $this->getOpt('timestamp_ms') ?? time() * 1000;
$timestamp = $this->getOpt('timestamp') ?? time();
$event = new Core\Analytics\Metrics\Event();
$event->setType('action')
->setProduct('platform')
->setUserGuid((string)$user_guid)
->setTimestamp($timestamp)
->setTimestamp($timestamp * 1000)
->setAction('active');
$this->out(print_r($event->push(), true));
$msg = $event->push() ? 'Added' : 'Error';
$this->out($msg);
}
public function deleteActivityDay()
{
$user_guid = $this->getOpt('user_guid');
$timestamp = $this->getOpt('timestamp');
if (empty($user_guid) || empty($timestamp)) {
$this->out('user_guid and timestamp are required');
}
$event = new Core\Analytics\Metrics\Event();
$event->setType('action')
->setProduct('platform')
->setUserGuid((string)$user_guid)
->setTimestamp($timestamp * 1000)
->setAction('active');
$msg = $event->delete() ? 'Deleted' : 'Error';
$this->out($msg);
}
}
......@@ -13,6 +13,7 @@ use Minds\Interfaces;
use Minds\Entities;
use Minds\Api\Factory;
use Minds\Common\ChannelMode;
use Minds\Core\Di\Di;
use ElggFile;
class channel implements Interfaces\Api
......@@ -46,6 +47,10 @@ class channel implements Interfaces\Api
return Factory::response(['status'=>'error', 'message'=>'The user is banned']);
}
Di::_()->get('Referrals\Cookie')
->setEntity($user)
->create();
$user->fullExport = true; //get counts
$user->exportCounts = true;
$return = Factory::exportable([$user]);
......
......@@ -67,14 +67,37 @@ class register implements Interfaces\Api, Interfaces\ApiIgnorePam
]);
}
if (!(isset($_POST['parentId']) || isset($_POST['previousUrl']) || isset($_SERVER['HTTP_APP_VERSION']))) {
return Factory::response(['status'=>'error', 'message' => "Please refresh your browser or update you app. We don't recognise your platform."]);
}
$user = register_user($_POST['username'], $_POST['password'], $_POST['username'], $_POST['email'], false);
$guid = $user->guid;
// Hacky, move to service soon!
$hasSignupTags = false;
if (isset($_COOKIE['mexp'])) {
$manager = Core\Di\Di::_()->get('Experiments\Manager');
$bucket = $manager->getBucketForExperiment('Homepage200619');
$user->expHomepage200619 = $bucket->getId();
}
if (isset($_POST['parentId'])) {
$user->signupParentId = (string) $_POST['parentId'];
$hasSignupTags = true;
}
if (isset($_POST['previousUrl'])) {
$user->signupPreviousUrl = (string) $_POST['previousUrl'];
$hasSignupTags = true;
}
if (isset($_SERVER['HTTP_APP_VERSION'])) {
$user->signupParentId = 'mobile-native';
$hasSignupTags = true;
}
if ($hasSignupTags) {
$user->save();
} else {
return Factory::response(['status'=>'error', 'message' => "Please refresh your browser or update you app. We don't recognise your platform."]);
}
$params = [
......
......@@ -113,6 +113,10 @@ class views implements Interfaces\Api
error_log($e);
}
Di::_()->get('Referrals\Cookie')
->setEntity($activity)
->create();
break;
}
......
......@@ -30,6 +30,13 @@ class connect implements Interfaces\Api
]);
}
if (!$account) {
return Factory::response([
'status' => 'error',
'message' => 'Account not found',
]);
}
return Factory::response([
'account' => $account->export(),
]);
......
......@@ -27,6 +27,7 @@ use Minds\Core;
*/
class Event
{
/** @var Core\Data\ElasticSearch\Client */
private $elastic;
private $index = 'minds-metrics-';
protected $data;
......@@ -40,7 +41,6 @@ class Event
public function setUserGuid($guid)
{
$this->data['user_guid'] = (string) $guid;
return $this;
}
......@@ -72,21 +72,24 @@ class Event
$this->data['platform'] = $platform;
}
$prepared = new Core\Data\ElasticSearch\Prepared\Index();
$prepared->query([
$query = [
'body' => $this->data,
'index' => $this->index,
'type' => $this->data['type'],
//'id' => $data['guid'],
'client' => [
'timeout' => 2,
'connect_timeout' => 1,
],
]);
'type' => $this->data['type']
];
/* Generate index for active days so we can use delete API in testing */
if ($this->data['action'] === 'active') {
$query['id'] = $this->getId();
}
$prepared = new Core\Data\ElasticSearch\Prepared\Index();
$prepared->query($query);
try {
return $this->elastic->request($prepared);
} catch (\Exception $e) {
//TODO: Should we be silently suppressing this exception???
}
}
......@@ -144,4 +147,34 @@ class Event
return '';
}
public function delete(): bool
{
$query = [
'index' => $this->index,
'type' => $this->data['type'],
'id' => $this->getId()
];
$prepared = new Core\Data\ElasticSearch\Prepared\Delete();
$prepared->query($query);
try {
$this->elastic->request($prepared);
} catch (\Exception $e) {
error_log('Error deleting: ' . $e->getMessage());
return false;
}
return true;
}
public function getId(): string
{
$uniques = [
$this->data['type'],
$this->data['@timestamp'],
$this->data['user_guid']
];
return implode('-', $uniques);
}
}
......@@ -170,6 +170,11 @@ class Manager
*/
public function isBoostLimitExceededBy($boost)
{
//onchain boosts allowed
if ($boost->isOnChain()) {
return false;
}
//get offchain boosts
$offchain = $this->getOffchainBoosts($boost);
......
......@@ -65,6 +65,6 @@ class Manager
return null;
}
return (string) $this->s3->createPresignedRequest($cmd, '+20 minutes')->getUri();
return (string) $this->s3->createPresignedRequest($cmd, '+48 hours')->getUri();
}
}
......@@ -14,5 +14,8 @@ class Provider extends DiProvider
$this->di->bind('Referrals\Manager', function ($di) {
return new Manager();
}, [ 'useFactory'=>false ]);
$this->di->bind('Referrals\Cookie', function ($di) {
return new ReferralCookie();
}, [ 'useFactory'=>true ]);
}
}
<?php
/**
* Referral Cookie
*/
namespace Minds\Core\Referrals;
use Minds\Entities\User;
use Minds\Common\Cookie;
use Zend\Diactoros\ServerRequest;
class ReferralCookie
{
/** @var Request */
private $request;
/** @var Entity */
private $entity;
/**
* Set the router request
* @param Request $request
* @param Response $response
* @return $this
*/
public function withRouterRequest(ServerRequest $request): ReferralCookie
{
$this->request = $request;
return $this;
}
/**
* Set Entity
* @param Entity|User $entity
* @return $this
*/
public function setEntity($entity): ReferralCookie
{
$this->entity = $entity;
return $this;
}
/**
* Set the referral cookie
* @return void
*/
public function create(): void
{
if (!$this->request) {
return;
}
$cookies = $this->request->getCookieParams();
$params = $this->request->getQueryParams();
if (isset($cookies['referrer'])) {
return; // Do not override previosuly set cookie
}
$referrerGuid = null;
if (isset($params['referrer'])) { // Is a referrer param set in the request?
$referrerGuid = $params['referrer'];
} elseif ($this->entity) { // Was an entity set?
switch (get_class($this->entity)) {
case User::class:
$referrerGuid = $this->entity->getGuid();
break;
default:
$referrerGuid = $this->entity->getOwnerGuid();
}
}
if ($referrerGuid) {
$cookie = new Cookie();
$cookie
->setName('referrer')
->setValue($referrerGuid)
->setExpire(time() + (60 * 60 * 24)) //valid for 24 hours
->setPath('/')
->create();
$_COOKIE['referrer'] = $referrerGuid; // TODO: replace with Response object later
}
}
}
......@@ -109,9 +109,10 @@ class Router
Di::_()->get('Email\RouterHooks')
->withRouterRequest($request);
if (isset($_GET['referrer'])) {
Helpers\Campaigns\Referrals::register($_GET['referrer']);
}
Di::_()->get('Referrals\Cookie')
->withRouterRequest($request)
->create();
$loop = count($segments);
while ($loop >= 0) {
$offset = $loop - 1;
......
<?php
namespace Minds\Helpers\Campaigns;
use Minds\Core;
use Minds\Core\Guid;
use Minds\Common\Cookie;
use Minds\Core\Di\Di;
class Referrals
{
/**
* Registers a cookie for the referral step
* @param string $username
* @return null
* @return void
*/
public static function register($username)
public static function register($username): void
{
if (!isset($_COOKIE['referrer'])) {
$cookie = new Cookie();
$cookie
->setName('referrer')
->setValue($username)
->setExpire(time() + (60 * 60 * 24)) //valid for 24 hours
->setPath('/')
->create();
$_COOKIE['referrer'] = $username;
}
Di::_()->get('Referrals\Cookie')->create();
}
}
......@@ -370,7 +370,25 @@ class ManagerSpec extends ObjectBehavior
$this->isBoostLimitExceededBy($boost)->shouldReturn(true);
}
public function runThroughGetList($boost, $existingBoosts)
public function it_should_allow_a_user_to_boost_onchain_when_offchain_limit_reached(Boost $boost)
{
$boostArray = [];
for ($i = 0; $i < 2; $i++) {
$newBoost = new Boost();
$newBoost->setCreatedTimestamp('9999999999999999');
$newBoost->setImpressions(5001);
array_push($boostArray, $newBoost);
}
$boost->isOnChain()
->shouldBeCalled()
->willReturn(true);
Di::_()->get('Config')->set('max_daily_boost_views', 20000);
$this->isBoostLimitExceededBy($boost)->shouldReturn(false);
}
public function runThroughGetList($boost, $existingBoosts, $onchain = false)
{
$this->elasticRepository->getList([
"hydrate" => true,
......@@ -392,7 +410,11 @@ class ManagerSpec extends ObjectBehavior
$boost->getType()
->shouldBeCalled()
->willReturn('newsfeed');
$boost->isOnChain()
->shouldBeCalled()
->willReturn($onchain);
$boost->getOwnerGuid()
->shouldBeCalled()
->willReturn('123');
......
<?php
namespace Spec\Minds\Core\Referrals;
use Minds\Core\Referrals\ReferralCookie;
use Minds\Entities\User;
use Minds\Entities\Activity;
use Zend\Diactoros\ServerRequest;
use Zend\Diactoros\ServerRequestFactory;
use Zend\Diactoros\Uri;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class ReferralCookieSpec extends ObjectBehavior
{
public function it_is_initializable()
{
$this->shouldHaveType(ReferralCookie::class);
}
public function it_should_set_a_referral_cookie_from_a_referral_param()
{
$request = (new ServerRequest())->withQueryParams(['referrer' => 'mark']);
$this->withRouterRequest($request);
$this->create();
expect($_COOKIE['referrer'])
->toBe('mark');
}
public function it_should_not_set_cookie_if_already_present()
{
$_COOKIE['referrer'] = 'bill';
$request = (new ServerRequest())
->withCookieParams(['referrer' => 'bill'])
->withQueryParams(['referrer' => 'mark']);
$this->withRouterRequest($request);
$this->create();
expect($_COOKIE['referrer'])
->toBe('bill');
}
public function it_should_set_cookie_from_user_entity()
{
$user = new User();
$user->guid = 123;
$request = (new ServerRequest());
$this->withRouterRequest($request);
$this->setEntity($user);
$this->create();
expect($_COOKIE['referrer'])
->toBe(123);
}
public function it_should_set_cookie_from_activity()
{
$activity = new Activity();
$activity->guid = 123;
$activity->owner_guid = 456;
$request = (new ServerRequest());
$this->withRouterRequest($request);
$this->setEntity($activity);
$this->create();
expect($_COOKIE['referrer'])
->toBe(456);
}
public function it_should_not_allow_entity_to_override_param()
{
$activity = new Activity();
$activity->guid = 123;
$activity->owner_guid = 456;
$request = (new ServerRequest())
->withQueryParams(['referrer' => 'mark']);
;
$this->withRouterRequest($request);
$this->setEntity($activity);
$this->create();
expect($_COOKIE['referrer'])
->toBe('mark');
}
public function it_should_not_allow_entity_to_override_cookie()
{
$activity = new Activity();
$activity->guid = 123;
$activity->owner_guid = 456;
$request = (new ServerRequest())
->withCookieParams(['referrer' => 'mark']);
;
$this->withRouterRequest($request);
$this->setEntity($activity);
$this->create();
expect($_COOKIE['referrer'])
->toBe('mark');
}
}