Skip to content

Commit cdb6b7d

Browse files
author
Aaron Scherer
committed
Merge pull request #13 from therealmikz/react
Enable ReactPHP Support
2 parents 17aef48 + d476472 commit cdb6b7d

4 files changed

Lines changed: 420 additions & 331 deletions

File tree

composer.json

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,13 @@
1111
"email": "aequasi@gmail.com",
1212
"role": "developer",
1313
"homepage": "https://github.com/aequasi"
14-
}
14+
},
15+
{
16+
"name": "Michał Matulka",
17+
"email": "therealmikz@gmail.com",
18+
"role": "developer",
19+
"homepage": "https://github.com/therealmikz"
20+
}
1521
],
1622
"support": {
1723
"email": "aaron@undergroundelephant.com"
@@ -26,7 +32,8 @@
2632
"symfony/symfony": "dev-master"
2733
},
2834
"suggest": {
29-
"monolog/monolog": "Allows more advanced logging of the application flow"
35+
"monolog/monolog": "Allows more advanced logging of the application flow",
36+
"react/react": "Enables react support - use ReactCommand instead of ExtendCommand"
3037
},
3138
"autoload": {
3239
"psr-0": {
Lines changed: 342 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,342 @@
1+
<?php
2+
/**
3+
* @author Aaron Scherer <aequasi@gmail.com>
4+
* @date Oct 12, 2012
5+
*/
6+
namespace Uecode\Bundle\DaemonBundle\Command;
7+
8+
use \Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
9+
use \Symfony\Component\Console\Input\InputInterface;
10+
use \Symfony\Component\Console\Input\InputArgument;
11+
use \Symfony\Component\Console\Output\OutputInterface;
12+
use \Symfony\Component\DependencyInjection\Container;
13+
14+
use \Uecode\Bundle\DaemonBundle\System\Daemon\Exception;
15+
use \Uecode\Bundle\DaemonBundle\Service\DaemonService;
16+
17+
/**
18+
* Abstract Command class
19+
*/
20+
abstract class AbstractCommand extends ContainerAwareCommand
21+
{
22+
23+
const EVENT_START = 'EVENT_START';
24+
25+
const EVENT_CYCLE_START = 'EVENT_CYCLE_START';
26+
27+
const EVENT_CYCLE_END = 'EVENT_CYCLE_END';
28+
29+
const EVENT_STOP = 'EVENT_STOP';
30+
31+
/**
32+
* @var DaemonService $daemon
33+
*/
34+
protected $daemon;
35+
36+
/**
37+
* @var Container
38+
*/
39+
protected $container;
40+
41+
/**
42+
* @var string Command Name
43+
*/
44+
protected $name;
45+
46+
/**
47+
* @var string Command Description
48+
*/
49+
protected $description;
50+
51+
/**
52+
* @var string Command Help
53+
*/
54+
protected $help;
55+
56+
/**
57+
* @var InputInterface $input;
58+
*/
59+
protected $input;
60+
61+
/**
62+
* @var OutputInterface $output;
63+
*/
64+
protected $output;
65+
66+
/**
67+
* @var array
68+
*/
69+
protected $events = array();
70+
71+
/**
72+
* @var array Allowed Methods
73+
*/
74+
protected $methods = array( 'start', 'stop', 'restart', 'test' );
75+
76+
/**
77+
* @var bool
78+
*/
79+
private $test = false;
80+
81+
abstract protected function loop();
82+
83+
/**
84+
* @return InputInterface
85+
*/
86+
public function getInput()
87+
{
88+
return $this->input;
89+
}
90+
91+
/**
92+
* @param InputInterface $input
93+
*/
94+
public function setInput( InputInterface $input )
95+
{
96+
$this->input = $input;
97+
}
98+
99+
/**
100+
* Configures the command
101+
*/
102+
final protected function configure()
103+
{
104+
$this->addMethods();
105+
106+
$this
107+
->setName( $this->name )
108+
->setDescription( $this->description )
109+
->setHelp( $this->help )
110+
->addArgument( 'method', InputArgument::REQUIRED, implode( '|', $this->methods ) );
111+
112+
$this->setArguments();
113+
$this->setOptions();
114+
}
115+
116+
/**
117+
* Set add new methods for the daemon
118+
*/
119+
protected function addMethods()
120+
{
121+
}
122+
123+
/**
124+
* Set the arguments for the command
125+
*/
126+
protected function setArguments()
127+
{
128+
}
129+
130+
/**
131+
* Set the options for the command
132+
*/
133+
protected function setOptions()
134+
{
135+
}
136+
137+
/**
138+
* Adds the given method to the list of allowed methods
139+
*
140+
* @param string $method
141+
*/
142+
protected function addMethod( $method )
143+
{
144+
if( !arra_key_exists( $method, $this->methods) ) {
145+
$this->methods[] = $method;
146+
}
147+
}
148+
149+
/**
150+
* Grabs the argument data and runs the argument on the daemon
151+
*
152+
* @param \Symfony\Component\Console\Input\InputInterface $input
153+
* @param \Symfony\Component\Console\Output\OutputInterface $output
154+
*
155+
* @return void
156+
* @throws \Exception
157+
*/
158+
final protected function execute( InputInterface $input, OutputInterface $output )
159+
{
160+
$method = $input->getArgument( 'method' );
161+
if ( !in_array( $method, $this->methods ) ) {
162+
throw new \Exception( sprintf( 'Method must be one of: %s', implode( ', ', $this->methods ) ) );
163+
}
164+
$this->setInput( $input );
165+
$this->setOutput( $output );
166+
$this->test = $method == 'test' ? true : false;
167+
$this->container = $this->getContainer();
168+
169+
$this->createDaemon();
170+
call_user_func( array( $this, $method ) );
171+
}
172+
173+
/**
174+
* Creates and Initializes the daemon
175+
*/
176+
final protected function createDaemon()
177+
{
178+
$this->daemon = $this->container->get( 'uecode.daemon_service' );
179+
$daemonName = strtolower( str_replace( ':', '_', $this->getName() ) );
180+
if ( !$this->container->hasParameter( $daemonName . '.daemon.options' ) ) {
181+
throw new \Exception( sprintf( "Couldnt find a daemon for %s", $daemonName . '.daemon.options' ) );
182+
}
183+
$this->daemon->initialize( $this->container->getParameter( $daemonName . '.daemon.options' ) );
184+
}
185+
186+
/**
187+
* Adds an event to the command
188+
*
189+
* @param string $type Type of the event, EVENT_START, EVENT_CYCLE_START, EVENT_CYCLE_STOP, EVENT_STOP right now
190+
* @param string $name Name of the event
191+
* @param \Closure|callable $function
192+
*
193+
* @throws \Exception Throws an exception on bad arguments
194+
*/
195+
protected function addEvent( $type, $name, $function )
196+
{
197+
if ( is_callable( $function ) || $function instanceof \Closure ) {
198+
if ( is_string( $name ) ) {
199+
$this->events[ $type ][ $name ] = $function;
200+
} else {
201+
throw new \Exception( "Name passed isn't a string. " );
202+
}
203+
} else {
204+
throw new \Exception( "Function passed is not a callable or a closure. " );
205+
}
206+
}
207+
208+
/**
209+
* Removes the named event for a given type.
210+
*
211+
* @param string $type Type of the event, EVENT_START, EVENT_CYCLE_START, EVENT_CYCLE_STOP, EVENT_STOP right now
212+
* @param string $name Name of the event
213+
*/
214+
protected function removeEvent( $type, $name )
215+
{
216+
unset( $this->events[ $type ][ $name ] );
217+
}
218+
219+
/**
220+
* Starts the Daemon
221+
*
222+
* @throws \Uecode\DaemonBundle\System\Daemon\Exception
223+
*/
224+
final protected function start()
225+
{
226+
if ( $this->daemon->isRunning() ) {
227+
throw new Exception( 'Daemon is already running!' );
228+
}
229+
230+
$this->daemon->start();
231+
232+
$this->runEvents( self::EVENT_START );
233+
234+
$this->loop();
235+
$this->runEvents( self::EVENT_STOP );
236+
$this->daemon->stop();
237+
}
238+
239+
/**
240+
* Restarts the Daemon
241+
*
242+
* @throws \Uecode\DaemonBundle\System\Daemon\Exception
243+
*/
244+
final protected function restart()
245+
{
246+
if ( !$this->daemon->isRunning() ) {
247+
throw new Exception( 'Daemon is not running!' );
248+
}
249+
250+
$this->daemon->restart();
251+
$this->runEvents( self::EVENT_START );
252+
$this->loop();
253+
$this->runEvents( self::EVENT_STOP );
254+
$this->daemon->stop();
255+
}
256+
257+
/**
258+
* Stops the Daemon
259+
*
260+
* @throws \Uecode\DaemonBundle\System\Daemon\Exception
261+
*/
262+
final protected function stop()
263+
{
264+
if ( !$this->daemon->isRunning() ) {
265+
throw new Exception( 'Daemon is not running!' );
266+
}
267+
$this->runEvents( self::EVENT_STOP );
268+
$this->daemon->stop();
269+
}
270+
271+
abstract protected function test();
272+
273+
protected function runEvents( $type )
274+
{
275+
$this->log( "Finding all {$type} events and running them. " );
276+
$events = $this->getEvents( $type );
277+
foreach ( $events as $name => $event ) {
278+
$this->log( "Running the `{$name}` {$type} event. " );
279+
if( $event instanceof \Closure ) {
280+
$event( $this );
281+
} else {
282+
call_user_func_array( $event, array( $this ) );
283+
}
284+
}
285+
}
286+
287+
protected function log( $content = '', $level = 'info' )
288+
{
289+
if ( null !== $this->test ) {
290+
$this->getOutput()->writeln( $content );
291+
}
292+
$this->container->get( 'logger' )->$level( $content );
293+
}
294+
295+
/**
296+
* @return OutputInterface
297+
*/
298+
public function getOutput()
299+
{
300+
return $this->output;
301+
}
302+
303+
/**
304+
* @param OutputInterface $output
305+
*/
306+
public function setOutput( OutputInterface $output )
307+
{
308+
$this->output = $output;
309+
}
310+
311+
/**
312+
* Gets an array of events for the given type
313+
*
314+
* @param string $type Type of events, EVENT_START, EVENT_CYCLE_START, EVENT_CYCLE_STOP, EVENT_STOP right now
315+
*
316+
* @return \Closure[]|callable[]
317+
*/
318+
protected function getEvents( $type )
319+
{
320+
return array_key_exists( $type, $this->events ) ? $this->events[ $type ] : array();
321+
}
322+
323+
/**
324+
* Sets the events for the command
325+
*/
326+
protected function setEvents()
327+
{
328+
$this->events = array();
329+
}
330+
331+
/**
332+
* Gets a service by id.
333+
*
334+
* @param string $id The service id
335+
*
336+
* @return object The service
337+
*/
338+
protected function get( $id )
339+
{
340+
return $this->container->get( $id );
341+
}
342+
}

0 commit comments

Comments
 (0)