Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • omadrid/engine
  • javanick/engine
  • minds/engine
  • joe59/engine
  • eiennohi/engine
  • edgebal/engine
  • msantang78/engine
  • maruthi-adithya/engine
  • duyquoc/engine
  • benhayward.ben/engine
  • rlperez/engine
  • priestd09/engine
  • dknunn/engine
  • ascenderking/engine
  • catastrop/engine
  • jim-toth/engine
  • project_connection/engine
  • manishoo/engine
  • murbo98/engine
  • namesty/engine
  • Moikapy/engine
  • bedriguler/engine
  • CodingNagger/engine
  • jun784/engine
  • alexgleason/engine
  • gigasim97/engine
  • auxchar/engine
  • pestixaba/engine
  • m994/engine
  • webprodev/minds_engine
  • fabiolalombardim/engine
  • zackwy/engine
  • linleyj7/engine
  • fiatjaf/minds-engine
  • ppitestsblishaokai/engine
  • VARUN-KUSH/engine
  • brainr386/engine
37 results
Show changes
Commits on Source (4)
Showing
with 1174 additions and 25 deletions
......@@ -2,6 +2,8 @@
namespace Minds\Api;
use Minds\Core\Di\Di;
use Minds\Core\Pro\Domain\Security as ProDomainSecurity;
use Minds\Interfaces;
use Minds\Helpers;
use Minds\Core\Security;
......@@ -32,6 +34,7 @@ class Factory
$loop = count($segments);
while ($loop >= 0) {
$offset = $loop -1;
if ($loop < count($segments)) {
$slug_length = strlen($segments[$offset+1].'\\');
$route_length = strlen($route);
......@@ -42,32 +45,51 @@ class Factory
$actual = str_replace('\\', '/', $route);
if (isset(Routes::$routes[$actual])) {
$class_name = Routes::$routes[$actual];
if (class_exists($class_name)) {
$handler = new $class_name();
if (property_exists($handler, 'request')) {
$handler->request = $request;
}
if ($handler instanceof Interfaces\ApiAdminPam) {
self::adminCheck();
}
if (!$handler instanceof Interfaces\ApiIgnorePam) {
self::pamCheck($request, $response);
}
$pages = array_splice($segments, $loop) ?: [];
return $handler->$method($pages);
}
}
//autloaded routes
$class_name = "\\Minds\\Controllers\api\\$route";
if (class_exists($class_name)) {
$handler = new $class_name();
if (property_exists($handler, 'request')) {
$handler->request = $request;
}
if ($handler instanceof Interfaces\ApiAdminPam) {
self::adminCheck();
}
if (!$handler instanceof Interfaces\ApiIgnorePam) {
self::pamCheck($request, $response);
}
$pages = array_splice($segments, $loop) ?: [];
return $handler->$method($pages);
}
--$loop;
}
}
......@@ -78,15 +100,18 @@ class Factory
*/
public static function pamCheck($request, $response)
{
if ($request->getAttribute('oauth_user_id')
|| Security\XSRF::validateRequest()
if (
$request->getAttribute('oauth_user_id') ||
Security\XSRF::validateRequest()
) {
return true;
} else {
//error_log('failed authentication:: OAUTH via API');
ob_end_clean();
static::setCORSHeader();
header('Content-type: application/json');
header("Access-Control-Allow-Origin: *");
header('HTTP/1.1 401 Unauthorized', true, 401);
echo json_encode([
'error' => 'Sorry, you are not authenticated',
......@@ -108,8 +133,10 @@ class Factory
} else {
error_log('security: unauthorized access to admin api');
ob_end_clean();
static::setCORSHeader();
header('Content-type: application/json');
header("Access-Control-Allow-Origin: *");
header('HTTP/1.1 401 Unauthorized', true, 401);
echo json_encode(['error'=>'You are not an admin', 'code'=>401]);
exit;
......@@ -126,8 +153,10 @@ class Factory
return true;
} else {
ob_end_clean();
static::setCORSHeader();
header('Content-type: application/json');
header("Access-Control-Allow-Origin: *");
header('HTTP/1.1 401 Unauthorized', true, 401);
echo json_encode([
'status' => 'error',
......@@ -151,11 +180,26 @@ class Factory
ob_end_clean();
static::setCORSHeader();
header('Content-type: application/json');
header("Access-Control-Allow-Origin: *");
echo json_encode($data);
}
/**
* Sets the CORS header, if not already set
*/
public static function setCORSHeader(): void
{
$wasSet = count(array_filter(headers_list(), function ($header) {
return stripos($header, 'Access-Control-Allow-Origin:') === 0;
})) > 0;
if (!$wasSet) {
header("Access-Control-Allow-Origin: *");
}
}
/**
* Returns the exportable form of the entities
* @param array $entities - an array of entities
......
<?php
/**
* Jwt
* @author edgebal
*/
namespace Minds\Common;
use Exception;
use Lcobucci\JWT\Builder;
use Lcobucci\JWT\Claim;
use Lcobucci\JWT\Parser;
use Lcobucci\JWT\Signer\Hmac\Sha256;
class Jwt
{
/** @var string */
protected $key;
/**
* @param string $key
* @return Jwt
*/
public function setKey(string $key): Jwt
{
$this->key = $key;
return $this;
}
/**
* @param object|array $payload
* @param int|null $exp
* @param int|null $nbf
* @return string
* @throws Exception
*/
public function encode($payload, $exp = null, $nbf = null): string
{
if (!$this->key) {
throw new Exception('Invalid JWT key');
}
$builder = new Builder();
foreach ($payload as $key => $value) {
$builder->set($key, $value);
}
if ($exp !== null) {
$builder->setExpiration($exp);
}
if ($nbf !== null) {
$builder->setNotBefore($nbf);
}
$builder->sign(new Sha256(), $this->key);
return (string) $builder->getToken();
}
/**
* @param string $jwt
* @return array
* @throws Exception
*/
public function decode($jwt): array
{
if (!$this->key) {
throw new Exception('Invalid JWT key');
}
$token = (new Parser())->parse($jwt);
if (!$token->verify(new Sha256(), $this->key)) {
throw new Exception('Invalid JWT');
}
return array_map(function (Claim $claim) {
return $claim->getValue();
}, $token->getClaims());
}
/**
* @return string
*/
public function randomString(): string
{
$bytes = openssl_random_pseudo_bytes(128);
return hash('sha512', $bytes);
}
}
......@@ -328,4 +328,13 @@ class Response implements \Iterator, \ArrayAccess, \Countable, \JsonSerializable
{
return array_reduce($this->data, $callback, $initialValue);
}
/**
* Returns the first element of the Response, or null if empty
* @return mixed|null
*/
public function first()
{
return $this->data[0] ?? null;
}
}
......@@ -16,6 +16,8 @@ use Minds\Entities;
use Minds\Interfaces;
use Minds\Api\Factory;
use Minds\Exceptions\TwoFactorRequired;
use Minds\Core\Queue;
use Minds\Core\Subscriptions;
class authenticate implements Interfaces\Api, Interfaces\ApiIgnorePam
{
......@@ -44,6 +46,7 @@ class authenticate implements Interfaces\Api, Interfaces\ApiIgnorePam
}
$user = new Entities\User(strtolower($_POST['username']));
/** @var Core\Security\LoginAttempts $attempts */
$attempts = Core\Di\Di::_()->get('Security\LoginAttempts');
......@@ -117,7 +120,7 @@ class authenticate implements Interfaces\Api, Interfaces\ApiIgnorePam
public function delete($pages)
{
$sessions = Di::_()->get('Sessions\Manager');
if (isset($pages[0]) && $pages[0] === 'all') {
$sessions->destroy(true);
} else {
......
......@@ -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]);
......@@ -87,6 +92,19 @@ class channel implements Interfaces\Api
$block = Core\Security\ACL\Block::_();
$response['channel']['blocked'] = $block->isBlocked($user);
if ($user->isPro()) {
/** @var Core\Pro\Manager $manager */
$manager = Core\Di\Di::_()->get('Pro\Manager');
$manager
->setUser($user);
$proSettings = $manager->get();
if ($proSettings) {
$response['channel']['pro_settings'] = $proSettings;
}
}
return Factory::response($response);
}
......
......@@ -5,14 +5,14 @@
* @version 1
* @author Mark Harding
*/
namespace Minds\Controllers\api\v1;
use Minds\Api\Factory;
use Minds\Core;
use Minds\Core\Di\Di;
use Minds\Entities;
use Minds\Entities\User;
use Minds\Interfaces;
use Minds\Api\Factory;
use Minds\Helpers;
class register implements Interfaces\Api, Interfaces\ApiIgnorePam
{
......@@ -21,7 +21,7 @@ class register implements Interfaces\Api, Interfaces\ApiIgnorePam
*/
public function get($pages)
{
return Factory::response(['status'=>'error', 'message'=>'GET is not supported for this endpoint']);
return Factory::response(['status' => 'error', 'message' => 'GET is not supported for this endpoint']);
}
/**
......@@ -37,11 +37,11 @@ class register implements Interfaces\Api, Interfaces\ApiIgnorePam
public function post($pages)
{
if (!isset($_POST['username']) || !isset($_POST['password']) || !isset($_POST['username']) || !isset($_POST['email'])) {
return Factory::response(['status'=>'error']);
return Factory::response(['status' => 'error']);
}
if (!$_POST['username'] || !$_POST['password'] || !$_POST['username'] || !$_POST['email']) {
return Factory::response(['status'=>'error', 'message' => "Please fill out all the fields"]);
return Factory::response(['status' => 'error', 'message' => "Please fill out all the fields"]);
}
try {
......@@ -119,11 +119,11 @@ class register implements Interfaces\Api, Interfaces\ApiIgnorePam
$sessions->save(); // Save to db and cookie
$response = [
'guid' => $guid,
'user' => $user->export()
'guid' => $guid,
'user' => $user->export(),
];
} catch (\Exception $e) {
$response = ['status'=>'error', 'message'=>$e->getMessage()];
$response = ['status' => 'error', 'message' => $e->getMessage()];
}
return Factory::response($response);
}
......
......@@ -69,10 +69,6 @@ class settings implements Interfaces\Api
{
Factory::isLoggedIn();
if (!Core\Security\XSRF::validateRequest()) {
//return false;
}
if (Core\Session::getLoggedInUser()->isAdmin() && isset($pages[0])) {
$user = new entities\User($pages[0]);
} else {
......
<?php
/**
* pro
*
* @author edgebal
*/
namespace Minds\Controllers\api\v2\admin;
use Minds\Api\Factory;
use Minds\Core\Pro\Manager;
use Minds\Entities\User as UserEntity;
use Minds\Interfaces;
use Minds\Core\Di\Di;
class pro implements Interfaces\Api, Interfaces\ApiAdminPam
{
/**
* Equivalent to HTTP GET method
* @param array $pages
* @return mixed|null
*/
public function get($pages)
{
return Factory::response([]);
}
/**
* Equivalent to HTTP POST method
* @param array $pages
* @return mixed|null
*/
public function post($pages)
{
return Factory::response([]);
}
/**
* Equivalent to HTTP PUT method
* @param array $pages
* @return mixed|null
*/
public function put($pages)
{
if (!($pages[0] ?? null)) {
return Factory::response([
'status' => 'error',
'message' => 'Emtpy target',
]);
}
$target = new UserEntity($pages[0]);
if (!$target || !$target->guid) {
return Factory::response([
'status' => 'error',
'message' => 'Invalid target',
]);
}
/** @var Manager $manager */
$manager = Di::_()->get('Pro\Manager');
$manager
->setUser($target);
$success = $manager->enable(time() + (365 * 86400));
if (!$success) {
return Factory::response([
'status' => 'error',
'message' => 'Error disabling Pro',
]);
}
return Factory::response([]);
}
/**
* Equivalent to HTTP DELETE method
* @param array $pages
* @return mixed|null
*/
public function delete($pages)
{
if (!($pages[0] ?? null)) {
return Factory::response([
'status' => 'error',
'message' => 'Emtpy target',
]);
}
$target = new UserEntity($pages[0]);
if (!$target || !$target->guid) {
return Factory::response([
'status' => 'error',
'message' => 'Invalid target',
]);
}
/** @var Manager $manager */
$manager = Di::_()->get('Pro\Manager');
$manager
->setUser($target);
$success = $manager->disable();
if (!$success) {
return Factory::response([
'status' => 'error',
'message' => 'Error disabling Pro',
]);
}
return Factory::response([]);
}
}
......@@ -113,6 +113,10 @@ class views implements Interfaces\Api
error_log($e);
}
Di::_()->get('Referrals\Cookie')
->setEntity($activity)
->create();
break;
}
......
<?php
/**
* pro
* @author edgebal
*/
namespace Minds\Controllers\api\v2;
use Exception;
use Minds\Core\Di\Di;
use Minds\Core\Pro\Manager;
use Minds\Core\Session;
use Minds\Interfaces;
use Minds\Api\Factory;
class pro implements Interfaces\Api
{
/**
* Equivalent to HTTP GET method
* @param array $pages
* @return mixed|null
* @throws Exception
*/
public function get($pages)
{
/** @var Manager $manager */
$manager = Di::_()->get('Pro\Manager');
$manager
->setUser(Session::getLoggedinUser());
return Factory::response([
'isActive' => $manager->isActive(),
]);
}
/**
* Equivalent to HTTP POST method
* @param array $pages
* @return mixed
*/
public function post($pages)
{
return Factory::response([
'status' => 'error',
'message' => 'Minds Pro is not yet publicly available.',
]);
// /** @var Manager $manager */
// $manager = Di::_()->get('Pro\Manager');
// $manager
// ->setUser(Session::getLoggedinUser());
//
// // TODO: Send and process payment data
// $success = $manager->enable(time() + (365 * 86400));
//
// if (!$success) {
// return Factory::response([
// 'status' => 'error',
// 'message' => 'Error activating Pro',
// ]);
// }
//
// return Factory::response([
// 'isActive' => $manager->isActive(),
// 'settings' => $manager->get(),
// ]);
}
/**
* Equivalent to HTTP PUT method
* @param array $pages
* @return mixed|null
*/
public function put($pages)
{
return Factory::response([]);
}
/**
* Equivalent to HTTP DELETE method
* @param array $pages
* @return mixed
*/
public function delete($pages)
{
/** @var Manager $manager */
$manager = Di::_()->get('Pro\Manager');
$manager
->setUser(Session::getLoggedinUser());
$success = $manager->disable();
if (!$success) {
return Factory::response([
'status' => 'error',
'message' => 'Error disabling Pro',
]);
}
return Factory::response([]);
}
}
<?php
/**
* channel
* @author edgebal
*/
namespace Minds\Controllers\api\v2\pro;
use Exception;
use Minds\Core\Di\Di;
use Minds\Core\Pro\Channel\Manager as ChannelManager;
use Minds\Core\Pro\Manager;
use Minds\Core\Session;
use Minds\Entities\User;
use Minds\Helpers\Campaigns\Referrals;
use Minds\Interfaces;
use Minds\Api\Factory;
class channel implements Interfaces\Api
{
public $request;
/**
* Equivalent to HTTP GET method
* @param array $pages
* @return mixed|null
* @throws Exception
*/
public function get($pages)
{
$currentUser = Session::getLoggedinUser();
$channel = new User($pages[0]);
$channel->fullExport = true; //get counts
$channel->exportCounts = true;
/** @var Manager $manager */
$manager = Di::_()->get('Pro\Manager');
$manager->setUser($channel);
/** @var ChannelManager $manager */
$channelManager = Di::_()->get('Pro\Channel\Manager');
$channelManager->setUser($channel);
switch ($pages[1] ?? '') {
case 'content':
return Factory::response([
'content' => $channelManager->getAllCategoriesContent(),
]);
default:
$proSettings = $manager->get();
$exportedChannel = $channel->export();
$exportedChannel['pro_settings'] = $proSettings;
$origin = strtolower($this->request->getServerParams()['HTTP_X_MINDS_ORIGIN'] ?? '');
$domain = strtolower($proSettings->getDomain());
if ($domain === $origin) {
Referrals::register($channel->username);
}
return Factory::response([
'channel' => $exportedChannel,
'me' => $currentUser ? $currentUser->export() : null,
]);
}
}
/**
* Equivalent to HTTP POST method
* @param array $pages
* @return mixed|null
*/
public function post($pages)
{
return Factory::response([]);
}
/**
* Equivalent to HTTP PUT method
* @param array $pages
* @return mixed|null
*/
public function put($pages)
{
return Factory::response([]);
}
/**
* Equivalent to HTTP DELETE method
* @param array $pages
* @return mixed|null
*/
public function delete($pages)
{
return Factory::response([]);
}
}
<?php
/**
* @author: eiennohi.
*/
namespace Minds\Controllers\api\v2\pro;
use Minds\Api\Exportable;
use Minds\Api\Factory;
use Minds\Common\Repository\Response;
use Minds\Core;
use Minds\Core\Di\Di;
use Minds\Entities\Factory as EntitiesFactory;
use Minds\Entities\User;
use Minds\Interfaces;
class content implements Interfaces\Api
{
const MIN_COUNT = 6;
public function get($pages)
{
/** @var User $currentUser */
$currentUser = Core\Session::getLoggedinUser();
$container_guid = $pages[0] ?? null;
$owner_guid = null;
if (!$container_guid) {
return Factory::response([
'status' => 'error',
'message' => 'Invalid container',
]);
}
$container = EntitiesFactory::build($container_guid);
if (!$container || !Core\Security\ACL::_()->read($container, $currentUser)) {
return Factory::response([
'status' => 'error',
'message' => 'Forbidden',
]);
}
$type = '';
switch ($pages[1]) {
case 'activities':
$type = 'activity';
break;
case 'images':
$type = 'object:image';
break;
case 'videos':
$type = 'object:video';
break;
case 'blogs':
$type = 'object:blog';
break;
case 'groups':
$type = 'group';
$container_guid = null;
$owner_guid = $pages[0];
break;
case 'all':
$type = 'all';
break;
}
$hardLimit = 5000;
$offset = 0;
if (isset($_GET['offset'])) {
$offset = intval($_GET['offset']);
}
$limit = 12;
if (isset($_GET['limit'])) {
$limit = abs(intval($_GET['limit']));
}
if (($offset + $limit) > $hardLimit) {
$limit = $hardLimit - $offset;
}
if ($limit <= 0) {
return Factory::response([
'status' => 'success',
'entities' => [],
'load-next' => $hardLimit,
'overflow' => true,
]);
}
$sync = (bool) ($_GET['sync'] ?? false);
$fromTimestamp = $_GET['from_timestamp'] ?? 0;
$exclude = explode(',', $_GET['exclude'] ?? '');
$forcePublic = (bool) ($_GET['force_public'] ?? false);
$asActivities = (bool) ($_GET['as_activities'] ?? true);
$query = null;
if (isset($_GET['query'])) {
$query = $_GET['query'];
}
/** @var Core\Feeds\Top\Entities $entities */
$entities = new Core\Feeds\Top\Entities();
$entities->setActor($currentUser);
$isOwner = false;
if ($currentUser) {
$entities->setActor($currentUser);
$isOwner = $currentUser->guid == $container_guid;
}
$opts = [
'cache_key' => $currentUser ? $currentUser->guid : null,
'container_guid' => $container_guid,
'owner_guid' => $owner_guid,
'access_id' => $isOwner && !$forcePublic ? [0, 1, 2, $container_guid] : [2, $container_guid],
'custom_type' => null,
'limit' => $limit,
'type' => $type,
'algorithm' => 'top',
'period' => '7d',
'sync' => $sync,
'from_timestamp' => $fromTimestamp,
'query' => $query,
'single_owner_threshold' => 0,
'pinned_guids' => $type === 'activity' ? array_reverse($container->getPinnedPosts()) : null,
'exclude' => $exclude,
];
if (isset($_GET['nsfw'])) {
$nsfw = $_GET['nsfw'] ?? '';
$opts['nsfw'] = explode(',', $nsfw);
}
$hashtag = null;
if (isset($_GET['hashtag'])) {
$hashtag = strtolower($_GET['hashtag']);
}
if ($hashtag) {
$opts['hashtags'] = [$hashtag];
$opts['filter_hashtags'] = true;
} elseif (isset($_GET['hashtags']) && $_GET['hashtags']) {
$opts['hashtags'] = explode(',', $_GET['hashtags']);
$opts['filter_hashtags'] = true;
}
try {
$result = $this->getData($entities, $opts, $asActivities, $sync);
if ($result->count() <= static::MIN_COUNT) {
$opts['algorithm'] = 'latest';
$result = $this->getData($entities, $opts, $asActivities, $sync);
}
$response = [
'status' => 'success',
'entities' => Exportable::_($result),
'load-next' => $result->getPagingToken(),
];
return Factory::response($response);
} catch (\Exception $e) {
error_log($e);
return Factory::response(['status' => 'error', 'message' => $e->getMessage()]);
}
}
/**
* @param Core\Feeds\Top\Entities $entities
* @param array $opts
* @param bool $asActivities
* @param bool $sync
* @return Response
* @throws \Exception
*/
private function getData($entities, $opts, $asActivities, $sync)
{
/** @var Core\Feeds\Top\Manager $manager */
$manager = Di::_()->get('Feeds\Top\Manager');
$result = $manager->getList($opts);
if (!$sync) {
// Remove all unlisted content, if ES document is not in sync, it'll
// also remove pending activities
$result = $result->filter([$entities, 'filter']);
if ($asActivities) {
// Cast to ephemeral Activity entities, if another type
$result = $result->map([$entities, 'cast']);
}
}
return $result;
}
public function post($pages)
{
return Factory::response([]);
}
public function put($pages)
{
return Factory::response([]);
}
public function delete($pages)
{
return Factory::response([]);
}
}
<?php
/**
* settings
* @author edgebal
*/
namespace Minds\Controllers\api\v2\pro;
use Exception;
use Minds\Core\Di\Di;
use Minds\Core\Pro\Manager;
use Minds\Core\Session;
use Minds\Entities\User;
use Minds\Interfaces;
use Minds\Api\Factory;
class settings implements Interfaces\Api
{
/**
* Equivalent to HTTP GET method
* @param array $pages
* @return mixed|null
*/
public function get($pages)
{
$user = Session::getLoggedinUser();
if (isset($pages[0]) && $pages[0]) {
if (!Session::isAdmin()) {
return Factory::response([
'status' => 'error',
'message' => 'You are not authorized',
]);
}
$user = new User($pages[0]);
}
/** @var Manager $manager */
$manager = Di::_()->get('Pro\Manager');
$manager
->setUser($user)
->setActor(Session::getLoggedinUser());
return Factory::response([
'isActive' => $manager->isActive(),
'settings' => $manager->get(),
]);
}
/**
* Equivalent to HTTP POST method
* @param array $pages
* @return mixed|null
*/
public function post($pages)
{
$user = Session::getLoggedinUser();
if (isset($pages[0]) && $pages[0]) {
if (!Session::isAdmin()) {
return Factory::response([
'status' => 'error',
'message' => 'You are not authorized',
]);
}
$user = new User($pages[0]);
}
/** @var Manager $manager */
$manager = Di::_()->get('Pro\Manager');
$manager
->setUser($user)
->setActor(Session::getLoggedinUser());
if (!$manager->isActive()) {
return Factory::response([
'status' => 'error',
'message' => 'You are not Pro',
]);
}
try {
$success = $manager->set($_POST);
if (!$success) {
throw new Exception('Cannot save Pro settings');
}
} catch (\Exception $e) {
return Factory::response([
'status' => 'error',
'message' => $e->getMessage(),
]);
}
return Factory::response([]);
}
/**
* Equivalent to HTTP PUT method
* @param array $pages
* @return mixed|null
*/
public function put($pages)
{
return Factory::response([]);
}
/**
* Equivalent to HTTP DELETE method
* @param array $pages
* @return mixed|null
*/
public function delete($pages)
{
return Factory::response([]);
}
}
......@@ -46,7 +46,15 @@ class thumbnail extends Core\page implements Interfaces\page
$contents = $thumbnail->read();
}
header('Content-type: image/jpeg');
try {
$finfo = new \finfo(FILEINFO_MIME);
$contentType = $finfo->buffer($contents) ?: 'image/jpeg';
} catch (\Exception $e) {
error_log($e);
$contentType = 'image/jpeg';
}
header('Content-type: ' . $contentType);
header('Expires: ' . date('r', strtotime('today + 6 months')), true);
header('Pragma: public');
header('Cache-Control: public');
......
......@@ -6,6 +6,7 @@ use Minds\Core;
use Minds\Entities;
use Minds\Helpers;
use Minds\Helpers\Counters;
use Zend\Diactoros\ServerRequestFactory;
class SEO
{
......@@ -76,18 +77,30 @@ class SEO
$params = $event->getParameters();
$slugs = $params['slugs'];
if ((count($slugs) < 3) || ($slugs[1] != 'blog')) {
/** @var Core\Pro\Domain $proDomain */
$proDomain = Core\Di\Di::_()->get('Pro\Domain');
$request = ServerRequestFactory::fromGlobals();
$serverParams = $request->getServerParams() ?? [];
$host = parse_url($serverParams['HTTP_ORIGIN'] ?? '', PHP_URL_HOST) ?: $serverParams['HTTP_HOST'];
$proSettings = $proDomain->lookup($host);
if ($proSettings && (count($slugs) < 2 || $slugs[0] === 'blog')) {
$slugParts = explode('-', $slugs[1]);
} elseif (!$proSettings && count($slugs) >= 3 && $slugs[1] === 'blog') {
$slugParts = explode('-', $slugs[2]);
} else {
return;
}
$slugParts = explode('-', $slugs[2]);
$guid = $slugParts[count($slugParts) - 1];
if (!is_numeric($guid)) {
return;
}
$event->setResponse($this->viewHandler([ $guid ]));
$event->setResponse($this->viewHandler([$guid]));
});
}
......
......@@ -7,6 +7,7 @@
namespace Minds\Core\Feeds;
use JsonSerializable;
use Minds\Traits\Exportable;
use Minds\Traits\MagicAttributes;
......@@ -22,7 +23,7 @@ use Minds\Traits\MagicAttributes;
* @method string getUrn()
* @method FeedSyncEntity setUrn(string $urn)
*/
class FeedSyncEntity
class FeedSyncEntity implements JsonSerializable
{
use MagicAttributes;
......@@ -55,4 +56,16 @@ class FeedSyncEntity
'entity' => $this->entity ? $this->entity->export() : null,
];
}
/**
* Specify data which should be serialized to JSON
* @link https://php.net/manual/en/jsonserializable.jsonserialize.php
* @return mixed data which can be serialized by <b>json_encode</b>,
* which is a value of any type other than a resource.
* @since 5.4.0
*/
public function jsonSerialize(): array
{
return $this->export();
}
}
......@@ -73,6 +73,7 @@ class Minds extends base
(new \Minds\Entities\EntitiesProvider())->register();
(new Config\ConfigProvider())->register();
(new Router\RouterProvider())->register();
(new OAuth\OAuthProvider())->register();
(new Sessions\SessionsProvider())->register();
(new Boost\BoostProvider())->register();
......@@ -105,6 +106,7 @@ class Minds extends base
(new Faq\FaqProvider())->register();
(new Rewards\RewardsProvider())->register();
(new Plus\PlusProvider())->register();
(new Pro\ProProvider())->register();
(new Hashtags\HashtagsProvider())->register();
(new Feeds\FeedsProvider())->register();
(new Analytics\AnalyticsProvider())->register();
......
<?php
/**
* Manager
* @author edgebal
*/
namespace Minds\Core\Pro\Channel;
use Exception;
use Minds\Core\Data\cache\abstractCacher;
use Minds\Core\Di\Di;
use Minds\Core\Feeds\Top\Manager as TopManager;
use Minds\Core\Pro\Repository;
use Minds\Core\Pro\Settings;
use Minds\Entities\User;
class Manager
{
const CACHE_TTL = 300; // Cache homepage content for 5 minutes
/** @var Repository */
protected $repository;
/** @var TopManager */
protected $top;
/** @var abstractCacher */
protected $cache;
/** @var User */
protected $user;
/**
* Manager constructor.
* @param Repository $repository
* @param TopManager $top
* @param abstractCacher $cache
*/
public function __construct(
$repository = null,
$top = null,
$cache = null
) {
$this->repository = $repository ?: new Repository();
$this->top = $top ?: new TopManager();
$this->cache = $cache ?: Di::_()->get('Cache');
}
/**
* @param User $user
* @return Manager
*/
public function setUser(User $user): Manager
{
$this->user = $user;
return $this;
}
/**
* @return array
* @throws Exception
*/
public function getAllCategoriesContent(): array
{
if (!$this->user) {
throw new Exception('No user set');
}
/** @var Settings $settings */
$settings = $this->repository->getList([
'user_guid' => $this->user->guid
])->first();
if (!$settings) {
throw new Exception('Invalid Pro user');
}
$cacheKey = sprintf("pro::v1::getAllCategoriesContent::%s", $this->user->guid);
$cachedContent = $this->cache->get($cacheKey);
if ($cachedContent) {
return $cachedContent;
}
$tags = $settings->getTagList() ?: [];
$output = [];
$container = (string) $this->user->guid;
foreach ($tags as $tag) {
$opts = [
'container_guid' => $container,
'access_id' => [2, $container],
'hashtags' => [strtolower($tag['tag'])],
'filter_hashtags' => true,
'limit' => 4,
'type' => 'all',
'algorithm' => 'top',
'period' => '7d',
'sync' => true,
'single_owner_threshold' => 0,
];
$content = $this->top->getList($opts)->toArray();
if (count($content) < 2) {
$opts['algorithm'] = 'latest';
$content = $this->top->getList($opts)->toArray();
}
$output[] = [
'tag' => $tag,
'content' => $content,
];
}
$this->cache->set($cacheKey, $output, static::CACHE_TTL);
return $output;
}
}
<?php
/**
* HydrateSettingsDelegate
* @author edgebal
*/
namespace Minds\Core\Pro\Delegates;
use Minds\Core\Config;
use Minds\Core\Di\Di;
use Minds\Core\EntitiesBuilder;
use Minds\Core\Pro\Settings;
use Minds\Entities\Object\Carousel;
use Minds\Entities\User;
use Minds\Helpers\Text;
class HydrateSettingsDelegate
{
/** @var EntitiesBuilder */
protected $entitiesBuilder;
/** @var Config */
protected $config;
/**
* HydrateSettingsDelegate constructor.
* @param EntitiesBuilder $entitiesBuilder
* @param Config $config
*/
public function __construct(
$entitiesBuilder = null,
$config = null
) {
$this->entitiesBuilder = $entitiesBuilder ?: Di::_()->get('EntitiesBuilder');
$this->config = $config ?: Di::_()->get('Config');
}
/**
* @param User $user
* @param Settings $settings
* @return Settings
*/
public function onGet(User $user, Settings $settings): Settings
{
try {
$logoImage = $settings->getLogoGuid() ? sprintf(
'%sfs/v1/thumbnail/%s/master',
$this->config->get('cdn_url'),
$settings->getLogoGuid()
) : $user->getIconURL('large');
if ($logoImage) {
$settings
->setLogoImage($logoImage);
}
} catch (\Exception $e) {
error_log($e);
}
try {
$carousels = $this->entitiesBuilder->get(['subtype' => 'carousel', 'owner_guid' => (string) $user->guid]);
$carousel = $carousels[0] ?? null;
if ($carousel) {
$settings
->setBackgroundImage(sprintf(
'%sfs/v1/banners/%s/fat/%s',
$this->config->get('cdn_url'),
$carousel->guid,
$carousel->last_updated
));
}
} catch (\Exception $e) {
error_log($e);
}
try {
if ($user->getPinnedPosts()) {
$pinnedPosts = $this->entitiesBuilder->get(['guids' => Text::buildArray($user->getPinnedPosts())]);
uasort($pinnedPosts, function ($a, $b) {
if (!$a || !$b) {
return 0;
}
return ($a->time_created < $b->time_created) ? 1 : -1;
});
$featuredContent = Text::buildArray(array_values(array_filter(array_map(function ($pinnedPost) {
return $pinnedPost->entity_guid ?: $pinnedPost->guid ?: null;
}, $pinnedPosts))));
$settings->setFeaturedContent($featuredContent);
}
} catch (\Exception $e) {
error_log($e);
}
return $settings;
}
}
<?php
/**
* InitializeSettingsDelegate
* @author edgebal
*/
namespace Minds\Core\Pro\Delegates;
use Exception;
use Minds\Core\Pro\Repository;
use Minds\Core\Pro\Settings;
use Minds\Entities\User;
class InitializeSettingsDelegate
{
/** @var Repository */
protected $repository;
/** @var SetupRoutingDelegate */
protected $setupRoutingDelegate;
/**
* InitializeSettingsDelegate constructor.
* @param Repository $repository
* @param SetupRoutingDelegate $setupRoutingDelegate
*/
public function __construct(
$repository = null,
$setupRoutingDelegate = null
) {
$this->repository = $repository ?: new Repository();
$this->setupRoutingDelegate = $setupRoutingDelegate ?: new SetupRoutingDelegate();
}
/**
* @param User $user
* @throws Exception
*/
public function onEnable(User $user): void
{
/** @var Settings|null $settings */
$settings = $this->repository
->getList(['user_guid' => $user->guid])
->first();
if (!$settings) {
$settings = new Settings();
$settings
->setUserGuid($user->guid);
}
if (!$settings->getTitle()) {
$settings->setTitle($user->name ?: $user->username);
}
$this->setupRoutingDelegate
->onUpdate($settings);
$this->repository
->add($settings);
}
}