Completed
Pull Request — 2.1 (#1489)
by Antoine
02:32
created

PHPDBG::start()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 1
1
<?php
2
/*
3
 * This file is part of the php-code-coverage package.
4
 *
5
 * (c) Sebastian Bergmann <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
namespace SebastianBergmann\CodeCoverage\Driver;
12
13
use SebastianBergmann\CodeCoverage\RuntimeException;
14
15
/**
16
 * Driver for PHPDBG's code coverage functionality.
17
 *
18
 * @codeCoverageIgnore
19
 */
20
class PHPDBG implements Driver
21
{
22
    /**
23
     * Constructor.
24
     */
25
    public function __construct()
26
    {
27
        if (PHP_SAPI !== 'phpdbg') {
28
            throw new RuntimeException(
29
                'This driver requires the PHPDBG SAPI'
30
            );
31
        }
32
33
        if (!function_exists('phpdbg_start_oplog')) {
34
            throw new RuntimeException(
35
                'This build of PHPDBG does not support code coverage'
36
            );
37
        }
38
    }
39
40
    /**
41
     * Start collection of code coverage information.
42
     *
43
     * @param bool $determineUnusedAndDead
44
     */
45
    public function start($determineUnusedAndDead = true)
46
    {
47
        phpdbg_start_oplog();
48
    }
49
50
    private function getFiles() {
51
        return array_filter(get_included_files(), function ($value, $key) {
0 ignored issues
show
Unused Code introduced by
The parameter $key is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
52
            return strpos(dirname($value), realpath(__DIR__.'/../../../../../src')) !== false;
53
        }, ARRAY_FILTER_USE_BOTH);
54
    }
55
56
    /**
57
     * Stop collection of code coverage information.
58
     *
59
     * @return array
60
     */
61
    public function stop()
62
    {
63
        static $fetchedLines = [];
64
65
        $dbgData = phpdbg_end_oplog();
66
67
        if ($fetchedLines == []) {
68
            $files = $this->getFiles();
69
            var_dump('initial files', count($files));
0 ignored issues
show
Security Debugging Code introduced by
var_dump('initial files', count($files)); looks like debug code. Are you sure you do not want to remove it? This might expose sensitive data.
Loading history...
70
71
            $sourceLines = phpdbg_get_executable(['files' => $files]);
72
        } else {
73
            $newFiles = array_diff(
74
                $this->getFiles(),
75
                array_keys($fetchedLines)
76
            );
77
78
            var_dump('new files', count($newFiles));
79
80
            if ($newFiles) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $newFiles of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
81
                $sourceLines = phpdbg_get_executable(
82
                    ['files' => $newFiles]
83
                );
84
            } else {
85
                $sourceLines = [];
86
            }
87
        }
88
89
        foreach ($sourceLines as $file => $lines) {
90
            foreach ($lines as $lineNo => $numExecuted) {
91
                $sourceLines[$file][$lineNo] = self::LINE_NOT_EXECUTED;
92
            }
93
        }
94
95
        $fetchedLines = array_merge($fetchedLines, $sourceLines);
96
97
        return $this->detectExecutedLines($fetchedLines, $dbgData);
98
    }
99
100
    /**
101
     * Convert phpdbg based data into the format CodeCoverage expects
102
     *
103
     * @param array $sourceLines
104
     * @param array $dbgData
105
     *
106
     * @return array
107
     */
108
    private function detectExecutedLines(array $sourceLines, array $dbgData)
109
    {
110
        foreach ($dbgData as $file => $coveredLines) {
111
            foreach ($coveredLines as $lineNo => $numExecuted) {
112
                // phpdbg also reports $lineNo=0 when e.g. exceptions get thrown.
113
                // make sure we only mark lines executed which are actually executable.
114
                if (isset($sourceLines[$file][$lineNo])) {
115
                    $sourceLines[$file][$lineNo] = self::LINE_EXECUTED;
116
                }
117
            }
118
        }
119
120
        return $sourceLines;
121
    }
122
}
123