Skip to content

Commit f2193aa

Browse files
authored
Merge pull request #6 from MacFJA/new-tool-phpca
Close #2 - Adding tool PhpCodeAnalyzer
2 parents da4f8b7 + 3123c3d commit f2193aa

File tree

8 files changed

+384
-11
lines changed

8 files changed

+384
-11
lines changed

.phpqa.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
tool:
22
phpa: MacFJA\PHPQAExtensions\Tools\Analyzer\PhpAssumptions
33
phpmnd: MacFJA\PHPQAExtensions\Tools\Analyzer\PhpMagicNumber
4+
phpca: MacFJA\PHPQAExtensions\Tools\Analyzer\PhpCodeAnalyzer
45
report:
56
phpa: app/report/phpassumptions.xsl
67
phpmnd: app/report/phpmagicnumber.xsl
8+
phpca: app/report/php-code-analyzer.xsl

README.md

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22

33
Add more tools to [PHPQA](https://github.com/EdgedesignCZ/phpqa)
44

5+
## List of tools
6+
7+
- [PHP Magic Number Detector](https://github.com/povils/phpmnd): PHP Magic Number Detector.
8+
- [PhpAssumptions](https://github.com/rskuipers/php-assumptions): Tool to detect assumptions.
9+
- [PhpCodeAnalyzer](https://github.com/wapmorgan/PhpCodeAnalyzer): PhpCodeAnalyzer finds usage of non-built-in extensions in your php code.
10+
511
## Usage
612

713
### Get the list of available tools
@@ -12,12 +18,13 @@ $ php vendor/bin/phpqa-extensions.php --tools
1218
List of available tools
1319
=======================
1420
15-
--------------------------- -------- --------------------------- -----------
16-
Name CLI Composer Installed
17-
--------------------------- -------- --------------------------- -----------
18-
PhpAssumptions phpa rskuipers/php-assumptions No
19-
PHP Magic Number Detector phpmnd povils/phpmnd No
20-
--------------------------- -------- --------------------------- -----------
21+
--------------------------- -------- ----------------------------- -----------
22+
Name CLI Composer Installed
23+
--------------------------- -------- ----------------------------- -----------
24+
PhpAssumptions phpa rskuipers/php-assumptions No
25+
PhpCodeAnalyzer phpca wapmorgan/php-code-analyzer No
26+
PHP Magic Number Detector phpmnd povils/phpmnd No
27+
--------------------------- -------- ----------------------------- -----------
2128
```
2229

2330
### Install a tool on a project
@@ -60,6 +67,8 @@ With:
6067
| phpmnd.ignore-funcs | _null_ | PHP Magic Number Detector | List (comma separate) of function to ignore |
6168
| phpmnd.ignore-strings | _null_ | PHP Magic Number Detector | List (comma separate) of strings value to ignore |
6269
| phpmnd.strings | `false` | PHP Magic Number Detector | Activate the strings literal analysis |
70+
| phpca.since | _null_ | PhpCodeAnalyzer | Only include extensions not included since version |
71+
| phpca.extension | _null_ | PhpCodeAnalyzer | Look for usage of a specific extension |
6372

6473
## How to contribute
6574

app/report/php-code-analyzer.xsl

Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:fn="http://www.w3.org/2005/xpath-functions">
3+
4+
<xsl:output method="html" encoding="UTF-8"/>
5+
<xsl:key name="file-category" match="//files/file" use="@extension" />
6+
<xsl:key name="file-path" match="//files/file" use="@path" />
7+
<xsl:param name="root-directory"/>
8+
9+
<xsl:template match="/">
10+
<html>
11+
<head>
12+
<title>PhpCodeAnalyzer report</title>
13+
<link rel="stylesheet"><xsl:attribute name="href"><xsl:value-of select="$bootstrap.min.css" /></xsl:attribute></link>
14+
<style>
15+
.file {
16+
background: #f9f9f9
17+
}
18+
.fixed-navbar {
19+
list-style-type: none;
20+
position: fixed;
21+
top: 0;
22+
right: 1em;
23+
}
24+
</style>
25+
<script>
26+
var onDocumentReady = [
27+
function () {
28+
$('[data-file]').each(function () {
29+
var pathWithoutRoot = $(this).text().replace('<xsl:value-of select="$root-directory"></xsl:value-of>', '');
30+
$(this).text(pathWithoutRoot);
31+
});
32+
}
33+
];
34+
</script>
35+
</head>
36+
<body>
37+
38+
<div class="container-fluid">
39+
40+
<h1>PhpCodeAnalyzer report</h1>
41+
42+
<nav>
43+
<ul class="nav nav-pills" role="tablist">
44+
<li role="presentation" class="active">
45+
<a href="#overview" aria-controls="overview" role="tab" data-toggle="tab">Overview</a>
46+
</li>
47+
<li role="presentation">
48+
<a href="#files" aria-controls="files" role="tab" data-toggle="tab">Details by files</a>
49+
</li>
50+
<li role="presentation">
51+
<a href="#extensions" aria-controls="extensions" role="tab" data-toggle="tab">Details by extensions</a>
52+
</li>
53+
</ul>
54+
</nav>
55+
56+
<div class="tab-content">
57+
58+
<div role="tabpanel" class="tab-pane active" id="overview">
59+
<table class="table table-striped">
60+
<thead>
61+
<tr>
62+
<th>Extensions</th>
63+
<th>Files</th>
64+
<th>Occurrence</th>
65+
</tr>
66+
</thead>
67+
<!-- http://stackoverflow.com/a/9589085/4587679 -->
68+
<xsl:for-each select="//files/file[generate-id() = generate-id(key('file-category', ./@extension)[1])]">
69+
<xsl:variable name="group" select="@extension"/>
70+
<!--<xsl:key name="file-name" match="//file[@extension = $group]" use="@path" />-->
71+
<tr>
72+
<td><strong data-file=""><xsl:value-of select="$group"/></strong></td>
73+
<td><xsl:value-of select="count(//file[@extension = $group and not(following::file[@extension = $group]/@path = @path)])"/></td>
74+
<td><xsl:value-of select="count(//file[@extension = $group])"/></td>
75+
</tr>
76+
</xsl:for-each>
77+
<tfoot>
78+
<tr>
79+
<th><span class="label label-info"><xsl:value-of select="count(//files/file[generate-id() = generate-id(key('file-category', @extension)[1])])"/></span></th>
80+
<th><span class="label label-warning"><xsl:value-of select="count(//file[not(following::file/@path = @path)])" /></span></th>
81+
<th>
82+
<span class="label label-warning"><xsl:value-of select="count(//files/file)" /></span>
83+
</th>
84+
</tr>
85+
</tfoot>
86+
</table>
87+
</div>
88+
89+
<div role="tabpanel" class="tab-pane" id="files">
90+
<div class="fixed-navbar">
91+
<div class="input-group" style="width: 20em">
92+
<span class="input-group-addon"><span class="glyphicon glyphicon-search" aria-hidden="true"></span></span>
93+
<input data-search="errors" type="text" class="form-control" placeholder="undefined..." />
94+
</div>
95+
</div>
96+
<script>
97+
onDocumentReady.push(function () {
98+
var groups = $('[data-filterable] tbody tr[data-permanent]');
99+
var rows = $('[data-filterable] tbody tr:not([data-permanent])');
100+
101+
$("[data-search]").keyup(function () {
102+
var term = $(this).val().toLowerCase();
103+
104+
rows.hide();
105+
groups.show();
106+
matchElements(rows).show();
107+
matchEmptyGroups().hide();
108+
109+
function matchElements(elements) {
110+
return elements.filter(function () {
111+
var rowContent = $(this).text().toLowerCase();
112+
return rowContent.indexOf(term) !== -1
113+
});
114+
}
115+
116+
function matchEmptyGroups() {
117+
return groups.filter(function () {
118+
var group = $(this).data('permanent');
119+
return rows
120+
.filter(function () {
121+
return $(this).data('group') == group <![CDATA[&&]]> $(this).is(':visible');
122+
})
123+
.length == 0;
124+
});
125+
}
126+
});
127+
});
128+
</script>
129+
130+
<table class="table" data-filterable="errors">
131+
<thead>
132+
<tr>
133+
<th>Message</th>
134+
<th>Line</th>
135+
</tr>
136+
</thead>
137+
<xsl:for-each select="//files/file[generate-id() = generate-id(key('file-path', ./@path)[1])]">
138+
<xsl:variable name="group" select="@path"/>
139+
<tr>
140+
<xsl:attribute name="data-permanent">
141+
<xsl:value-of select="$group" />
142+
</xsl:attribute>
143+
<td colspan="3" class="file"><strong data-file=""><xsl:value-of select="$group" /></strong></td>
144+
</tr>
145+
<xsl:for-each select="//files/file[@path = $group]">
146+
<tr>
147+
<xsl:attribute name="data-group">
148+
<xsl:value-of select="./text()" />
149+
</xsl:attribute>
150+
<td>
151+
<xsl:choose>
152+
<xsl:when test="@type = 'class'"><xsl:text>The class </xsl:text></xsl:when>
153+
<xsl:when test="@type = 'function'"><xsl:text>The function </xsl:text></xsl:when>
154+
<xsl:when test="@type = 'constant'"><xsl:text>The constant </xsl:text></xsl:when>
155+
</xsl:choose>
156+
<strong><code><xsl:value-of select="./text()" /></code></strong>
157+
<xsl:text>of the extension </xsl:text>
158+
<strong><xsl:value-of select="@extension" /></strong>
159+
<xsl:text> is used.</xsl:text>
160+
</td>
161+
<td><xsl:value-of select="@line" /></td>
162+
</tr>
163+
</xsl:for-each>
164+
</xsl:for-each>
165+
</table>
166+
</div>
167+
168+
<div role="tabpanel" class="tab-pane" id="extensions">
169+
<div class="fixed-navbar">
170+
<div class="input-group" style="width: 20em">
171+
<span class="input-group-addon"><span class="glyphicon glyphicon-search" aria-hidden="true"></span></span>
172+
<input data-search="errors" type="text" class="form-control" placeholder="undefined..." />
173+
</div>
174+
</div>
175+
176+
<table class="table" data-filterable="errors">
177+
<thead>
178+
<tr>
179+
<th>Message</th>
180+
<th>Line</th>
181+
</tr>
182+
</thead>
183+
<xsl:for-each select="//files/file[generate-id() = generate-id(key('file-category', ./@extension)[1])]">
184+
<xsl:variable name="group" select="@extension"/>
185+
<tr>
186+
<xsl:attribute name="data-permanent">
187+
<xsl:value-of select="$group" />
188+
</xsl:attribute>
189+
<td colspan="3" class="file"><strong data-file=""><xsl:value-of select="$group" /></strong></td>
190+
</tr>
191+
<xsl:for-each select="//files/file[@extension = $group]">
192+
<tr>
193+
<xsl:attribute name="data-group">
194+
<xsl:value-of select="./text()" />
195+
</xsl:attribute>
196+
<td>
197+
<xsl:choose>
198+
<xsl:when test="@type = 'class'"><xsl:text>The class </xsl:text></xsl:when>
199+
<xsl:when test="@type = 'function'"><xsl:text>The function </xsl:text></xsl:when>
200+
<xsl:when test="@type = 'constant'"><xsl:text>The constant </xsl:text></xsl:when>
201+
</xsl:choose>
202+
<strong><code><xsl:value-of select="./text()" /></code></strong>
203+
<xsl:text> is used in the file </xsl:text>
204+
<code><xsl:value-of select="@path" /></code>
205+
<xsl:text>.</xsl:text>
206+
</td>
207+
<td><xsl:value-of select="@line" /></td>
208+
</tr>
209+
</xsl:for-each>
210+
</xsl:for-each>
211+
</table>
212+
</div>
213+
</div>
214+
</div>
215+
216+
217+
<script><xsl:attribute name="src"><xsl:value-of select="$jquery.min.js" /></xsl:attribute></script>
218+
<script><xsl:attribute name="src"><xsl:value-of select="$bootstrap.min.js" /></xsl:attribute></script>
219+
<script>
220+
$(document).ready(onDocumentReady);
221+
</script>
222+
</body>
223+
</html>
224+
</xsl:template>
225+
</xsl:stylesheet>

composer.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,12 @@
2424
},
2525
"require-dev": {
2626
"povils/phpmnd": "^2.0",
27-
"rskuipers/php-assumptions": "^0.7.0"
27+
"rskuipers/php-assumptions": "^0.7.0",
28+
"wapmorgan/php-code-analyzer": "^1.0.5"
29+
},
30+
"suggest": {
31+
"povils/phpmnd": "PHP Magic Number Detector",
32+
"rskuipers/php-assumptions": "Tool to detect assumptions",
33+
"wapmorgan/php-code-analyzer": "PhpCodeAnalyzer finds usage of non-built-in extensions in your php code."
2834
}
2935
}

src/ToolDefinition.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,10 @@ public static function getCliName();
3939
* @return string
4040
*/
4141
public static function getInternalClass();
42+
43+
/**
44+
* Return the global tool settings.
45+
* @return array
46+
*/
47+
public static function getToolSettings();
4248
}

src/Tools/Analyzer/PhpAssumptions.php

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ public function __invoke()
4646
*/
4747
public static function getComposer()
4848
{
49-
return static::$SETTINGS['composer'];
49+
return static::getToolSettings()['composer'];
5050
}
5151

5252
/**
@@ -87,6 +87,16 @@ public static function getCliName()
8787
*/
8888
public static function getInternalClass()
8989
{
90-
return static::$SETTINGS['internalClass'];
90+
return static::getToolSettings()['internalClass'];
91+
}
92+
93+
/**
94+
* Return the global tool settings.
95+
*
96+
* @return array
97+
*/
98+
public static function getToolSettings()
99+
{
100+
return self::$SETTINGS;
91101
}
92102
}

0 commit comments

Comments
 (0)