...
 
Commits (6)
......@@ -9,6 +9,7 @@ stages:
- prepare
- review
- deploy:staging
- qa
- deploy:canary
- deploy:production
......@@ -127,6 +128,17 @@ review:stop:
- master
- test/gitlab-ci
qa:manual:
stage: qa
script:
- echo "Manually approved"
when: manual
only:
refs:
- master
- test/gitlab-ci
allow_failure: false
staging:fpm:
stage: deploy:staging
image: minds/ci:latest
......
......@@ -171,8 +171,9 @@ class Factory
/**
* Builds an API response
* @param array $data
* @return true
*/
public static function response($data = [])
public static function response($data = []): bool
{
$data = array_merge([
'status' => 'success', //should success be assumed?
......@@ -184,6 +185,8 @@ class Factory
header('Content-type: application/json');
echo json_encode($data);
return true;
}
/**
......
<?php
namespace Minds\Controllers\api\v2\subscriptions;
use Minds\Api\Factory;
use Minds\Core\Di\Di;
use Minds\Core\Session;
use Minds\Interfaces;
/**
* Incoming subscritions
*/
class incoming implements Interfaces\Api
{
public function get($pages): bool
{
if (!isset($pages[0])) {
return $this->getSingle($pages[0]);
} else {
return $this->getList($pages[0]);
}
}
/**
* Return a single request
* @param string $subscriberGuid
* @return void
*/
private function getSingle(string $subscriberGuid): bool
{
// Return a single request
$manager = Di::_()->get('Subscriptions\Requests\Manager');
// Construct URN on the fly
$urn = "urn:subscription-request:" . implode('-', [ Session::getLoggedInUserGuid(), $subscriberGuid ]);
$request = $manager->get($urn);
if (!$request || $request->getPublisherGuid() != Session::getLoggedInUserGuid()) {
return Factory::response([
'status' => 'error',
'message' => 'Not found',
]);
}
return Factory::response([
'request' => $request->export(),
]);
}
/**
* Return a list of subscription requests
* @return bool
*/
private function getList(): bool
{
// Return a list of subscription requests
$manager = Di::_()->get('Subscriptions\Requests\Manager');
$requests = $manager->getIncomingList(Session::getLoggedInUserGuid(), []);
return Factory::response([
'requests' => Factory::exportable($requests),
'next' => $requests->getPagingToken(),
]);
}
public function post($pages)
{
// Void
return Factory::response([]);
}
public function put($pages)
{
// Accept / Deny
$manager = Di::_()->get('Subscriptions\Requests\Manager');
// Construct URN on the fly
$subscriberGuid = $pages[0];
$urn = "urn:subscription-request:" . implode('-', [ Session::getLoggedInUserGuid(), $subscriberGuid ]);
$request = $manager->get($urn);
if (!$request || $request->getPublisherGuid() != Session::getLoggedInUserGuid()) {
return Factory::response([
'status' => 'error',
'message' => 'Not found',
]);
}
try {
switch ($pages[1]) {
case "accept":
$manager->accept($request);
break;
case "decline":
$manager->decline($request);
break;
}
} catch (\Exception $e) {
return Factory::response([
'status' => 'error',
'message' => $e->getMessage(),
]);
}
return Factory::response([]);
}
public function delete($pages)
{
// Void
return Factory::response([]);
}
}
<?php
namespace Minds\Controllers\api\v2\subscriptions;
use Minds\Api\Factory;
use Minds\Core\Di\Di;
use Minds\Core\Session;
use Minds\Core\Subscriptions\Requests\SubscriptionRequest;
use Minds\Entities\Factory as EntitiesFactory;
use Minds\Interfaces;
/**
* Outgoing subscritions
*/
class outgoing implements Interfaces\Api
{
public function get($pages): bool
{
if (isset($pages[0])) {
return $this->getSingle($pages[0]);
} else {
return $this->getList();
}
}
/**
* Return a single request
* @param string $publisherGuid
* @return void
*/
private function getSingle(string $publisherGuid): bool
{
// Return a single request
$manager = Di::_()->get('Subscriptions\Requests\Manager');
// Construct URN on the fly
$urn = "urn:subscription-request:" . implode('-', [ $publisherGuid, Session::getLoggedInUserGuid() ]);
$request = $manager->get($urn);
if (!$request || $request->getSubscriberGuid() != Session::getLoggedInUserGuid()) {
return Factory::response([
'status' => 'error',
'message' => 'Not found',
]);
}
return Factory::response([
'request' => $request->export(),
]);
}
/**
* Return a list of subscription requests
* @return bool
*/
private function getList(): bool
{
return Factory::response([
'requests' => [],
'next' => null,
]);
}
public function post($pages)
{
// Void
return Factory::response([]);
}
public function put($pages)
{
// Make a subscription request
$manager = Di::_()->get('Subscriptions\Requests\Manager');
$request = new SubscriptionRequest();
$request->setPublisherGuid($pages[0])
->setSubscriberGuid(Session::getLoggedInUserGuid());
try {
$manager->add($request);
} catch (\Exception $e) {
return Factory::response([
'status' => 'error',
'message' => $e->getMessage(),
]);
}
return Factory::response([]);
}
public function delete($pages)
{
// Delete a subscription request
return Factory::response([]);
}
}
......@@ -1448,6 +1448,14 @@ CREATE TABLE minds.email_campaign_logs (
ALTER TABLE minds.views ADD owner_guid text;
CREATE TABLE minds.subscription_requests (
publisher_guid bigint,
subscriber_guid bigint,
timestamp timestamp,
declined boolean,
PRIMARY KEY (publisher_guid, subscriber_guid)
);
CREATE TABLE minds.pro (
user_guid bigint,
domain text,
......
......@@ -94,14 +94,19 @@ class Manager
/**
* Subscribe to a publisher
* @param User $publisher
* @param bool $force
* @return Subscription
*/
public function subscribe($publisher)
public function subscribe($publisher, bool $force = false): ?Subscription
{
$subscription = new Subscription();
$subscription->setSubscriberGuid($this->subscriber->getGuid())
->setPublisherGuid($publisher->getGuid());
if ($publisher->getMode() === 2 && !$force) {
throw new RequiresSubscriptionRequestException();
}
if ($this->getSubscriptionsCount() >= static::MAX_SUBSCRIPTIONS) {
$this->sendNotificationDelegate->onMaxSubscriptions($subscription);
throw new TooManySubscriptionsException();
......
......@@ -14,5 +14,8 @@ class Provider extends DiProvider
$this->di->bind('Subscriptions\Manager', function ($di) {
return new Manager();
}, [ 'useFactory'=>false ]);
$this->di->bind('Subscriptions\Requests\Manager', function ($di) {
return new Requests\Manager();
}, [ 'useFactory'=>false ]);
}
}
<?php
namespace Minds\Core\Subscriptions\Requests\Delegates;
use Minds\Core\Di\Di;
use Minds\Core\Events\EventsDispatcher;
use Minds\Core\Subscriptions\Requests\SubscriptionRequest;
class NotificationsDelegate
{
/** @var EventsDispatcher */
private $eventsDispatcher;
public function __construct($eventsDispatcher = null)
{
$this->eventsDispatcher = $eventsDispatcher ?: Di::_()->get('EventsDispatcher');
}
/**
* Called when subscription request is made
* @param SubscriptionRequest $subscriptionRequest
* @return void
*/
public function onAdd(SubscriptionRequest $subscriptionRequest): void
{
$this->eventsDispatcher->trigger('notification', 'all', [
'to' => [ $subscriptionRequest->getPublisherGuid() ],
'entity' => $subscriptionRequest->getSubscriberGuid(),
'notification_view' => 'subscription_request_received',
'from' => $subscriptionRequest->getSubscriberGuid(),
'params' => [],
]);
}
/**
* Called when subscription request is accepted
* @param SubscriptionRequest $subscriptionRequest
* @return void
*/
public function onAccept(SubscriptionRequest $subscriptionRequest): void
{
$this->eventsDispatcher->trigger('notification', 'all', [
'to' => [ $subscriptionRequest->getSubscriberGuid() ],
'entity' => $subscriptionRequest->getPublisherGuid(),
'notification_view' => 'subscription_request_accepted',
'from' => $subscriptionRequest->getPublisherGuid(),
'params' => [],
]);
}
/**
* Called when subscription request is declined
* @param SubscriptionRequest $subscriptionRequest
* @return void
*/
public function onDecline(SubscriptionRequest $subscriptionRequest): void
{
$this->eventsDispatcher->trigger('notification', 'all', [
'to' => [ $subscriptionRequest->getSubscriberGuid() ],
'entity' => $subscriptionRequest->getPublisherGuid(),
'notification_view' => 'subscription_request_declined',
'from' => $subscriptionRequest->getPublisherGuid(),
'params' => [],
]);
}
}
<?php
namespace Minds\Core\Subscriptions\Requests\Delegates;
use Minds\Core\Di\Di;
use Minds\Core\EntitiesBuilder;
use Minds\Core\Subscriptions\Manager as SubscriptionsManager;
use Minds\Core\Subscriptions\Requests\SubscriptionRequest;
class SubscriptionsDelegate
{
/** @var SubscriptionsManager */
private $subscriptionsManager;
/** @var EntitiesBuilder */
private $entitiesBuilder;
public function __construct($subscriptionsManager = null, $entitiesBuilder = null)
{
$this->subscriptionsManager = $subscriptionsManager ?? Di::_()->get('Subscriptions\Manager');
$this->entitiesBuilder = $entitiesBuilder ?? Di::_()->get('EntitiesBuilder');
}
/**
* Called when subscription request is accepted
* @param SubscriptionRequest $subscriptionRequest
* @return void
*/
public function onAccept(SubscriptionRequest $subscriptionRequest): void
{
$subscriber = $this->entitiesBuilder->single($subscriptionRequest->getSubscriberGuid());
$publisher = $this->entitiesBuilder->single($subscriptionRequest->getPublisherGuid());
$this->subscriptionsManager->setSubscriber($subscriber);
$this->subscriptionsManager->subscribe($publisher, true);
}
}
<?php
/**
* Subscriptions Requests Manager
*/
namespace Minds\Core\Subscriptions\Requests;
use Minds\Core\Subscriptions\Requests\Delegates\NotificationsDelegate;
use Minds\Core\Subscriptions\Requests\Delegates\SubscriptionsDelegate;
use Minds\Core\EntitiesBuilder;
use Minds\Core\Di\Di;
use Minds\Common\Repository\Response;
use Minds\Entities\User;
class Manager
{
/** @var Repository */
private $repository;
/** @var NotificationsDelegate */
private $notificationsDelegate;
/** @var SubscriptionsDelegate */
private $subscriptionsDelegate;
/** @var EntitiesBuilder */
private $entitiesBuilder;
public function __construct($repository = null, $notificationsDelegate = null, $subscriptionsDelegate = null, $entitiesBuilder = null)
{
$this->repository = $repository ?? new Repository();
$this->notificationsDelegate = $notificationsDelegate ?? new NotificationsDelegate;
$this->subscriptionsDelegate = $subscriptionsDelegate ?? new SubscriptionsDelegate;
$this->entitiesBuilder = $entitiesBuilder ?? Di::_()->get('EntitiesBuilder');
}
/**
* Return a list of incoming subscription requests
* @param string $userGuid
* @param array $opts
* @return Response
*/
public function getIncomingList(string $userGuid, array $opts = []): Response
{
$opts = array_merge([
'hydrate' => true,
], $opts);
$opts['publisher_guid'] = $user_guid;
$response = $this->repository->getList($opts);
if ($opts['hydrate']) {
foreach ($response as $i => $request) {
$request->setSubscriber($this->entitiesBuilder->single($request->getSubscriberGuid()));
}
}
return $response;
}
/**
* Return a subscription request
* @param string $urn
* @return SubscriptionRequest
*/
public function get(string $urn): ?SubscriptionRequest
{
return $this->repository->get($urn);
}
/**
* Add a subscription request
* @param SubscriptionRequest $subscriptionRequest
* @return bool
*/
public function add(SubscriptionRequest $subscriptionRequest): bool
{
// Check if exists
$existing = $this->get($subscriptionRequest->getUrn());
if ($existing) {
throw new SubscriptionRequestExistsException();
}
// Check if the user exists
$publisher = $this->entitiesBuilder->single($subscriptionRequest->getPublisherGuid());
if (!$publisher || !$publisher instanceof User) {
throw new SubscriptionRequestChannelDoesntExist();
}
$this->repository->add($subscriptionRequest);
$this->notificationsDelegate->onAdd($subscriptionRequest);
return true;
}
/**
* Accept a subscription request
* @param SubscriptionRequest $subscriptionRequest
* @return bool
*/
public function accept(SubscriptionRequest $subscriptionRequest): bool
{
// Check if exists
$existing = $this->get($subscriptionRequest->getUrn());
if (!$existing) {
throw new SubscriptionRequestDoesntExistException();
}
if ($existing->isDeclined()) {
throw new SubscriptionRequestAlreadyCompletedException();
}
$this->repository->delete($subscriptionRequest);
$this->notificationsDelegate->onAccept($subscriptionRequest);
$this->subscriptionsDelegate->onAccept($subscriptionRequest);
return true;
}
/**
* Decline a subscription request
* @param SubscriptionRequest $subscriptionRequest
* @return bool
*/
public function decline(SubscriptionRequest $subscriptionRequest): bool
{
// Check if exists
$existing = $this->get($subscriptionRequest->getUrn());
if (!$existing) {
throw new SubscriptionRequestDoesntExistException();
}
if ($existing->isDeclined()) {
throw new SubscriptionRequestAlreadyCompletedException();
}
$subscriptionRequest->setDeclined(true);
$this->repository->update($subscriptionRequest);
$this->notificationsDelegate->onDecline($subscriptionRequest);
return true;
}
}
<?php
/**
* Subscriptions Requests Repository
*/
namespace Minds\Core\Subscriptions\Requests;
use Minds\Core\Di\Di;
use Minds\Core\Data\Cassandra\Client;
use Minds\Core\Data\Cassandra\Prepared;
use Minds\Common\Repository\Response;
use Minds\Common\Urn;
use Cassandra\Timestamp;
use Cassandra\Bigint;
class Repository
{
/** @var Client */
private $db;
public function __construct($db = null)
{
$this->db = $db ?? Di::_()->get('Database\Cassandra\Cql');
}
/**
* Return a list of subscription requests
* @param array $opts
* @return Response
*/
public function getList(array $opts = []): Response
{
$opts = array_merge([
'publisher_guid' => null,
'show_declined' => false,
'limit' => 5000,
'token' => '',
], $opts);
if (!$opts['publisher_guid']) {
throw new \Exception('publisher_guid not set');
}
$prepared = new Prepared\Custom();
$prepared->query(
"SELECT * FROM subscription_requests
WHERE publisher_guid = ?",
[
new Bigint($opts['publisher_guid']),
]
);
$result = $this->db->request($prepared);
$response = new Response;
foreach ($result as $row) {
$subscriptionRequest = new SubscriptionRequest();
$subscriptionRequest
->setPublisherGuid((string) $row['publisher_guid'])
->setSubscriberGuid((string) $row['subscriber_guid'])
->setTimestampMs((int) $row['timestamp']->time())
->setDeclined((bool) $row['declined']);
if ($subscriptionRequest->isDeclined() && !$opts['show_declined']) {
continue;
}
$response[] = $subscriptionRequest;
}
return $response;
}
/**
* Return a single subscription request from a urn
* @param string $urn
* @return SubscriptionRequest
*/
public function get(string $urn): ?SubscriptionRequest
{
$urn = new Urn($urn);
list($publisherGuid, $subscriberGuid) = explode('-', $urn->getNss());
$prepared = new Prepared\Custom();
$prepared->query(
"SELECT * FROM subscription_requests
WHERE publisher_guid = ?
AND subscriber_guid = ?",
[
new Bigint($publisherGuid),
new Bigint($subscriberGuid),
]
);
$result = $this->db->request($prepared);
if (!$result) {
return null;
}
$row = $result[0];
if (!$row) {
return null;
}
$subscriptionRequest = new SubscriptionRequest();
$subscriptionRequest
->setPublisherGuid((string) $row['publisher_guid'])
->setSubscriberGuid((string) $row['subscriber_guid'])
->setTimestampMs((int) $row['timestamp']->time())
->setDeclined((bool) $row['declined']);
return $subscriptionRequest;
}
/**
* Add a subscription request
* @param SubscriptionRequest $subscriptionRequest
* @return bool
*/
public function add(SubscriptionRequest $subscriptionRequest): bool
{
$statement = "INSERT INTO subscription_requests
(publisher_guid, subscriber_guid, timestamp)
VALUES
(?, ?, ?)
IF NOT EXISTS";
$values = [
new Bigint($subscriptionRequest->getPublisherGuid()),
new Bigint($subscriptionRequest->getSubscriberGuid()),
new Timestamp($subscriptionRequest->getTimestampMs() ?? round(microtime(true) * 1000)),
];
$prepared = new Prepared\Custom();
$prepared->query($statement, $values);
return (bool) $this->db->request($prepared);
}
/**
* Update a subscription request
* @param SubscriptionRequest $subscriptionRequest
* @param array $fields
* @return bool
*/
public function update(SubscriptionRequest $subscriptionRequest, array $field = []): bool
{
$statement = "UPDATE subscription_requests
SET declined = ?
WHERE publisher_guid = ?
AND subscriber_guid = ?";
$values = [
$subscriptionRequest->isDeclined(),
new Bigint($subscriptionRequest->getPublisherGuid()),
new Bigint($subscriptionRequest->getSubscriberGuid()),
];
$prepared = new Prepared\Custom();
$prepared->query($statement, $values);
return (bool) $this->db->request($prepared);
}
/**
* Delete a subscription request
* @param SubscriptionRequest $subscriptionRequest
* @return bool
*/
public function delete(SubscriptionRequest $subscriptionRequest): bool
{
$statement = "DELETE FROM subscription_requests
WHERE publisher_guid = ?
AND subscriber_guid = ?";
$values = [
new Bigint($subscriptionRequest->getPublisherGuid()),
new Bigint($subscriptionRequest->getSubscriberGuid()),
];
$prepared = new Prepared\Custom();
$prepared->query($statement, $values);
return (bool) $this->db->request($prepared);
}
}
<?php
/**
* SubscriptionRequest Model
*/
namespace Minds\Core\Subscriptions\Requests;
use Minds\Entities\User;
use Minds\Traits\MagicAttributes;
/**
* @method SubscriptionRequest setPublisherGuid(string $publisherGuid)
* @method string getPublisherGuid()
* @method SubscriptionRequest setPublisher(User $user)
* @method User getPublisher()
* @method SubscriptionRequest setSubscriberGuid(string $subscriberGuid)
* @method string getSubscriberGuid()
* @method SubscriptionRequest setSubscriber(User $subscriber)
* @method User getSubscriber()
* @method SubscriptionRequest setDeclined(bool $declined)
* @method bool getDeclined()
* @method SubscriptionRequest setTimestampMs(int $timestampMs)
* @method int getTimestampMs()
*/
class SubscriptionRequest
{
use MagicAttributes;
/** @var string */
private $publisherGuid;
/** @var User */
private $publisher;
/** @var string */
private $subscriberGuid;
/** @var User */
private $subscriber;
/** @var bool */
private $declined = false;
/** @var int */
private $timestampMs;
/**
* @return string
*/
public function getUrn(): string
{
return "urn:subscription-request:" . implode('-', [ $this->publisherGuid, $this->subscriberGuid ]);
}
/**
* Export
* @return array
*/
public function export(): array
{
return [
'publisher_guid' => (string) $this->publisherGuid,
'publisher' => $this->publisher ? $this->publisher->export() : null,
'subscriber_guid' => (string) $this->subscriberGuid,
'subscriber' => $this->subscriber ? $this->subscriber->export() : null,
'declined' => (bool) $this->declined,
'timestamp_ms' => $this->timestampMs,
'timestamp_sec' => round($this->timestampMs / 1000),
];
}
}
<?php
namespace Minds\Core\Subscriptions\Requests;
use Exception;
class SubscriptionRequestAlreadyCompletedException extends Exception
{
/** @var string */
protected $message = "A subscription request was accepted/declined but has already been actioned.";
}
<?php
namespace Minds\Core\Subscriptions\Requests;
use Exception;
class SubscriptionRequestChannelDoesntExist extends Exception
{
/** @var string */
protected $message = "A subscription request was made to a channel that doesnt exist";
}
<?php
namespace Minds\Core\Subscriptions\Requests;
use Exception;
class SubscriptionRequestDoesntExistException extends Exception
{
/** @var string */
protected $message = "A subscription request currently does not exist, but was interacted with";
}
<?php
namespace Minds\Core\Subscriptions\Requests;
use Exception;
class SubscriptionRequestExistsException extends Exception
{
/** @var string */
protected $message = "A subscription request already exists but tried to be created.";
}
<?php
namespace Spec\Minds\Core\Subscriptions\Requests\Delegates;
use Minds\Core\Subscriptions\Requests\Delegates\SubscriptionsDelegate;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class SubscriptionsDelegateSpec extends ObjectBehavior
{
public function it_is_initializable()
{
$this->shouldHaveType(SubscriptionsDelegate::class);
}
}
<?php
namespace Spec\Minds\Core\Subscriptions\Requests;
use Minds\Core\Subscriptions\Requests\Manager;
use Minds\Core\Subscriptions\Requests\Repository;
use Minds\Core\Subscriptions\Requests\SubscriptionRequest;
use Minds\Core\Subscriptions\Requests\Delegates;
use Minds\Core\EntitiesBuilder;
use Minds\Entities\User;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class ManagerSpec extends ObjectBehavior
{
private $repository;
private $notificationsDelegate;
private $subscriptionsDelegate;
private $entitiesBuilder;
public function let(
Repository $repository,
Delegates\NotificationsDelegate $notificationsDelegate,
Delegates\SubscriptionsDelegate $subscriptionsDelegate,
EntitiesBuilder $entitiesBuilder
) {
$this->beConstructedWith($repository, $notificationsDelegate, $subscriptionsDelegate, $entitiesBuilder);
$this->repository = $repository;
$this->notificationsDelegate = $notificationsDelegate;
$this->subscriptionsDelegate = $subscriptionsDelegate;
$this->entitiesBuilder = $entitiesBuilder;
}
public function it_is_initializable()
{
$this->shouldHaveType(Manager::class);
}
public function it_should_add_a_request()
{
$subscriptionRequest = new SubscriptionRequest();
$subscriptionRequest->setPublisherGuid(123)
->setSubscriberGuid(456);
$this->entitiesBuilder->single(123)
->willReturn(new User);
$this->repository->get("urn:subscription-request:123-456")
->willReturn(null);
$this->repository->add($subscriptionRequest)
->willReturn(true);
$this->notificationsDelegate->onAdd($subscriptionRequest)
->shouldBeCalled();
$this->add($subscriptionRequest)
->shouldBe(true);
}
public function it_should_accept_a_request()
{
$subscriptionRequest = new SubscriptionRequest();
$subscriptionRequest->setPublisherGuid(123)
->setSubscriberGuid(456);
$this->repository->get("urn:subscription-request:123-456")
->willReturn($subscriptionRequest);
$this->repository->delete(Argument::any())
->willReturn(true);
$this->notificationsDelegate->onAccept($subscriptionRequest)
->shouldBeCalled();
$this->subscriptionsDelegate->onAccept($subscriptionRequest)
->shouldBeCalled();
$this->accept($subscriptionRequest)
->shouldBe(true);
}
public function it_should_decline_a_request()
{
$subscriptionRequest = new SubscriptionRequest();
$subscriptionRequest->setPublisherGuid(123)
->setSubscriberGuid(456);
$this->repository->get("urn:subscription-request:123-456")
->willReturn($subscriptionRequest);
$this->repository->update(Argument::that(function ($sr) {
return $sr->isDeclined() === true;
}))
->willReturn(true);
$this->notificationsDelegate->onDecline($subscriptionRequest)
->shouldBeCalled();
$this->decline($subscriptionRequest)
->shouldBe(true);
}
}
<?php
namespace Spec\Minds\Core\Subscriptions\Requests;
use Minds\Core\Subscriptions\Requests\Repository;
use Minds\Core\Subscriptions\Requests\SubscriptionRequest;
use Minds\Core\Data\Cassandra\Client;
use Spec\Minds\Mocks\Cassandra\Rows;
use Cassandra\Timestamp;
use Cassandra\Bigint;
use Cassandra\Boolean;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
class RepositorySpec extends ObjectBehavior
{
private $db;
public function let(Client $db)
{
$this->beConstructedWith($db);
$this->db = $db;
}
public function it_is_initializable()
{
$this->shouldHaveType(Repository::class);
}
public function it_should_get_a_request_from_a_urn()
{
$this->db->request(Argument::that(function ($prepared) {
$query = $prepared->build();
return $query['values'][0]->value() == '123'
&& $query['values'][1]->value() == '456';
}))
->willReturn(new Rows([
[
'publisher_guid' => '123',
'subscriber_guid' => '456',
'timestamp' => new Timestamp(time()),
'declined' => null,
]
], 'next-page-token'));
$subscriptionRequest = $this->get("urn:subscription-request:123-456");
$subscriptionRequest->getPublisherGuid()
->shouldBe('123');
$subscriptionRequest->getSubscriberGuid()
->shouldBe('456');
}
public function it_should_get_a_list_of_requests()
{
$this->db->request(Argument::that(function ($prepared) {
$query = $prepared->build();
return $query['values'][0]->value() == '123';
}))
->willReturn(new Rows([
[
'publisher_guid' => new Bigint(123),
'subscriber_guid' => new Bigint(456),
'timestamp' => new Timestamp(time()),
'declined' => null,
],
[
'publisher_guid' => new Bigint('1789'),
'subscriber_guid' => new Bigint('1123'),
'timestamp' => new Timestamp(time()),
'declined' => true,
]
], 'next-page-token'));
$response = $this->getList([
'publisher_guid' => '123',
'show_declined' => true,
]);
$response[0]->getPublisherGuid()
->shouldBe('123');
$response[0]->getSubscriberGuid()
->shouldBe('456');
$response[1]->getPublisherGuid()
->shouldBe('1789');
$response[1]->getSubscriberGuid()
->shouldBe('1123');
$response[1]->isDeclined()
->shouldBe(true);
}
public function it_should_add_to_repository()
{
$subscriptionRequest = new SubscriptionRequest();
$subscriptionRequest->setPublisherGuid('123')
->setSubscriberGuid('456')
->setTimestampMs(1568711904123);
$this->db->request(Argument::that(function ($prepared) {
$values = $prepared->build()['values'];
return $values[0]->value() === '123'
&& $values[1]->value() === '456'
&& $values[2]->time() === 1568711904123;
}))
->willReturn(true);
$this->add($subscriptionRequest)
->shouldReturn(true);
}
public function it_should_update_a_request()
{
$subscriptionRequest = new SubscriptionRequest();
$subscriptionRequest->setPublisherGuid('123')
->setSubscriberGuid('456')
->setDeclined(true);
$this->db->request(Argument::that(function ($prepared) {
$values = $prepared->build()['values'];
return $values[0] == true
&& $values[1]->value() === '123'
&& $values[2]->value() === '456';
}))
->willReturn(true);
$this->update($subscriptionRequest)
->shouldReturn(true);
}
public function it_should_delete_a_request()
{
$subscriptionRequest = new SubscriptionRequest();
$subscriptionRequest->setPublisherGuid('123')
->setSubscriberGuid('456');
$this->db->request(Argument::that(function ($prepared) {
$values = $prepared->build()['values'];
return $values[0]->value() === '123'
&& $values[1]->value() === '456';
}))
->willReturn(true);
$this->delete($subscriptionRequest)
->shouldReturn(true);
}
}