Completed
Push — master ( b77c5c...4fbeac )
by Jeroen
10s
created

Builder::createTaskRunner()   B

Complexity

Conditions 2
Paths 1

Size

Total Lines 40
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 23
CRAP Score 2.0002

Importance

Changes 0
Metric Value
dl 0
loc 40
ccs 23
cts 24
cp 0.9583
rs 8.8571
c 0
b 0
f 0
cc 2
eloc 24
nc 1
nop 1
crap 2.0002
1
<?php
2
3
/*
4
 * This file is part of the Conveyor package.
5
 *
6
 * (c) Jeroen Fiege <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Webcreate\Conveyor\Builder;
13
14
use Symfony\Component\EventDispatcher\Event;
15
use Symfony\Component\EventDispatcher\EventDispatcher;
16
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
17
use Symfony\Component\EventDispatcher\GenericEvent;
18
use Webcreate\Conveyor\Context;
19
use Webcreate\Conveyor\Event\BuilderEvents;
20
use Webcreate\Conveyor\Event\TaskRunnerEvents;
21
use Webcreate\Conveyor\IO\IOInterface;
22
use Webcreate\Conveyor\Repository\Version;
23
use Webcreate\Conveyor\Task\Result\ExecuteResult;
24
use Webcreate\Conveyor\Task\Task;
25
use Webcreate\Conveyor\Task\TaskRunner;
26
27
/**
28
 * @todo remove dependency on Context, have the BuildStage request the files
29
 */
