CommandExecuter::execute()   F
last analyzed

Complexity

Conditions 25
Paths 12802

Size

Total Lines 119
Code Lines 72

Duplication

Lines 16
Ratio 13.45 %

Importance

Changes 0
Metric Value
cc 25
eloc 72
nc 12802
nop 8
dl 16
loc 119
rs 2
c 0
b 0
f 0

How to fix   Long Method    Complexity    Many Parameters   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
/**
4
 * This class help for executing external programs
5
 * This is necessary as PHP Threads are not very popular
6
 * It also requires an extra dependency
7
 * Relying on system execution
8
 */
9
10
use SA\CpeSdk;
11
12
class CommandExecuter
13
{
14
    private $cpeLogger;
15
    private $logKey;
16
17
    const EXEC_FAILED = "EXEC_FAILED";
18
19
    public function __construct($cpeLogger, $logKey = null)
20
    {
21
        $this->cpeLogger = $cpeLogger;
22
        $this->logKey    = $logKey;
23
    }
24
25
    public function execute(
26
        $cmd,
27
        $sleep = 1,
28
        $descriptors = array(
29
            1 => array("pipe", "w"),
30
            2 => array("pipe", "w")
31
        ),
32
        $progressCallback = null,
33
        $progressCallbackParams = null,
34
        $showProgress = false,
35
        $callbackTurns = 0,
36
        $logKey = null)
37
    {
38
        if ($logKey)
39
            $this->logKey = $logKey;
40
        
41
        $this->cpeLogger->logOut("INFO", basename(__FILE__), "Executing: $cmd", $this->logKey);
42
43
        // Start execution of $cmd
44
        if (!($process = proc_open($cmd, $descriptors, $pipes)) ||
45
            !is_resource($process)) {
46
            $this->cpeLogger->logOut("ERROR",
47
                                     basename(__FILE__), "Unable to execute command:\n$cmd",
48
                                     $this->logKey);
49
            throw new CpeSdk\CpeException("Unable to execute command:\n$cmd\n",
50
                                          self::EXEC_FAILED);
51
        }
52
53
        // Set the pipes as non-blocking
54 View Code Duplication
        if (isset($descriptors[1]) &&
55
            $descriptors[1]) {
56
            stream_set_blocking($pipes[1], FALSE);
57
        }
58 View Code Duplication
        if (isset($descriptors[2]) &&
59
            $descriptors[2]) {
60
            stream_set_blocking($pipes[2], FALSE);
61
        }
62
63
        $i = 0;
64
65
        // Used to store all output
66
        $allOut = "";
67
        $allOutErr = "";
68
69
        // Check process status at every turn
70
        do {
71
            sleep($sleep);
72
73
            // If callback only after N turns
74
            if ( !$callbackTurns || in_array($i, array(0, $callbackTurns)) )
75
            {
76
                if ($showProgress) {
77
                    echo ".\n";
78
                }
79
80
                // Call user provided callback.
81
                // Callback should be an array as per doc here:
82
                // http://www.php.net/manual/en/language.types.callable.php
83
                // Type 3: Object method call
84
                if (isset($progressCallback) && $progressCallback) {
85
                    call_user_func($progressCallback, $progressCallbackParams,
86
                                   $allOut, $allOutErr);
87
                }
88
89
                $i = 0;
90
            }
91
92
            // Get latest status
93
            $procStatus = proc_get_status($process);
94
            if ($showProgress) {
95
                echo ".";
96
                flush();
97
            }
98
            
99
            // Read prog output
100 View Code Duplication
            if (isset($pipes[1]) && $pipes[1]) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
101
                $out = stream_get_contents($pipes[1], -1);
102
                $allOut .= $out;
103
            }
104
105
            // Read prog errors
106 View Code Duplication
            if (isset($pipes[2]) && $pipes[2]) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
107
                $outErr = stream_get_contents($pipes[2], -1);
108
                $allOutErr .= $outErr;
109
            }
110
111
            $i++;
112
        } while ($procStatus['running']);
113
114
        if (isset($pipes[1]))
115
            fclose($pipes[1]);
116
        if (isset($pipes[2]))
117
            fclose($pipes[2]);
118
119
        if ($procStatus['exitcode'] > 0)
120
        {
121
            $this->cpeLogger->logOut("ERROR",
122
                                     basename(__FILE__),
123
                                     "Can't execute: $cmd. Exit Code: ".$procStatus['exitcode'],
124
                                     $this->logKey);
125
            if ($allOut)
126
                $this->cpeLogger->logOut("ERROR",
127
                                         basename(__FILE__), "COMMAND STDOUT: ".$allOut,
128
                                         $this->logKey);
129
            if ($allOutErr)
130
                $this->cpeLogger->logOut("ERROR",
131
                                         basename(__FILE__), "COMMAND STDERR: ".$allOutErr,
132
                                         $this->logKey);
133
        }
134
135
        if ($showProgress) {
136
            echo "\n";
137
        }
138
139
        // Process is over
140
        proc_close($process);
141
142
        return array('out' => $allOut, 'outErr' => $allOutErr);
143
    }
144
}
145