...
 
Commits (9)
......@@ -4,7 +4,50 @@ namespace Minds\Api;
abstract class Api implements \Minds\Interfaces\Api
{
protected $accessControlAllowOrigin = ['*'];
protected $accessControlAllowHeaders = [];
protected $accessControlAllowMethods = [];
protected $defaultResponse = ['status' => 'success'];
const HTTP_CODES = [
100 => 'Continue',
101 => 'Switching Protocols',
200 => 'OK',
201 => 'Created',
202 => 'Accepted',
203 => 'Non-Authoritative Information',
204 => 'No Content',
205 => 'Reset Content',
206 => 'Partial Content',
300 => 'Multiple Choices',
301 => 'Moved Permanently',
302 => 'Moved Temporarily',
303 => 'See Other',
304 => 'Not Modified',
305 => 'Use Proxy',
400 => 'Bad Request',
401 => 'Unauthorized',
402 => 'Payment Required',
403 => 'Forbidden',
404 => 'Not Found',
405 => 'Method Not Allowed',
406 => 'Not Acceptable',
407 => 'Proxy Authentication Required',
408 => 'Request Time-out',
409 => 'Conflict',
410 => 'Gone',
411 => 'Length Required',
412 => 'Precondition Failed',
413 => 'Request Entity Too Large',
414 => 'Request-URI Too Large',
415 => 'Unsupported Media Type',
500 => 'Internal Server Error',
501 => 'Not Implemented',
502 => 'Bad Gateway',
503 => 'Service Unavailable',
504 => 'Gateway Time-out',
505 => 'HTTP Version not supported',
];
public function __construct()
{
......@@ -13,16 +56,40 @@ abstract class Api implements \Minds\Interfaces\Api
protected function sendAccessControlHeaders(): void
{
header('Access-Control-Allow-Origin: *', false);
//header("Access-Control-Allow-Headers: " . $this->accessControlAllowHeaders(), false);
//header("Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS");
$this->sendAccessControlAllowOrigin();
$this->sendAccessControlAllowHeaders();
$this->sendAccessControlAllowMethods();
}
protected function accessControlAllowHeaders(): string
protected function sendAccessControlAllowOrigin(): void
{
if (!empty($this->accessControlAllowOrigin)) {
header("Access-Control-Allow-Origin: " .
$this->parseAccessControlArray($this->accessControlAllowOrigin), false);
}
}
protected function sendAccessControlAllowHeaders(): void
{
if (!empty($this->accessControlAllowHeaders)) {
header("Access-Control-Allow-Headers: " .
$this->parseAccessControlArray($this->accessControlAllowHeaders), false);
}
}
protected function sendAccessControlAllowMethods(): void
{
if (!empty($this->accessControlAllowMethods)) {
header("Access-Control-Allow-Methods: " .
$this->parseAccessControlArray($this->accessControlAllowMethods), false);
}
}
protected function parseAccessControlArray(array $accessControlArray): string
{
$output = "";
$lastHeader = end($this->accessControlAllowHeaders);
foreach ($this->accessControlAllowHeaders as $header) {
$lastHeader = end($accessControlArray);
foreach ($accessControlArray as $header) {
$output .= $header;
if ($header !== $lastHeader) {
$output .= ",";
......@@ -34,123 +101,11 @@ abstract class Api implements \Minds\Interfaces\Api
protected function setResponseCode(int $code = 200): int
{
switch ($code) {
case 100:
$text = 'Continue';
break;
case 101:
$text = 'Switching Protocols';
break;
case 200:
$text = 'OK';
break;
case 201:
$text = 'Created';
break;
case 202:
$text = 'Accepted';
break;
case 203:
$text = 'Non-Authoritative Information';
break;
case 204:
$text = 'No Content';
break;
case 205:
$text = 'Reset Content';
break;
case 206:
$text = 'Partial Content';
break;
case 300:
$text = 'Multiple Choices';
break;
case 301:
$text = 'Moved Permanently';
break;
case 302:
$text = 'Moved Temporarily';
break;
case 303:
$text = 'See Other';
break;
case 304:
$text = 'Not Modified';
break;
case 305:
$text = 'Use Proxy';
break;
case 400:
$text = 'Bad Request';
break;
case 401:
$text = 'Unauthorized';
break;
case 402:
$text = 'Payment Required';
break;
case 403:
$text = 'Forbidden';
break;
case 404:
$text = 'Not Found';
break;
case 405:
$text = 'Method Not Allowed';
break;
case 406:
$text = 'Not Acceptable';
break;
case 407:
$text = 'Proxy Authentication Required';
break;
case 408:
$text = 'Request Time-out';
break;
case 409:
$text = 'Conflict';
break;
case 410:
$text = 'Gone';
break;
case 411:
$text = 'Length Required';
break;
case 412:
$text = 'Precondition Failed';
break;
case 413:
$text = 'Request Entity Too Large';
break;
case 414:
$text = 'Request-URI Too Large';
break;
case 415:
$text = 'Unsupported Media Type';
break;
case 500:
$text = 'Internal Server Error';
break;
case 501:
$text = 'Not Implemented';
break;
case 502:
$text = 'Bad Gateway';
break;
case 503:
$text = 'Service Unavailable';
break;
case 504:
$text = 'Gateway Time-out';
break;
case 505:
$text = 'HTTP Version not supported';
break;
default:
exit('Unknown http status code "' . htmlentities($code) . '"');
break;
if (!isset(self::HTTP_CODES[$code])) {
exit('Unknown http status code "' . htmlentities($code) . '"');
}
$text = self::HTTP_CODES[$code];
$protocol = (isset($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0');
header("${protocol} ${code} ${text}");
......@@ -164,6 +119,7 @@ abstract class Api implements \Minds\Interfaces\Api
protected function send($responseArray, int $code = 200, $jsonOptions = 0): void
{
$responseArray = array_merge($this->defaultResponse, $responseArray);
$returnString = json_encode($responseArray, $jsonOptions);
$this->sendJsonString($returnString, $code);
}
......@@ -176,49 +132,55 @@ abstract class Api implements \Minds\Interfaces\Api
echo $jsonString;
}
protected function sendInternalServerError(string $message = 'Internal Server Error'): void
protected function sendInternalServerError(): void
{
$this->sendError($message, 500);
$this->sendError(500);
}
protected function sendBadRequest(): void
{
$this->sendError('Bad Request', 400);
$this->sendError(400);
}
protected function sendNotImplemented(): void
{
$this->sendError('Not Implemented', 501);
$this->sendError(501);
}
protected function sendNotModified(string $message = 'Not Modified'): void
protected function sendNotModified(): void
{
$this->sendError($message, 304);
$this->sendError(304);
}
protected function sendNotAcceptable(string $message = 'Not Acceptable'): void
protected function sendNotAcceptable(): void
{
$this->sendError($message, 406);
$this->sendError(406);
}
protected function sendUnauthorised(): void
{
$this->sendError('Unauthorised', 401);
$this->sendError(401);
}
protected function sendSuccess(): void
{
$this->send(['status' => 'success']);
$this->send([]);
}
protected function sendError(string $message, int $code = 406): void
protected function sendError(int $code = 406, string $message = null): void
{
if (is_null($message)) {
$message = self::HTTP_CODES[$code];
}
$this->send($this->buildError($message), $code);
}
protected function buildError(string $message): array
{
return ["message" => $message];
return [
'status' => 'error',
'message' => $message
];
}
public function get($pages): void
......
......@@ -10,6 +10,7 @@ use Minds\Core\Di\Di;
use Minds\Entities;
use Minds\Helpers\Counters;
use Minds\Interfaces;
use Minds\Core\Boost;
class views implements Interfaces\Api
{
......@@ -23,10 +24,10 @@ class views implements Interfaces\Api
$viewsManager = new Core\Analytics\Views\Manager();
/** @var Core\Boost\Campaigns\Manager $campaignsManager */
$campaignsManager = Di::_()->get('Boost\Campaigns\Manager');
$campaignsManager = Di::_()->get(Boost\Campaigns\Manager::getDiAlias());
/** @var Core\Boost\Campaigns\Metrics $campaignsMetricsManager */
$campaignsMetricsManager = Di::_()->get('Boost\Campaigns\Metrics');
$campaignsMetricsManager = Di::_()->get(Boost\Campaigns\Metrics::getDiAlias());
switch ($pages[0]) {
case 'boost':
......
......@@ -29,6 +29,8 @@ class preview extends Api
/** @var Stats $statsManager */
$statsManager = Di::_()->get('Boost\Campaigns\Stats');
$this->send($statsManager->setCampaign($campaign)->getAll());
$this->send([
'preview' => $statsManager->setCampaign($campaign)->getAll()
]);
}
}
<?php
/**
* Boost Fetch
*
* @version 2
* @author emi
*
*/
namespace Minds\Controllers\api\v2\boost;
use Minds\Api\Exportable;
use Minds\Common\Urn;
use Minds\Core;
use Minds\Core\Di\Di;
use Minds\Helpers;
use Minds\Entities;
use Minds\Entities\User;
use Minds\Interfaces;
use Minds\Api\Factory;
class feed implements Interfaces\Api
{
/** @var User */
protected $currentUser;
/** @var array */
protected $boosts = [];
protected $next;
protected $type;
protected $limit;
protected $offset;
protected $rating;
protected $platform;
protected $quality = 0;
protected $isBoostFeed;
/**
* Equivalent to HTTP GET method
* @param array $pages
......@@ -30,133 +34,84 @@ class feed implements Interfaces\Api
{
Factory::isLoggedIn();
/** @var Entities\User $currentUser */
$currentUser = Core\Session::getLoggedinUser();
$this->currentUser = Core\Session::getLoggedinUser();
if ($currentUser->disabled_boost && $currentUser->isPlus()) {
return Factory::response([
'entities' => [],
]);
if (!$this->parseAndValidateParams() || !$this->validBoostUser()) {
$this->sendResponse();
return;
}
// Parse parameters
$type = $pages[0] ?? 'newsfeed';
$limit = abs(intval($_GET['limit'] ?? 2));
$offset = $_GET['offset'] ?? null;
$rating = intval($_GET['rating'] ?? $currentUser->getBoostRating());
$platform = $_GET['platform'] ?? 'other';
$quality = 0;
$isBoostFeed = $_GET['boostfeed'] ?? false;
if ($limit === 0) {
return Factory::response([
'boosts' => [],
]);
} elseif ($limit > 500) {
$limit = 500;
}
$this->type = $pages[0] ?? 'newsfeed';
$cacher = Core\Data\cache\factory::build('Redis');
$offset = $cacher->get(Core\Session::getLoggedinUser()->guid . ':boost-offset-rotator');
if ($this->isBoostFeed) {
$this->offset = $_GET['from_timestamp'] ?: 0;
}
if ($isBoostFeed) {
$offset = $_GET['from_timestamp'] ?? 0;
switch ($this->type) {
case 'newsfeed':
$this->getBoosts();
break;
default:
$this->sendError('Unsupported boost type');
return;
}
// Options specific to newly created users (<=1 hour) and iOS users
$this->sendResponse();
}
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;
protected function parseAndValidateParams(): bool
{
$this->limit = abs(intval($_GET['limit'] ?? 2));
$this->offset = $_GET['offset'] ?? null;
$this->rating = intval($_GET['rating'] ?? $this->currentUser->getBoostRating());
$this->platform = $_GET['platform'] ?? 'other';
$this->isBoostFeed = $_GET['boostfeed'] ?? false;
if ($this->limit === 0) {
return false;
}
//
if ($this->limit > 500) {
$this->limit = 500;
}
$boosts = [];
$next = null;
return true;
}
switch ($type) {
case 'newsfeed':
// Newsfeed boosts
$resolver = new Core\Entities\Resolver();
/** @var Core\Boost\Network\Iterator $iterator */
$iterator = Core\Di\Di::_()->get('Boost\Network\Iterator');
$iterator
->setLimit(10)
->setOffset($offset)
->setRating($rating)
->setQuality($quality)
->setType($type)
->setPriority(true)
->setHydrate(false);
foreach ($iterator as $boost) {
$feedSyncEntity = new Core\Feeds\FeedSyncEntity();
$feedSyncEntity
->setGuid((string) $boost->getGuid())
->setOwnerGuid((string) $boost->getOwnerGuid())
->setTimestamp($boost->getCreatedTimestamp())
->setUrn(new Urn("urn:boost:{$boost->getType()}:{$boost->getGuid()}"));
$entity = $resolver->single(new Urn("urn:boost:{$boost->getType()}:{$boost->getGuid()}"));
if (!$entity) {
continue; // Duff entity?
}
$feedSyncEntity->setEntity($entity);
$boosts[] = $feedSyncEntity;
}
// $boosts = iterator_to_array($iterator, false);
$next = $iterator->getOffset();
if (isset($boosts[1]) && !$isBoostFeed) { // Always offset to 2rd in list if in rotator
// if (!$offset) {
// $next = $boosts[1]->getTimestamp();
// } else {
// $next = 0;
// }
$len = count($boosts);
if ($boosts[$len -1]) {
$next = $boosts[$len -1]->getTimestamp();
}
} elseif ($isBoostFeed) {
$len = count($boosts);
if ($boosts[$len -1]) {
$next = $boosts[$len -1]->getTimestamp();
}
}
// $ttl = 1800; // 30 minutes
// if (($next / 1000) < strtotime('48 hours ago')) {
$ttl = 300; // 5 minutes;
// }
$cacher->set(Core\Session::getLoggedinUser()->guid . ':boost-offset-rotator', $next, $ttl);
break;
protected function validBoostUser(): bool
{
return !($this->currentUser->disabled_boost && $this->currentUser->isPlus());
}
case 'content':
// TODO: Content boosts
default:
return Factory::response([
'status' => 'error',
'message' => 'Unsupported boost type'
]);
}
protected function sendResponse(): void
{
$boosts = empty($this->boosts) ? [] : Exportable::_($this->boosts);
Factory::response([
'entities' => $boosts,
'load-next' => $this->next,
]);
}
return Factory::response([
'entities' => Exportable::_($boosts),
'load-next' => $next ?: null,
protected function sendError(string $message): void
{
Factory::response([
'status' => 'error',
'message' => $message
]);
}
protected function getBoosts()
{
$feed = new Core\Boost\Feeds\Boost($this->currentUser);
$this->boosts = $feed->setLimit($this->limit)
->setOffset($this->offset)
->setRating($this->rating)
->setPlatform($this->platform)
->setQuality($this->quality)
->get();
$this->next = $feed->getOffset();
}
/**
* Equivalent to HTTP POST method
* @param array $pages
......@@ -186,4 +141,6 @@ class feed implements Interfaces\Api
{
return Factory::response([]);
}
}
......@@ -2,7 +2,6 @@
namespace Minds\Core\Boost;
use Minds\Core\Boost\Network;
use Minds\Core\Data;
use Minds\Core\Data\Client;
use Minds\Core\Di\Provider;
......@@ -59,19 +58,19 @@ class BoostProvider extends Provider
$this->di->bind('Boost\Payment', function ($di) {
return new Payment();
}, ['useFactory' => true]);
$this->di->bind('Boost\Campaigns\Dispatcher', function ($di) {
$this->di->bind(Campaigns\Dispatcher::getDiAlias(), function ($di) {
return new Campaigns\Dispatcher();
}, ['useFactory' => true]);
$this->di->bind('Boost\Campaigns\Metrics', function ($di) {
$this->di->bind(Campaigns\Metrics::getDiAlias(), function ($di) {
return new Campaigns\Metrics();
}, ['useFactory' => true]);
$this->di->bind('Boost\Campaigns\Manager', function ($di) {
$this->di->bind(Campaigns\Manager::getDiAlias(), function ($di) {
return new Campaigns\Manager();
}, ['useFactory' => true]);
$this->di->bind('Boost\Campaigns\Repository', function ($di) {
$this->di->bind(Campaigns\Repository::getDiAlias(), function ($di) {
return new Campaigns\Repository();
}, ['useFactory' => true]);
$this->di->bind('Boost\Campaigns\Stats', function ($di) {
$this->di->bind(Campaigns\Stats::getDiAlias(), function ($di) {
return new Campaigns\Stats();
}, ['useFactory' => true]);
}
......
......@@ -3,9 +3,12 @@
namespace Minds\Core\Boost\Campaigns;
use Exception;
use Minds\Traits\DiAlias;
class Dispatcher
{
use DiAlias;
const IMPRESSIONS_SYNC_THRESHOLD = 5;
/** @var Manager */
......
......@@ -42,7 +42,8 @@ class ElasticRepository
{
$this->opts = array_merge([
'limit' => 12,
'from' => 0
'from' => 0,
'type' => ''
], $opts);
$this->queryBuilder->setOpts($opts);
......@@ -51,7 +52,7 @@ class ElasticRepository
$prepared->query([
'index' => 'minds-boost-campaigns',
'type' => '_doc',
'type' => $this->opts['type'],
'body' => $this->queryBuilder->query(),
'size' => $this->opts['limit'],
'from' => (int)($this->opts['from'] ?? 0),
......@@ -101,7 +102,8 @@ class ElasticRepository
{
$this->opts = array_merge([
'limit' => 24,
'from' => 0
'from' => 0,
'type' => ''
], $opts);
$this->queryBuilder->setOpts($this->opts);
......@@ -109,7 +111,7 @@ class ElasticRepository
$prepared = new Search();
$prepared->query([
'index' => 'minds-boost,minds-boost-campaigns',
'type' => '_doc',
'type' => $this->opts['type'],
'body' => $this->queryBuilder->query(),
'from' => $this->opts['from'] ?? 0,
'size' => $this->opts['limit'],
......
<?php
/**
* @author: eiennohi.
*/
namespace Minds\Core\Boost\Campaigns;
use Minds\Core\Di\Di;
use Minds\Traits\DiAlias;
class Iterator implements \Iterator
{
use DiAlias;
/** @var Manager */
protected $manager;
......@@ -25,9 +25,9 @@ class Iterator implements \Iterator
/** @var array */
protected $list = null;
public function __construct($manager = null)
public function __construct(Manager $manager = null)
{
$this->manager = $manager ?: Di::_()->get('Boost\Campaigns\Manager');
$this->manager = $manager ?: Di::_()->get(Manager::getDiAlias());
}
/**
......@@ -130,7 +130,7 @@ class Iterator implements \Iterator
public function getList()
{
$response = $this->manager->getCampaigns([
$response = $this->manager->getCampaignsAndBoosts([
'limit' => $this->limit,
'from' => $this->from,
'offset' => $this->offset,
......
......@@ -11,9 +11,12 @@ use Minds\Core\Boost\Checksum;
use Minds\Core\Queue\Client as QueueClient;
use Minds\Core\Queue\Interfaces\QueueClient as QueueClientInterface;
use Minds\Entities\User;
use Minds\Traits\DiAlias;
class Manager
{
use DiAlias;
/** @var Repository */
protected $repository;
......
......@@ -7,9 +7,12 @@ use Minds\Common\Urn;
use Minds\Core\Counters\Manager as Counters;
use Minds\Core\Di\Di;
use Minds\Core\Entities\Resolver;
use Minds\Traits\DiAlias;
class Metrics
{
use DiAlias;
/** @var Counters */
protected $counters;
......
......@@ -11,9 +11,12 @@ use Minds\Core\Data\Cassandra\Prepared\Custom;
use Minds\Core\Di\Di;
use Minds\Helpers\Number;
use Minds\Helpers\Text;
use Minds\Traits\DiAlias;
class Repository
{
use DiAlias;
/** @var CassandraClient */
protected $db;
......
......@@ -4,9 +4,12 @@ namespace Minds\Core\Boost\Campaigns;
use Minds\Core\Analytics\EntityCentric\BoostViewsDaily;
use Minds\Core\Time;
use Minds\Traits\DiAlias;
class Stats
{
use DiAlias;
/** @var Campaign */
protected $campaign;
......
<?php
namespace Minds\Core\Boost;
use Minds\Core\Data\cache\abstractCacher;
use Minds\Core\Entities\Resolver;
use Minds\Entities\User;
use Minds\Core;
abstract class Feed
{
const RATING_SAFE = 1;
/** @var Resolver */
protected $resolver;
/** @var User */
protected $currentUser;
/** @var abstractCacher */
protected $cacher;
protected $mockIterator;
/** @var array */
protected $boosts = [];
protected $offset;
protected $limit;
protected $rating;
protected $platform;
protected $quality = 0;
protected $type = 'newsfeed';
protected $offsetCacheTtl = Core\Time::FIVE_MIN;
public function __construct(
User $currentUser = null,
Resolver $resolver = null,
abstractCacher $cacher = null
)
{
$this->currentUser = $currentUser ?: Core\Session::getLoggedinUser();
$this->resolver = $resolver ?: new Resolver();
$this->cacher = $cacher ?: Core\Data\cache\factory::build('Redis');
}
public function setMockIterator($mockIterator): self
{
$this->mockIterator = $mockIterator;
return $this;
}
public function setLimit(int $limit): self
{
$this->limit = $limit;
return $this;
}
public function getOffset(): int
{
return $this->offset;
}
public function setOffset(int $offset): self
{
$this->offset = $offset;
return $this;
}
public function setRating(int $rating): self
{
$this->rating = $rating;
return $this;
}
public function setPlatform(string $platform): self
{
$this->platform = $platform;
return $this;
}
public function setQuality(int $quality): self
{
$this->quality = $quality;
return $this;
}
public function setType(string $type): self
{
$this->type = $type;
return $this;
}
/**
* @return Core\Feeds\FeedSyncEntity[]
*/
public function get(): array
{
$this->makeRatingAndQualitySafe();
$this->setOffsetFromCache();
$this->getItems();
$this->setOffsetCache();
return $this->boosts;
}
protected function makeRatingAndQualitySafe(): void
{
if ($this->platform === 'ios') {
$this->rating = self::RATING_SAFE;
$this->quality = 90;
} elseif (time() - $this->currentUser->getTimeCreated() <= Core\Time::ONE_HOUR) {
$this->rating = self::RATING_SAFE;
$this->quality = 75;
}
}
protected function setOffsetFromCache(): void
{
$offsetCache = $this->getOffsetCache();
if (is_int($offsetCache)) {
$this->offset = $offsetCache;
}
}
protected function setOffsetCache(): void
{
$this->cacher->set($this->getOffsetCacheKey(), $this->offset, $this->offsetCacheTtl);
}
protected function getOffsetCache()
{
return $this->cacher->get($this->getOffsetCacheKey());
}
abstract protected function getItems(): void;
abstract protected function getOffsetCacheKey(): string;
}
<?php
namespace Minds\Core\Boost\Feeds;
use Minds\Common\Urn;
use Minds\Core;
use Minds\Core\Boost\Feed;
class Boost extends Feed
{
protected function getItems(): void
{
/** @var Core\Boost\Network\Iterator $iterator */
$iterator = $this->mockIterator ?: Core\Di\Di::_()->get('Boost\Network\Iterator');
$iterator
->setLimit(10)
->setOffset($this->offset)
->setRating($this->rating)
->setQuality($this->quality)
->setType($this->type)
->setHydrate(false);
/** @var Core\Boost\Network\Boost $boost */
foreach ($iterator as $boost) {
$boostUrn = new Urn("urn:boost:{$boost->getType()}:{$boost->getGuid()}");
$feedSyncEntity = new Core\Feeds\FeedSyncEntity();
$feedSyncEntity
->setGuid((string)$boost->getGuid())
->setOwnerGuid((string)$boost->getOwnerGuid())
->setTimestamp($boost->getCreatedTimestamp())
->setUrn($boostUrn);
$entity = $this->resolver->single($boostUrn);
if (!$entity) {
echo PHP_EOL . 'bad entity';
continue; // Duff entity?
}
$feedSyncEntity->setEntity($entity);
$this->boosts[] = $feedSyncEntity;
echo PHP_EOL . 'iterate';
}
$this->offset = $iterator->getOffset();
if (isset($this->boosts[1])) { // Always offset to 2rd in list if in rotator
$len = count($this->boosts);
if ($this->boosts[$len - 1]) {
$this->offset = $this->boosts[$len - 1]->getTimestamp();
}
}
}
protected function getOffsetCacheKey(): string
{
return $this->currentUser->guid . ':boost-offset-rotator';
}
}
......@@ -114,24 +114,6 @@ class Iterator implements \Iterator
public function getList()
{
$match = [
'type' => $this->type,
'state' => 'approved',
'rating' => [
//'$exists' => true,
'$lte' => $this->rating ? $this->rating : (int) Core\Session::getLoggedinUser()->getBoostRating()
],
'quality' => [
'$gte' => $this->quality
]
];
$sort = ['_id' => 1];
if ($this->priority) {
$sort = ['priority' => -1, '_id' => 1];
}
$boosts = $this->elasticRepository->getList([
'type' => $this->type,
'limit' => self::MONGO_LIMIT,
......
<?php
/**
* FeedSyncEntity.
*
* @author emi
*/
namespace Minds\Core\Feeds;
use JsonSerializable;
use Minds\Traits\Exportable;
use Minds\Entities\Entity;
use Minds\Traits\MagicAttributes;
/**
......@@ -22,6 +17,8 @@ use Minds\Traits\MagicAttributes;
* @method FeedSyncEntity setTimestamp(int $timestamp)
* @method string getUrn()
* @method FeedSyncEntity setUrn(string $urn)
* @method Entity getEntity()
* @method FeedSyncEntity setEntity(Entity $entity)
*/
class FeedSyncEntity implements JsonSerializable
{
......@@ -46,7 +43,7 @@ class FeedSyncEntity implements JsonSerializable
* Export to public API
* @return array
*/
public function export()
public function export(): array
{
return [
'guid' => (string) $this->guid,
......
......@@ -24,7 +24,7 @@ class BoostCampaignDispatcher implements Interfaces\QueueRunner
error_log("Checking boost campaign {$campaignRef->getUrn()} status...");
/** @var Dispatcher $dispatcher */
$dispatcher = Di::_()->get('Boost\Campaigns\Dispatcher');
$dispatcher = Di::_()->get(Dispatcher::getDiAlias());
$dispatcher->onLifecycle($campaignRef->getUrn());
});
}
......
<?php
namespace Spec\Minds\Core\Boost\Feeds;
use Minds\Common\Urn;
use Minds\Core\Boost\Feeds\Boost;
use Minds\Core\Boost\Network\Iterator;
use Minds\Core\Data\cache\abstractCacher;
use Minds\Core\Entities\Resolver;
use Minds\Core\Feeds\FeedSyncEntity;
use Minds\Entities\Entity;
use Minds\Entities\User;
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use Minds\Core\Boost\Network\Boost as BoostObj;
class BoostSpec extends ObjectBehavior
{
protected $user;
protected $resolver;
protected $cacher;
protected $iterator;
public function let(User $user, Resolver $resolver, abstractCacher $cacher, Iterator $iterator)
{
$this->beConstructedWith($user, $resolver, $cacher);
$this->user = $user;
$this->resolver = $resolver;
$this->cacher = $cacher;
$this->iterator = $iterator;
$this->setMockIterator($iterator);
}
public function it_is_initializable()
{
$this->shouldHaveType(Boost::class);
}
public function it_should_get_boosts(BoostObj $boost1, BoostObj $boost2)
{
$params = [
'limit' => 10,
'offset' => 10,
'rating' => 0,
'quality' => 0
];
$this->iterator->setLimit(10)->shouldBeCalled()->willReturn($this->iterator);
$this->iterator->setOffset(10)->shouldBeCalled()->willReturn($this->iterator);
$this->iterator->setRating(0)->shouldBeCalled()->willReturn($this->iterator);
$this->iterator->setQuality(0)->shouldBeCalled()->willReturn($this->iterator);
$this->iterator->setType('newsfeed')->shouldBeCalled()->willReturn($this->iterator);
$this->iterator->setHydrate(false)->shouldBeCalled()->willReturn($this->iterator);
$this->iterator->rewind()->shouldBeCalled();
$this->iterator->valid()->shouldBeCalled()->willReturn(true, true, false);
$this->iterator->current()->shouldBeCalled()->willReturn($boost1, $boost2);
$this->iterator->next()->shouldBeCalled();
$this->iterator->getOffset()->shouldBeCalled()->willReturn($params['offset']);
$boost1->getCreatedTimestamp()->shouldBeCalled()->willReturn(1571749729);
$boost1->getGuid()->shouldBeCalled()->willReturn(1234);
$boost1->getOwnerGuid()->shouldBeCalled()->willReturn(5678);
$boost1->getType()->shouldBeCalled()->willReturn('newsfeed');
$this->resolver->single(Argument::type(Urn::class))->shouldBeCalled()->willReturn(new Entity());
$boost2->getCreatedTimestamp()->shouldBeCalled()->willReturn(1571750627);
$boost2->getGuid()->shouldBeCalled()->willReturn(3456);
$boost2->getOwnerGuid()->shouldBeCalled()->willReturn(5678);
$boost2->getType()->shouldBeCalled()->willReturn('newsfeed');
$this->setLimit($params['limit'])->shouldReturn($this);
$this->setOffset($params['offset'])->shouldReturn($this);
$this->setRating(0)->shouldReturn($this);
$this->get()->shouldBeArray();
}
}
<?php
namespace Minds\Traits;
trait DiAlias
{
static function getDiAlias(): string
{
return self::class;
}
}