source: trunk/coverager/coverager.php @ 124

Last change on this file since 124 was 124, checked in by moo, 8 years ago

Chinese translation for coverager

File size: 6.9 KB
Line 
1<?php
2
3include("./common.php");
4
5class Cycle
6{
7    var $values;
8    var $i;
9    var $count;
10
11    function Cycle($v)
12    {
13        $this->values = func_get_args();
14        $this->i = -1;
15        $this->count = count($this->values);
16    }
17
18    function next()
19    {
20        $this->i = ($this->i + 1) % $this->count;
21        return $this->values[$this->i];
22    }
23
24    function cur()
25    {
26        return $this->values[$this->i];
27    }
28
29    function reset()
30    {
31        $this->i = -1;
32    }
33}
34
35class XcacheCoverageViewer
36{
37    var $syntaxhiglight = true;
38    var $usecache = false;
39    var $include_paths = array();
40    var $exclude_paths = array();
41    var $charset = 'UTF-8';
42    var $lang = 'en-us';
43    var $datadir = null;
44    var $datadir_len = null;
45    var $path = null;
46    var $outpath = null;
47
48    function XcacheCoverageViewer()
49    {
50        $this->datadir = ini_get('xcache.coveragedump_directory');
51
52        // copy config
53        foreach (array('charset', 'include_paths', 'exclude_paths', 'syntaxhiglight', 'usecache', 'datadir', 'lang') as $k) {
54            if (isset($GLOBALS[$k])) {
55                $this->{$k} = $GLOBALS[$k];
56            }
57        }
58
59        $this->datadir = preg_replace('!/$!', '', $this->datadir);
60        $this->datadir_len = strlen($this->datadir);
61
62        $this->path = isset($_GET['path']) ? $_GET['path'] : '';
63        $this->path = preg_replace('!\.{2,}!', '.', $this->path);
64        $this->path = preg_replace('![\\\\/]{2,}!', '/', $this->path);
65        if ($this->path == '/') {
66            $this->path = '';
67        }
68        $this->outpath = $this->datadir . $this->path;
69    }
70
71    function main()
72    {
73        $path = $this->path;
74
75        if (is_dir($this->outpath)) {
76            $action = 'dir';
77            $prefix_len = strlen($path) + 1;
78            $dirinfo = $this->loadDir($this->outpath);
79            if (!$this->usecache) {
80                ksort($dirinfo['subdirs']);
81                ksort($dirinfo['files']);
82            }
83        }
84        else if (is_file($this->outpath . ".pcov")) {
85            $action = 'file';
86
87            $dir = dirname($path);
88            $filename = basename($path);
89
90            $fileinfo = $this->loadCov($this->outpath . ".pcov");
91
92            $lines = file($path);
93            // fix the tabs not in the middle
94            foreach ($lines as $l => $line) {
95                if (preg_match('!^(\\t*)([^\\t]+\\t.*)$!s', $line, $m)) {
96                    $lines[$l] = $m[1];
97                    $chunks = explode("\t", $m[2]);
98                    for ($i = 0, $c = count($chunks) - 1; $i < $c; $i ++) {
99                        $lines[$l] .= $chunks[$i] . str_repeat(" ", 4 - (strlen($chunks[$i]) % 4));
100                    }
101                    $lines[$l] .= $chunks[$c];
102                }
103            }
104            if ($this->syntaxhiglight) {
105                $source = implode('', $lines);
106                ob_start();
107                highlight_string($source);
108                $lines = explode('<br />', str_replace("\n", "", ob_get_clean()));
109                $last = array_pop($lines);
110                $filecov = sprint_cov($fileinfo['cov'], $lines, false);
111                $filecov .= $last;
112                unset($source);
113            }
114            else {
115                $filecov = sprint_cov($fileinfo['cov'], $lines);
116            }
117
118            list($tplfile, $tpllines, $tplcov) = $this->loadTplCov($fileinfo['cov'], substr($this->outpath, $this->datadir_len));
119            if ($tplfile) {
120                $tplcov = sprint_cov($tplinfo['tplcov'], $tpllines);
121                unset($tpllines);
122            }
123        }
124        else if (!$this->datadir) {
125            $action = 'require xcache.coveragedump_directory';
126        }
127        else {
128            $action = "no data";
129        }
130
131        $xcache_version = XCACHE_VERSION;
132        include("coverager.tpl.php");
133    }
134
135    function loadDir($outdir, $addtodo = null)
136    {
137        if ($this->usecache) {
138            $cachefile = $outdir . "/.pcovcache";
139            if (file_exists($cachefile)) {
140                return unserialize(file_get_contents($cachefile));
141            }
142        }
143        $srcdir = substr($outdir, $this->datadir_len);
144
145        $total = $hits = $todos = 0;
146        $files = array();
147        $subdirs = array();
148        if (!isset($addtodo)) {
149            if ($this->include_paths) {
150                foreach ($this->include_paths as $p) {
151                    if (strncmp($p, $srcdir, strlen($p)) == 0) {
152                        $addtodo = true;
153                        break;
154                    }
155                }
156            }
157        }
158        if ($addtodo) {
159            if ($this->exclude_paths) {
160                foreach ($this->exclude_paths as $p) {
161                    if (strncmp($p, $srcdir, strlen($p)) == 0) {
162                        $addtodo = false;
163                        break;
164                    }
165                }
166            }
167        }
168        foreach (glob($outdir . "/*") as $outfile) {
169            if (is_dir($outfile)) {
170                $info = $this->loadDir($outfile, $addtodo);
171                $srcfile = substr($outfile, $this->datadir_len);
172                $subdirs += $info['subdirs'];
173                $total   += $info['total'];
174                $hits    += $info['hits'];
175                $todos   += $info['todos'];
176                unset($info['subdirs']);
177                $subdirs[$srcfile] = $info;
178            }
179            else if (substr($outfile, -5) == ".pcov") {
180                // pass
181                $info = $this->loadFile($outfile);
182                $total += $info['total'];
183                $hits  += $info['hits'];
184                $srcfile = substr($outfile, $this->datadir_len, -5);
185                $files[$srcfile] = $info;
186            }
187            else {
188                continue;
189            }
190        }
191        if ($addtodo === true) {
192            foreach (glob($srcdir . "/*") as $srcfile) {
193                if (!isset($files[$srcfile]) && is_file($srcfile)) {
194                    $files[$srcfile] = array('total' => 0, 'hits' => 0);
195                    $todos ++;
196                }
197                else if (!isset($subdirs[$srcfile]) && is_dir($srcfile)) {
198                    $subdirs[$srcfile] = array('total' => 0, 'hits' => 0, 'todos' => 1, 'files' => 0, 'subdirs' => array());
199                    $todos ++;
200                }
201            }
202        }
203
204        if ($this->usecache) {
205            ksort($subdirs);
206            ksort($files);
207        }
208
209        $info = array(
210                'total'   => $total,
211                'hits'    => $hits,
212                'todos'   => $todos,
213                'files'   => $files,
214                'subdirs' => $subdirs,
215                );
216
217        if ($this->usecache) {
218            $fp = fopen($cachefile, "wb");
219            fwrite($fp, serialize($info));
220            fclose($fp);
221        }
222        return $info;
223    }
224
225    function loadFile($file)
226    {
227        if ($this->usecache) {
228            $cachefile = $file . "cache";
229            if (file_exists($cachefile)) {
230                return unserialize(file_get_contents($cachefile));
231            }
232        }
233
234        $info = $this->loadCov($file); //, $lines);
235        unset($info['cov']);
236
237        if ($this->usecache) {
238            $fp = fopen($cachefile, "wb");
239            fwrite($fp, serialize($info));
240            fclose($fp);
241        }
242        return $info;
243    }
244
245    function loadCov($file)//, $lines)
246    {
247        $total = $hits = 0;
248
249        $cov = xcache_coverager_decode(file_get_contents($file));
250
251        return array('total' => count($cov) - 1, 'hits' => $cov[0], 'cov' => $cov);
252    }
253
254    function loadTplCov($cov, $ctpl)
255    {
256        $tplinfofile = $ctpl . '.phpinfo';
257
258        if (!file_exists($tplinfofile)) {
259            return;
260        }
261
262        $tplinfo = unserialize(file_get_contents($tplinfofile));
263
264        if (!isset($tplinfo['sourceFile'])) {
265            return;
266        }
267        $tplfile = $tplinfo['sourceFile'];
268        if (!isset($tplinfo['lineMap']) || !count($tplinfo['lineMap'])) {
269            return;
270        }
271
272        $tpllines = file($tplfile);
273
274        $dline = 0;
275        $sline = 0;
276        $tplcov = array();
277        foreach ($cov as $line => $times) {
278            // find nearest line
279            while ($dline < $line) {
280                if ((list($dline, $sline) = each($tplinfo['lineMap'])) === false) {
281                    break 2;
282                }
283            }
284
285            $tplcov[$sline] = $times;
286        }
287        return array($tplfile, $tpllines, $tplcov);
288    }
289}
290
291function sprint_cov($cov, $lines, $encode = true)
292{
293    foreach ($lines as $l => $line) {
294        $offs = $l + 1;
295        if ($encode) {
296            $line = str_replace("\n", "", htmlspecialchars($line));
297        }
298        if (isset($cov[$offs])) {
299            $lines[$l] = sprintf("<li class=\"line%sCov\"> %s\t%s</li>\n"
300                    , $cov[$offs] ? '' : 'No'
301                    , $cov[$offs]
302                    , $line);
303        }
304        else {
305            $lines[$l] = "<li>\t$line</li>\n";
306        }
307    }
308    return implode('', $lines);
309}
310
311$app = new XcacheCoverageViewer();
312$app->main();
313
314?>
Note: See TracBrowser for help on using the repository browser.