...
 
<?php
/**
* Boost & Boost Campaigns fetch
* @author: eiennohi.
*/
namespace Minds\Controllers\api\v2\boost\fetch;
use Minds\Api\Exportable;
use Minds\Api\Factory;
use Minds\Common\Urn;
use Minds\Core\Boost\Campaigns;
use Minds\Core\Boost\Campaigns\Campaign;
use Minds\Core\Boost\Network;
use Minds\Core\Di\Di;
use Minds\Core\Feeds\FeedSyncEntity;
use Minds\Core\Session;
use Minds\Entities;
use Minds\Interfaces;
class campaigns implements Interfaces\Api
{
public function get($pages)
{
Factory::isLoggedIn();
/** @var Entities\User $currentUser */
$currentUser = Session::getLoggedinUser();
if ($currentUser->disabled_boost && $currentUser->isPlus()) {
return Factory::response([
'boosts' => [],
]);
}
// Parse parameters
$type = $pages[0] ?? 'newsfeed';
$limit = abs(intval($_GET['limit'] ?? 2));
$offset = $_GET['offset'] ?? 0;
$rating = intval($_GET['rating'] ?? $currentUser->getBoostRating());
$platform = $_GET['platform'] ?? 'other';
$quality = 0;
$sync = (bool) ($_GET['sync'] ?? true);
if ($limit === 0) {
return Factory::response([
'boosts' => [],
]);
} elseif ($sync && $limit > 500) {
$limit = 500;
} elseif (!$sync && $limit > 50) {
$limit = 50;
}
// Options specific to newly created users (<=1 hour) and iOS users
if ($platform === 'ios') {
$rating = 1; // they can only see safe content
$quality = 90;
} elseif (time() - $currentUser->getTimeCreated() <= 3600) {
$rating = 1; // they can only see safe content
$quality = 75;
}
/** @var Campaigns\Manager $manager */
$manager = Di::_()->get('Boost\Campaigns\Manager');
$data = [];
try{
$result = $manager->fetch([
'limit' => $limit,
'from' => $offset,
'rating' => $rating,
'quality' => $quality,
'type' => $type,
]);
foreach ($result as $entity) {
$feedSyncEntity = (new FeedSyncEntity())
->setGuid((string) $entity->getGuid())
->setOwnerGuid((string) $entity->getOwnerGuid());
if ($entity instanceof Campaign) {
$feedSyncEntity->setUrn($entity->getUrn());
} elseif ($entity instanceof Network\Boost) {
$feedSyncEntity->setUrn(new Urn("urn:boost:{$entity->getType()}:{$entity->getGuid()}"));
}
$data[] = $feedSyncEntity;
}
} catch(\Exception $e) {
error_log($e);
}
return Factory::response([
'boosts' => Exportable::_($data),
'load-next' => $data->getPagingToken() ?: null,
]);
}
public function post($pages)
{
return Factory::response([]);
}
public function put($pages)
{
return Factory::response([]);
}
public function delete($pages)
{
return Factory::response([]);
}
}
......@@ -46,6 +46,10 @@ use Minds\Traits\MagicAttributes;
* @method Campaign setImpressions(int $impressions)
* @method int getImpressionsMet()
* @method Campaign setImpressionsMet(int $impressionsMet)
* @method int getRating()
* @method Campaign setRating(int $value)
* @method int getQuality()
* @method Campaign setQuality(int $value)
* @method int getCreatedTimestamp()
* @method Campaign setCreatedTimestamp(int $createdTimestamp)
* @method int getReviewedTimestamp()
......@@ -124,6 +128,12 @@ class Campaign implements JsonSerializable
/** @var int */
protected $impressionsMet;
/** @var int */
protected $rating;
/** @var int */
protected $quality;
/** @var int */
protected $createdTimestamp;
......
......@@ -8,6 +8,7 @@ namespace Minds\Core\Boost\Campaigns;
use Exception;
use Minds\Common\Repository\Response;
use Minds\Core\Boost\Network\Boost;
use Minds\Core\Data\ElasticSearch\Client as ElasticSearchClient;
use Minds\Core\Data\ElasticSearch\Prepared\Search;
use Minds\Core\Data\ElasticSearch\Prepared\Update;
......@@ -48,6 +49,8 @@ class ElasticRepository
'owner_guid' => null,
'entity_urn' => null,
'state' => null,
'rating' => null,
'quality' => null,
], $opts);
$must = [];
......@@ -124,6 +127,22 @@ class ElasticRepository
];
}
if ($opts['rating']) {
$must[] = [
'term' => [
'rating' => $opts['rating']
]
];
}
if ($opts['quality']) {
$must[] = [
'term' => [
'rating' => $opts['quality']
]
];
}
if ($opts['offset']) {
$rangeKey = $opts['sort'] === 'asc' ? 'gt' : 'lt';
......@@ -181,6 +200,8 @@ class ElasticRepository
->setChecksum($doc['_source']['checksum'])
->setImpressions((int) $doc['_source']['impressions'])
->setImpressionsMet($doc['_source']['impressions_met'])
->setRating($doc['_source']['rating'])
->setQuality($doc['_source']['quality'])
->setCreatedTimestamp(((int) $doc['_source']['@timestamp']) ?: null)
->setReviewedTimestamp(((int) $doc['_source']['@reviewed']) ?: null)
->setRejectedTimestamp(((int) $doc['_source']['@rejected']) ?: null)
......@@ -196,6 +217,96 @@ class ElasticRepository
return $response;
}
public function fetch(array $opts = [])
{
$opts = array_merge([
'limit' => 24,
'from' => 0,
'rating' => null,
'quality' => null,
'type' => null,
'sort' => 'asc',
], $opts);
$must = [];
if ($opts['offset']) {
$rangeKey = $opts['sort'] === 'asc' ? 'gt' : 'lt';
$must[] = [
'range' => [
'@timestamp' => [
$rangeKey => $opts['offset'],
],
],
];
}
$prepared = new Search();
$body = [
'query' => [
'bool' => [
'must' => $must,
]
]
];
$prepared->query([
'index' => 'minds-boost,minds-boost-campaigns',
'type' => '_doc',
'body' => $body,
'from' => $opts['from'] ?? 0,
'size' => $opts['limit'],
]);
$result = $this->es->request($prepared);
$next = [];
$data = [];
foreach ($result['hits']['hits'] as $doc) {
$entity = null;
switch ($doc['index']) {
case 'minds-boost':
$entity = (new Boost())
->setGuid($doc['_id'])
->setOwnerGuid($doc['_source']['owner_guid'])
->setCreatedTimestamp($doc['_source']['@timestamp'])
->setType($doc['_source']['type']);
$next[0] = $entity->getCreatedTimestamp();
break;
case 'minds-boost-campaigns':
$entity = (new Campaign())
->setUrn("urn:campaign:{$doc['_id']}")
->setType($doc['_source']['type'])
->setOwnerGuid($doc['_source']['owner_guid'])
->setCreatedTimestamp(((int) $doc['_source']['@timestamp']) ?: null);
$next[1] = $entity->getCreatedTimestamp();
break;
default:
continue;
}
$data[] = $entity;
}
uasort($data, function ($a, $b) {
$aTime = $a instanceof Campaign ? $a->getCreatedTimestamp() : $a->getTimeCreated();
$bTime = $b instanceof Campaign ? $b->getCreatedTimestamp() : $b->getTimeCreated();
return $aTime > $bTime;
});
$data = array_slice($data, 0, $opts['limit']);
$response = new Response($data, count($data));
return $response;
}
/**
* @param Campaign $campaign
* @return bool
......@@ -226,6 +337,14 @@ class ElasticRepository
$body['doc']['impressions_met'] = $campaign->getImpressionsMet();
}
if ($campaign->getRating()) {
$body['doc']['rating'] = $campaign->getRating();
}
if ($campaign->getQuality()) {
$body['doc']['quality'] = $campaign->getQuality();
}
if ($campaign->getReviewedTimestamp()) {
$body['doc']['@reviewed'] = $campaign->getReviewedTimestamp();
}
......
......@@ -5,7 +5,6 @@
namespace Minds\Core\Boost\Campaigns;
use Minds\Core\Di\Di;
class Iterator implements \Iterator
......@@ -20,13 +19,13 @@ class Iterator implements \Iterator
protected $type = 'newsfeed';
protected $ownerGuid = null;
protected $state = null;
protected $rating = null;
protected $quality = null;
/** @var array */
protected $list = null;
public function __construct(
$manager = null
)
public function __construct($manager = null)
{
$this->manager = $manager ?: Di::_()->get('Boost\Campaigns\Manager');
}
......@@ -109,23 +108,36 @@ class Iterator implements \Iterator
return $this;
}
/**
* @param int $rating
* @return Iterator
*/
public function setRating(int $rating)
{
$this->rating = $rating;
return $this;
}
public function getList()
/**
* @param int $quality
* @return Iterator
*/
public function setQuality(int $quality)
{
$response = $this->manager->getList([
'limit' => $this->limit,
'from' => $this->from,
'offset' => $this->offset,
'type' => $this->type,
'owner_guid' => $this->ownerGuid,
'state' => $this->state,
]);
$this->quality = $quality;
return $this;
}
public function getList()
{
$response = $this->manager->getList(['limit' => $this->limit, 'from' => $this->from, 'offset' => $this->offset, 'type' => $this->type, 'owner_guid' => $this->ownerGuid, 'state' => $this->state, 'rating' => $this->rating, 'quality' => $this->quality,]);
$this->offset = $response->getPagingToken();
$this->list = $response;
}
/**
* @return Campaign
*/
public function current()
{
return current($this->list);
......
......@@ -119,6 +119,21 @@ class Manager
});
}
/**
* @param array $opts
* @return Response|null
*/
public function fetch(array $opts = [])
{
$response = null;
try {
$response = $this->elasticRepository->fetch($opts);
} catch (Exception $e) {
error_log("[BoostCampaignsManager] {$e}");
}
return $response;
}
/**
* @param $urn
* @return Campaign|null
......
......@@ -66,6 +66,8 @@ class Repository
'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(),
......
......@@ -23,17 +23,23 @@ use Minds\Traits\MagicAttributes;
* @method long getOwnerGuid()
* @method Boost setOwner()
* @method User getOwner()
*
* @method Boost setRejectedReason(int $reason)
*
* @method int getRejectedReason()
* @method Boost setRejectedReason(int $reason)
* @method int getCompletedTimestamp()
* @method Boost setCompletedTimestamp(int $ts)
* @method int getReviewedTimestamp()
* @method Boost setReviewedTimestamp(int $ts)
* @method int getRejectedTimestamp()
* @method Boost setRejectedTimestamp(int $ts)
* @method int getCreatedTimestamp()
* @method Boost setCreatedTimestamp(int $ts)
* @method int getRevokedTimestamp()
* @method Boost setRevokedTimestamp(int $ts)
* @method array getTags()
* @method Boost setTags(array $value)
* @method string getType()
* @method Boost setType(string $value)
*/
class Boost
{
......