Completed
Pull Request — 2.1 (#1489)
by Antoine
03:10
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
            $sourceLines = phpdbg_get_executable(['files' => $this->getFiles()]);
69
        } else {
70
            $newFiles = array_diff(
71
                $this->getFiles(),
72
                array_keys($fetchedLines)
73
            );
74
75
            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...
76
                $sourceLines = phpdbg_get_executable(
77
                    ['files' => $newFiles]
78
                );
79
            } else {
80
                $sourceLines = [];
81
            }
82
        }
83
84
        foreach ($sourceLines as $file => $lines) {
85
            foreach ($lines as $lineNo => $numExecuted) {
86
                $sourceLines[$file][$lineNo] = self::LINE_NOT_EXECUTED;
87
            }
88
        }
89
90
        $fetchedLines = array_merge($fetchedLines, $sourceLines);
91
92
        return $this->detectExecutedLines($fetchedLines, $dbgData);
93
    }
94
95
    /**
96
     * Convert phpdbg based data into the format CodeCoverage expects
97
     *
98
     * @param array $sourceLines
99
     * @param array $dbgData
100
     *
101
     * @return array
102
     */
103
    private function detectExecutedLines(array $sourceLines, array $dbgData)
104
    {
105
        foreach ($dbgData as $file => $coveredLines) {
106
            foreach ($coveredLines as $lineNo => $numExecuted) {
107
                // phpdbg also reports $lineNo=0 when e.g. exceptions get thrown.
108
                // make sure we only mark lines executed which are actually executable.
109
                if (isset($sourceLines[$file][$lineNo])) {
110
                    $sourceLines[$file][$lineNo] = self::LINE_EXECUTED;
111
                }
112
            }
113
        }
114
115
        return $sourceLines;
116
    }
117
}
118