Skip to content

Commit

Permalink
feat: redirect to primary domain name if host is different
Browse files Browse the repository at this point in the history
  • Loading branch information
carlalexander committed Aug 24, 2020
1 parent 0dae3cc commit 8c75763
Show file tree
Hide file tree
Showing 5 changed files with 171 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/Configuration/EventManagementConfiguration.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ public function modify(Container $container)
new Subscriber\HttpApiSubscriber(),
new Subscriber\ImageEditorSubscriber($container['console_client'], $container['file_manager']),
new Subscriber\PluploadSubscriber($container['plugin_relative_path'], $container['rest_namespace'], $container['assets_url'], $container['plupload_error_messages']),
new Subscriber\RedirectSubscriber($container['ymir_primary_domain_name'], $container['is_multisite']),
new Subscriber\RestApiSubscriber($container['rest_namespace'], $container['rest_endpoints']),
new Subscriber\SecurityHeadersSubscriber(),
new Subscriber\WordPressSubscriber($container['server_software'], $container['site_url']),
Expand Down
1 change: 1 addition & 0 deletions src/Configuration/WordPressConfiguration.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ public function modify(Container $container)
return 'wordpress@'.$sitename;
});
$container['http_transport'] = _wp_http_get_object();
$container['is_multisite'] = is_multisite();
$container['phpmailer'] = function () {
if (!class_exists(\PHPMailer::class)) {
require_once ABSPATH.WPINC.'/class-phpmailer.php';
Expand Down
1 change: 1 addition & 0 deletions src/Configuration/YmirConfiguration.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class YmirConfiguration implements ContainerConfigurationInterface
public function modify(Container $container)
{
$container['ymir_environment'] = getenv('YMIR_ENVIRONMENT') ?: '';
$container['ymir_primary_domain_name'] = getenv('YMIR_PRIMARY_DOMAIN_NAME') ?: '';
$container['ymir_project_type'] = getenv('YMIR_PROJECT_TYPE') ?: 'wordpress';
}
}
75 changes: 75 additions & 0 deletions src/Subscriber/RedirectSubscriber.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<?php

declare(strict_types=1);

/*
* This file is part of Ymir WordPress plugin.
*
* (c) Carl Alexander <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Ymir\Plugin\Subscriber;

use Ymir\Plugin\EventManagement\SubscriberInterface;

/**
* Subscriber that manages redirects that would have been handled by the web server.
*/
class RedirectSubscriber implements SubscriberInterface
{
/**
* The primary domain name that we want to redirect requests to.
*
* @var string
*/
private $domainName;

/**
* Flag whether this is a multisite installation or not.
*
* @var bool
*/
private $isMultisite;

/**
* Constructor.
*/
public function __construct(string $domainName, bool $isMultisite)
{
$this->domainName = $domainName;
$this->isMultisite = $isMultisite;
}

/**
* {@inheritdoc}
*/
public static function getSubscribedEvents(): array
{
return [
'init' => ['redirectToDomainName', 1],
];
}

/**
* Redirect to the primary domain name if necessary.
*/
public function redirectToDomainName()
{
if ($this->isMultisite || empty($_SERVER['HTTP_HOST']) || $_SERVER['HTTP_HOST'] === $this->domainName) {
return;
}

$url = 'https://'.$this->domainName;

if (!empty($_SERVER['REQUEST_URI'])) {
$url .= $_SERVER['REQUEST_URI'];
}

if (wp_redirect($url, 301)) {
exit;
}
}
}
93 changes: 93 additions & 0 deletions tests/Unit/Subscriber/RedirectSubscriberTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
<?php

declare(strict_types=1);

/*
* This file is part of Ymir WordPress plugin.
*
* (c) Carl Alexander <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Ymir\Plugin\Tests\Unit\Subscriber;

use Ymir\Plugin\Subscriber\RedirectSubscriber;
use Ymir\Plugin\Tests\Mock\FunctionMockTrait;
use Ymir\Plugin\Tests\Unit\TestCase;

/**
* @covers \Ymir\Plugin\Subscriber\RedirectSubscriber
*/
class RedirectSubscriberTest extends TestCase
{
use FunctionMockTrait;

public function testGetSubscribedEvents()
{
$callbacks = RedirectSubscriber::getSubscribedEvents();

foreach ($callbacks as $callback) {
$this->assertTrue(method_exists(RedirectSubscriber::class, is_array($callback) ? $callback[0] : $callback));
}

$subscribedEvents = [
'init' => ['redirectToDomainName', 1],
];

$this->assertSame($subscribedEvents, $callbacks);
}

/**
* @backupGlobals enabled
*/
public function testRedirectToDomainNameWithHttpHostDifferentThanDomainName()
{
$_SERVER['HTTP_HOST'] = 'another_domain_name';

$wp_redirect = $this->getFunctionMock($this->getNamespace(RedirectSubscriber::class), 'wp_redirect');
$wp_redirect->expects($this->once())
->with($this->identicalTo('https://domain_name'), $this->identicalTo(301))
->willReturn(false);

(new RedirectSubscriber('domain_name', false))->redirectToDomainName();
}

/**
* @backupGlobals enabled
*/
public function testRedirectToDomainNameWithHttpHostDifferentThanDomainNameAddsRequestUri()
{
$_SERVER['HTTP_HOST'] = 'another_domain_name';
$_SERVER['REQUEST_URI'] = '/uri';

$wp_redirect = $this->getFunctionMock($this->getNamespace(RedirectSubscriber::class), 'wp_redirect');
$wp_redirect->expects($this->once())
->with($this->identicalTo('https://domain_name/uri'), $this->identicalTo(301))
->willReturn(false);

(new RedirectSubscriber('domain_name', false))->redirectToDomainName();
}

/**
* @backupGlobals enabled
*/
public function testRedirectToDomainNameWithHttpHostSameAsDomainName()
{
$_SERVER['HTTP_HOST'] = 'domain_name';

$wp_redirect = $this->getFunctionMock($this->getNamespace(RedirectSubscriber::class), 'wp_redirect');
$wp_redirect->expects($this->never());

(new RedirectSubscriber('domain_name', false))->redirectToDomainName();
}

public function testRedirectToDomainNameWithMultisiteEnabled()
{
$wp_redirect = $this->getFunctionMock($this->getNamespace(RedirectSubscriber::class), 'wp_redirect');
$wp_redirect->expects($this->never());

(new RedirectSubscriber('domain_name', true))->redirectToDomainName();
}
}

0 comments on commit 8c75763

Please sign in to comment.