]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - tests/PHPUnit/PHP/CodeCoverage/Report/Factory.php
Merge branch 'master' of github.com:sugarcrm/sugarcrm_dev
[Github/sugarcrm.git] / tests / PHPUnit / PHP / CodeCoverage / Report / Factory.php
1 <?php
2 /**
3  * PHP_CodeCoverage
4  *
5  * Copyright (c) 2009-2011, Sebastian Bergmann <sb@sebastian-bergmann.de>.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  *   * Redistributions of source code must retain the above copyright
13  *     notice, this list of conditions and the following disclaimer.
14  *
15  *   * Redistributions in binary form must reproduce the above copyright
16  *     notice, this list of conditions and the following disclaimer in
17  *     the documentation and/or other materials provided with the
18  *     distribution.
19  *
20  *   * Neither the name of Sebastian Bergmann nor the names of his
21  *     contributors may be used to endorse or promote products derived
22  *     from this software without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
28  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
29  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
30  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
34  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35  * POSSIBILITY OF SUCH DAMAGE.
36  *
37  * @category   PHP
38  * @package    CodeCoverage
39  * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
40  * @copyright  2009-2011 Sebastian Bergmann <sb@sebastian-bergmann.de>
41  * @license    http://www.opensource.org/licenses/bsd-license.php  BSD License
42  * @link       http://github.com/sebastianbergmann/php-code-coverage
43  * @since      File available since Release 1.1.0
44  */
45
46 /**
47  * Factory for PHP_CodeCoverage_Report_Node_* object graphs.
48  *
49  * @category   PHP
50  * @package    CodeCoverage
51  * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
52  * @copyright  2009-2011 Sebastian Bergmann <sb@sebastian-bergmann.de>
53  * @license    http://www.opensource.org/licenses/bsd-license.php  BSD License
54  * @version    Release: 1.1.1
55  * @link       http://github.com/sebastianbergmann/php-code-coverage
56  * @since      Class available since Release 1.1.0
57  */
58 class PHP_CodeCoverage_Report_Factory
59 {
60     /**
61      * @param PHP_CodeCoverage $coverage
62      */
63     public function create(PHP_CodeCoverage $coverage)
64     {
65         $files      = $coverage->getData();
66         $commonPath = $this->reducePaths($files);
67         $root       = new PHP_CodeCoverage_Report_Node_Directory(
68                         $commonPath, NULL
69                       );
70
71         $this->addItems(
72           $root,
73           $this->buildDirectoryStructure($files),
74           $coverage->getTests(),
75           $coverage->getCacheTokens()
76         );
77
78         return $root;
79     }
80
81     /**
82      * @param PHP_CodeCoverage_Report_Node_Directory $root
83      * @param array                                  $items
84      * @param array                                  $tests
85      * @param boolean                                $cacheTokens
86      */
87     protected function addItems(PHP_CodeCoverage_Report_Node_Directory $root, array $items, array $tests, $cacheTokens)
88     {
89         foreach ($items as $key => $value) {
90             if (substr($key, -2) == '/f') {
91                 $key = substr($key, 0, -2);
92                 $root->addFile($key, $value, $tests, $cacheTokens);
93             } else {
94                 $child = $root->addDirectory($key);
95                 $this->addItems($child, $value, $tests, $cacheTokens);
96             }
97         }
98     }
99
100     /**
101      * Builds an array representation of the directory structure.
102      *
103      * For instance,
104      *
105      * <code>
106      * Array
107      * (
108      *     [Money.php] => Array
109      *         (
110      *             ...
111      *         )
112      *
113      *     [MoneyBag.php] => Array
114      *         (
115      *             ...
116      *         )
117      * )
118      * </code>
119      *
120      * is transformed into
121      *
122      * <code>
123      * Array
124      * (
125      *     [.] => Array
126      *         (
127      *             [Money.php] => Array
128      *                 (
129      *                     ...
130      *                 )
131      *
132      *             [MoneyBag.php] => Array
133      *                 (
134      *                     ...
135      *                 )
136      *         )
137      * )
138      * </code>
139      *
140      * @param  array $files
141      * @return array
142      */
143     protected function buildDirectoryStructure($files)
144     {
145         $result = array();
146
147         foreach ($files as $path => $file) {
148             $path    = explode('/', $path);
149             $pointer = &$result;
150             $max     = count($path);
151
152             for ($i = 0; $i < $max; $i++) {
153                 if ($i == ($max - 1)) {
154                     $type = '/f';
155                 } else {
156                     $type = '';
157                 }
158
159                 $pointer = &$pointer[$path[$i] . $type];
160             }
161
162             $pointer = $file;
163         }
164
165         return $result;
166     }
167
168     /**
169      * Reduces the paths by cutting the longest common start path.
170      *
171      * For instance,
172      *
173      * <code>
174      * Array
175      * (
176      *     [/home/sb/Money/Money.php] => Array
177      *         (
178      *             ...
179      *         )
180      *
181      *     [/home/sb/Money/MoneyBag.php] => Array
182      *         (
183      *             ...
184      *         )
185      * )
186      * </code>
187      *
188      * is reduced to
189      *
190      * <code>
191      * Array
192      * (
193      *     [Money.php] => Array
194      *         (
195      *             ...
196      *         )
197      *
198      *     [MoneyBag.php] => Array
199      *         (
200      *             ...
201      *         )
202      * )
203      * </code>
204      *
205      * @param  array $files
206      * @return string
207      */
208     protected function reducePaths(&$files)
209     {
210         if (empty($files)) {
211             return '.';
212         }
213
214         $commonPath = '';
215         $paths      = array_keys($files);
216
217         if (count($files) == 1) {
218             $commonPath                 = dirname($paths[0]) . '/';
219             $files[basename($paths[0])] = $files[$paths[0]];
220
221             unset($files[$paths[0]]);
222
223             return $commonPath;
224         }
225
226         $max = count($paths);
227
228         for ($i = 0; $i < $max; $i++) {
229             $paths[$i] = explode(DIRECTORY_SEPARATOR, $paths[$i]);
230
231             if (empty($paths[$i][0])) {
232                 $paths[$i][0] = DIRECTORY_SEPARATOR;
233             }
234         }
235
236         $done = FALSE;
237         $max  = count($paths);
238
239         while (!$done) {
240             for ($i = 0; $i < $max - 1; $i++) {
241                 if (!isset($paths[$i][0]) ||
242                     !isset($paths[$i+1][0]) ||
243                     $paths[$i][0] != $paths[$i+1][0]) {
244                     $done = TRUE;
245                     break;
246                 }
247             }
248
249             if (!$done) {
250                 $commonPath .= $paths[0][0];
251
252                 if ($paths[0][0] != DIRECTORY_SEPARATOR) {
253                     $commonPath .= DIRECTORY_SEPARATOR;
254                 }
255
256                 for ($i = 0; $i < $max; $i++) {
257                     array_shift($paths[$i]);
258                 }
259             }
260         }
261
262         $original = array_keys($files);
263         $max      = count($original);
264
265         for ($i = 0; $i < $max; $i++) {
266             $files[join('/', $paths[$i])] = $files[$original[$i]];
267             unset($files[$original[$i]]);
268         }
269
270         ksort($files);
271
272         return substr($commonPath, 0, -1);
273     }
274 }