Skip to content

Commit e5aae16

Browse files
committed
introduce PseudoKernel.
PseudoKernel allows Drupal's bootstrap to be treated as a service, which means it can be injected into dependencies so that Drupal can be only bootstrapped as needed when the request is not a Drupal route. Bootstrap now depends on the event dispatcher so that events can be triggered before and after bootstrap phases.
1 parent 964c677 commit e5aae16

10 files changed

+476
-29
lines changed

BangpoundDrupalBundle.php

-16
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,6 @@
1212
*/
1313
class BangpoundDrupalBundle extends Bundle
1414
{
15-
/**
16-
* Boots the Bundle.
17-
*/
18-
public function boot()
19-
{
20-
// Console applications boot twice, which leads to harmless but noisy PHP warnings.
21-
if (!defined('DRUPAL_ROOT')) {
22-
define('DRUPAL_ROOT', realpath($this->container->get('kernel')->getRootDir() .'/../web'));
23-
}
24-
25-
require_once DRUPAL_ROOT . '/includes/bootstrap.inc';
26-
27-
drupal_override_server_variables(array('url' => $this->container->getParameter('bangpound_drupal.url')));
28-
drupal_bootstrap(NULL, TRUE, $this->container->getParameter('bangpound_drupal.bootstrap.class'));
29-
}
30-
3115
/**
3216
* {@inheritDoc}
3317
*/

Bootstrap.php

+32
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,19 @@
33
namespace Bangpound\Bundle\DrupalBundle;
44

55
use Bangpound\Drupal\Bootstrap\AutoloadBootstrap;
6+
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
67

78
/**
89
* Class Bootstrap
910
* @package Bangpound\Bundle\DrupalBundle
1011
*/
1112
class Bootstrap extends AutoloadBootstrap
1213
{
14+
/**
15+
* @var EventDispatcherInterface
16+
*/
17+
private $dispatcher;
18+
1319
/**
1420
* @param array $values
1521
*/
@@ -146,4 +152,30 @@ public function __construct(array $values = array())
146152
// menu_get_item().
147153
});
148154
}
155+
156+
/**
157+
* @param null $phase
158+
*/
159+
protected function call($phase = NULL)
160+
{
161+
$this->dispatcher->dispatch(BootstrapEvents::preEvent($phase));
162+
parent::call($phase);
163+
$this->dispatcher->dispatch(BootstrapEvents::postEvent($phase));
164+
}
165+
166+
/**
167+
* @param EventDispatcherInterface $dispatcher
168+
*/
169+
public function setEventDispatcher(EventDispatcherInterface $dispatcher)
170+
{
171+
$this->dispatcher = $dispatcher;
172+
}
173+
174+
/**
175+
* {@inheritdoc}
176+
*/
177+
public function getEventDispatcher()
178+
{
179+
return $this->dispatcher;
180+
}
149181
}

