Skip to content

Commit 1d11269

Browse files
committed
Merge pull request #40 from phpcr/embedded_shell
[POC] Added support for embedding the shell
2 parents 4eb6150 + 28a1be7 commit 1d11269

File tree

9 files changed

+168
-23
lines changed

9 files changed

+168
-23
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ dev-master
66

77
### Features
88

9+
- [general] The shell supports being embedded as a dependency
910
- [node:edit] New command `node:edit` enables editing of entire node
1011

1112
alpha-4

features/bootstrap/FeatureContext.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ public function beforeScenario()
5050

5151
$session = $this->getSession(null, true);
5252

53-
$this->applicationTester = new ApplicationTester($this->application);
53+
$this->applicationTester = new ApplicationTester();
5454
$this->applicationTester->run(array(
5555
'--transport' => 'jackrabbit',
5656
'--no-interaction' => true,
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
3+
namespace spec\PHPCR\Shell\Console\Application;
4+
5+
use PhpSpec\ObjectBehavior;
6+
use Prophecy\Argument;
7+
use PHPCR\Shell\Console\Application\EmbeddedApplication;
8+
9+
class EmbeddedApplicationSpec extends ObjectBehavior
10+
{
11+
function let()
12+
{
13+
$this->beConstructedWith(EmbeddedApplication::MODE_COMMAND);
14+
}
15+
16+
function it_is_initializable()
17+
{
18+
$this->shouldHaveType('PHPCR\Shell\Console\Application\EmbeddedApplication');
19+
}
20+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
<?php
2+
3+
namespace PHPCR\Shell\Console\Application;
4+
5+
use PHPCR\Shell\Subscriber;
6+
7+
/**
8+
* Subclass of the full ShellApplication for running as an EmbeddedApplication
9+
* (e.g. from with the DoctrinePhpcrBundle)
10+
*
11+
* @author Daniel Leech <[email protected]>
12+
*/
13+
class EmbeddedApplication extends ShellApplication
14+
{
15+
const MODE_SHELL = 'shell';
16+
const MODE_COMMAND = 'command';
17+
18+
protected $mode = self::MODE_SHELL;
19+
20+
/**
21+
* The $mode can be one of EmbeddedApplication::MODE_SHELL or EmbeddedApplication::MODE_COMMAND.
22+
*
23+
* - Shell mode initializes the whole environement
24+
* - Command mode initailizes only enough to run commands
25+
*
26+
* @param string $mode
27+
*/
28+
public function __construct($mode)
29+
{
30+
parent::__construct(SessionApplication::APP_NAME, SessionApplication::APP_VERSION);
31+
$this->mode = $mode;
32+
$this->setAutoExit(false);
33+
}
34+
35+
/**
36+
* {@inheritDoc}
37+
*/
38+
public function init()
39+
{
40+
if (true === $this->initialized) {
41+
return;
42+
}
43+
44+
$this->registerPhpcrCommands();
45+
46+
if ($this->mode === self::MODE_SHELL) {
47+
$this->registerShellCommands();
48+
}
49+
50+
$this->initialized = true;
51+
}
52+
53+
/**
54+
* {@inheritDoc}
55+
*/
56+
protected function getDefaultCommand()
57+
{
58+
return 'shell:path:show';
59+
}
60+
61+
/**
62+
* {@inheritDoc}
63+
*/
64+
protected function registerEventListeners()
65+
{
66+
$this->dispatcher->addSubscriber(new Subscriber\ProfileFromSessionInputSubscriber());
67+
$this->dispatcher->addSubscriber(new Subscriber\ExceptionSubscriber());
68+
$this->dispatcher->addSubscriber(new Subscriber\AliasSubscriber($this->getHelperSet()));
69+
$this->dispatcher->addSubscriber(new Subscriber\AutoSaveSubscriber());
70+
}
71+
}

src/PHPCR/Shell/Console/Application/SessionApplication.php

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,7 @@ public function __construct()
2828
{
2929
parent::__construct(self::APP_NAME, self::APP_VERSION);
3030

31-
$this->shellApplication = new ShellApplication(
32-
self::APP_NAME,
33-
self::APP_VERSION
34-
);
31+
$this->shellApplication = new ShellApplication();
3532

3633
$command = new ShellCommand($this->shellApplication);
3734
$command->setApplication($this);

src/PHPCR/Shell/Console/Application/ShellApplication.php

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,11 @@ class ShellApplication extends Application
5656
*
5757
* {@inheritDoc}
5858
*/
59-
public function __construct($name = 'UNKNOWN', $version = 'UNKNOWN')
59+
public function __construct()
6060
{
61-
parent::__construct($name, $version);
61+
parent::__construct(SessionApplication::APP_NAME, SessionApplication::APP_VERSION);
6262
$this->profile = new Profile();
63-
$this->dispatcher = new EventDispatcher();
63+
$this->setDispatcher($this->dispatcher = new EventDispatcher());
6464
$this->transportRegistry = new TransportRegistry();
6565
$this->registerTransports();
6666
$this->registerHelpers();
@@ -101,14 +101,18 @@ public function setShowUnsupported($boolean)
101101
* Note that we do this "lazily" because we instantiate the ShellApplication early,
102102
* before the SessionInput has been set. The SessionInput must be set before we
103103
* can initialize the application.
104+
*
105+
* @todo: The above scenario is no longer true, we use a Profile. So maybe it can
106+
* be refactored.
104107
*/
105108
public function init()
106109
{
107110
if (true === $this->initialized) {
108111
return;
109112
}
110113

111-
$this->registerCommands();
114+
$this->registerPhpcrCommands();
115+
$this->registerShellCommands();
112116

113117
$event = new ApplicationInitEvent($this);
114118
$this->dispatcher->dispatch(PhpcrShellEvents::APPLICATION_INIT, $event);
@@ -119,7 +123,7 @@ public function init()
119123
/**
120124
* Register the helpers required by the application
121125
*/
122-
private function registerHelpers()
126+
protected function registerHelpers()
123127
{
124128
$phpcrHelper = new PhpcrHelper($this->transportRegistry, $this->profile);
125129

@@ -143,7 +147,7 @@ private function registerHelpers()
143147
/**
144148
* Register the commands used in the shell
145149
*/
146-
private function registerCommands()
150+
protected function registerPhpcrCommands()
147151
{
148152
// phpcr commands
149153
$this->add(new CommandPhpcr\AccessControlPrivilegeListCommand());
@@ -217,7 +221,10 @@ private function registerCommands()
217221
$this->add(new CommandPhpcr\LockTokenListCommand());
218222
$this->add(new CommandPhpcr\LockTokenRemoveCommand());
219223
$this->add(new CommandPhpcr\LockUnlockCommand());
224+
}
220225

226+
protected function registerShellCommands()
227+
{
221228
// add shell-specific commands
222229
$this->add(new CommandShell\AliasListCommand());
223230
$this->add(new CommandShell\ConfigInitCommand());
@@ -227,7 +234,7 @@ private function registerCommands()
227234
$this->add(new CommandShell\ExitCommand());
228235
}
229236

230-
private function registerEventListeners()
237+
protected function registerEventListeners()
231238
{
232239
$this->dispatcher->addSubscriber(new Subscriber\ProfileFromSessionInputSubscriber());
233240
$this->dispatcher->addSubscriber(new Subscriber\ProfileWriterSubscriber(
@@ -293,7 +300,7 @@ public function doRun(InputInterface $input, OutputInterface $output)
293300
$input = $event->getInput();
294301

295302
if (!$name) {
296-
$input = new ArrayInput(array('command' => 'shell:path:show'));
303+
$input = new ArrayInput(array('command' => $this->getDefaultCommand()));
297304
}
298305

299306
try {
@@ -307,6 +314,14 @@ public function doRun(InputInterface $input, OutputInterface $output)
307314
return $exitCode;
308315
}
309316

317+
/**
318+
* Return the default command
319+
*/
320+
protected function getDefaultCommand()
321+
{
322+
return 'shell:path:show';
323+
}
324+
310325
/**
311326
* Render an exception to the console
312327
*

src/PHPCR/Shell/Console/Helper/ConfigHelper.php

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,11 @@ public function getConfigDir()
9898
return $home;
9999
}
100100

101+
private function getDistConfigDir()
102+
{
103+
return __DIR__ . '/../../Resources/config.dist';
104+
}
105+
101106
/**
102107
* Load the configuration
103108
*/
@@ -106,13 +111,17 @@ public function loadConfig()
106111
$config = array();
107112

108113
$configDir = $this->getConfigDir();
114+
$distConfigDir = $this->getDistConfigDir();
109115

110116
foreach ($this->configKeys as $configKey) {
111117
$fullPath = $configDir . '/' . $configKey . '.yml';
118+
$fullDistPath = $distConfigDir . '/' . $configKey . '.yml';
112119
$config[$configKey] = array();
113120

114121
if ($this->filesystem->exists($fullPath)) {
115122
$config[$configKey] = Yaml::parse($fullPath);
123+
} elseif($this->filesystem->exists($fullDistPath)) {
124+
$config[$configKey] = Yaml::parse($fullDistPath);
116125
}
117126
}
118127

@@ -153,7 +162,7 @@ public function initConfig(OutputInterface $output = null, DialogHelper $dialogH
153162
}
154163

155164
$configDir = $this->getConfigDir();
156-
$distDir = __DIR__ . '/../../Resources/config.dist';
165+
$distDir = $this->getDistConfigDir();
157166

158167
if (!$this->filesystem->exists($configDir)) {
159168
$log('<info>[+] Creating directory:</info> ' . $configDir);

src/PHPCR/Shell/Console/Helper/PhpcrHelper.php

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use PHPCR\Shell\PhpcrSession;
99
use PHPCR\SimpleCredentials;
1010
use PHPCR\Shell\Transport\TransportRegistryInterface;
11+
use PHPCR\SessionInterface;
1112

1213
/**
1314
* Helper for managing PHPCR sessions
@@ -30,13 +31,6 @@ class PhpcrHelper extends Helper
3031
*/
3132
protected $transportRegistry;
3233

33-
/**
34-
* Lazy initialize PHPCR session
35-
*
36-
* @var boolean
37-
*/
38-
protected $initialized = false;
39-
4034
/**
4135
* @param TransportRegistryInterface $transportRegistry
4236
* @param Profile $profile
@@ -57,12 +51,16 @@ public function getName()
5751

5852
private function init()
5953
{
60-
if (false === $this->initialized) {
54+
if (null === $this->session) {
6155
$this->initSession();
62-
$this->initialized = true;
6356
}
6457
}
6558

59+
public function setSession(SessionInterface $session)
60+
{
61+
$this->session = $session;
62+
}
63+
6664
/**
6765
* Initialize the PHPCR session
6866
*
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
3+
namespace PHPCR\Shell\Subscriber;
4+
5+
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
6+
use Symfony\Component\Console\Event\ConsoleTerminateEvent;
7+
use Symfony\Component\Console\ConsoleEvents;
8+
9+
/**
10+
* Automatically save on console terminate event
11+
*
12+
* @author Daniel Leech <[email protected]>
13+
*/
14+
class AutoSaveSubscriber implements EventSubscriberInterface
15+
{
16+
public static function getSubscribedEvents()
17+
{
18+
return array(
19+
ConsoleEvents::TERMINATE => 'handleTerminate',
20+
);
21+
}
22+
23+
public function handleTerminate(ConsoleTerminateEvent $event)
24+
{
25+
$command = $event->getCommand();
26+
$output = $event->getOutput();
27+
$session = $command->getHelper('phpcr')->getSession();
28+
29+
if ($session->hasPendingChanges()) {
30+
$output->writeln('<info>Auto-saving session</info>');
31+
}
32+
$session->save();
33+
}
34+
}

0 commit comments

Comments
 (0)