...
 
Commits (3)
<?php
/**
* Campaign
* @author edgebal
*/
namespace Minds\Core\Boost\Campaigns;
......@@ -153,10 +149,8 @@ class Campaign implements JsonSerializable
/** @var int */
protected $completedTimestamp;
/**
* @return int|string
*/
public function getGuid()
public function getGuid(): string
{
if (!$this->urn) {
return '';
......@@ -173,7 +167,7 @@ class Campaign implements JsonSerializable
* @param User $owner
* @return Campaign
*/
public function setOwner(User $owner = null)
public function setOwner(User $owner = null): self
{
$this->ownerGuid = $owner ? $owner->guid : null;
return $this;
......@@ -181,18 +175,15 @@ class Campaign implements JsonSerializable
/**
* @param Payment $payment
* @return $this
* @return Campaign
*/
public function pushPayment(Payment $payment)
public function pushPayment(Payment $payment): self
{
$this->payments[] = $payment;
return $this;
}
/**
* @return string
*/
public function getDeliveryStatus()
public function getDeliveryStatus(): string
{
if ($this->completedTimestamp) {
return static::STATUS_COMPLETED;
......@@ -211,9 +202,9 @@ class Campaign implements JsonSerializable
/**
* @param int[] $value
* @return $this
* @return Campaign
*/
public function setNsfw($value)
public function setNsfw($value): self
{
$this->nsfw = $value;
$this->setRating(count($this->getNsfw()) > 0 ? static::RATING_OPEN : static::RATING_SAFE); // 2 = open; 1 = safe
......@@ -221,10 +212,7 @@ class Campaign implements JsonSerializable
return $this;
}
/**
* @return float
*/
public function cpm()
public function cpm(): float
{
if (!$this->impressions || $this->impressions === 0) {
return 0;
......@@ -233,19 +221,12 @@ class Campaign implements JsonSerializable
return ($this->budget / $this->impressions) * 1000;
}
/**
* @return bool
*/
public function isDelivering()
public function isDelivering(): bool
{
return $this->getDeliveryStatus() === static::STATUS_APPROVED;
}
/**
* @param $now
* @return bool
*/
public function shouldBeStarted($now)
public function shouldBeStarted(int $now): bool
{
$isCreated = $this->getDeliveryStatus() === static::STATUS_CREATED;
$started = $now >= $this->getStart() && $now < $this->getEnd();
......@@ -253,11 +234,7 @@ class Campaign implements JsonSerializable
return $isCreated && $started;
}
/**
* @param $now
* @return bool
*/
public function shouldBeCompleted($now)
public function shouldBeCompleted(int $now): bool
{
$isDelivering = $this->isDelivering();
$ended = $now >= $this->getEnd();
......@@ -266,33 +243,23 @@ class Campaign implements JsonSerializable
return $isDelivering && ($ended || $fulfilled);
}
/**
* @return bool
*/
public function hasStarted(): bool
{
return !in_array($this->getDeliveryStatus(), [static::STATUS_PENDING, static::STATUS_CREATED], true);
}
/**
* @return bool
*/
public function hasFinished(): bool
{
return in_array($this->getDeliveryStatus(), [
static::STATUS_COMPLETED,
static::STATUS_REJECTED,
static::STATUS_REVOKED,
], true);
], false);
}
/**
* @return array
*/
public function export()
public function export(bool $isGetData = false): array
{
return [
'type' => $this->type,
$data = [
'urn' => $this->urn,
'name' => $this->name,
'entity_urns' => $this->entityUrns,
......@@ -302,7 +269,6 @@ class Campaign implements JsonSerializable
'end' => $this->end,
'budget' => $this->budget,
'budget_type' => $this->budgetType,
'payments' => $this->payments,
'checksum' => $this->checksum,
'impressions' => $this->impressions,
'impressions_met' => $this->impressionsMet,
......@@ -311,9 +277,20 @@ class Campaign implements JsonSerializable
'revoked_timestamp' => $this->revokedTimestamp,
'rejected_timestamp' => $this->rejectedTimestamp,
'completed_timestamp' => $this->completedTimestamp,
'delivery_status' => $this->getDeliveryStatus(),
'cpm' => $this->cpm(),
];
if ($isGetData) {
$data['owner_guid'] = (string)$this->ownerGuid;
$data['rating'] = $this->rating;
$data['quality'] = $this->quality;
} else {
$data['type'] = $this->type;
$data['payments'] = $this->payments;
$data['delivery_status'] = $this->getDeliveryStatus();
$data['cpm'] = $this->cpm();
}
return $data;
}
/**
......@@ -327,4 +304,9 @@ class Campaign implements JsonSerializable
{
return $this->export();
}
public function getData(): array
{
return $this->export(true);
}
}
<?php
/**
* Repository
* @author edgebal
*/
namespace Minds\Core\Boost\Campaigns;
......@@ -26,9 +22,8 @@ class Repository
* Repository constructor.
* @param CassandraClient $db
*/
public function __construct(
$db = null
) {
public function __construct($db = null)
{
$this->db = $db ?: Di::_()->get('Database\Cassandra\Cql');
}
......@@ -78,8 +73,8 @@ class Repository
foreach ($rows as $row) {
$campaign = new Campaign();
$campaign
->setUrn("urn:campaign:{$row['guid']->toInt()}")
->setOwnerGuid($row['owner_guid']->toInt())
->setUrn("urn:campaign:{$row['guid']}")
->setOwnerGuid($row['owner_guid'])
->setType($row['type']);
$json_data = json_decode($row['json_data'] ?: '{}', true);
......@@ -126,35 +121,11 @@ class Repository
{
$cql = "INSERT INTO boost_campaigns (type, guid, owner_guid, json_data, delivery_status) VALUES (?, ?, ?, ?, ?)";
$json_data = [
'urn' => $campaign->getUrn(),
'owner_guid' => (string) $campaign->getOwnerGuid(),
'name' => $campaign->getName(),
'type' => $campaign->getType(),
'entity_urns' => $campaign->getEntityUrns(),
'hashtags' => $campaign->getHashtags(),
'nsfw' => $campaign->getNsfw(),
'start' => $campaign->getStart(),
'end' => $campaign->getEnd(),
'budget' => $campaign->getBudget(),
'budget_type' => $campaign->getBudgetType(),
'checksum' => $campaign->getChecksum(),
'impressions' => $campaign->getImpressions(),
'impressions_met' => $campaign->getImpressionsMet(),
'rating' => $campaign->getRating(),
'quality' => $campaign->getQuality(),
'created_timestamp' => $campaign->getCreatedTimestamp(),
'reviewed_timestamp' => $campaign->getReviewedTimestamp(),
'rejected_timestamp' => $campaign->getRejectedTimestamp(),
'revoked_timestamp' => $campaign->getRevokedTimestamp(),
'completed_timestamp' => $campaign->getCompletedTimestamp(),
];
$values = [
$campaign->getType(),
new Bigint($campaign->getGuid()),
new Bigint($campaign->getOwnerGuid()),
json_encode($json_data),
json_encode($campaign->getData()),
$campaign->getDeliveryStatus(),
];
......
......@@ -128,7 +128,7 @@ class CampaignSpec extends ObjectBehavior
->setImpressions(0)
->setBudget(0)
->cpm()
->shouldReturn(0);
->shouldReturn(0.0);
$this
->setImpressions(5000)
......@@ -156,7 +156,7 @@ class CampaignSpec extends ObjectBehavior
->shouldReturn(true);
}
public function it_should_calculate_if_be_started()
public function it_should_return_should_be_started()
{
$this
->setCreatedTimestamp(1564537097)
......@@ -172,4 +172,54 @@ class CampaignSpec extends ObjectBehavior
->callOnWrappedObject('shouldBeStarted', [ 1564611111 ])
->shouldReturn(true);
}
public function it_should_not_return_should_be_completed()
{
$this
->setCreatedTimestamp(1564537097)
->setStart(1564600000)
->setEnd(1564700000)
->callOnWrappedObject('shouldBeCompleted', [1564611111])
->shouldReturn(false);
}
public function it_should_return_should_be_completed()
{
$this
->setCreatedTimestamp(1564537097)
->setReviewedTimestamp(1564537097)
->setStart(1564600000)
->setEnd(1564700000)
->setImpressions(1000)
->setImpressionsMet(1000)
->callOnWrappedObject('shouldBeCompleted', [1564711100])
->shouldReturn(true);
}
public function it_should_not_return_has_started()
{
$this->setCreatedTimestamp(1564537097);
$this->hasStarted()->shouldReturn(false);
}
public function it_should_return_has_started()
{
$this->setCreatedTimestamp(1564537097)
->setCompletedTimestamp(1564537097)
->hasStarted()->shouldReturn(true);
}
public function it_should_not_return_has_finished()
{
$this->setCreatedTimestamp(1564537097)
->setReviewedTimestamp(1564537097)
->hasFinished()->shouldReturn(false);
}
public function it_should_return_has_finished()
{
$this->setCreatedTimestamp(1564537097)
->setCompletedTimestamp(1564537097)
->hasFinished()->shouldReturn(true);
}
}
......@@ -2,14 +2,126 @@
namespace Spec\Minds\Core\Boost\Campaigns;
use Minds\Core\Boost\Campaigns\Campaign;
use Minds\Core\Boost\Campaigns\Repository;
use Minds\Core\Data\Cassandra\Client;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use Spec\Minds\Mocks;
use Minds\Core\Data\Cassandra\Prepared;
class RepositorySpec extends ObjectBehavior
{
/** @var Client */
protected $client;
protected $boostCampaignJsonDataMock = [
'urn' => 'urn:campaign:1234',
'owner_guid' => '1001',
'name' => 'Test Campaign 1',
'type' => 'newsfeed',
'entity_urns' => [
'urn:activity:1234'
],
'hashtags' => [],
'nsfw' => null,
'start' => 0,
'end' => 0,
'budget' => 1,
'budget_type' => 'tokens',
'checksum' => '',
'impressions' => 1000,
'impressions_met' => null,
'rating' => null,
'quality' => null,
'created_timestamp' => null,
'reviewed_timestamp' => null,
'rejected_timestamp' => null,
'revoked_timestamp' => null,
'completed_timestamp' => null
];
public function let(Client $client)
{
$this->beConstructedWith($client);
$this->client = $client;
}
public function it_is_initializable()
{
$this->shouldHaveType(Repository::class);
}
public function it_should_return_a_list_of_campaigns_by_guid()
{
$rows = new Mocks\Cassandra\Rows([
[
'guid' => 1234,
'delivery_status' => '',
'json_data' => json_encode($this->boostCampaignJsonDataMock),
'owner_guid' => 1234,
'type' => 'newsfeed'
],
[
'guid' => 1235,
'delivery_status' => '',
'json_data' => json_encode($this->boostCampaignJsonDataMock),
'owner_guid' => 1235,
'type' => 'newsfeed'
],
], '');
$this->client->request(Argument::type(Prepared\Custom::class))
->shouldBeCalled()
->willReturn($rows);
$return = $this->getList(['guid' => 1234]);
$return[0]->shouldBeAnInstanceOf(Campaign::class);
$return[1]->shouldBeAnInstanceOf(Campaign::class);
}
public function it_should_not_return_a_list_if_no_args_passed()
{
$this->shouldThrow('Exception')->duringGetList();
}
public function it_should_store_a_boost_campaign()
{
$campaign = (new Campaign())
->setType('newsfeed')
->setUrn('urn:campaign:1234')
->setOwnerGuid(1234)
->setCreatedTimestamp(1569974400)
->setBudget(1)
->setBudgetType('tokens');
$this->client->request(Argument::type(Prepared\Custom::class), true)
->shouldBeCalled()
->willReturn(true);
$this->add($campaign)->shouldReturn(true);
}
public function it_should_update_a_boost_campaign()
{
$campaign = (new Campaign())
->setType('newsfeed')
->setUrn('urn:campaign:1234')
->setOwnerGuid(1234)
->setCreatedTimestamp(1569974400)
->setBudget(1)
->setBudgetType('tokens');
$this->client->request(Argument::type(Prepared\Custom::class), true)
->shouldBeCalled()
->willReturn(true);
$this->update($campaign)->shouldReturn(true);
}
public function it_should_throw_not_implemented_exception_on_delete_a_boost_campaign()
{
$this->shouldThrow('NotImplementedException')->during('delete', [new Campaign()]);
}
}