BootstrapEvents.php

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
<?php
2+
3+
namespace Bangpound\Bundle\DrupalBundle;
4+
5+
/**
6+
* Class BootstrapEvents
7+
* @package Bangpound\Bundle\DrupalBundle
8+
*/
9+
final class BootstrapEvents
10+
{
11+
const PRE_CONFIGURATION = 'drupal_bootstrap.pre.configuration';
12+
const POST_CONFIGURATION = 'drupal_bootstrap.post.configuration';
13+
const PRE_PAGE_CACHE = 'drupal_bootstrap.pre.page_cache';
14+
const POST_PAGE_CACHE = 'drupal_bootstrap.post.page_cache';
15+
const PRE_DATABASE = 'drupal_bootstrap.pre.database';
16+
const POST_DATABASE = 'drupal_bootstrap.post.database';
17+
const PRE_VARIABLES = 'drupal_bootstrap.pre.variables';
18+
const POST_VARIABLES = 'drupal_bootstrap.post.variables';
19+
const PRE_SESSION = 'drupal_bootstrap.pre.session';
20+
const POST_SESSION = 'drupal_bootstrap.post.session';
21+
const PRE_PAGE_HEADER = 'drupal_bootstrap.pre.page_header';
22+
const POST_PAGE_HEADER = 'drupal_bootstrap.post.page_header';
23+
const PRE_LANGUAGE = 'drupal_bootstrap.pre.language';
24+
const POST_LANGUAGE = 'drupal_bootstrap.post.language';
25+
const PRE_FULL = 'drupal_bootstrap.pre.full';
26+
const POST_FULL = 'drupal_bootstrap.post.full';
27+
28+
/**
29+
* @param $phase
30+
* @return mixed
31+
*/
32+
public static function preEvent($phase)
33+
{
34+
$events = array(
35+
DRUPAL_BOOTSTRAP_CONFIGURATION => self::PRE_CONFIGURATION,
36+
DRUPAL_BOOTSTRAP_PAGE_CACHE => self::PRE_PAGE_CACHE,
37+
DRUPAL_BOOTSTRAP_DATABASE => self::PRE_DATABASE,
38+
DRUPAL_BOOTSTRAP_VARIABLES => self::PRE_VARIABLES,
39+
DRUPAL_BOOTSTRAP_SESSION => self::PRE_SESSION,
40+
DRUPAL_BOOTSTRAP_PAGE_HEADER => self::PRE_PAGE_HEADER,
41+
DRUPAL_BOOTSTRAP_LANGUAGE => self::PRE_LANGUAGE,
42+
DRUPAL_BOOTSTRAP_FULL => self::PRE_FULL,
43+
);
44+
45+
return $events[$phase];
46+
}
47+
48+
/**
49+
* @param $phase
50+
* @return mixed
51+
*/
52+
public static function postEvent($phase)
53+
{
54+
$events = array(
55+
DRUPAL_BOOTSTRAP_CONFIGURATION => self::POST_CONFIGURATION,
56+
DRUPAL_BOOTSTRAP_PAGE_CACHE => self::POST_PAGE_CACHE,
57+
DRUPAL_BOOTSTRAP_DATABASE => self::POST_DATABASE,
58+
DRUPAL_BOOTSTRAP_VARIABLES => self::POST_VARIABLES,
59+
DRUPAL_BOOTSTRAP_SESSION => self::POST_SESSION,
60+
DRUPAL_BOOTSTRAP_PAGE_HEADER => self::POST_PAGE_HEADER,
61+
DRUPAL_BOOTSTRAP_LANGUAGE => self::POST_LANGUAGE,
62+
DRUPAL_BOOTSTRAP_FULL => self::POST_FULL,
63+
);
64+
65+
return $events[$phase];
66+
}
67+
}

EventListener/BootstrapListener.php

+26-9
Original file line numberDiff line numberDiff line change
@@ -3,26 +3,47 @@
33
namespace Bangpound\Bundle\DrupalBundle\EventListener;
44

55
use Bangpound\Bundle\DrupalBundle\Globals;
6+
use Bangpound\Bundle\DrupalBundle\PseudoKernel;
67
use Symfony\Component\DependencyInjection\ContainerAware;
8+
use Symfony\Component\EventDispatcher\Event;
79
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
10+
use Symfony\Component\HttpKernel\HttpKernelInterface;
811

