Commit 29d07b79 authored by Marcelo Rivera's avatar Marcelo Rivera

WIP: (feat): pro SEO

1 merge request!308WIP: (feat): Minds Pro
Pipeline #80226882 failed with stages
in 4 minutes and 50 seconds
<?php
/**
* @author: eiennohi.
*/
namespace Minds\Core\Pro;
use Minds\Core\Config;
use Minds\Core\Di\Di;
use Minds\Core\EntitiesBuilder;
use Minds\Core\SEO\Manager;
use Minds\Entities\Activity;
use Minds\Entities\User;
use Minds\Helpers;
class SEO
{
/** @var EntitiesBuilder */
protected $entitiesBuilder;
/** @var Config */
protected $config;
public function __construct(EntitiesBuilder $entitiesBuilder = null, Config $config = null)
{
$this->entitiesBuilder = $entitiesBuilder ?: Di::_()->get('EntitiesBuilder');
$this->config = $config ?: Di::_()->get('Config');
}
public function setup(Settings $proSettings)
{
Manager::reset();
$channel = new User($proSettings->getUserGuid());
$title = $proSettings->getOneLineHeadline() ?? $channel->name;
Manager::setDefaults([
'title' => $title,
'description' => $proSettings->getOneLineHeadline(),
'keywords' => $channel->getTags(),
'og:title' => $title,
'og:url' => $proSettings->getDomain(),
'og:description' => $proSettings->getOneLineHeadline(),
'og:type' => 'website',
'og:image' => $proSettings->getLogoImage() ?? $this->config->cdn_assets_url . 'assets/logos/placeholder.jpg',
'og:image:width' => 471,
'og:image:height' => 199,
]);
Manager::add('/feed', [$this, 'activityHandler']);
Manager::add('/videos', [$this, 'entityHandler']);
Manager::add('/images', [$this, 'entityHandler']);
Manager::add('/articles', [$this, 'entityHandler']);
Manager::add('/groups', [$this, 'entityHandler']);
// Manager::add('/login', [$this, 'entityHandler']);
// blog slugs
// media slugs
}
function activityHandler($slugs = [])
{
if (isset($slugs[0]) && is_numeric($slugs[0])) {
$activity = new Activity($slugs[0]);
if (!$activity->guid || Helpers\Flags::shouldFail($activity)) {
header("HTTP/1.0 404 Not Found");
return [
'robots' => 'noindex',
];
}
if ($activity->paywall) {
return;
}
$title = $activity->title ?: $activity->message;
$description = $activity->blurb ?: "@{$activity->ownerObj['username']} on {$this->config->site_name}";
$meta = [
'title' => $title,
'description' => $description,
'og:title' => $title,
'og:description' => $description,
'og:url' => $activity->getUrl(),
'og:image' => $activity->custom_type == 'batch' ? $activity->custom_data[0]['src'] : $activity->thumbnail_src,
'og:image:width' => 2000,
'og:image:height' => 1000,
'twitter:site' => '@minds',
'twitter:card' => 'summary',
'al:ios:url' => 'minds://activity/' . $activity->guid,
'al:android:url' => 'minds://minds/activity/' . $activity->guid,
'robots' => 'all',
];
if ($activity->custom_type == 'video') {
$meta['og:type'] = "video";
$meta['og:image'] = $activity->custom_data['thumbnail_src'];
}
return $meta;
}
}
function getEntityProperty($entity, $prop)
{
$getter = "get${$prop}";
return Helpers\MagicAttributes::getterExists($entity, $getter) ? $entity->{$getter}() : $entity->{$prop};
}
function entityHandler($slugs = [])
{
if (isset($slugs[0]) && is_numeric($slugs[0])) {
$entity = $this->entitiesBuilder->single($slugs[0]);
if (!$entity->guid || Helpers\Flags::shouldFail($entity)) {
header("HTTP/1.0 404 Not Found");
return [
'robots' => 'noindex',
];
}
if ($entity->paywall) {
return;
}
$owner = $this->getEntityProperty($entity, 'ownerObj');
$title = $this->getEntityProperty($entity, 'title') ?: $this->getEntityProperty($entity, 'message');
$siteName = $this->config->site_name;
$description = $this->getEntityProperty($entity, 'blurb') ?: "@{$owner['username']} on {$siteName}";
$meta = [
'title' => $title,
'description' => $description,
'og:title' => $title,
'og:description' => $description,
'og:url' => $entity->getUrl(),
'og:image:width' => 2000,
'og:image:height' => 1000,
'robots' => 'all',
];
switch ($entity->subtype) {
case 'video':
$meta['og:type'] = "video";
$meta['og:image'] = $entity->getIconUrl();
break;
case 'image':
$meta['og:type'] = "image";
$meta['og:image'] = $entity->getIconUrl();
break;
case 'blog':
$meta['og:type'] = "blog";
$meta['og:image'] = $entity->getIconUrl();
break;
case 'group':
$meta['og:type'] = "group";
$meta['og:image'] = $this->config->cdn_url . 'fs/v1/banner/' . $entity->banner;
break;
}
return $meta;
}
}
}
......@@ -103,6 +103,10 @@ class Settings implements JsonSerializable
/** @var array */
protected $featuredContent = [];
public function getOneLineHeadline() {
return preg_replace("/\\r?\\n+/", ' ', $this->headline);
}
/**
* @return array
*/
......@@ -112,14 +116,12 @@ class Settings implements JsonSerializable
$primaryColor = $this->primaryColor ?: static::DEFAULT_PRIMARY_COLOR;
$plainBackgroundColor = $this->plainBackgroundColor ?: static::DEFAULT_PLAIN_BACKGROUND_COLOR;
$oneLineHeadline = preg_replace("/\\r?\\n+/", ' ', $this->headline);
return [
'user_guid' => (string) $this->userGuid,
'domain' => $this->domain,
'title' => $this->title,
'headline' => $this->headline,
'one_line_headline' => $oneLineHeadline,
'one_line_headline' => $this->getOneLineHeadline(),
'text_color' => $textColor,
'primary_color' => $primaryColor,
'plain_background_color' => $plainBackgroundColor,
......
......@@ -2,12 +2,11 @@
namespace Minds\Core;
use Minds\Core\Di\Di;
use Minds\Core\I18n\I18n;
use Minds\Helpers;
use Minds\Core\Di\Di;
use Zend\Diactoros\ServerRequestFactory;
use Zend\Diactoros\Response;
use Zend\Diactoros\Response\JsonResponse;
use Zend\Diactoros\ServerRequestFactory;
/**
* Minds Core Router.
......@@ -104,8 +103,6 @@ class Router
// XSRF Cookie - may be able to remove now with OAuth flow
Security\XSRF::setCookie();
new SEO\Defaults(Di::_()->get('Config'));
if (Session::isLoggedin()) {
Helpers\Analytics::increment('active');
}
......
......@@ -21,8 +21,10 @@ class Manager
*/
public function __construct(
$middleware = null
) {
)
{
$this->middleware = $middleware ?: [
new Middleware\SEOMiddleware(),
new Middleware\ProMiddleware(), // this needs to always be the last element in this array
];
}
......
......@@ -10,6 +10,7 @@ use Minds\Core\Di\Di;
use Minds\Core\Pro\Domain;
use Zend\Diactoros\Response\JsonResponse;
use Zend\Diactoros\ServerRequest;
use Minds\Core\Pro\SEO;
class ProMiddleware implements RouterMiddleware
{
......@@ -22,7 +23,8 @@ class ProMiddleware implements RouterMiddleware
*/
public function __construct(
$proDomain = null
) {
)
{
$this->proDomain = $proDomain ?: Di::_()->get('Pro\Domain');
}
......@@ -35,17 +37,27 @@ class ProMiddleware implements RouterMiddleware
{
$origin = $request->getServerParams()['HTTP_ORIGIN'];
$host = parse_url($origin, PHP_URL_HOST);
// var_dump('server');
// var_dump($_SERVER);
// var_dump('origin');
// var_dump($origin);
// var_dump('host');
// var_dump($host);
if (!$host) {
return;
}
$settings = $this->proDomain->lookup($host);
// var_dump('settings');
// var_dump($settings);
if (!$settings) {
return;
}
(new SEO())->setup($settings);
header(sprintf("Access-Control-Allow-Origin: %s", $origin));
header('Access-Control-Allow-Credentials: true');
header('Access-Control-Max-Age: 86400');
......
<?php
namespace Minds\Core\Router\Middleware;
use Minds\Core\Di\Di;
use Minds\Core\SEO;
use Zend\Diactoros\Response\JsonResponse;
use Zend\Diactoros\ServerRequest;
class SEOMiddleware implements RouterMiddleware
{
public function onRequest(ServerRequest $request, JsonResponse &$response)
{
new SEO\Defaults(Di::_()->get('Config'));
}
}
......@@ -2,6 +2,7 @@
/**
* SEO Manager
*/
namespace Minds\Core\SEO;
use Minds\Core\Events\Dispatcher;
......@@ -10,9 +11,15 @@ class Manager
{
public static $routes = [];
public static $defaults = [
'title' => ''
'title' => '',
];
public static function reset()
{
self::$routes = [];
self::$defaults = ['title' => ''];
}
/**
* Add a callback to provide metadata
* @param string $route
......@@ -49,9 +56,9 @@ class Manager
while ($route) {
$event = Dispatcher::trigger('seo:route', $route, [
'route' => $route,
'slugs' => array_reverse($slugs)
], false);
'route' => $route,
'slugs' => array_reverse($slugs),
], false);
if ($event !== false) {
$meta = $event;
......@@ -62,7 +69,7 @@ class Manager
$meta = call_user_func_array(self::$routes[$route], [array_reverse($slugs)]) ?: [];
break;
} else {
$slugs[] = substr($route, strrpos($route, '/')+1);
$slugs[] = substr($route, strrpos($route, '/') + 1);
if (strrpos($route, '/') === 0) {
$route = '/';
} else {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment