-
Notifications
You must be signed in to change notification settings - Fork 305
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Task assembly #284
Task assembly #284
Conversation
… us to reduce internal coupling, and also support temporary and simulated tasks in a uniform way.
@@ -36,7 +45,10 @@ protected function taskSemVer($pathToSemVer = '.semver') | |||
*/ | |||
protected function taskServer($port = 8000) | |||
{ | |||
return new PhpServer($port); | |||
return $this->taskAssembler()->assemble( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Line indented incorrectly; expected at least 12 spaces, found 8
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see what's wrong about the formatting of this line. Looks the same as all of the others like it. No tabs that I can see. Odd.
The accessor methods added here were showing up as commands, so I added a filter to automatically remove accessors from command lists. It would also be possible to add an annotation to opt-out of command selection. |
It also seems that we could replace task assemblers with direct use of a DI container. This would be particularly convenient if we used a container that supported inflectors, such as League\Container. Doing this would substantially change the syntax of Robo, though; UPDATE: I think I'd prefer to avoid tying this part of the code to the specific container implementation. It will reduce coupling between the code to rely only on constructor / setter injection. |
See the discussion in the Drush issue queue on the thought process I went through to select a proposed DI container for Drush. Aurora DI could work; it's syntax is fine, but I didn't really like the names of its methods. I like league/container quite a bit more than Symfony DI. |
{ | ||
$this->logger = $logger; | ||
} | ||
use LoggerAwareTrait; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Line indented incorrectly; expected at least 4 spaces, found 3
Switched to league/container for DI. The inflector feature allows us to automatically inject a logger into any object (managed by the DI container) simply by having it implement LoggerAwareInterface and use LoggerAwareTrait. This gives us the convenience of auto-wiring, but in a more controlled, declarative way. |
@@ -21,7 +21,7 @@ | |||
"symfony/console": "~2.5|~3.0", | |||
"symfony/process": "~2.5|~3.0", | |||
"symfony/filesystem": "~2.5|~3.0", | |||
"symfony/dependency-injection": "~2.5|~3.0" | |||
"league/container": "~2" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good choice )
I really like your choice of container But I think If we choose it, maybe we can use it in full and not include task assembler class. The overall concept seems like factory method, so it can be moved to the container.
Yes, this will be much cleaner if container would manage creation of tasks, and inject everything. Probably you can use http://container.thephpleague.com/factory-closures/ to implement Also I'd ask you to use And thanks for your work. I really like the way it is moving, but I'm still desore to find a way to keep things simpler ) |
@@ -14,6 +16,25 @@ | |||
*/ | |||
trait TaskIO | |||
{ | |||
use LoggerAwareTrait; | |||
|
|||
static $gaveDeprecationWarning = false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Visibility must be declared on property $gaveDeprecationWarning
|
||
if (is_dir($tmpPath)) { | ||
$this->say("Created a temporary directory at $tmpPath"); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Expected 1 space after closing brace; newline found
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Expected 1 space after closing brace; newline found
00d525f
to
9b31b4e
Compare
The latest technique does not quite work due to a limitation in League/Container. I have submitted a PR to rectify the situation. I suspect the maintainer might want to see the strictly backwards-compatible implementation of this. |
Submitted a backwards compatible version: thephpleague/container#94 |
Hope this is agreeable thephpleague/container#94 (comment) |
… multiple providers may be registered.
Thanks, @philipobenito! Works great & is totally awesome. This will be great for both Robo and Drush. |
Brilliant stuff, I'll get you a tag sorted in the next few mins. |
@DavertMik this is now using the tagged release of league/container. I think this should now meet all of your expectations per our last chat -- and, against all odds, even maintains bc (although --simulate won't work for folks who keep using the deprecated bc loadTasks conventions). Take a look and let me know. Excited to see this merged soon! |
Not captured in the discussion above (from chat): we want to preserve loadTasks for parameter type hinting, and autocomplete in IDEs. However, now that we have combined the service provider into the loadTasks file, it isn't so bad to have both. The pattern for making new tasks is pretty apparent from the existing examples; I'll also update the documentation on this. |
Awesome ❤️ ❤️ ❤️ |
This PR introduces the concept of task assembly, which is done by way of the TaskAssembler, a helper object that helps do dependency injection on tasks that are created at runtime (as opposed to during container initialization, where the DI container can be used for this purpose).
The old way to build tasks looks like this:
With task assembly, it now looks like this:
The benefit of using the task assembler is threefold:
setLogger
& c. as necessary on the task, after it is constructed, reducing coupling between the different areas of the code.complete()
method will be called at shutdown time, if the task isrun()
.run()
without actually making any persistent changes.This PR does not break backwards compatibility with existing external Robo tasks. Existing tasks that continue to use the old builder pattern will still work; however, they will silently ignore the
--simulate
flag, and execute instead. To break backwards compatibility and force old tasks to update, all that needs to be done is remove one of the last references to the Config class, and then all task printing operations will fail for tasks that have not updated to the new mechanism.