912
/**
1013
* Class BootstrapListener
1114
* @package Bangpound\Bundle\DrupalBundle\EventListener
1215
*/
1316
class BootstrapListener extends ContainerAware
1417
{
15-
// This looks dumb.
16-
private $globalz;
18+
/**
19+
* @var PseudoKernel
20+
*/
21+
private $kernel;
1722

1823
/**
1924
* @param \Bangpound\Bundle\DrupalBundle\Globals $globalz
25+
* @param PseudoKernel $kernel
2026
*/
21-
public function __construct(Globals $globalz)
27+
public function __construct(Globals $globalz, PseudoKernel $kernel)
2228
{
23-
require_once DRUPAL_ROOT . '/includes/bootstrap.inc';
29+
// Abandon the Globals object. It just needs to be instantiated.
2430

25-
$this->globalz = $globalz;
31+
$this->kernel = $kernel;
32+
}
33+
34+
/**
35+
* Listener prepares Drupal bootstrap environment.
36+
*
37+
* @param Event $event
38+
*/
39+
public function onPreConfiguration(Event $event)
40+
{
41+
if (!defined('DRUPAL_ROOT')) {
42+
define('DRUPAL_ROOT', $this->kernel->getDrupalRoot());
43+
}
44+
45+
chdir(DRUPAL_ROOT);
46+
drupal_override_server_variables(array('url' => $this->kernel->getUri()));
2647
}
2748

2849
/**
@@ -32,10 +53,6 @@ public function __construct(Globals $globalz)
3253
*/
3354
public function onKernelRequestEarly(GetResponseEvent $event)
3455
{
35-
chdir(DRUPAL_ROOT);
36-
37-
// Original bootstrap phases mostly take care of including files.
38-
drupal_bootstrap(DRUPAL_BOOTSTRAP_CONFIGURATION);
3956

4057
$request = $event->getRequest();
4158

HttpKernel/PseudoKernel.php

+149
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
<?php
2+
3+
namespace Bangpound\Bundle\DrupalBundle\HttpKernel;
4+
5+
abstract class PseudoKernel implements PseudoKernelInterface
6+
{
7+
/**
8+
* @var string
9+
*/
10+
protected $workingDir;
11+
12+
/**
13+
* @var string
14+
*/
15+
protected $environment;
16+
17+
/**
18+
* @var bool
19+
*/
20+
protected $debug;
21+
22+
/**
23+
* @var string
24+
*/
25+
protected $name;
26+
27+
/**
28+
* @var mixed
29+
*/
30+
protected $startTime;
31+
32+
/**
33+
* @var bool
34+
*/
35+
protected $booted = false;
36+
37+
/**
38+
* Constructor.
39+
*
40+
* @param string $environment The environment
41+
* @param Boolean $debug Whether to enable debugging or not
42+
*
43+
* @api
44+
*/
45+
public function __construct($environment, $debug)
46+
{
47+
$this->environment = $environment;
48+
$this->debug = (Boolean) $debug;
49+
$this->workingDir = $this->getWorkingDir();
50+
$this->name = $this->getName();
51+
52+
if ($this->debug) {
53+
$this->startTime = microtime(true);
54+
}
55+
}
56+
57+
/**
58+
* {@inheritdoc}
59+
*
60+
* @api
61+
*/
62+
public function getName()
63+
{
64+
if (null === $this->name) {
65+
$this->name = preg_replace('/[^a-zA-Z0-9_]+/', '', basename($this->workingDir));
66+
}
67+
68+
return $this->name;
69+
}
70+
71+
/**
72+
* {@inheritdoc}
73+
*
74+
* @api
75+
*/
76+
public function getEnvironment()
77+
{
78+
return $this->environment;
79+
}
80+
81+
/**
82+
* {@inheritdoc}
83+
*
84+
* @api
85+
*/
86+
public function isDebug()
87+
{
88+
return $this->debug;
89+
}
90+
91+
/**
92+
* {@inheritdoc}
93+
*
94+
* @api
95+
*/
96+
public function getWorkingDir()
97+
{
98+
if (null === $this->workingDir) {
99+
$r = new \ReflectionObject($this);
100+
$this->workingDir = str_replace('\\', '/', dirname($r->getFileName()));
101+
}
102+
103+
return $this->workingDir;
104+
}
105+
106+
/**
107+
* {@inheritdoc}
108+
*
109+
* @api
110+
*/
111+
public function getStartTime()
112+
{
113+
return $this->debug ? $this->startTime : -INF;
114+
}
115+
116+
/**
117+
* {@inheritdoc}
118+
*
119+
* @api
120+
*/
121+
public function getCharset()
122+
{
123+
return 'UTF-8';
124+
}
125+
126+
/**
127+
* {@inheritdoc}
128+
*
129+
* @api
130+
*/
131+
public function boot()
132+
{
133+
$this->booted = true;
134+
}
135+
136+
/**
137+
* {@inheritdoc}
138+
*
139+
* @api
140+
*/
141+
public function shutdown()
142+
{
143+
if (false === $this->booted) {
144+
return;
145+
}
146+
147+
$this->booted = false;
148+
}
149+
}

0 commit comments

Comments
 (0)