Skip to content

Commit

Permalink
Introduce a factory for the Doctype view helper.
Browse files Browse the repository at this point in the history
This factory and default configuration preserves the historic method of configuring the doctype for an MVC application
  • Loading branch information
gsteel committed Aug 8, 2022
1 parent 36a790a commit 019c5b9
Show file tree
Hide file tree
Showing 4 changed files with 150 additions and 0 deletions.
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"php": "^7.4 || ~8.0.0 || ~8.1.0",
"laminas/laminas-http": "^2.15",
"laminas/laminas-servicemanager": "^3.16.0",
"laminas/laminas-view": "^2.22.0",
"psr/container": "^1 || ^2",
"webmozart/assert": "^1.11.0"
},
Expand Down
15 changes: 15 additions & 0 deletions src/ConfigProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Laminas\Mvc\View;

use Laminas\ServiceManager\ConfigInterface;
use Laminas\View\Helper as ViewHelper;

/** @psalm-import-type ServiceManagerConfigurationType from ConfigInterface */
final class ConfigProvider
Expand All @@ -27,6 +28,16 @@ public function __invoke(): array
*/
'server_url' => null, // i.e 'https://example.com'
],
/**
* MVC has historically used the `view_manager` top-level key for a range of configuration options
*/
'view_manager' => [
/**
* Configure a doctype for HTML views by selecting one of the available constants in the
* {@link ViewHelper\Doctype} helper class.
*/
'doctype' => null,
],
];
}

Expand All @@ -42,6 +53,10 @@ public function getViewHelperConfig(): array
return [
'factories' => [
Helper\ServerUrl::class => Helper\Factory\ServerUrlFactory::class,
/**
* Factories for helpers in Laminas\View
*/
ViewHelper\Doctype::class => Helper\Factory\DoctypeFactory::class,
],
'aliases' => [
'serverUrl' => Helper\ServerUrl::class,
Expand Down
39 changes: 39 additions & 0 deletions src/Helper/Factory/DoctypeFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

declare(strict_types=1);

namespace Laminas\Mvc\View\Helper\Factory;

use ArrayAccess;
use Laminas\View\Helper\Doctype;
use Psr\Container\ContainerInterface;

use function assert;
use function is_array;
use function is_string;

final class DoctypeFactory
{
public function __invoke(ContainerInterface $container): Doctype
{
$helper = new Doctype();

if (! $container->has('config')) {
return $helper;
}

$config = $container->get('config');
assert(is_array($config) || $config instanceof ArrayAccess);

$options = $config['view_manager'] ?? [];
assert(is_array($options));

/** @var mixed $doctype */
$doctype = $options['doctype'] ?? null;
if (is_string($doctype)) {
$helper->setDoctype($doctype);
}

return $helper;
}
}
95 changes: 95 additions & 0 deletions test/Helper/Factory/DoctypeFactoryTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
<?php

declare(strict_types=1);

namespace LaminasTest\Mvc\View\Helper\Factory;

use Laminas\Mvc\View\Helper\Factory\DoctypeFactory;
use Laminas\View\Helper\Doctype;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Psr\Container\ContainerInterface;

final class DoctypeFactoryTest extends TestCase
{
private DoctypeFactory $factory;
/** @var MockObject&ContainerInterface */
private ContainerInterface $container;

protected function setUp(): void
{
parent::setUp();

$this->factory = new DoctypeFactory();
$this->container = $this->createMock(ContainerInterface::class);
Doctype::unsetDoctypeRegistry(); // Overcome nasty static state
}

public function testAHelperWillBeReturnedWhenNoConfigIsFound(): void
{
$this->container->expects(self::once())
->method('has')
->with('config')
->willReturn(false);

$this->container->expects(self::never())
->method('get');

$this->factory->__invoke($this->container);
}

public function testThatTheDoctypeWillBeAsConfiguredWhenAppropriateConfigCanBeFound(): void
{
$config = [
'view_manager' => [
'doctype' => Doctype::HTML4_FRAMESET,
],
];

$this->container->expects(self::once())
->method('has')
->with('config')
->willReturn(true);

$this->container->expects(self::once())
->method('get')
->with('config')
->willReturn($config);

$helper = $this->factory->__invoke($this->container);

self::assertEquals(Doctype::HTML4_FRAMESET, $helper->getDoctype());
}

/** @return array<string, array{0: iterable<mixed>, 1: string}> */
public function configProvider(): array
{
$helper = new Doctype();
$default = $helper->getDoctype();

return [
'Empty Config' => [[], $default],
'Missing Doctype Key' => [['view_manager' => []], $default],
'Doctype Configured' => [['view_manager' => ['doctype' => Doctype::XHTML1_RDFA]], Doctype::XHTML1_RDFA],
'Doctype Explicit Null' => [['view_manager' => ['doctype' => null]], $default],
];
}

/** @dataProvider configProvider */
public function testConfigScenarios(iterable $config, string $expectedDoctype): void
{
$this->container->expects(self::once())
->method('has')
->with('config')
->willReturn(true);

$this->container->expects(self::once())
->method('get')
->with('config')
->willReturn($config);

$helper = $this->factory->__invoke($this->container);

self::assertEquals($expectedDoctype, $helper->getDoctype());
}
}

0 comments on commit 019c5b9

Please sign in to comment.