Skip to content

Commit 1048d65

Browse files
committed
First bundle setup
1 parent b4dfa7b commit 1048d65

20 files changed

+978
-1
lines changed

.gitignore

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
composer.lock
2+
vendor/
3+
.php_cs
4+
.php_cs.cache

.php_cs.dist

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
return PhpCsFixer\Config::create()
4+
->setRules([
5+
'@Symfony' => true,
6+
'declare_strict_types' => true,
7+
'ordered_imports' => true,
8+
'psr0' => false,
9+
'yoda_style' => false,
10+
'phpdoc_order' => true,
11+
'array_syntax' => [
12+
'syntax' => 'short',
13+
],
14+
'binary_operator_spaces' => [
15+
'align_equals' => true,
16+
'align_double_arrow' => true,
17+
],
18+
'header_comment' => [
19+
'header' => <<<EOH
20+
This file is part of the ConnectHolland CookieConsentBundle package.
21+
(c) Connect Holland.
22+
EOH
23+
,
24+
]
25+
])
26+
->setFinder(
27+
PhpCsFixer\Finder::create()->in([
28+
__DIR__.'/src',
29+
__DIR__.'/tests',
30+
__DIR__.'/app',
31+
__DIR__.'/web',
32+
]
33+
));

.scrutinizer.yml

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
build:
2+
environment:
3+
timezone: Europe/Amsterdam
4+
postgresql: false
5+
rabbitmq: false
6+
mysql: false
7+
redis: false
8+
php:
9+
version: 7.2
10+
ini:
11+
'date.timezone': 'Europe/Amsterdam'
12+
project_setup:
13+
override: true
14+
tests:
15+
override:
16+
command: "php -v"
17+
# before:
18+
# - command: 'bin/websiteconsole doctrine:migrations:migrate --no-interaction --env=test'
19+
# override:
20+
# - php-scrutinizer-run
21+
# -
22+
# command: 'bin/phpunit --coverage-clover=code-coverage'
23+
# coverage:
24+
# file: 'code-coverage'
25+
# format: 'clover'

CHCookieConsentBundle.php

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of the ConnectHolland CookieConsentBundle package.
7+
* (c) Connect Holland.
8+
*/
9+
10+
namespace ConnectHolland\CookieConsentBundle;
11+
12+
use Symfony\Component\HttpKernel\Bundle\Bundle;
13+
14+
class CHCookieConsentBundle extends Bundle
15+
{
16+
}

Cookie/CookieHandler.php

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of the ConnectHolland CookieConsentBundle package.
7+
* (c) Connect Holland.
8+
*/
9+
10+
namespace ConnectHolland\CookieConsentBundle\Cookie;
11+
12+
use Symfony\Component\HttpFoundation\Cookie;
13+
use Symfony\Component\HttpFoundation\Request;
14+
use Symfony\Component\HttpFoundation\RequestStack;
15+
use Symfony\Component\HttpFoundation\Response;
16+
17+
class CookieHandler
18+
{
19+
const COOKIE_CONSENT_NAME = 'Cookie_Consent';
20+
21+
const COOKIE_CATEGORY_NAME = 'Cookie_Category_';
22+
23+
/**
24+
* @var Request
25+
*/
26+
private $request;
27+
28+
public function __construct(RequestStack $requestStack)
29+
{
30+
$this->request = $requestStack->getCurrentRequest();
31+
}
32+
33+
/**
34+
* Check if cookie consent has already been saved.
35+
*/
36+
public function hasCookieConsent(): bool
37+
{
38+
return $this->request->cookies->has(self::COOKIE_CONSENT_NAME);
39+
}
40+
41+
/**
42+
* Check if given cookie category is permitted by user.
43+
*/
44+
public function isCategoryPermitted(string $category): bool
45+
{
46+
return $this->request->cookies->get(self::COOKIE_CATEGORY_NAME.$category) === 'true';
47+
}
48+
49+
/**
50+
* Save chosen cookie categories in cookies.
51+
*/
52+
public function saveCookieConsent(Response $response, array $categories): void
53+
{
54+
$this->addCookie($response, self::COOKIE_CONSENT_NAME, date('r'));
55+
56+
foreach ($categories as $category => $permitted) {
57+
$this->addCookie($response, self::COOKIE_CATEGORY_NAME.$category, $permitted);
58+
}
59+
}
60+
61+
/**
62+
* Add cookie to response headers.
63+
*/
64+
protected function addCookie(Response $response, string $name, string $value): void
65+
{
66+
$response->headers->setCookie(
67+
new Cookie($name, $value, 0, '/', null, null, true, true)
68+
);
69+
}
70+
}

