License updated to GPLv3

🧲 New features
Custom user role permissions
Employee edit form updated
Employee daily task list
Attendance and employee distribution charts on dashboard
Improvements to company structure and company assets module
Improved tables for displaying data in several modules
Faster data loading (specially for employee module)
Initials based profile pictures
Re-designed login page
Re-designed user profile page
Improvements to filtering
New REST endpoints for employee qualifications

🐛 Bug fixes
Fixed, issue with managers being able to create performance reviews for employees who are not their direct reports
Fixed, issues related to using full profile image instead of using smaller version of profile image
Changing third gender to other
Improvements and fixes for internal frontend data caching
This commit is contained in:
Thilina Pituwala
2020-10-31 19:02:37 +01:00
parent 86b8345505
commit b1df0037db
29343 changed files with 867614 additions and 2191082 deletions
@@ -0,0 +1 @@
*.php diff=php
@@ -0,0 +1,7 @@
/build/phar
/build/*.phar*
/.idea
/composer.lock
/vendor
/tools
/.php_cs.cache
+78
View File
@@ -0,0 +1,78 @@
<?php
$header = <<<'EOF'
This file is part of PHPLOC.
(c) Sebastian Bergmann <sebastian@phpunit.de>
For the full copyright and license information, please view the LICENSE
file that was distributed with this source code.
EOF;
return PhpCsFixer\Config::create()
->setRiskyAllowed(true)
->setRules(
[
'array_syntax' => ['syntax' => 'short'],
'binary_operator_spaces' => [
'align_double_arrow' => true,
'align_equals' => true
],
'blank_line_after_namespace' => true,
'blank_line_before_return' => true,
'braces' => true,
'cast_spaces' => true,
'concat_space' => ['spacing' => 'one'],
'elseif' => true,
'encoding' => true,
'full_opening_tag' => true,
'function_declaration' => true,
'header_comment' => ['header' => $header, 'separate' => 'none'],
'indentation_type' => true,
'line_ending' => true,
'lowercase_constants' => true,
'lowercase_keywords' => true,
'method_argument_space' => true,
'native_function_invocation' => true,
'no_alias_functions' => true,
'no_blank_lines_after_class_opening' => true,
'no_blank_lines_after_phpdoc' => true,
'no_closing_tag' => true,
'no_empty_phpdoc' => true,
'no_empty_statement' => true,
'no_extra_consecutive_blank_lines' => true,
'no_leading_namespace_whitespace' => true,
'no_singleline_whitespace_before_semicolons' => true,
'no_spaces_after_function_name' => true,
'no_spaces_inside_parenthesis' => true,
'no_trailing_comma_in_list_call' => true,
'no_trailing_whitespace' => true,
'no_unused_imports' => true,
'no_whitespace_in_blank_line' => true,
'phpdoc_align' => true,
'phpdoc_indent' => true,
'phpdoc_no_access' => true,
'phpdoc_no_empty_return' => true,
'phpdoc_no_package' => true,
'phpdoc_scalar' => true,
'phpdoc_separation' => true,
'phpdoc_to_comment' => true,
'phpdoc_trim' => true,
'phpdoc_types' => true,
'phpdoc_var_without_name' => true,
'self_accessor' => true,
'simplified_null_return' => true,
'single_blank_line_at_eof' => true,
'single_import_per_statement' => true,
'single_line_after_imports' => true,
'single_quote' => true,
'ternary_operator_spaces' => true,
'trim_array_spaces' => true,
'visibility_required' => true,
]
)
->setFinder(
PhpCsFixer\Finder::create()
->files()
->in(__DIR__ . '/src')
->name('*.php')
);
+32
View File
@@ -0,0 +1,32 @@
language: php
php:
- 5.6
- 7.0
- 7.1
- 7.2
- master
env:
matrix:
- DEPENDENCIES="high"
- DEPENDENCIES="low"
sudo: false
before_install:
- composer self-update
- composer clear-cache
- if [ $(phpenv version-name) = "5.6" ]; then wget https://phar.phpunit.de/phpunit-5.7.phar -O phpunit.phar; fi
- if [ $(phpenv version-name) != "5.6" ]; then wget https://phar.phpunit.de/phpunit.phar; fi
install:
- if [[ "$DEPENDENCIES" = 'high' ]]; then travis_retry composer update --no-interaction --no-ansi --no-progress --no-suggest --optimize-autoloader --prefer-stable; fi
- if [[ "$DEPENDENCIES" = 'low' ]]; then travis_retry composer update --no-interaction --no-ansi --no-progress --no-suggest --optimize-autoloader --prefer-stable --prefer-lowest; fi
script:
- php phpunit.phar
notifications:
email: false
+31
View File
@@ -0,0 +1,31 @@
# Changes in PHPLOC
All notable changes in PHPLOC are documented in this file using the [Keep a CHANGELOG](http://keepachangelog.com/) principles.
## [4.0.1] - 2017-11-18
### Changed
* This tool is now compatible with Symfony Console 4
## [4.0.0] - 2017-06-06
### Removed
* Removed the '--git-repository' option (and the corresponding functionality)
* Removed the '--progress' option (and the corresponding functionality)
## [3.0.1] - 2016-04-25
* Fixed [#139](https://github.com/sebastianbergmann/phploc/issues/139): Introduction of `T_USE` in `Analyser.php` gives `PHP Notice: Undefined index: ccn`
* Fixed [#141](https://github.com/sebastianbergmann/phploc/issues/141): `Undefined index: ccn in phar:///usr/local/bin/phploc/src/Analyser.php on line 507`
### Fixed
## [3.0.0] - 2016-01-13
[4.0.1]: https://github.com/sebastianbergmann/phploc/compare/4.0.0...4.0.1
[4.0.0]: https://github.com/sebastianbergmann/phploc/compare/3.0...4.0.0
[3.0.1]: https://github.com/sebastianbergmann/phploc/compare/3.0.0...3.0.1
[3.0.0]: https://github.com/sebastianbergmann/phploc/compare/2.1.5...3.0.0
+33
View File
@@ -0,0 +1,33 @@
phploc
Copyright (c) 2009-2017, Sebastian Bergmann <sebastian@phpunit.de>.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name of Sebastian Bergmann nor the names of his
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
+99
View File
@@ -0,0 +1,99 @@
[![Latest Stable Version](https://img.shields.io/packagist/v/phploc/phploc.svg?style=flat-square)](https://packagist.org/packages/phploc/phploc)
[![Build Status](https://img.shields.io/travis/sebastianbergmann/phploc/master.svg?style=flat-square)](https://travis-ci.org/sebastianbergmann/phploc)
# PHPLOC
`phploc` is a tool for quickly measuring the size and analyzing the structure of a PHP project.
## Installation
### PHP Archive (PHAR)
The easiest way to obtain PHPLOC is to download a [PHP Archive (PHAR)](http://php.net/phar) that has all required dependencies of PHPLOC bundled in a single file:
$ wget https://phar.phpunit.de/phploc.phar
$ chmod +x phploc.phar
$ mv phploc.phar /usr/local/bin/phploc
You can also immediately use the PHAR after you have downloaded it, of course:
$ wget https://phar.phpunit.de/phploc.phar
$ php phploc.phar
### Composer
You can add this tool as a local, per-project, development-time dependency to your project using [Composer](https://getcomposer.org/):
$ composer require --dev phploc/phploc
You can then invoke it using the `vendor/bin/phploc` executable.
## Usage Examples
### Analyse a directory and print the result
```
$ phploc src
phploc 4.0.0 by Sebastian Bergmann.
Directories 3
Files 10
Size
Lines of Code (LOC) 1882
Comment Lines of Code (CLOC) 255 (13.55%)
Non-Comment Lines of Code (NCLOC) 1627 (86.45%)
Logical Lines of Code (LLOC) 377 (20.03%)
Classes 351 (93.10%)
Average Class Length 35
Minimum Class Length 0
Maximum Class Length 172
Average Method Length 2
Minimum Method Length 1
Maximum Method Length 117
Functions 0 (0.00%)
Average Function Length 0
Not in classes or functions 26 (6.90%)
Cyclomatic Complexity
Average Complexity per LLOC 0.49
Average Complexity per Class 19.60
Minimum Class Complexity 1.00
Maximum Class Complexity 139.00
Average Complexity per Method 2.43
Minimum Method Complexity 1.00
Maximum Method Complexity 96.00
Dependencies
Global Accesses 0
Global Constants 0 (0.00%)
Global Variables 0 (0.00%)
Super-Global Variables 0 (0.00%)
Attribute Accesses 85
Non-Static 85 (100.00%)
Static 0 (0.00%)
Method Calls 280
Non-Static 276 (98.57%)
Static 4 (1.43%)
Structure
Namespaces 3
Interfaces 1
Traits 0
Classes 9
Abstract Classes 0 (0.00%)
Concrete Classes 9 (100.00%)
Methods 130
Scope
Non-Static Methods 130 (100.00%)
Static Methods 0 (0.00%)
Visibility
Public Methods 103 (79.23%)
Non-Public Methods 27 (20.77%)
Functions 0
Named Functions 0 (0.00%)
Anonymous Functions 0 (0.00%)
Constants 0
Global Constants 0 (0.00%)
Class Constants 0 (0.00%)
```
+121
View File
@@ -0,0 +1,121 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="phploc" default="setup">
<target name="setup" depends="clean,install-dependencies"/>
<target name="clean" description="Cleanup build artifacts">
<delete dir="${basedir}/build/phar"/>
<delete dir="${basedir}/vendor"/>
<delete file="${basedir}/composer.lock"/>
<delete>
<fileset dir="${basedir}/build">
<include name="**/phploc*.phar"/>
<include name="**/phploc*.phar.asc"/>
</fileset>
</delete>
</target>
<target name="install-dependencies" unless="dependencies-installed" depends="-dependencies-installed" description="Install dependencies with Composer">
<exec executable="composer" taskname="composer">
<arg value="update"/>
<arg value="--no-interaction"/>
<arg value="--no-progress"/>
<arg value="--no-ansi"/>
<arg value="--no-suggest"/>
<arg value="--optimize-autoloader"/>
<arg value="--prefer-stable"/>
</exec>
</target>
<target name="install-tools" unless="tools-installed" depends="-tools-installed" description="Install tools using phive">
<exec executable="phive" taskname="phive">
<arg value="install"/>
</exec>
</target>
<target name="test" depends="install-dependencies,install-tools" description="Run tests with PHPUnit">
<exec executable="${basedir}/tools/phpunit" failonerror="true"/>
</target>
<target name="signed-phar"
description="Create signed PHAR archive of PHPUnit and all its dependencies (release)"
depends="phar">
<exec executable="bash" outputproperty="version">
<arg value="-c" />
<arg value="${basedir}/phploc --version | awk 'BEGIN { ORS = &quot;&quot;; } {print $2}'" />
</exec>
<exec executable="gpg" failonerror="true">
<arg value="--armor" />
<arg value="--detach-sign" />
<arg path="${basedir}/build/phploc-${version}.phar" />
</exec>
</target>
<target name="phar"
description="Create PHAR archive of PHPLOC and all its dependencies"
depends="setup,phar-build">
<mkdir dir="${basedir}/build/phar"/>
</target>
<target name="phar-build">
<exec executable="bash" outputproperty="version">
<arg value="-c" />
<arg value="${basedir}/phploc --version | awk 'BEGIN { ORS = &quot;&quot;; } {print $2}'" />
</exec>
<copy todir="${basedir}/build/phar/src">
<fileset dir="${basedir}/src">
<include name="**/*.php" />
</fileset>
</copy>
<copy todir="${basedir}/build/phar/finder-facade">
<fileset dir="${basedir}/vendor/sebastian/finder-facade/src">
<include name="**/*.php" />
<exclude name="**/autoload.php" />
</fileset>
</copy>
<copy todir="${basedir}/build/phar/version">
<fileset dir="${basedir}/vendor/sebastian/version/src">
<include name="**/*.php" />
<exclude name="**/autoload.php" />
</fileset>
</copy>
<copy todir="${basedir}/build/phar/symfony">
<fileset dir="${basedir}/vendor/symfony">
<include name="**/*.php" />
<exclude name="**/Tests/**" />
</fileset>
</copy>
<copy todir="${basedir}/build/phar/fdomdocument">
<fileset dir="${basedir}/vendor/theseer/fdomdocument/src"/>
</copy>
<exec executable="${basedir}/build/phar-manifest.php" output="${basedir}/build/phar/manifest.txt"/>
<exec executable="${basedir}/tools/phpab">
<arg value="--all" />
<arg value="--phar" />
<arg value="--output" />
<arg path="${basedir}/build/phploc-${version}.phar" />
<arg value="--template" />
<arg path="${basedir}/build/phar-autoload.php.in" />
<arg value="--indent" />
<arg value=" " />
<arg path="${basedir}/build/phar" />
</exec>
<chmod file="${basedir}/build/phploc-${version}.phar" perm="ugo+rx"/>
</target>
<target name="-dependencies-installed">
<available file="${basedir}/vendor" property="dependencies-installed" type="dir"/>
</target>
<target name="-tools-installed">
<available file="${basedir}/tools" property="tools-installed" type="dir"/>
</target>
</project>
@@ -0,0 +1,42 @@
#!/usr/bin/env php
<?php
if ($_SERVER['SCRIPT_NAME'] != '-') {
$phar = realpath($_SERVER['SCRIPT_NAME']);
} else {
$files = get_included_files();
$phar = $files[0];
}
define('__PHPLOC_PHAR__', str_replace(DIRECTORY_SEPARATOR, '/', $phar));
define('__PHPLOC_PHAR_ROOT__', 'phar://___PHAR___');
spl_autoload_register(
function ($class)
{
static $classes = NULL;
if ($classes === NULL) {
$classes = array(
___CLASSLIST___
);
}
$class = strtolower($class);
if (isset($classes[$class])) {
require 'phar://___PHAR___' . $classes[$class];
}
}
);
Phar::mapPhar('___PHAR___');
if (isset($_SERVER['argv'][1]) && $_SERVER['argv'][1] == '--manifest') {
print file_get_contents(__PHPLOC_PHAR_ROOT__ . '/manifest.txt');
exit;
}
$application = new SebastianBergmann\PHPLOC\CLI\Application;
$application->run();
__HALT_COMPILER();
+27
View File
@@ -0,0 +1,27 @@
#!/usr/bin/env php
<?php
print 'phploc/phploc: ';
$tag = @exec('git describe --tags 2>&1');
if (strpos($tag, '-') === false && strpos($tag, 'No names found') === false) {
print $tag;
} else {
$branch = @exec('git rev-parse --abbrev-ref HEAD');
$hash = @exec('git log -1 --format="%H"');
print $branch . '@' . $hash;
}
print "\n";
$lock = json_decode(file_get_contents(__DIR__ . '/../composer.lock'));
foreach ($lock->packages as $package) {
print $package->name . ': ' . $package->version;
if (!preg_match('/^[v= ]*(([0-9]+)(\\.([0-9]+)(\\.([0-9]+)(-([0-9]+))?(-?([a-zA-Z-+][a-zA-Z0-9\\.\\-:]*)?)?)?)?)$/', $package->version)) {
print '@' . $package->source->reference;
}
print "\n";
}
+35
View File
@@ -0,0 +1,35 @@
{
"name": "phploc/phploc",
"description": "A tool for quickly measuring the size of a PHP project.",
"homepage": "https://github.com/sebastianbergmann/phploc",
"license": "BSD-3-Clause",
"authors": [
{
"name": "Sebastian Bergmann",
"email": "sebastian@phpunit.de",
"role": "lead"
}
],
"support": {
"issues": "https://github.com/sebastianbergmann/phploc/issues"
},
"require": {
"php": "^5.6 || ^7.0",
"sebastian/finder-facade": "^1.1",
"sebastian/version": "^2.0",
"symfony/console": "^2.7|^3.0|^4.0"
},
"autoload": {
"classmap": [
"src/"
]
},
"bin": [
"phploc"
],
"extra": {
"branch-alias": {
"dev-master": "4.0-dev"
}
}
}
+5
View File
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<phive xmlns="https://phar.io/phive">
<phar name="phpunit" version="5.7.10" installed="5.7.10" location="./tools/phpunit"/>
<phar name="phpab" version="*" installed="1.23.0" location="./tools/phpab"/>
</phive>
+31
View File
@@ -0,0 +1,31 @@
#!/usr/bin/env php
<?php
/*
* This file is part of PHPLOC.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
$loaded = false;
foreach (array(__DIR__ . '/../../autoload.php', __DIR__ . '/vendor/autoload.php') as $file) {
if (file_exists($file)) {
require $file;
$loaded = true;
break;
}
}
if (!$loaded) {
die(
'You need to set up the project dependencies using the following commands:' . PHP_EOL .
'wget http://getcomposer.org/composer.phar' . PHP_EOL .
'php composer.phar install' . PHP_EOL
);
}
$application = new SebastianBergmann\PHPLOC\CLI\Application;
$application->run();
+20
View File
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/5.7/phpunit.xsd"
bootstrap="vendor/autoload.php"
backupGlobals="false"
beStrictAboutCoversAnnotation="true"
beStrictAboutOutputDuringTests="true"
beStrictAboutTestsThatDoNotTestAnything="true"
beStrictAboutTodoAnnotatedTests="true"
verbose="true">
<testsuite>
<directory suffix="Test.php">tests</directory>
</testsuite>
<filter>
<whitelist processUncoveredFilesFromWhitelist="true">
<directory suffix=".php">src</directory>
</whitelist>
</filter>
</phpunit>
+604
View File
@@ -0,0 +1,604 @@
<?php
/*
* This file is part of PHPLOC.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace SebastianBergmann\PHPLOC;
/**
* PHPLOC code analyser.
*/
class Analyser
{
/**
* @var Collector
*/
private $collector;
/**
* @var array
*/
private $classes = [];
/**
* @var array
*/
private $superGlobals = [
'$_ENV' => true,
'$_POST' => true,
'$_GET' => true,
'$_COOKIE' => true,
'$_SERVER' => true,
'$_FILES' => true,
'$_REQUEST' => true,
'$HTTP_ENV_VARS' => true,
'$HTTP_POST_VARS' => true,
'$HTTP_GET_VARS' => true,
'$HTTP_COOKIE_VARS' => true,
'$HTTP_SERVER_VARS' => true,
'$HTTP_POST_FILES' => true
];
public function __construct()
{
$this->collector = new Collector();
}
/**
* Processes a set of files.
*
* @param array $files
* @param bool $countTests
*
* @return array
*/
public function countFiles(array $files, $countTests)
{
foreach ($files as $file) {
$this->countFile($file, $countTests);
}
return $this->collector->getPublisher()->toArray();
}
/**
* Pre-processes a single file.
*
* @param string $filename
*/
public function preProcessFile($filename)
{
$tokens = \token_get_all(\file_get_contents($filename));
$numTokens = \count($tokens);
$namespace = false;
for ($i = 0; $i < $numTokens; $i++) {
if (\is_string($tokens[$i])) {
continue;
}
switch ($tokens[$i][0]) {
case T_NAMESPACE:
$namespace = $this->getNamespaceName($tokens, $i);
break;
case T_CLASS:
if (!$this->isClassDeclaration($tokens, $i)) {
continue;
}
$className = $this->getClassName($namespace, $tokens, $i);
if (isset($tokens[$i + 4]) && \is_array($tokens[$i + 4]) &&
$tokens[$i + 4][0] == T_EXTENDS) {
$parent = $this->getClassName($namespace, $tokens, $i + 4);
} else {
$parent = null;
}
$this->classes[$className] = $parent;
break;
}
}
}
/**
* Processes a single file.
*
* @param string $filename
* @param bool $countTests
*/
public function countFile($filename, $countTests)
{
if ($countTests) {
$this->preProcessFile($filename);
}
$buffer = \file_get_contents($filename);
$this->collector->incrementLines(\substr_count($buffer, "\n"));
$tokens = \token_get_all($buffer);
$numTokens = \count($tokens);
unset($buffer);
$this->collector->addFile($filename);
$blocks = [];
$currentBlock = false;
$namespace = false;
$className = null;
$functionName = null;
$testClass = false;
$this->collector->currentClassReset();
$isInMethod = false;
for ($i = 0; $i < $numTokens; $i++) {
if (\is_string($tokens[$i])) {
$token = \trim($tokens[$i]);
if ($token == ';') {
if ($className !== null && !$testClass) {
$this->collector->currentClassIncrementLines();
if ($functionName !== null) {
$this->collector->currentMethodIncrementLines();
}
} elseif ($functionName !== null) {
$this->collector->incrementFunctionLines();
}
$this->collector->incrementLogicalLines();
} elseif ($token == '?' && !$testClass) {
if ($className !== null) {
$this->collector->currentClassIncrementComplexity();
$this->collector->currentMethodIncrementComplexity();
}
$this->collector->incrementComplexity();
} elseif ($token == '{') {
if ($currentBlock == T_CLASS) {
$block = $className;
} elseif ($currentBlock == T_FUNCTION) {
$block = $functionName;
} else {
$block = false;
}
\array_push($blocks, $block);
$currentBlock = false;
} elseif ($token == '}') {
$block = \array_pop($blocks);
if ($block !== false && $block !== null) {
if ($block == $functionName) {
$functionName = null;
if ($isInMethod) {
$this->collector->currentMethodStop();
$isInMethod = false;
}
} elseif ($block == $className) {
$className = null;
$testClass = false;
$this->collector->currentClassReset();
}
}
}
continue;
}
list($token, $value) = $tokens[$i];
switch ($token) {
case T_NAMESPACE:
$namespace = $this->getNamespaceName($tokens, $i);
$this->collector->addNamespace($namespace);
break;
case T_CLASS:
case T_INTERFACE:
case T_TRAIT:
if (!$this->isClassDeclaration($tokens, $i)) {
continue;
}
$this->collector->currentClassReset();
$this->collector->currentClassIncrementComplexity();
$className = $this->getClassName($namespace, $tokens, $i);
$currentBlock = T_CLASS;
if ($token == T_TRAIT) {
$this->collector->incrementTraits();
} elseif ($token == T_INTERFACE) {
$this->collector->incrementInterfaces();
} else {
if ($countTests && $this->isTestClass($className)) {
$testClass = true;
$this->collector->incrementTestClasses();
} else {
if (isset($tokens[$i - 2]) &&
\is_array($tokens[$i - 2]) &&
$tokens[$i - 2][0] == T_ABSTRACT) {
$this->collector->incrementAbstractClasses();
} else {
$this->collector->incrementConcreteClasses();
}
}
}
break;
case T_FUNCTION:
$prev = $this->getPreviousNonWhitespaceTokenPos($tokens, $i);
if ($tokens[$prev][0] === T_USE) {
continue;
}
$currentBlock = T_FUNCTION;
$next = $this->getNextNonWhitespaceTokenPos($tokens, $i);
if (!\is_array($tokens[$next]) && $tokens[$next] == '&') {
$next = $this->getNextNonWhitespaceTokenPos($tokens, $next);
}
if (\is_array($tokens[$next]) &&
$tokens[$next][0] == T_STRING) {
$functionName = $tokens[$next][1];
} else {
$currentBlock = 'anonymous function';
$functionName = 'anonymous function';
$this->collector->incrementAnonymousFunctions();
}
if ($currentBlock == T_FUNCTION) {
if ($className === null &&
$functionName != 'anonymous function') {
$this->collector->incrementNamedFunctions();
} else {
$static = false;
$visibility = T_PUBLIC;
for ($j = $i; $j > 0; $j--) {
if (\is_string($tokens[$j])) {
if ($tokens[$j] == '{' ||
$tokens[$j] == '}' ||
$tokens[$j] == ';') {
break;
}
continue;
}
if (isset($tokens[$j][0])) {
switch ($tokens[$j][0]) {
case T_PRIVATE:
$visibility = T_PRIVATE;
break;
case T_PROTECTED:
$visibility = T_PROTECTED;
break;
case T_STATIC:
$static = true;
break;
}
}
}
if ($testClass &&
$this->isTestMethod($functionName, $visibility, $static, $tokens, $i)) {
$this->collector->incrementTestMethods();
} elseif (!$testClass) {
$isInMethod = true;
$this->collector->currentMethodStart();
if (!$static) {
$this->collector->incrementNonStaticMethods();
} else {
$this->collector->incrementStaticMethods();
}
if ($visibility == T_PUBLIC) {
$this->collector->incrementPublicMethods();
} else {
$this->collector->incrementNonPublicMethods();
}
}
}
}
break;
case T_CURLY_OPEN:
$currentBlock = T_CURLY_OPEN;
\array_push($blocks, $currentBlock);
break;
case T_DOLLAR_OPEN_CURLY_BRACES:
$currentBlock = T_DOLLAR_OPEN_CURLY_BRACES;
\array_push($blocks, $currentBlock);
break;
case T_IF:
case T_ELSEIF:
case T_FOR:
case T_FOREACH:
case T_WHILE:
case T_CASE:
case T_CATCH:
case T_BOOLEAN_AND:
case T_LOGICAL_AND:
case T_BOOLEAN_OR:
case T_LOGICAL_OR:
if (!$testClass) {
if ($isInMethod) {
$this->collector->currentClassIncrementComplexity();
$this->collector->currentMethodIncrementComplexity();
}
$this->collector->incrementComplexity();
}
break;
case T_COMMENT:
case T_DOC_COMMENT:
// We want to count all intermediate lines before the token ends
// But sometimes a new token starts after a newline, we don't want to count that.
// That happened with /* */ and /** */, but not with // since it'll end at the end
$this->collector->incrementCommentLines(\substr_count(\rtrim($value, "\n"), "\n") + 1);
break;
case T_CONST:
$this->collector->incrementClassConstants();
break;
case T_STRING:
if ($value == 'define') {
$this->collector->incrementGlobalConstants();
$j = $i + 1;
while (isset($tokens[$j]) && $tokens[$j] != ';') {
if (\is_array($tokens[$j]) &&
$tokens[$j][0] == T_CONSTANT_ENCAPSED_STRING) {
$this->collector->addConstant(\str_replace('\'', '', $tokens[$j][1]));
break;
}
$j++;
}
} else {
$this->collector->addPossibleConstantAccesses($value);
}
break;
case T_DOUBLE_COLON:
case T_OBJECT_OPERATOR:
$n = $this->getNextNonWhitespaceTokenPos($tokens, $i);
$nn = $this->getNextNonWhitespaceTokenPos($tokens, $n);
if ($n && $nn &&
isset($tokens[$n][0]) &&
($tokens[$n][0] == T_STRING ||
$tokens[$n][0] == T_VARIABLE) &&
$tokens[$nn] == '(') {
if ($token == T_DOUBLE_COLON) {
$this->collector->incrementStaticMethodCalls();
} else {
$this->collector->incrementNonStaticMethodCalls();
}
} else {
if ($token == T_DOUBLE_COLON &&
$tokens[$n][0] == T_VARIABLE) {
$this->collector->incrementStaticAttributeAccesses();
} elseif ($token == T_OBJECT_OPERATOR) {
$this->collector->incrementNonStaticAttributeAccesses();
}
}
break;
case T_GLOBAL:
$this->collector->incrementGlobalVariableAccesses();
break;
case T_VARIABLE:
if ($value == '$GLOBALS') {
$this->collector->incrementGlobalVariableAccesses();
} elseif (isset($this->superGlobals[$value])) {
$this->collector->incrementSuperGlobalVariableAccesses();
}
break;
}
}
}
/**
* @param array $tokens
* @param int $i
*
* @return string
*/
private function getNamespaceName(array $tokens, $i)
{
if (isset($tokens[$i + 2][1])) {
$namespace = $tokens[$i + 2][1];
for ($j = $i + 3;; $j += 2) {
if (isset($tokens[$j]) && $tokens[$j][0] == T_NS_SEPARATOR) {
$namespace .= '\\' . $tokens[$j + 1][1];
} else {
break;
}
}
return $namespace;
}
return false;
}
/**
* @param string $namespace
* @param array $tokens
* @param int $i
*
* @return string
*/
private function getClassName($namespace, array $tokens, $i)
{
$i += 2;
if (!isset($tokens[$i][1])) {
return 'invalid class name';
}
$className = $tokens[$i][1];
$namespaced = $className === '\\';
while (\is_array($tokens[$i + 1]) && $tokens[$i + 1][0] !== T_WHITESPACE) {
$className .= $tokens[++$i][1];
}
if (!$namespaced && $namespace !== false) {
$className = $namespace . '\\' . $className;
}
return \strtolower($className);
}
/**
* @param string $className
*
* @return bool
*/
private function isTestClass($className)
{
$parent = $this->classes[$className];
$count = 0;
// Check ancestry for PHPUnit_Framework_TestCase.
while ($parent !== null) {
$count++;
if ($count > 100) {
// Prevent infinite loops and just bail
break;
}
if ($parent == 'phpunit_framework_testcase' ||
$parent == '\\phpunit_framework_testcase' ||
// TODO: Recognize PHPUnit\Framework\TestCase when it is imported
$parent == 'phpunit\\framework\\testcase' ||
$parent == '\\phpunit\\framework\\testcase') {
return true;
}
if (isset($this->classes[$parent]) && $parent !== $this->classes[$parent]) {
$parent = $this->classes[$parent];
} else {
// Class has a parent that is declared in a file
// that was not pre-processed.
break;
}
}
// Fallback: Treat the class as a test case class if the name
// of the parent class ends with "TestCase".
return \substr($this->classes[$className], -8) === 'testcase';
}
/**
* @param string $functionName
* @param int $visibility
* @param bool $static
* @param array $tokens
* @param int $currentToken
*
* @return bool
*/
private function isTestMethod($functionName, $visibility, $static, array $tokens, $currentToken)
{
if ($static || $visibility != T_PUBLIC) {
return false;
}
if (\strpos($functionName, 'test') === 0) {
return true;
}
while ($tokens[$currentToken][0] != T_DOC_COMMENT) {
if ($tokens[$currentToken] == '{' || $tokens[$currentToken] == '}') {
return false;
}
--$currentToken;
}
return \strpos($tokens[$currentToken][1], '@test') !== false ||
\strpos($tokens[$currentToken][1], '@scenario') !== false;
}
/**
* @param array $tokens
* @param int $start
*
* @return bool
*/
private function getNextNonWhitespaceTokenPos(array $tokens, $start)
{
if (isset($tokens[$start + 1])) {
if (isset($tokens[$start + 1][0]) &&
$tokens[$start + 1][0] == T_WHITESPACE &&
isset($tokens[$start + 2])) {
return $start + 2;
} else {
return $start + 1;
}
}
return false;
}
/**
* @param array $tokens
* @param int $start
*
* @return bool
*/
private function getPreviousNonWhitespaceTokenPos(array $tokens, $start)
{
if (isset($tokens[$start - 1])) {
if (isset($tokens[$start - 1][0]) &&
$tokens[$start - 1][0] == T_WHITESPACE &&
isset($tokens[$start - 2])) {
return $start - 2;
} else {
return $start - 1;
}
}
return false;
}
/**
* @param array $tokens
* @param int $i
*
* @return bool
*/
private function isClassDeclaration(array $tokens, $i)
{
$n = $this->getPreviousNonWhitespaceTokenPos($tokens, $i);
return !isset($tokens[$n])
|| !\is_array($tokens[$n])
|| !\in_array($tokens[$n][0], [T_DOUBLE_COLON, T_NEW], true);
}
}
@@ -0,0 +1,114 @@
<?php
/*
* This file is part of PHPLOC.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace SebastianBergmann\PHPLOC\CLI;
use SebastianBergmann\Version;
use Symfony\Component\Console\Application as AbstractApplication;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\ArrayInput;
/**
* TextUI frontend for PHPLOC.
*/
class Application extends AbstractApplication
{
public function __construct()
{
$version = new Version('4.0.1', \dirname(\dirname(__DIR__)));
parent::__construct('phploc', $version->getVersion());
}
/**
* Gets the name of the command based on input.
*
* @param InputInterface $input The input interface
*
* @return string The command name
*/
protected function getCommandName(InputInterface $input)
{
return 'phploc';
}
/**
* Gets the default commands that should always be available.
*
* @return array An array of default Command instances
*/
protected function getDefaultCommands()
{
$defaultCommands = parent::getDefaultCommands();
$defaultCommands[] = new Command;
return $defaultCommands;
}
/**
* Overridden so that the application doesn't expect the command
* name to be the first argument.
*/
public function getDefinition()
{
$inputDefinition = parent::getDefinition();
$inputDefinition->setArguments();
return $inputDefinition;
}
/**
* Runs the current application.
*
* @param InputInterface $input An Input instance
* @param OutputInterface $output An Output instance
*
* @return int 0 if everything went fine, or an error code
*/
public function doRun(InputInterface $input, OutputInterface $output)
{
$this->disableXdebug();
if (!$input->hasParameterOption('--quiet')) {
$output->write(
\sprintf(
"phploc %s by Sebastian Bergmann.\n\n",
$this->getVersion()
)
);
}
if ($input->hasParameterOption('--version') ||
$input->hasParameterOption('-V')) {
exit;
}
if (!$input->getFirstArgument()) {
$input = new ArrayInput(['--help']);
}
parent::doRun($input, $output);
}
private function disableXdebug()
{
if (!\extension_loaded('xdebug')) {
return;
}
\ini_set('xdebug.scream', 0);
\ini_set('xdebug.max_nesting_level', 8192);
\ini_set('xdebug.show_exception_trace', 0);
\ini_set('xdebug.show_error_trace', 0);
\xdebug_disable();
}
}
@@ -0,0 +1,152 @@
<?php
/*
* This file is part of PHPLOC.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace SebastianBergmann\PHPLOC\CLI;
use SebastianBergmann\FinderFacade\FinderFacade;
use SebastianBergmann\PHPLOC\Analyser;
use SebastianBergmann\PHPLOC\Log\Csv;
use SebastianBergmann\PHPLOC\Log\Text;
use SebastianBergmann\PHPLOC\Log\Xml;
use Symfony\Component\Console\Command\Command as AbstractCommand;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
class Command extends AbstractCommand
{
/**
* Configures the current command.
*/
protected function configure()
{
$this->setName('phploc')
->setDefinition(
[
new InputArgument(
'values',
InputArgument::IS_ARRAY
)
]
)
->addOption(
'names',
null,
InputOption::VALUE_REQUIRED,
'A comma-separated list of file names to check',
['*.php']
)
->addOption(
'names-exclude',
null,
InputOption::VALUE_REQUIRED,
'A comma-separated list of file names to exclude',
[]
)
->addOption(
'count-tests',
null,
InputOption::VALUE_NONE,
'Count PHPUnit test case classes and test methods'
)
->addOption(
'exclude',
null,
InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY,
'Exclude a directory from code analysis'
)
->addOption(
'log-csv',
null,
InputOption::VALUE_REQUIRED,
'Write result in CSV format to file'
)
->addOption(
'log-xml',
null,
InputOption::VALUE_REQUIRED,
'Write result in XML format to file'
);
}
/**
* Executes the current command.
*
* @param InputInterface $input An InputInterface instance
* @param OutputInterface $output An OutputInterface instance
*
* @return null|int null or 0 if everything went fine, or an error code
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$count = $this->count(
$input->getArgument('values'),
$input->getOption('exclude'),
$this->handleCSVOption($input, 'names'),
$this->handleCSVOption($input, 'names-exclude'),
$input->getOption('count-tests')
);
if (!$count) {
$output->writeln('No files found to scan');
exit(1);
}
$printer = new Text;
$printer->printResult(
$output,
$count,
$input->getOption('count-tests')
);
if ($input->getOption('log-csv')) {
$printer = new Csv;
$printer->printResult($input->getOption('log-csv'), $count);
}
if ($input->getOption('log-xml')) {
$printer = new Xml;
$printer->printResult($input->getOption('log-xml'), $count);
}
}
private function count(array $arguments, $excludes, $names, $namesExclude, $countTests)
{
try {
$finder = new FinderFacade($arguments, $excludes, $names, $namesExclude);
$files = $finder->findFiles();
} catch (\InvalidArgumentException $ex) {
return false;
}
if (empty($files)) {
return false;
}
$analyser = new Analyser;
return $analyser->countFiles($files, $countTests);
}
/**
* @param InputInterface $input
* @param string $option
*
* @return array
*/
private function handleCSVOption(InputInterface $input, $option)
{
$result = $input->getOption($option);
return \is_array($result) ? $result : \explode(',', $result);
}
}
+242
View File
@@ -0,0 +1,242 @@
<?php
/*
* This file is part of PHPLOC.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace SebastianBergmann\PHPLOC;
class Collector
{
private $counts = [];
private $currentClassComplexity = 0;
private $currentClassLines = 0;
private $currentMethodComplexity = 0;
private $currentMethodLines = 0;
public function getPublisher()
{
return new Publisher($this->counts);
}
public function addFile($filename)
{
$this->increment('files');
$this->addUnique('directories', \dirname($filename));
}
public function incrementLines($number)
{
$this->increment('lines', $number);
}
public function incrementCommentLines($number)
{
$this->increment('comment lines', $number);
}
public function incrementLogicalLines()
{
$this->increment('logical lines');
}
public function currentClassReset()
{
if ($this->currentClassComplexity > 0) {
$this->addToArray('class complexity', $this->currentClassComplexity);
$this->addToArray('class lines', $this->currentClassLines);
}
$this->currentClassComplexity = 0;
$this->currentClassLines = 0;
}
public function currentClassIncrementComplexity()
{
$this->currentClassComplexity++;
}
public function currentClassIncrementLines()
{
$this->currentClassLines++;
}
public function currentMethodStart()
{
$this->currentMethodComplexity = 1;
$this->currentMethodLines = 0;
}
public function currentMethodIncrementComplexity()
{
$this->currentMethodComplexity++;
$this->increment('total method complexity');
}
public function currentMethodIncrementLines()
{
$this->currentMethodLines++;
}
public function currentMethodStop()
{
$this->addToArray('method complexity', $this->currentMethodComplexity);
$this->addToArray('method lines', $this->currentMethodLines);
}
public function incrementFunctionLines()
{
$this->increment('function lines');
}
public function incrementComplexity()
{
$this->increment('complexity');
}
public function addPossibleConstantAccesses($name)
{
$this->addToArray('possible constant accesses', $name);
}
public function addConstant($name)
{
$this->addToArray('constant', $name);
}
public function incrementGlobalVariableAccesses()
{
$this->increment('global variable accesses');
}
public function incrementSuperGlobalVariableAccesses()
{
$this->increment('super global variable accesses');
}
public function incrementNonStaticAttributeAccesses()
{
$this->increment('non-static attribute accesses');
}
public function incrementStaticAttributeAccesses()
{
$this->increment('static attribute accesses');
}
public function incrementNonStaticMethodCalls()
{
$this->increment('non-static method calls');
}
public function incrementStaticMethodCalls()
{
$this->increment('static method calls');
}
public function addNamespace($namespace)
{
$this->addUnique('namespaces', $namespace);
}
public function incrementInterfaces()
{
$this->increment('interfaces');
}
public function incrementTraits()
{
$this->increment('traits');
}
public function incrementAbstractClasses()
{
$this->increment('abstract classes');
}
public function incrementConcreteClasses()
{
$this->increment('concrete classes');
}
public function incrementNonStaticMethods()
{
$this->increment('non-static methods');
}
public function incrementStaticMethods()
{
$this->increment('static methods');
}
public function incrementPublicMethods()
{
$this->increment('public methods');
}
public function incrementNonPublicMethods()
{
$this->increment('non-public methods');
}
public function incrementNamedFunctions()
{
$this->increment('named functions');
}
public function incrementAnonymousFunctions()
{
$this->increment('anonymous functions');
}
public function incrementGlobalConstants()
{
$this->increment('global constants');
}
public function incrementClassConstants()
{
$this->increment('class constants');
}
public function incrementTestClasses()
{
$this->increment('test classes');
}
public function incrementTestMethods()
{
$this->increment('test methods');
}
private function addUnique($key, $name)
{
$this->check($key, []);
$this->counts[$key][$name] = true;
}
private function addToArray($key, $value)
{
$this->check($key, []);
$this->counts[$key][] = $value;
}
private function increment($key, $number = 1)
{
$this->check($key, 0);
$this->counts[$key] += $number;
}
private function check($key, $default)
{
if (!isset($this->counts[$key])) {
$this->counts[$key] = $default;
}
}
}
@@ -0,0 +1,15 @@
<?php
/*
* This file is part of PHPLOC.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace SebastianBergmann\PHPLOC;
interface Exception
{
}
@@ -0,0 +1,15 @@
<?php
/*
* This file is part of PHPLOC.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace SebastianBergmann\PHPLOC;
class RuntimeException extends \RuntimeException implements Exception
{
}
+112
View File
@@ -0,0 +1,112 @@
<?php
/*
* This file is part of PHPLOC.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace SebastianBergmann\PHPLOC\Log;
/**
* A CSV ResultPrinter for the TextUI.
*/
class Csv
{
/**
* Mapping between internal and human-readable metric names
*
* @var array
*/
private $colmap = [
'directories' => 'Directories',
'files' => 'Files',
'loc' => 'Lines of Code (LOC)',
'ccnByLloc' => 'Cyclomatic Complexity / Lines of Code',
'cloc' => 'Comment Lines of Code (CLOC)',
'ncloc' => 'Non-Comment Lines of Code (NCLOC)',
'lloc' => 'Logical Lines of Code (LLOC)',
'llocGlobal' => 'LLOC outside functions or classes',
'namespaces' => 'Namespaces',
'interfaces' => 'Interfaces',
'traits' => 'Traits',
'classes' => 'Classes',
'abstractClasses' => 'Abstract Classes',
'concreteClasses' => 'Concrete Classes',
'llocClasses' => 'Classes Length (LLOC)',
'methods' => 'Methods',
'nonStaticMethods' => 'Non-Static Methods',
'staticMethods' => 'Static Methods',
'publicMethods' => 'Public Methods',
'nonPublicMethods' => 'Non-Public Methods',
'methodCcnAvg' => 'Cyclomatic Complexity / Number of Methods',
'functions' => 'Functions',
'namedFunctions' => 'Named Functions',
'anonymousFunctions' => 'Anonymous Functions',
'llocFunctions' => 'Functions Length (LLOC)',
'llocByNof' => 'Average Function Length (LLOC)',
'constants' => 'Constants',
'globalConstants' => 'Global Constants',
'classConstants' => 'Class Constants',
'attributeAccesses' => 'Attribute Accesses',
'instanceAttributeAccesses' => 'Non-Static Attribute Accesses',
'staticAttributeAccesses' => 'Static Attribute Accesses',
'methodCalls' => 'Method Calls',
'instanceMethodCalls' => 'Non-Static Method Calls',
'staticMethodCalls' => 'Static Method Calls',
'globalAccesses' => 'Global Accesses',
'globalVariableAccesses' => 'Global Variable Accesses',
'superGlobalVariableAccesses' => 'Super-Global Variable Accesses',
'globalConstantAccesses' => 'Global Constant Accesses',
'testClasses' => 'Test Classes',
'testMethods' => 'Test Methods'
];
/**
* Prints a result set.
*
* @param string $filename
* @param array $count
*/
public function printResult($filename, array $count)
{
\file_put_contents(
$filename,
$this->getKeysLine($count) . $this->getValuesLine($count)
);
}
/**
* @param array $count
*
* @return string
*/
protected function getKeysLine(array $count)
{
return \implode(',', \array_values($this->colmap)) . PHP_EOL;
}
/**
* @param array $count
*
* @throws \InvalidArgumentException
*
* @return string
*/
protected function getValuesLine(array $count)
{
$values = [];
foreach ($this->colmap as $key => $name) {
if (isset($count[$key])) {
$values[] = $count[$key];
} else {
throw new \InvalidArgumentException('Attempted to print row with missing keys');
}
}
return '"' . \implode('","', $values) . '"' . PHP_EOL;
}
}
+190
View File
@@ -0,0 +1,190 @@
<?php
/*
* This file is part of PHPLOC.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace SebastianBergmann\PHPLOC\Log;
use Symfony\Component\Console\Output\OutputInterface;
/**
* A ResultPrinter for the TextUI.
*/
class Text
{
/**
* Prints a result set.
*
* @param OutputInterface $output
* @param array $count
* @param bool $printTests
*/
public function printResult(OutputInterface $output, array $count, $printTests)
{
if ($count['directories'] > 0) {
$output->write(
\sprintf(
"Directories %10d\n" .
"Files %10d\n\n",
$count['directories'],
$count['files']
)
);
}
$format = <<<END
Size
Lines of Code (LOC) %10d
Comment Lines of Code (CLOC) %10d (%.2f%%)
Non-Comment Lines of Code (NCLOC) %10d (%.2f%%)
Logical Lines of Code (LLOC) %10d (%.2f%%)
Classes %10d (%.2f%%)
Average Class Length %10d
Minimum Class Length %10d
Maximum Class Length %10d
Average Method Length %10d
Minimum Method Length %10d
Maximum Method Length %10d
Functions %10d (%.2f%%)
Average Function Length %10d
Not in classes or functions %10d (%.2f%%)
Cyclomatic Complexity
Average Complexity per LLOC %10.2f
Average Complexity per Class %10.2f
Minimum Class Complexity %10.2f
Maximum Class Complexity %10.2f
Average Complexity per Method %10.2f
Minimum Method Complexity %10.2f
Maximum Method Complexity %10.2f
Dependencies
Global Accesses %10d
Global Constants %10d (%.2f%%)
Global Variables %10d (%.2f%%)
Super-Global Variables %10d (%.2f%%)
Attribute Accesses %10d
Non-Static %10d (%.2f%%)
Static %10d (%.2f%%)
Method Calls %10d
Non-Static %10d (%.2f%%)
Static %10d (%.2f%%)
Structure
Namespaces %10d
Interfaces %10d
Traits %10d
Classes %10d
Abstract Classes %10d (%.2f%%)
Concrete Classes %10d (%.2f%%)
Methods %10d
Scope
Non-Static Methods %10d (%.2f%%)
Static Methods %10d (%.2f%%)
Visibility
Public Methods %10d (%.2f%%)
Non-Public Methods %10d (%.2f%%)
Functions %10d
Named Functions %10d (%.2f%%)
Anonymous Functions %10d (%.2f%%)
Constants %10d
Global Constants %10d (%.2f%%)
Class Constants %10d (%.2f%%)
END;
$output->write(
\sprintf(
$format,
$count['loc'],
$count['cloc'],
$count['loc'] > 0 ? ($count['cloc'] / $count['loc']) * 100 : 0,
$count['ncloc'],
$count['loc'] > 0 ? ($count['ncloc'] / $count['loc']) * 100 : 0,
$count['lloc'],
$count['loc'] > 0 ? ($count['lloc'] / $count['loc']) * 100 : 0,
$count['llocClasses'],
$count['lloc'] > 0 ? ($count['llocClasses'] / $count['lloc']) * 100 : 0,
$count['classLlocAvg'],
$count['classLlocMin'],
$count['classLlocMax'],
$count['methodLlocAvg'],
$count['methodLlocMin'],
$count['methodLlocMax'],
$count['llocFunctions'],
$count['lloc'] > 0 ? ($count['llocFunctions'] / $count['lloc']) * 100 : 0,
$count['llocByNof'],
$count['llocGlobal'],
$count['lloc'] > 0 ? ($count['llocGlobal'] / $count['lloc']) * 100 : 0,
$count['ccnByLloc'],
$count['classCcnAvg'],
$count['classCcnMin'],
$count['classCcnMax'],
$count['methodCcnAvg'],
$count['methodCcnMin'],
$count['methodCcnMax'],
$count['globalAccesses'],
$count['globalConstantAccesses'],
$count['globalAccesses'] > 0 ? ($count['globalConstantAccesses'] / $count['globalAccesses']) * 100 : 0,
$count['globalVariableAccesses'],
$count['globalAccesses'] > 0 ? ($count['globalVariableAccesses'] / $count['globalAccesses']) * 100 : 0,
$count['superGlobalVariableAccesses'],
$count['globalAccesses'] > 0 ? ($count['superGlobalVariableAccesses'] / $count['globalAccesses']) * 100 : 0,
$count['attributeAccesses'],
$count['instanceAttributeAccesses'],
$count['attributeAccesses'] > 0 ? ($count['instanceAttributeAccesses'] / $count['attributeAccesses']) * 100 : 0,
$count['staticAttributeAccesses'],
$count['attributeAccesses'] > 0 ? ($count['staticAttributeAccesses'] / $count['attributeAccesses']) * 100 : 0,
$count['methodCalls'],
$count['instanceMethodCalls'],
$count['methodCalls'] > 0 ? ($count['instanceMethodCalls'] / $count['methodCalls']) * 100 : 0,
$count['staticMethodCalls'],
$count['methodCalls'] > 0 ? ($count['staticMethodCalls'] / $count['methodCalls']) * 100 : 0,
$count['namespaces'],
$count['interfaces'],
$count['traits'],
$count['classes'],
$count['abstractClasses'],
$count['classes'] > 0 ? ($count['abstractClasses'] / $count['classes']) * 100 : 0,
$count['concreteClasses'],
$count['classes'] > 0 ? ($count['concreteClasses'] / $count['classes']) * 100 : 0,
$count['methods'],
$count['nonStaticMethods'],
$count['methods'] > 0 ? ($count['nonStaticMethods'] / $count['methods']) * 100 : 0,
$count['staticMethods'],
$count['methods'] > 0 ? ($count['staticMethods'] / $count['methods']) * 100 : 0,
$count['publicMethods'],
$count['methods'] > 0 ? ($count['publicMethods'] / $count['methods']) * 100 : 0,
$count['nonPublicMethods'],
$count['methods'] > 0 ? ($count['nonPublicMethods'] / $count['methods']) * 100 : 0,
$count['functions'],
$count['namedFunctions'],
$count['functions'] > 0 ? ($count['namedFunctions'] / $count['functions']) * 100 : 0,
$count['anonymousFunctions'],
$count['functions'] > 0 ? ($count['anonymousFunctions'] / $count['functions']) * 100 : 0,
$count['constants'],
$count['globalConstants'],
$count['constants'] > 0 ? ($count['globalConstants'] / $count['constants']) * 100 : 0,
$count['classConstants'],
$count['constants'] > 0 ? ($count['classConstants'] / $count['constants']) * 100 : 0
)
);
if ($printTests) {
$output->write(
\sprintf(
"\nTests\n" .
" Classes %10d\n" .
" Methods %10d\n",
$count['testClasses'],
$count['testMethods']
)
);
}
}
}
+53
View File
@@ -0,0 +1,53 @@
<?php
/*
* This file is part of PHPLOC.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace SebastianBergmann\PHPLOC\Log;
/**
* An XML ResultPrinter for the TextUI.
*/
class Xml
{
/**
* Prints a result set.
*
* @param string $filename
* @param array $count
*/
public function printResult($filename, array $count)
{
$document = new \DOMDocument('1.0', 'UTF-8');
$document->formatOutput = true;
$root = $document->createElement('phploc');
$document->appendChild($root);
if ($count['directories'] > 0) {
$root->appendChild(
$document->createElement('directories', $count['directories'])
);
$root->appendChild(
$document->createElement('files', $count['files'])
);
}
unset($count['directories']);
unset($count['files']);
foreach ($count as $k => $v) {
$root->appendChild(
$document->createElement($k, $v)
);
}
\file_put_contents($filename, $document->saveXML());
}
}
+385
View File
@@ -0,0 +1,385 @@
<?php
/*
* This file is part of PHPLOC.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace SebastianBergmann\PHPLOC;
class Publisher
{
private $counts;
public function __construct(array $counts)
{
$this->counts = $counts;
}
public function getDirectories()
{
return $this->getCount('directories') - 1;
}
public function getFiles()
{
return $this->getValue('files');
}
public function getLines()
{
return $this->getValue('lines');
}
public function getCommentLines()
{
return $this->getValue('comment lines');
}
public function getNonCommentLines()
{
return $this->getLines() - $this->getCommentLines();
}
public function getLogicalLines()
{
return $this->getValue('logical lines');
}
public function getClassLines()
{
return $this->getSum('class lines');
}
public function getAverageClassLength()
{
return $this->getAverage('class lines');
}
public function getMinimumClassLength()
{
return $this->getMinimum('class lines');
}
public function getMaximumClassLength()
{
return $this->getMaximum('class lines');
}
public function getAverageMethodLength()
{
return $this->getAverage('method lines');
}
public function getMinimumMethodLength()
{
return $this->getMinimum('method lines');
}
public function getMaximumMethodLength()
{
return $this->getMaximum('method lines');
}
public function getFunctionLines()
{
return $this->getValue('function lines');
}
public function getAverageFunctionLength()
{
return $this->divide($this->getFunctionLines(), $this->getFunctions());
}
public function getNotInClassesOrFunctions()
{
return $this->getLogicalLines() - $this->getClassLines() - $this->getFunctionLines();
}
public function getComplexity()
{
return $this->getValue('complexity');
}
public function getMethodComplexity()
{
return $this->getValue('total method complexity');
}
public function getAverageComplexityPerLogicalLine()
{
return $this->divide($this->getComplexity(), $this->getLogicalLines());
}
public function getAverageComplexityPerClass()
{
return $this->getAverage('class complexity');
}
public function getMinimumClassComplexity()
{
return $this->getMinimum('class complexity');
}
public function getMaximumClassComplexity()
{
return $this->getMaximum('class complexity');
}
public function getAverageComplexityPerMethod()
{
return $this->getAverage('method complexity');
}
public function getMinimumMethodComplexity()
{
return $this->getMinimum('method complexity');
}
public function getMaximumMethodComplexity()
{
return $this->getMaximum('method complexity');
}
public function getGlobalAccesses()
{
return $this->getGlobalConstantAccesses() + $this->getGlobalVariableAccesses() + $this->getSuperGlobalVariableAccesses();
}
public function getGlobalConstantAccesses()
{
return \count(\array_intersect($this->getValue('possible constant accesses', []), $this->getValue('constant', [])));
}
public function getGlobalVariableAccesses()
{
return $this->getValue('global variable accesses');
}
public function getSuperGlobalVariableAccesses()
{
return $this->getValue('super global variable accesses');
}
public function getAttributeAccesses()
{
return $this->getNonStaticAttributeAccesses() + $this->getStaticAttributeAccesses();
}
public function getNonStaticAttributeAccesses()
{
return $this->getValue('non-static attribute accesses');
}
public function getStaticAttributeAccesses()
{
return $this->getValue('static attribute accesses');
}
public function getMethodCalls()
{
return $this->getNonStaticMethodCalls() + $this->getStaticMethodCalls();
}
public function getNonStaticMethodCalls()
{
return $this->getValue('non-static method calls');
}
public function getStaticMethodCalls()
{
return $this->getValue('static method calls');
}
public function getNamespaces()
{
return $this->getCount('namespaces');
}
public function getInterfaces()
{
return $this->getValue('interfaces');
}
public function getTraits()
{
return $this->getValue('traits');
}
public function getClasses()
{
return $this->getAbstractClasses() + $this->getConcreteClasses();
}
public function getAbstractClasses()
{
return $this->getValue('abstract classes');
}
public function getConcreteClasses()
{
return $this->getValue('concrete classes');
}
public function getMethods()
{
return $this->getNonStaticMethods() + $this->getStaticMethods();
}
public function getNonStaticMethods()
{
return $this->getValue('non-static methods');
}
public function getStaticMethods()
{
return $this->getValue('static methods');
}
public function getPublicMethods()
{
return $this->getValue('public methods');
}
public function getNonPublicMethods()
{
return $this->getValue('non-public methods');
}
public function getFunctions()
{
return $this->getNamedFunctions() + $this->getAnonymousFunctions();
}
public function getNamedFunctions()
{
return $this->getValue('named functions');
}
public function getAnonymousFunctions()
{
return $this->getValue('anonymous functions');
}
public function getConstants()
{
return $this->getGlobalConstants() + $this->getClassConstants();
}
public function getGlobalConstants()
{
return $this->getValue('global constants');
}
public function getClassConstants()
{
return $this->getValue('class constants');
}
public function getTestClasses()
{
return $this->getValue('test classes');
}
public function getTestMethods()
{
return $this->getValue('test methods');
}
public function toArray()
{
return [
'files' => $this->getFiles(),
'loc' => $this->getLines(),
'lloc' => $this->getLogicalLines(),
'llocClasses' => $this->getClassLines(),
'llocFunctions' => $this->getFunctionLines(),
'llocGlobal' => $this->getNotInClassesOrFunctions(),
'cloc' => $this->getCommentLines(),
'ccn' => $this->getComplexity(),
'ccnMethods' => $this->getMethodComplexity(),
'interfaces' => $this->getInterfaces(),
'traits' => $this->getTraits(),
'classes' => $this->getClasses(),
'abstractClasses' => $this->getAbstractClasses(),
'concreteClasses' => $this->getConcreteClasses(),
'functions' => $this->getFunctions(),
'namedFunctions' => $this->getNamedFunctions(),
'anonymousFunctions' => $this->getAnonymousFunctions(),
'methods' => $this->getMethods(),
'publicMethods' => $this->getPublicMethods(),
'nonPublicMethods' => $this->getNonPublicMethods(),
'nonStaticMethods' => $this->getNonStaticMethods(),
'staticMethods' => $this->getStaticMethods(),
'constants' => $this->getConstants(),
'classConstants' => $this->getClassConstants(),
'globalConstants' => $this->getGlobalConstants(),
'testClasses' => $this->getTestClasses(),
'testMethods' => $this->getTestMethods(),
'ccnByLloc' => $this->getAverageComplexityPerLogicalLine(),
'llocByNof' => $this->getAverageFunctionLength(),
'methodCalls' => $this->getMethodCalls(),
'staticMethodCalls' => $this->getStaticMethodCalls(),
'instanceMethodCalls' => $this->getNonStaticMethodCalls(),
'attributeAccesses' => $this->getAttributeAccesses(),
'staticAttributeAccesses' => $this->getStaticAttributeAccesses(),
'instanceAttributeAccesses' => $this->getNonStaticAttributeAccesses(),
'globalAccesses' => $this->getGlobalAccesses(),
'globalVariableAccesses' => $this->getGlobalVariableAccesses(),
'superGlobalVariableAccesses' => $this->getSuperGlobalVariableAccesses(),
'globalConstantAccesses' => $this->getGlobalConstantAccesses(),
'directories' => $this->getDirectories(),
'classCcnMin' => $this->getMinimumClassComplexity(),
'classCcnAvg' => $this->getAverageComplexityPerClass(),
'classCcnMax' => $this->getMaximumClassComplexity(),
'classLlocMin' => $this->getMinimumClassLength(),
'classLlocAvg' => $this->getAverageClassLength(),
'classLlocMax' => $this->getMaximumClassLength(),
'methodCcnMin' => $this->getMinimumMethodComplexity(),
'methodCcnAvg' => $this->getAverageComplexityPerMethod(),
'methodCcnMax' => $this->getMaximumMethodComplexity(),
'methodLlocMin' => $this->getMinimumMethodLength(),
'methodLlocAvg' => $this->getAverageMethodLength(),
'methodLlocMax' => $this->getMaximumMethodLength(),
'namespaces' => $this->getNamespaces(),
'ncloc' => $this->getNonCommentLines(),
];
}
private function getAverage($key)
{
return $this->divide($this->getSum($key), $this->getCount($key));
}
private function getCount($key)
{
return isset($this->counts[$key]) ? \count($this->counts[$key]) : 0;
}
private function getSum($key)
{
return isset($this->counts[$key]) ? \array_sum($this->counts[$key]) : 0;
}
private function getMaximum($key)
{
return isset($this->counts[$key]) ? \max($this->counts[$key]) : 0;
}
private function getMinimum($key)
{
return isset($this->counts[$key]) ? \min($this->counts[$key]) : 0;
}
private function getValue($key, $default = 0)
{
return isset($this->counts[$key]) ? $this->counts[$key] : $default;
}
private function divide($x, $y)
{
return $y != 0 ? $x / $y : 0;
}
}
@@ -0,0 +1,322 @@
<?php
/*
* This file is part of PHPLOC.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace SebastianBergmann\PHPLOC;
use PHPUnit\Framework\TestCase;
class AnalyserTest extends TestCase
{
/**
* @var Analyser
*/
private $analyser;
protected function setUp()
{
$this->analyser = new Analyser;
}
public function testWithoutTests()
{
$this->assertEquals(
[
'files' => 1,
'loc' => 75,
'lloc' => 26,
'llocClasses' => 22,
'llocFunctions' => 1,
'llocGlobal' => 3,
'cloc' => 7,
'ccn' => 2,
'ccnMethods' => 2,
'interfaces' => 1,
'traits' => 0,
'classes' => 2,
'abstractClasses' => 1,
'concreteClasses' => 1,
'functions' => 2,
'namedFunctions' => 1,
'anonymousFunctions' => 1,
'methods' => 4,
'publicMethods' => 2,
'nonPublicMethods' => 2,
'nonStaticMethods' => 3,
'staticMethods' => 1,
'constants' => 2,
'classConstants' => 1,
'globalConstants' => 1,
'testClasses' => 0,
'testMethods' => 0,
'ccnByLloc' => 0.08,
'llocByNof' => 0.5,
'methodCalls' => 6,
'staticMethodCalls' => 4,
'instanceMethodCalls' => 2,
'attributeAccesses' => 6,
'staticAttributeAccesses' => 4,
'instanceAttributeAccesses' => 2,
'globalAccesses' => 4,
'globalVariableAccesses' => 2,
'superGlobalVariableAccesses' => 1,
'globalConstantAccesses' => 1,
'directories' => 0,
'namespaces' => 1,
'ncloc' => 68,
'classCcnMin' => 1,
'classCcnAvg' => 1.65,
'classCcnMax' => 3,
'methodCcnMin' => 1,
'methodCcnAvg' => 1.65,
'methodCcnMax' => 2,
'classLlocMin' => 0,
'classLlocAvg' => 7.3,
'classLlocMax' => 22,
'methodLlocMin' => 4,
'methodLlocAvg' => 5.6,
'methodLlocMax' => 7
],
$this->analyser->countFiles(
[__DIR__ . '/_files/source.php'],
false
),
'',
0.1
);
}
public function testWithTests()
{
$this->assertEquals(
[
'files' => 2,
'loc' => 98,
'lloc' => 26,
'llocClasses' => 22,
'llocFunctions' => 1,
'llocGlobal' => 3,
'cloc' => 11,
'ccn' => 2,
'ccnMethods' => 2,
'interfaces' => 1,
'traits' => 0,
'classes' => 2,
'abstractClasses' => 1,
'concreteClasses' => 1,
'functions' => 2,
'namedFunctions' => 1,
'anonymousFunctions' => 1,
'methods' => 4,
'publicMethods' => 2,
'nonPublicMethods' => 2,
'nonStaticMethods' => 3,
'staticMethods' => 1,
'constants' => 2,
'classConstants' => 1,
'globalConstants' => 1,
'testClasses' => 1,
'testMethods' => 2,
'ccnByLloc' => 0.08,
'llocByNof' => 0.5,
'methodCalls' => 6,
'staticMethodCalls' => 4,
'instanceMethodCalls' => 2,
'attributeAccesses' => 6,
'staticAttributeAccesses' => 4,
'instanceAttributeAccesses' => 2,
'globalAccesses' => 4,
'globalVariableAccesses' => 2,
'superGlobalVariableAccesses' => 1,
'globalConstantAccesses' => 1,
'directories' => 0,
'namespaces' => 1,
'ncloc' => 87,
'classCcnMin' => 1,
'classCcnAvg' => 1.5,
'classCcnMax' => 3,
'methodCcnMin' => 1,
'methodCcnAvg' => 1.66,
'methodCcnMax' => 2,
'classLlocMin' => 0,
'classLlocAvg' => 5.5,
'classLlocMax' => 22,
'methodLlocMin' => 4,
'methodLlocAvg' => 5.6,
'methodLlocMax' => 7
],
$this->analyser->countFiles(
[
__DIR__ . '/_files/source.php',
__DIR__ . '/_files/tests.php'
],
true
),
'',
0.1
);
}
public function testFilesThatExtendPHPUnitTestCaseAreCountedAsTests()
{
$result = $this->analyser->countFiles(
[
__DIR__ . '/_files/tests.php'
],
true
);
$this->assertEquals(1, $result['testClasses']);
}
public function testFilesThatExtendPHPUnitTestCaseAreCountedAsTests2()
{
$result = $this->analyser->countFiles(
[
__DIR__ . '/_files/tests_old.php'
],
true
);
$this->assertEquals(1, $result['testClasses']);
}
public function testFilesThatIndirectlyExtendPHPUnitTestCaseAreCountedAsTests()
{
$result = $this->analyser->countFiles(
[
__DIR__ . '/_files/twoTestsThatIndirectlyExtendOldPHPUnitTestCase.php'
],
true
);
$this->assertEquals(3, $result['testClasses']);
}
public function testFilesThatIndirectlyExtendPHPUnitTestCaseAreCountedAsTests2()
{
$result = $this->analyser->countFiles(
[
__DIR__ . '/_files/twoTestsThatIndirectlyExtendPHPUnitTestCase.php'
],
true
);
$this->assertEquals(3, $result['testClasses']);
}
public function testTraitsAreCountedCorrectly()
{
$result = $this->analyser->countFiles(
[
__DIR__ . '/_files/trait.php'
],
false
);
$this->assertEquals(1, $result['traits']);
}
/**
* @ticket 64
*/
public function testIssue64IsFixed()
{
$result = $this->analyser->countFiles(
[
__DIR__ . '/_files/issue_62.php'
],
false
);
$this->assertEquals(1, $result['cloc']);
}
/**
* @ticket 112
*/
public function testIssue112IsFixed()
{
$result = $this->analyser->countFiles(
[
__DIR__ . '/_files/issue_112.php'
],
false
);
$this->assertEquals(5, $result['loc']);
}
/**
* @ticket 126
* @dataProvider issue126Provider
*/
public function testIssue126IsFixed($fileNumber, $cloc)
{
$file = __DIR__ . '/_files/issue_126/issue_126_' . $fileNumber . '.php';
$result = $this->analyser->countFiles([$file], false);
$assertString = \sprintf('Failed asserting that %s matches expected %s in issue_126_%d.php',
$result['cloc'],
$cloc,
$fileNumber
);
$this->assertEquals($cloc, $result['cloc'], $assertString);
}
public function issue126Provider()
{
// issue_126_X.php => CLOC
return [
[1, 1],
[2, 1],
[3, 1],
[4, 2],
[5, 3],
[6, 3],
[7, 3],
];
}
/**
* @requires PHP 7
* @ticket 138
*/
public function testIssue138IsFixed()
{
\error_reporting(E_ALL);
$result = $this->analyser->countFiles(
[
__DIR__ . '/_files/issue_138.php'
],
false
);
$this->assertSame(1, $result['classes']);
}
/**
* @ticket 139
*/
public function testIssue139IsFixed()
{
\error_reporting(E_ALL);
$result = $this->analyser->countFiles(
[
__DIR__ . '/_files/issue_139.php'
],
false
);
$this->assertEquals(1, $result['anonymousFunctions']);
}
}
@@ -0,0 +1,137 @@
<?php
/*
* This file is part of PHPLOC.
*
* (c) Sebastian Bergmann <sebastian@phpunit.de>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace SebastianBergmann\PHPLOC;
use PHPUnit\Framework\TestCase;
class SingleTest extends TestCase
{
/**
* @var \SebastianBergmann\PHPLOC\Log\Csv
*/
private $single;
private $sample_row = [
'directories' => 1,
'files' => 2,
'loc' => 3,
'ccnByLloc' => 4,
'cloc' => 5,
'ncloc' => 6,
'lloc' => 7,
'llocGlobal' => 8,
'namespaces' => 9,
'interfaces' => 10,
'traits' => 11,
'classes' => 12,
'abstractClasses' => 13,
'concreteClasses' => 14,
'llocClasses' => 15,
'methods' => 16,
'nonStaticMethods' => 17,
'staticMethods' => 18,
'publicMethods' => 19,
'nonPublicMethods' => 20,
'methodCcnAvg' => 21,
'functions' => 22,
'namedFunctions' => 23,
'anonymousFunctions' => 24,
'llocFunctions' => 25,
'llocByNof' => 26,
'constants' => 27,
'globalConstants' => 28,
'classConstants' => 29,
'attributeAccesses' => 30,
'instanceAttributeAccesses' => 31,
'staticAttributeAccesses' => 32,
'methodCalls' => 33,
'instanceMethodCalls' => 34,
'staticMethodCalls' => 35,
'globalAccesses' => 36,
'globalVariableAccesses' => 37,
'superGlobalVariableAccesses' => 38,
'globalConstantAccesses' => 39,
'testClasses' => 40,
'testMethods' => 41
];
protected function setUp()
{
$this->single = new \SebastianBergmann\PHPLOC\Log\Csv;
}
public function testPrintedResultContainsHeadings()
{
\ob_start();
$this->single->printResult('php://output', $this->sample_row);
$output = \ob_get_clean();
$this->assertRegExp('#Directories,Files.+$#is', $output, 'Printed result does not contain a heading line');
}
public function testPrintedResultContainsData()
{
\ob_start();
$this->single->printResult('php://output', $this->sample_row);
$output = \ob_get_clean();
$this->assertRegExp('#"1","2".+$#is', $output, 'Printed result does not contain a value line');
}
public function testPrintedResultContainsEqualNumHeadingsAndValues()
{
\ob_start();
$this->single->printResult('php://output', $this->sample_row);
$output = \ob_get_clean();
$rows = \explode("\n", $output);
$headings = \explode(',', $rows[0]);
$vals = \explode(',', $rows[1]);
$this->assertEquals(
\count($headings),
\count($vals),
'Printed result does not contain same number of headings and values'
);
}
public function testExactlyTwoRowsArePrinted()
{
\ob_start();
$this->single->printResult('php://output', $this->sample_row);
$output = \ob_get_clean();
$rows = \explode("\n", \trim($output));
$this->assertEquals(2, \count($rows), 'Printed result contained more or less than expected 2 rows');
}
/**
* @expectedException \InvalidArgumentException
*/
public function testPrintPartialRow()
{
$count = $this->sample_row;
unset($count['llocByNof']);
try {
\ob_start();
$this->single->printResult('php://output', $count);
} finally {
\ob_end_clean();
}
$this->fail('No exception was raised for malformed input var');
}
}
@@ -0,0 +1,5 @@
<?php
$container['test.key'] = function() {
echo 'Test';
};
@@ -0,0 +1,7 @@
<?php
/* this is a for-loop */
for ($i = 0; $i < 100; $i++)
{
printf("hello");
}
@@ -0,0 +1,7 @@
<?php
/** this is a for-loop */
for ($i = 0; $i < 100; $i++)
{
printf("hello");
}
@@ -0,0 +1,7 @@
<?php
// this is a for-loop
for ($i = 0; $i < 100; $i++)
{
printf("hello");
}
@@ -0,0 +1,8 @@
<?php
/*
this is a for-loop */
for ($i = 0; $i < 100; $i++)
{
printf("hello");
}
@@ -0,0 +1,9 @@
<?php
/*
*
this is a for-loop */
for ($i = 0; $i < 100; $i++)
{
printf("hello");
}
@@ -0,0 +1,5 @@
<?php
/*
* comment
*/
@@ -0,0 +1,5 @@
<?php
/**
* comment
*/
@@ -0,0 +1,17 @@
<?php
class Issue138
{
public function first()
{
new class() {
};
}
public function second()
{
new class() {
public $x;
};
}
}
@@ -0,0 +1,17 @@
<?php
class SomeClass
{
public function someFunction($in)
{
function () use ($in) {
return '';
};
}
public function someOtherFunction()
{
//trigger Undefined index: ccn
return false || true;
}
}
@@ -0,0 +1,5 @@
<?php
function fn()
{
// CLOC
}
@@ -0,0 +1,75 @@
<?php
namespace a\name\space;
/*
* A comment.
*/
define('A_GLOBAL_CONSTANT', 'foo');
use function time;
function &a_global_function()
{
$a = AClass::CLASS;
}
interface AnInterface
{
}
abstract class AnAbstractClass
{
}
/**
* A comment.
*/
class AClass extends AnAbstractClass implements AnInterface
{
const A_CLASS_CONSTANT = 'bar';
private static $a = array();
public static function aStaticMethod()
{
global $foo;
$a = $_GET['a'];
$GLOBALS['bar'] = A_GLOBAL_CONSTANT;
// Another comment
$o->m();
$o->$m();
$o->a;
$o->$a;
}
public function aPublicMethod()
{
$a = true ? true : false;
c::m();
c::$m();
c::$a;
c::$a;
c::aConstant;
}
protected function aProtectedMethod()
{
if (true) {
}
$c::m();
$c::$m();
$c::$a;
$c::$a;
}
private function aPrivateMethod()
{
$function = function() {};
echo "This is {$great}";
echo "This is ${great}";
}
}
@@ -0,0 +1,23 @@
<?php
class ATest extends PHPUnit\Framework\TestCase
{
public function testFoo()
{
}
/**
* @test
* @dataProvider barProvider
*/
public function bar()
{
}
protected function doSomething()
{
}
public function barProvider()
{
}
}
@@ -0,0 +1,23 @@
<?php
class ATest extends PHPUnit_Framework_TestCase
{
public function testFoo()
{
}
/**
* @test
* @dataProvider barProvider
*/
public function bar()
{
}
protected function doSomething()
{
}
public function barProvider()
{
}
}
@@ -0,0 +1,7 @@
<?php
trait t
{
public function m()
{
}
}
@@ -0,0 +1,11 @@
<?php
class BaseTest extends PHPUnit_Framework_TestCase {
}
class AIndirectExtendTest extends BaseTest {
}
class BIndirectExtendTest extends BaseTest {
}
@@ -0,0 +1,11 @@
<?php
class BaseTest extends PHPUnit\Framework\TestCase {
}
class AIndirectExtendTest extends BaseTest {
}
class BIndirectExtendTest extends BaseTest {
}