30
class Builder
0 ignored issues
show
Complexity introduced by
The class Builder has a coupling between objects value of 14. Consider to reduce the number of dependencies under 13.
Loading history...
31
{
32
    protected $builddir;
33
    protected $io;
0 ignored issues
show
Comprehensibility introduced by
Avoid variables with short names like $io. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
34
    protected $dispatcher;
35
36
    /**
37
     * @var Context
38
     */
39
    protected $context;
40
41
    /**
42
     * @var \Webcreate\Conveyor\Task\TaskRunner
43
     */
44
    protected $taskRunner;
45
46
    /**
47
     * Constructor.
48
     *
49
     * @todo Can we refactor so we don't have to depend on the IOInterface?
50
     *
51
     * @param string                   $builddir   destionation path for build
52
     * @param array                    $tasks
53
     * @param IOInterface              $io
54
     * @param EventDispatcherInterface $dispatcher
55
     */
56 3
    public function __construct($builddir, array $tasks = array(),
0 ignored issues
show
Coding Style introduced by
The first parameter of a multi-line function declaration must be on the line after the opening bracket
Loading history...
Coding Style introduced by
Multi-line function declarations must define one parameter per line
Loading history...
57
            IOInterface $io = null, EventDispatcherInterface $dispatcher = null
0 ignored issues
show
Coding Style introduced by
Multi-line function declarations must define one parameter per line
Loading history...
Comprehensibility introduced by
Avoid variables with short names like $io. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
Coding Style introduced by
Multi-line function declaration not indented correctly; expected 8 spaces but found 12
Loading history...
58
    )
59
    {
0 ignored issues
show
Coding Style introduced by
The closing parenthesis and the opening brace of a multi-line function declaration must be on the same line
Loading history...
60 3
        $this->builddir   = rtrim($builddir, '/');
61 3
        $this->io         = $io;
62 3
        $this->dispatcher = $dispatcher;
63 3
        $this->taskRunner = $this->createTaskRunner($tasks);
64 3
    }
65
66
    /**
67
     * Creates a task runner for builder tasks
68
     *
69
     * @param  Task[]     $tasks
70
     * @return TaskRunner
71
     */
72 3
    protected function createTaskRunner(array $tasks)
73
    {
74 3
        $self = $this;
75
76 3
        $taskRunner = new TaskRunner($this->io, new EventDispatcher());
0 ignored issues
show
Bug introduced by
It seems like $this->io can be null; however, __construct() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
77 3
        $taskRunner->setTasks($tasks);
78
79 3
        $taskRunner->getDispatcher()->addListener(
80 3
            TaskRunnerEvents::TASKRUNNER_PRE_EXECUTE_TASK,
81
            function (GenericEvent $event) use ($self) {
82 2
                $task  = $event->getSubject();
83 2
                $t     = $event->getArgument('index');
84 2
                $total = $event->getArgument('total');
85
86 2
                $self->dispatch(BuilderEvents::BUILDER_PRE_TASK,
87 2
                    new GenericEvent($task, array('index' => $t, 'total' => $total))
88
                );
89 3
            }
90
        );
91
92 3
        $taskRunner->getDispatcher()->addListener(
93 3
            TaskRunnerEvents::TASKRUNNER_POST_EXECUTE_TASK,
94
            function (GenericEvent $event) use ($self) {
95 2
                $task   = $event->getSubject();
96 2
                $t      = $event->getArgument('index');
97 2
                $total  = $event->getArgument('total');
98 2
                $result = $event->getArgument('result');
99
100 2
                if ($result instanceof ExecuteResult) {
101
                    $self->applyResultToFilelist($result);
102
                }
103
104 2
                $self->dispatch(BuilderEvents::BUILDER_POST_TASK,
105 2
                    new GenericEvent($task, array('index' => $t, 'total' => $total))
106
                );
107 3
            }
108
        );
109
110 3
        return $taskRunner;
111
    }
112
113
    /**
114
     * Add task to the build process
115
     *
116
     * @param  Task  $task
117
     * @return $this
118
     */
119
    public function addTask(Task $task)
120
    {
121
        $this->taskRunner->addTask($task);
122
123
        return $this;
124
    }
125
126
    /**
127
     * Return destination path for build
128
     *
129
     * @return string
130
     */
131 1
    public function getBuildDir()
132
    {
133 1
        return $this->builddir;
134
    }
135
136
    /**
137
     * @deprecated I rather not have the builder depend on the context,
138
     *             that's something for the BuildStage
139
     *
140
     * @param  Context $context
141
     * @return $this
142
     */
143
    public function setContext(Context $context)
144
    {
145
        $this->context = $context;
146
147
        return $this;
148
    }
149
150
    /**
151
     * Run added tasks
152
     *
153
     * @param string  $target
154
     * @param Version $version
155
     */
156 2
    public function build($target, Version $version)
157
    {
158 2
        $this->dispatch(BuilderEvents::BUILDER_PRE_BUILD);
159
160 2
        $tasks = $this->getSupportedTasks($target, $version);
161
162 2
        $this->taskRunner->setTasks($tasks);
163
164 2
        $this->taskRunner->execute($target, $version);
165
166 2
        $this->dispatch(BuilderEvents::BUILDER_POST_BUILD);
167 2
    }
168
169
    protected function applyResultToFilelist(ExecuteResult $result)
170
    {
171
        $filesModified = $this->context->getFilesModified();
172
173
        foreach ($result->getDerived() as $pattern) {
174
            $filesModified->add($pattern);
175
        }
176
177
        foreach ($result->getRemoved() as $pattern) {
178
            $filesModified->remove($pattern);
179
        }
180
    }
181
182
    /**
183
     * Filters the tasks for given target
184
     *
185
     * @param  string                                 $target
186
     * @param  \Webcreate\Conveyor\Repository\Version $version
187
     * @return Task[]                                 task for the specific target
188
     */
189 2
    protected function getSupportedTasks($target, Version $version)
190
    {
191
        $tasks = array_filter($this->taskRunner->getTasks(), function ($task) use ($target, $version) {
192 2
            return (true === $task->supports($target, $version));
193 2
        });
194
195
        // reindex
196 2
        $tasks = array_values($tasks);
197
198 2
        return $tasks;
199
    }
200
201
    /**
202
     * Dispatch event when a dispatcher is available
203
     *
204
     * @param string $eventName
205
     * @param Event  $event
206
     */
207 2
    protected function dispatch($eventName, Event $event = null)
208
    {
209 2
        if (null !== $this->dispatcher) {
210 1
            $this->dispatcher->dispatch($eventName, $event);
211
        }
212 2
    }
213
}
214