DOM/DOMParser.php

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of the ConnectHolland CookieConsentBundle package.
7+
* (c) Connect Holland.
8+
*/
9+
10+
namespace ConnectHolland\CookieConsentBundle\DOM;
11+
12+
use ConnectHolland\CookieConsentBundle\Cookie\CookieHandler;
13+
use Symfony\Component\Form\FormInterface;
14+
use Symfony\Component\HttpFoundation\Response;
15+
use Symfony\Component\Templating\EngineInterface;
16+
use Wa72\HtmlPageDom\HtmlPageCrawler;
17+
18+
class DOMParser
19+
{
20+
/**
21+
* @var EngineInterface
22+
*/
23+
private $templating;
24+
25+
/**
26+
* @var CookieHandler
27+
*/
28+
private $cookieHandler;
29+
30+
/**
31+
* @var string
32+
*/
33+
private $cookieConsentTheme;
34+
35+
public function __construct(EngineInterface $templating, CookieHandler $cookieHandler, string $cookieConsentTheme)
36+
{
37+
$this->templating = $templating;
38+
$this->cookieHandler = $cookieHandler;
39+
$this->cookieConsentTheme = $cookieConsentTheme;
40+
}
41+
42+
/**
43+
* Append content of cookie consent to Kernel Response content.
44+
*/
45+
public function appendCookieConsent(Response $response, FormInterface $form): string
46+
{
47+
$crawler = new HtmlPageCrawler($response->getContent());
48+
$crawler->filter('body')->append(
49+
$this->generateCookieConsentContent($form)
50+
);
51+
52+
return $crawler->saveHTML();
53+
}
54+
55+
/**
56+
* Generate content of CookieConsent.
57+
*/
58+
public function generateCookieConsentContent(FormInterface $form): string
59+
{
60+
return $this->templating->render('@CHCookieConsent/cookie_consent.html.twig', [
61+
'form' => $form->createView(),
62+
'theme' => $this->cookieConsentTheme,
63+
]);
64+
}
65+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of the ConnectHolland CookieConsentBundle package.
7+
* (c) Connect Holland.
8+
*/
9+
10+
namespace ConnectHolland\CookieConsentBundle\DependencyInjection;
11+
12+
use Symfony\Component\Config\FileLocator;
13+
use Symfony\Component\DependencyInjection\ContainerBuilder;
14+
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
15+
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
16+
17+
class CHCookieConsentExtension extends Extension
18+
{
19+
public function load(array $configs, ContainerBuilder $container): void
20+
{
21+
$configuration = new Configuration();
22+
23+
$config = $this->processConfiguration($configuration, $configs);
24+
25+
$container->setParameter('ch_cookie_consent.categories', $config['categories']);
26+
$container->setParameter('ch_cookie_consent.theme', $config['theme']);
27+
28+
$loader = new YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
29+
$loader->load('services.yml');
30+
}
31+
}

DependencyInjection/Configuration.php

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of the ConnectHolland CookieConsentBundle package.
7+
* (c) Connect Holland.
8+
*/
9+
10+
namespace ConnectHolland\CookieConsentBundle\DependencyInjection;
11+
12+
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
13+
use Symfony\Component\Config\Definition\ConfigurationInterface;
14+
use Symfony\Component\Config\Definition\Exception\InvalidTypeException;
15+
16+
class Configuration implements ConfigurationInterface
17+
{
18+
public function getConfigTreeBuilder(): TreeBuilder
19+
{
20+
$treeBuilder = new TreeBuilder();
21+
$rootNode = $treeBuilder->root('ch_cookie_consent');
22+
23+
$rootNode
24+
->children()
25+
->variableNode('categories')
26+
->defaultValue(['analytics', 'marketing'])
27+
->validate()
28+
->always(function ($values) {
29+
foreach ((array) $values as $value) {
30+
if (!in_array($value, ['analytics', 'marketing'])) {
31+
throw new InvalidTypeException(sprintf('Invalid cookie type %s', $value));
32+
}
33+
}
34+
35+
return (array) $values;
36+
})
37+
->end()
38+
->end()
39+
->scalarNode('theme')
40+
->defaultValue('light')
41+
->end()
42+
->end()
43+
->end()
44+
;
45+
46+
return $treeBuilder;
47+
}
48+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of the ConnectHolland CookieConsentBundle package.
7+
* (c) Connect Holland.
8+
*/
9+
10+
namespace ConnectHolland\CookieConsentBundle\EventSubscriber;
11+
12+
use ConnectHolland\CookieConsentBundle\Cookie\CookieHandler;
13+
use ConnectHolland\CookieConsentBundle\DOM\DOMParser;
14+
use ConnectHolland\CookieConsentBundle\Form\CookieConsentType;
15+
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
16+
use Symfony\Component\Form\FormFactoryInterface;
17+
use Symfony\Component\Form\FormInterface;
18+
use Symfony\Component\HttpFoundation\Cookie;
19+
use Symfony\Component\HttpFoundation\Response;
20+
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
21+
use Symfony\Component\HttpKernel\KernelEvents;
22+
23+
class AppendCookieConsentSubcriber implements EventSubscriberInterface
24+
{
25+
/**
26+
* @var CookieHandler
27+
*/
28+
private $cookieHandler;
29+
30+
/**
31+
* @var DOMParser
32+
*/
33+
private $domParser;
34+
35+
/**
36+
* @var FormFactoryInterface
37+
*/
38+
private $formFactory;
39+
40+
public function __construct(CookieHandler $cookieHandler, DOMParser $domParser, FormFactoryInterface $formFactory)
41+
{
42+
$this->cookieHandler = $cookieHandler;
43+
$this->domParser = $domParser;
44+
$this->formFactory = $formFactory;
45+
}
46+
47+
public static function getSubscribedEvents(): array
48+
{
49+
return [
50+
KernelEvents::RESPONSE => ['onResponse'],
51+
];
52+
}
53+
54+
/**
55+
* Appends Cookie Consent scripts into body.
56+
*/
57+
public function onResponse(FilterResponseEvent $event): void
58+
{
59+
if ($event->isMasterRequest() === false || $this->cookieHandler->hasCookieConsent()) {
60+
return;
61+
}
62+
63+
$request = $event->getRequest();
64+
$response = $event->getResponse();
65+
66+
$form = $this->createCookieConsentForm();
67+
$form->handleRequest($request);
68+
69+
// If form is submitted save in cookies, otherwise display cookie consent
70+
if ($form->isSubmitted() && $form->isValid()) {
71+
$this->cookieHandler->saveCookieConsent($response, $form->getData());
72+
} else {
73+
$this->showCookieConsent($response, $form);
74+
}
75+
}
76+
77+
/**
78+
* Create cookie consent form.
79+
*/
80+
protected function createCookieConsentForm(): FormInterface
81+
{
82+
return $this->formFactory->create(CookieConsentType::class);
83+
}
84+
85+
/**
86+
* Append cookie consent to Kernel Response.
87+
*/
88+
protected function showCookieConsent(Response $response, FormInterface $form)
89+
{
90+
$response->setContent(
91+
$this->domParser->appendCookieConsent($response, $form)
92+
);
93+
}
94+
}

0 commit comments

Comments
 (0)