These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | // @codingStandardsIgnoreFile |
||
3 | // @codeCoverageIgnoreStart |
||
4 | |||
5 | /** |
||
6 | * C3 - Codeception Code Coverage |
||
7 | * |
||
8 | * @author tiger |
||
9 | */ |
||
10 | |||
11 | // $_SERVER['HTTP_X_CODECEPTION_CODECOVERAGE_DEBUG'] = 1; |
||
12 | |||
13 | if (isset($_COOKIE['CODECEPTION_CODECOVERAGE'])) { |
||
14 | $cookie = json_decode($_COOKIE['CODECEPTION_CODECOVERAGE'], true); |
||
15 | |||
16 | // fix for improperly encoded JSON in Code Coverage cookie with WebDriver. |
||
17 | // @see https://github.com/Codeception/Codeception/issues/874 |
||
18 | if (!is_array($cookie)) { |
||
19 | $cookie = json_decode($cookie, true); |
||
20 | } |
||
21 | |||
22 | if ($cookie) { |
||
23 | foreach ($cookie as $key => $value) { |
||
24 | $_SERVER["HTTP_X_CODECEPTION_".strtoupper($key)] = $value; |
||
25 | } |
||
26 | } |
||
27 | } |
||
28 | |||
29 | if (!array_key_exists('HTTP_X_CODECEPTION_CODECOVERAGE', $_SERVER)) { |
||
30 | return; |
||
31 | } |
||
32 | |||
33 | if (!function_exists('__c3_error')) { |
||
34 | function __c3_error($message) |
||
35 | { |
||
36 | /* file_put_contents(C3_CODECOVERAGE_MEDIATE_STORAGE . DIRECTORY_SEPARATOR . 'error.txt', $message); |
||
37 | if (!headers_sent()) { |
||
38 | header('X-Codeception-CodeCoverage-Error: ' . str_replace("\n", ' ', $message), true, 500); |
||
39 | }*/ |
||
40 | setcookie('CODECEPTION_CODECOVERAGE_ERROR', $message); |
||
41 | } |
||
42 | } |
||
43 | |||
44 | // Autoload Codeception classes |
||
45 | if (!class_exists('\\Codeception\\Codecept')) { |
||
46 | if (stream_resolve_include_path(__DIR__ . '/vendor/autoload.php')) { |
||
47 | require_once __DIR__ . '/vendor/autoload.php'; |
||
48 | } elseif (file_exists(__DIR__ . '/codecept.phar')) { |
||
49 | require_once 'phar://'.__DIR__ . '/codecept.phar/autoload.php'; |
||
50 | } elseif (stream_resolve_include_path('Codeception/autoload.php')) { |
||
51 | require_once 'Codeception/autoload.php'; |
||
52 | } else { |
||
53 | __c3_error('Codeception is not loaded. Please check that either PHAR or Composer or PEAR package can be used'); |
||
54 | } |
||
55 | } |
||
56 | |||
57 | // Load Codeception Config |
||
58 | $config_file = realpath(__DIR__) . DIRECTORY_SEPARATOR . 'codeception.yml'; |
||
59 | if (isset($_SERVER['HTTP_X_CODECEPTION_CODECOVERAGE_CONFIG'])) { |
||
60 | $config_file = realpath(__DIR__) . DIRECTORY_SEPARATOR . $_SERVER['HTTP_X_CODECEPTION_CODECOVERAGE_CONFIG']; |
||
61 | } |
||
62 | if (!file_exists($config_file)) { |
||
63 | __c3_error(sprintf("Codeception config file '%s' not found", $config_file)); |
||
64 | } |
||
65 | try { |
||
66 | \Codeception\Configuration::config($config_file); |
||
67 | } catch (\Exception $e) { |
||
68 | __c3_error($e->getMessage()); |
||
69 | } |
||
70 | |||
71 | if (!defined('C3_CODECOVERAGE_MEDIATE_STORAGE')) { |
||
72 | |||
73 | // workaround for 'zend_mm_heap corrupted' problem |
||
74 | gc_disable(); |
||
75 | |||
76 | if ((integer)ini_get('memory_limit') < 384) { |
||
77 | ini_set('memory_limit', '384M'); |
||
78 | } |
||
79 | |||
80 | define('C3_CODECOVERAGE_MEDIATE_STORAGE', Codeception\Configuration::logDir() . 'c3tmp'); |
||
81 | define('C3_CODECOVERAGE_PROJECT_ROOT', Codeception\Configuration::projectDir()); |
||
82 | define('C3_CODECOVERAGE_TESTNAME', $_SERVER['HTTP_X_CODECEPTION_CODECOVERAGE']); |
||
83 | |||
84 | function __c3_build_html_report(PHP_CodeCoverage $codeCoverage, $path) |
||
85 | { |
||
86 | $writer = new PHP_CodeCoverage_Report_HTML(); |
||
87 | $writer->process($codeCoverage, $path . 'html'); |
||
88 | |||
89 | if (file_exists($path . '.tar')) { |
||
90 | unlink($path . '.tar'); |
||
91 | } |
||
92 | |||
93 | $phar = new PharData($path . '.tar'); |
||
94 | $phar->setSignatureAlgorithm(Phar::SHA1); |
||
95 | $files = $phar->buildFromDirectory($path . 'html'); |
||
96 | array_map('unlink', $files); |
||
97 | |||
98 | if (in_array('GZ', Phar::getSupportedCompression())) { |
||
99 | if (file_exists($path . '.tar.gz')) { |
||
100 | unlink($path . '.tar.gz'); |
||
101 | } |
||
102 | |||
103 | $phar->compress(\Phar::GZ); |
||
104 | |||
105 | // close the file so that we can rename it |
||
106 | unset($phar); |
||
107 | |||
108 | unlink($path . '.tar'); |
||
109 | rename($path . '.tar.gz', $path . '.tar'); |
||
110 | } |
||
111 | |||
112 | return $path . '.tar'; |
||
113 | } |
||
114 | |||
115 | function __c3_build_clover_report(PHP_CodeCoverage $codeCoverage, $path) |
||
116 | { |
||
117 | $writer = new PHP_CodeCoverage_Report_Clover(); |
||
118 | $writer->process($codeCoverage, $path . '.clover.xml'); |
||
119 | |||
120 | return $path . '.clover.xml'; |
||
121 | } |
||
122 | |||
123 | function __c3_send_file($filename) |
||
124 | { |
||
125 | if (!headers_sent()) { |
||
126 | readfile($filename); |
||
127 | } |
||
128 | |||
129 | return __c3_exit(); |
||
130 | } |
||
131 | |||
132 | /** |
||
133 | * @param $filename |
||
134 | * @return null|PHP_CodeCoverage |
||
135 | */ |
||
136 | function __c3_factory($filename) |
||
137 | { |
||
138 | $phpCoverage = is_readable($filename) |
||
139 | ? unserialize(file_get_contents($filename)) |
||
140 | : new PHP_CodeCoverage(); |
||
141 | |||
142 | |||
143 | if (isset($_SERVER['HTTP_X_CODECEPTION_CODECOVERAGE_SUITE'])) { |
||
144 | $suite = $_SERVER['HTTP_X_CODECEPTION_CODECOVERAGE_SUITE']; |
||
145 | try { |
||
146 | $settings = \Codeception\Configuration::suiteSettings($suite, \Codeception\Configuration::config()); |
||
147 | } catch (Exception $e) { |
||
148 | __c3_error($e->getMessage()); |
||
149 | } |
||
150 | } else { |
||
151 | $settings = \Codeception\Configuration::config(); |
||
152 | } |
||
153 | |||
154 | try { |
||
155 | \Codeception\Coverage\Filter::setup($phpCoverage) |
||
156 | ->whiteList($settings) |
||
157 | ->blackList($settings); |
||
158 | } catch (Exception $e) { |
||
159 | __c3_error($e->getMessage()); |
||
160 | } |
||
161 | |||
162 | return $phpCoverage; |
||
163 | } |
||
164 | |||
165 | function __c3_exit() |
||
166 | { |
||
167 | if (!isset($_SERVER['HTTP_X_CODECEPTION_CODECOVERAGE_DEBUG'])) { |
||
168 | exit; |
||
169 | } |
||
170 | return null; |
||
171 | } |
||
172 | |||
173 | function __c3_clear() |
||
174 | { |
||
175 | \Codeception\Util\FileSystem::doEmptyDir(C3_CODECOVERAGE_MEDIATE_STORAGE); |
||
176 | } |
||
177 | } |
||
178 | |||
179 | if (!is_dir(C3_CODECOVERAGE_MEDIATE_STORAGE)) { |
||
180 | if (mkdir(C3_CODECOVERAGE_MEDIATE_STORAGE, 0777, true) === false) { |
||
181 | __c3_error('Failed to create directory "' . C3_CODECOVERAGE_MEDIATE_STORAGE . '"'); |
||
182 | } |
||
183 | } |
||
184 | |||
185 | // evaluate base path for c3-related files |
||
186 | $path = realpath(C3_CODECOVERAGE_MEDIATE_STORAGE) . DIRECTORY_SEPARATOR . 'codecoverage'; |
||
187 | |||
188 | $requested_c3_report = (strpos($_SERVER['REQUEST_URI'], 'c3/report') !== false); |
||
189 | |||
190 | $complete_report = $current_report = $path . '.serialized'; |
||
191 | if ($requested_c3_report) { |
||
192 | set_time_limit(0); |
||
193 | |||
194 | $route = ltrim(strrchr($_SERVER['REQUEST_URI'], '/'), '/'); |
||
195 | |||
196 | if ($route == 'clear') { |
||
197 | __c3_clear(); |
||
198 | return __c3_exit(); |
||
199 | } |
||
200 | |||
201 | $codeCoverage = __c3_factory($complete_report); |
||
202 | |||
203 | switch ($route) { |
||
204 | View Code Duplication | case 'html': |
|
0 ignored issues
–
show
|
|||
205 | try { |
||
206 | __c3_send_file(__c3_build_html_report($codeCoverage, $path)); |
||
0 ignored issues
–
show
It seems like
$codeCoverage defined by __c3_factory($complete_report) on line 201 can be null ; however, __c3_build_html_report() does not accept null , maybe add an additional type check?
Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code: /** @return stdClass|null */
function mayReturnNull() { }
function doesNotAcceptNull(stdClass $x) { }
// With potential error.
function withoutCheck() {
$x = mayReturnNull();
doesNotAcceptNull($x); // Potential error here.
}
// Safe - Alternative 1
function withCheck1() {
$x = mayReturnNull();
if ( ! $x instanceof stdClass) {
throw new \LogicException('$x must be defined.');
}
doesNotAcceptNull($x);
}
// Safe - Alternative 2
function withCheck2() {
$x = mayReturnNull();
if ($x instanceof stdClass) {
doesNotAcceptNull($x);
}
}
![]() |
|||
207 | } catch (Exception $e) { |
||
208 | __c3_error($e->getMessage()); |
||
209 | } |
||
210 | return __c3_exit(); |
||
211 | View Code Duplication | case 'clover': |
|
0 ignored issues
–
show
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. ![]() |
|||
212 | try { |
||
213 | __c3_send_file(__c3_build_clover_report($codeCoverage, $path)); |
||
0 ignored issues
–
show
It seems like
$codeCoverage defined by __c3_factory($complete_report) on line 201 can be null ; however, __c3_build_clover_report() does not accept null , maybe add an additional type check?
Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code: /** @return stdClass|null */
function mayReturnNull() { }
function doesNotAcceptNull(stdClass $x) { }
// With potential error.
function withoutCheck() {
$x = mayReturnNull();
doesNotAcceptNull($x); // Potential error here.
}
// Safe - Alternative 1
function withCheck1() {
$x = mayReturnNull();
if ( ! $x instanceof stdClass) {
throw new \LogicException('$x must be defined.');
}
doesNotAcceptNull($x);
}
// Safe - Alternative 2
function withCheck2() {
$x = mayReturnNull();
if ($x instanceof stdClass) {
doesNotAcceptNull($x);
}
}
![]() |
|||
214 | } catch (Exception $e) { |
||
215 | __c3_error($e->getMessage()); |
||
216 | } |
||
217 | return __c3_exit(); |
||
218 | case 'serialized': |
||
219 | try { |
||
220 | __c3_send_file($complete_report); |
||
221 | } catch (Exception $e) { |
||
222 | __c3_error($e->getMessage()); |
||
223 | } |
||
224 | return __c3_exit(); |
||
225 | } |
||
226 | |||
227 | } else { |
||
228 | $codeCoverage = __c3_factory($current_report); |
||
229 | $codeCoverage->start(C3_CODECOVERAGE_TESTNAME); |
||
230 | if (!array_key_exists('HTTP_X_CODECEPTION_CODECOVERAGE_DEBUG', $_SERVER)) { |
||
231 | register_shutdown_function( |
||
232 | function () use ($codeCoverage, $current_report) { |
||
233 | $codeCoverage->stop(); |
||
234 | file_put_contents($current_report, serialize($codeCoverage)); |
||
235 | } |
||
236 | ); |
||
237 | } |
||
238 | } |
||
239 | |||
240 | // @codeCoverageIgnoreEnd |
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.