RunOnce   A
last analyzed

Complexity

Total Complexity 15

Size/Duplication

Total Lines 98
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 15
c 2
b 0
f 0
lcom 1
cbo 3
dl 0
loc 98
rs 10

8 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 7 1
B __invoke() 0 25 4
A readArguments() 0 11 3
A acquireLock() 0 4 1
A releaseLock() 0 4 1
A execCommand() 0 11 2
A debug() 0 6 2
A pidFileFactory() 0 7 1
1
<?php
2
namespace KIVagant\RunOnce;
3
4
use Liip\ProcessManager\LockException;
5
use Liip\ProcessManager\ProcessManager;
6
use Liip\ProcessManager\PidFile;
7
8
class RunOnce
9
{
10
    protected $debug = false;
11
    protected $arguments = [];
12
13
    /**
14
     * @var ProcessManager
15
     */
16
    private $processManager;
17
18
    /**
19
     * @var PidFile
20
     */
21
    private $pidFile;
22
23
    public function __construct(ProcessManager $processManager, $argv)
24
    {
25
        $this->processManager = $processManager;
26
        $this->readArguments($argv);
27
        $pidFile = $this->pidFileFactory($processManager);
28
        $this->pidFile = $pidFile;
29
    }
30
31
    public function __invoke()
32
    {
33
        try {
34
            $this->acquireLock();
35
            $this->execCommand();
36
        } catch (RuntimeException $e) {
37
            $this->releaseLock();
38
            echo $e->getMessage(), PHP_EOL;
39
40
            return false;
41
        } catch (LockException $e) {
42
            $locker = $this->pidFile->getPid();
43
            if ($this->processManager->isProcessRunning($locker)) {
44
                $this->debug('Command was already executed with PID ', $locker);
45
46
                return false;
47
            }
48
            $this->debug($locker . ' lock released');
49
            $this->releaseLock();
50
            $this->acquireLock();
51
            $this->execCommand();
52
        }
53
54
        return true;
55
    }
56
57
    protected function readArguments($argv)
58
    {
59
        $this->arguments = $argv;
60
        unset($this->arguments[0]);
61
        if (array_key_exists(1, $this->arguments) && $this->arguments[1] === '-v') {
62
            $this->debug = true;
63
            unset($this->arguments[1]);
64
        }
65
66
        return $this->arguments;
67
    }
68
69
    protected function acquireLock()
70
    {
71
        $this->pidFile->acquireLock();
72
    }
73
74
    protected function releaseLock()
75
    {
76
        $this->pidFile->acquireLock();
77
    }
78
79
    protected function execCommand()
80
    {
81
        $command = implode(' ', $this->arguments);
82
        if (empty($command)) {
83
            throw new RuntimeException('You need to set a command as the argument to this tool');
84
        }
85
        $this->debug($command);
86
        $runningPid = $this->pidFile->execProcess($command);
87
        $this->pidFile->setPid($runningPid);
88
        $this->debug($runningPid, ' is executed and locked');
89
    }
90
91
    protected function debug()
92
    {
93
        if ($this->debug) {
94
            echo implode(' ', func_get_args()), PHP_EOL;
95
        }
96
    }
97
98
    protected function pidFileFactory(ProcessManager $processManager)
99
    {
100
        $argsHash = md5(implode(' ', $this->arguments));
101
        $pidFile = new PidFile($processManager, PID_DIR . PID_FILE . '.' . $argsHash . '.pid');
102
103
        return $pidFile;
104
    }
105
}
106