Completed
Push — master ( 98a1eb...1750fe )
by Frank
03:28
created

src/LockedCommandDecorator.php (1 issue)

Labels
Severity

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace FrankDeJonge\LockedConsoleCommand;
4
5
use Symfony\Component\Console\Application;
6
use Symfony\Component\Console\Command\Command;
7
use Symfony\Component\Console\Helper\HelperSet;
8
use Symfony\Component\Console\Input\InputInterface;
9
use Symfony\Component\Console\Output\OutputInterface;
10
use Symfony\Component\Filesystem\LockHandler;
11
12
class LockedCommandDecorator extends Command
13
{
14
    /**
15
     * @var Command
16
     */
17
    private $decoratedCommand;
18
19
    /**
20
     * @var string|LockHandler
21
     */
22
    private $lockName;
23
24
    /**
25
     * @var string
26
     */
27
    private $lockPath;
28
29
    /**
30
     * Constructor.
31
     *
32
     * @param Command            $command
33
     * @param string|LockHandler $lockName
34
     * @param string             $lockPath
35
     */
36 30
    public function __construct(Command $command, $lockName = null, $lockPath = null)
37
    {
38 30
        $this->decoratedCommand = $command;
39 30
        $this->setLockName($lockName);
40 30
        $this->lockPath = $lockPath;
41 30
    }
42
43
    /**
44
     * {@inheritdoc}
45
     */
46 3
    public function ignoreValidationErrors()
47
    {
48 3
        $this->decoratedCommand->ignoreValidationErrors();
49 3
    }
50
51
    /**
52
     * {@inheritdoc}
53
     */
54 3
    public function setApplication(Application $application = null)
55
    {
56 3
        $this->decoratedCommand->setApplication($application);
57 3
    }
58
59
    /**
60
     * {@inheritdoc}
61
     */
62 3
    public function setHelperSet(HelperSet $helperSet)
63
    {
64 3
        $this->decoratedCommand->setHelperSet($helperSet);
65 3
    }
66
67
    /**
68
     * {@inheritdoc}
69
     */
70 3
    public function getHelperSet()
71
    {
72 3
        return $this->decoratedCommand->getHelperSet();
73
    }
74
75
    /**
76
     * {@inheritdoc}
77
     */
78 3
    public function getApplication()
79
    {
80 3
        return $this->decoratedCommand->getApplication();
81
    }
82
83
    /**
84
     * {@inheritdoc}
85
     */
86 3
    public function isEnabled()
87
    {
88 3
        return $this->decoratedCommand->isEnabled();
89
    }
90
91
    /**
92
     * @param string|LockHandler|null $lockName
93
     */
94 30
    public function setLockName($lockName)
95
    {
96 30
        $this->lockName = $lockName;
97 30
    }
98
99
    /**
100
     * Runs the command.
101
     *
102
     * Before the decorated command is run, a lock is requested.
103
     * When failed to acquire the lock, the command exits.
104
     *
105
     * @param InputInterface  $input  An InputInterface instance
106
     * @param OutputInterface $output An OutputInterface instance
107
     *
108
     * @return int The command exit code
109
     */
110 12
    public function run(InputInterface $input, OutputInterface $output)
111
    {
112 12
        $this->mergeApplicationDefinition();
113 12
        $input->bind($this->getDefinition());
114 12
        $lock = $this->getLockHandler($input);
115
116 12
        if ( ! $lock->lock()) {
117 6
            $this->writeLockedMessage($input, $output);
118
119 3
            return 1;
120
        }
121
122
        try {
123 6
            return $this->decoratedCommand->run($input, $output);
124
        } finally {
125 6
            $lock->release();
126
        }
127
    }
128
129
    /**
130
     * {@inheritdoc}
131
     */
132 3
    public function setCode(callable $code)
133
    {
134 3
        $this->decoratedCommand->setCode($code);
135
136 3
        return $this;
137
    }
138
139
    /**
140
     * {@inheritdoc}
141
     */
142 15
    public function mergeApplicationDefinition($mergeArgs = true)
143
    {
144 15
        $this->decoratedCommand->mergeApplicationDefinition($mergeArgs);
145 15
    }
146
147
    /**
148
     * {@inheritdoc}
149
     */
150 3
    public function setDefinition($definition)
151
    {
152 3
        $this->decoratedCommand->setDefinition($definition);
153
154 3
        return $this;
155
    }
156
157
    /**
158
     * {@inheritdoc}
159
     */
160 15
    public function getDefinition()
161
    {
162 15
        return $this->decoratedCommand->getDefinition();
163
    }
164
165
    /**
166
     * {@inheritdoc}
167
     */
168 3
    public function getNativeDefinition()
169
    {
170 3
        return $this->decoratedCommand->getNativeDefinition();
171
    }
172
173
    /**
174
     * {@inheritdoc}
175
     */
176 3
    public function addArgument($name, $mode = null, $description = '', $default = null)
177
    {
178 3
        $this->decoratedCommand->addArgument($name, $mode, $description, $default);
179
180 3
        return $this;
181
    }
182
183
    /**
184
     * {@inheritdoc}
185
     */
186 3
    public function addOption($name, $shortcut = null, $mode = null, $description = '', $default = null)
187
    {
188 3
        $this->decoratedCommand->addOption($name, $shortcut, $mode, $description, $default);
189
190 3
        return $this;
191
    }
192
193
    /**
194
     * {@inheritdoc}
195
     */
196 3
    public function setName($name)
197
    {
198 3
        $this->decoratedCommand->setName($name);
199
200 3
        return $this;
201
    }
202
203
    /**
204
     * {@inheritdoc}
205
     */
206 3
    public function setProcessTitle($title)
207
    {
208 3
        $this->decoratedCommand->setProcessTitle($title);
209
210 3
        return $this;
211
    }
212
213
    /**
214
     * {@inheritdoc}
215
     */
216 3
    public function getName()
217
    {
218 3
        return $this->decoratedCommand->getName();
219
    }
220
221
    /**
222
     * {@inheritdoc}
223
     */
224 3
    public function setDescription($description)
225
    {
226 3
        $this->decoratedCommand->setDescription($description);
227
228 3
        return $this;
229
    }
230
231
    /**
232
     * {@inheritdoc}
233
     */
234 3
    public function getDescription()
235
    {
236 3
        return $this->decoratedCommand->getDescription();
237
    }
238
239
    /**
240
     * {@inheritdoc}
241
     */
242 3
    public function setHelp($help)
243
    {
244 3
        $this->decoratedCommand->setHelp($help);
245
246 3
        return $this;
247
    }
248
249
    /**
250
     * {@inheritdoc}
251
     */
252 3
    public function getHelp()
253
    {
254 3
        return $this->decoratedCommand->getHelp();
255
    }
256
257
    /**
258
     * {@inheritdoc}
259
     */
260 3
    public function getProcessedHelp()
261
    {
262 3
        return $this->decoratedCommand->getProcessedHelp();
263
    }
264
265
    /**
266
     * {@inheritdoc}
267
     */
268 3
    public function setAliases($aliases)
269
    {
270 3
        $this->decoratedCommand->setAliases($aliases);
271
272 3
        return $this;
273
    }
274
275
    /**
276
     * {@inheritdoc}
277
     */
278 3
    public function getAliases()
279
    {
280 3
        return $this->decoratedCommand->getAliases();
281
    }
282
283
    /**
284
     * {@inheritdoc}
285
     */
286 3
    public function getSynopsis($short = false)
287
    {
288 3
        return $this->decoratedCommand->getSynopsis($short);
289
    }
290
291
    /**
292
     * {@inheritdoc}
293
     */
294 3
    public function getHelper($name)
295
    {
296 3
        return $this->decoratedCommand->getHelper($name);
297
    }
298
299
    /**
300
     * Get the locking helper.
301
     *
302
     * @param  InputInterface $input
303
     *
304
     * @return LockHandler
305
     */
306 12
    private function getLockHandler(InputInterface $input)
307
    {
308 12
        if ($this->lockName instanceof LockHandler) {
309 9
            return $this->lockName;
310
        }
311
312 3
        $lockName = $this->getLockName($input);
313 3
        $lockPath = $this->getLockPath($input);
314
315 3
        return new LockHandler($lockName, $lockPath);
316
    }
317
318
    /**
319
     * Get the name for the lock.
320
     *
321
     * @param  InputInterface $input
322
     *
323
     * @return string
324
     */
325 15
    public function getLockName(InputInterface $input)
326
    {
327 15
        if (is_string($this->lockName)) {
328 6
            return $this->lockName;
329
        }
330
331 9
        if ($this->lockName instanceof LockHandler) {
332 3
            return 'UNKNOWN';
333
        }
334
335 6
        if ($this->decoratedCommand instanceof SpecifiesLockName) {
336 3
            return $this->decoratedCommand->getLockName($input);
337
        }
338
339 3
        return $this->decoratedCommand->getName();
340
    }
341
342
    /**
343
     * Get the lock path.
344
     *
345
     * @param  InputInterface $input
346
     *
347
     * @return null|string
348
     */
349 12
    public function getLockPath(InputInterface $input)
350
    {
351 12
        if ($this->lockName instanceof LockHandler) {
352 3
            return 'UNKNOWN';
353
        }
354
355 9
        if ($this->lockPath !== null) {
356 3
            return $this->lockPath;
357
        }
358
359 6
        if ($this->decoratedCommand instanceof SpecifiesLockPath) {
360 3
            return $this->decoratedCommand->getLockPath($input);
361
        }
362
363 3
        return sys_get_temp_dir();
364
    }
365
366
    /**
367
     * Write the "is locked" message.
368
     *
369
     * @param InputInterface  $input
370
     * @param OutputInterface $output
371
     */
372 6
    private function writeLockedMessage(InputInterface $input, OutputInterface $output)
373
    {
374 6
        $commandName = $this->decoratedCommand->getName();
375 6
        $lockName = $this->getLockName($input);
376 6
        $lockPath = $this->getLockPath($input);
377 6
        $message = sprintf(
378 6
            '<error>Command "%s" is already running, locked with "%s" at path "%s"</error>',
379 6
            $commandName,
380 6
            $lockName,
381
            $lockPath
382 6
        );
383
384 6
        if ($output instanceof ConsoleOutputInterface) {
0 ignored issues
show
The class FrankDeJonge\LockedConso...\ConsoleOutputInterface does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
385
            $output = $output->getErrorOutput();
386
        }
387
388 6
        if ($output->getVerbosity() >= OutputInterface::VERBOSITY_VERBOSE) {
389 3
            $output->writeln($message);
390 3
        }
391 3
    }
392
}
393