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

View File

@@ -0,0 +1,8 @@
.buildpath
.project
.settings*
.idea/
build
vendor
composer.lock
*.phar

View File

@@ -0,0 +1,12 @@
dist: trusty
language: php
php:
- 5.6
- 7.0
- 7.1
- 7.2
- hhvm
before_script:
- composer install
script:
- vendor/bin/phpunit

View File

@@ -0,0 +1,74 @@
PHP_CodeBrowser 1.1.0
-------------------
* Switch to stable composer dependencies (Symfony2 Console and Monolog)
PHP_CodeBrowser 1.0.4
-------------------
* Fix invalid XML errors
PHP_CodeBrowser 1.0.3
-------------------
* If mbstring is available, we'll now try to detect file encodings
* Allow the exclusion of files without errors
PHP_CodeBrowser 1.0.2
-------------------
* Fixed some bugs.
* Allow custom extensions for php files
PHP_CodeBrowser 1.0
-------------------
* Added --ignore option.
* Fixed a few bugs.
* Improved windows support.
PHP_CodeBrowser 0.9.1
---------------------
* Fixed various Windows-related issues.
* Added error/warning count to the file tree.
* Added a commandline switch to debug exclude options.
* Made XHTML output W3C-compliant.
PHP_CodeBrowser 0.9.0
---------------------
* Added support for CRAP with PHPUnit 3.5
* Improved performance
* Now using jQuery as JavaScript framework
* Added --exclude and --excludePCRE option
* Allowed multiple --source options
PHP_CodeBrowser 0.1.4
---------------------
* Fixed missing line numbers bug in PMD plugin
* Fixed bug in PMD plugin (Issue #5)
* Now using Sebastian Bergmann's PHP_Timer utility
PHP_CodeBrowser 0.1.3
---------------------
* Fixed filename mismatch (Issue #4).
* Improved execution time output.
PHP_CodeBrowser 0.1.2
---------------------
* Added additional view if source has no errors or valid XML files.
PHP_CodeBrowser 0.1.1
---------------------
* Fixed PHP_CodeBrowser error, in case of project does not has any error log
files or only empty error log files.
PHP_CodeBrowser 0.1.0
---------------------
* Initial version of PHP_CodeBrowser.

View File

@@ -0,0 +1,27 @@
Copyright (c) 2007-2014, Mayflower GmbH
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 Mayflower GmbH nor the names of its
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.

View File

@@ -0,0 +1,99 @@
# PHP_CodeBrowser #
[![Latest Stable Version](https://poser.pugx.org/mayflower/php-codebrowser/v/stable.png)](https://packagist.org/packages/mayflower/php-codebrowser)
[![Build Status](https://travis-ci.org/mayflower/PHP_CodeBrowser.png?branch=master)](https://travis-ci.org/mayflower/PHP_CodeBrowser)
[![Scrutinizer Quality Score](https://scrutinizer-ci.com/g/Mayflower/PHP_CodeBrowser/badges/quality-score.png?s=2c0379f0efea966daeaef3fc5abf8adb4a910b24)](https://scrutinizer-ci.com/g/Mayflower/PHP_CodeBrowser/)
[![Code Coverage](https://scrutinizer-ci.com/g/Mayflower/PHP_CodeBrowser/badges/coverage.png?s=543238e3d9fb4584d8cb31e3af48e67ed846f9e5)](https://scrutinizer-ci.com/g/Mayflower/PHP_CodeBrowser/)
[![SensioLabsInsight](https://insight.sensiolabs.com/projects/79205008-1c3d-4142-ab81-a9465008d440/mini.png)](https://insight.sensiolabs.com/projects/79205008-1c3d-4142-ab81-a9465008d440)
## Structure ##
|--> bin/ PHP_CodeBrowser scripts
|--> src/ Source files for PHP_CodeBrowser
| |--> Plugins/ Plugins for different error handling/types
|
|--> templates/ Template files for PHP_CodeBrowser
| |--> css/ Used CSS by templates, Color definition for errors
| |--> img/ Used images for PHP_CodeBrowser
| |--> js/ Used javascript for PHP_CodeBrowser
|
|--> tests/ PHPUnit test suite
|
|--> package.xml PEAR package information file
|
|--> LICENCE Licence information
|--> README Structure and install information
|--> CHANGELOG Update information
## Installation ##
### Git Checkout ###
$ git clone git://github.com/Mayflower/PHP_CodeBrowser.git
### Installation via Composer ###
Add this line to the require section in composer.json:
"mayflower/php-codebrowser": "~1.1"
Or to install it globally
composer global require "mayflower/php-codebrowser=~1.1"
### Get PHAR ###
see [Releases](https://github.com/Mayflower/PHP_CodeBrowser/releases)
## Usage ##
### Shell Usage ###
Try ./bin/phpcb.php -h for usage information.
### Integration in Jenkins, CruiseControl and Hudson ###
...
<!-- phpcb should be called after xml file generation -->
<target name="build" depends="...,phpcb" />
...
<target name="phpcb">
<exec executable="phpcb">
<arg line="--log path/to/log/dir
--output path/to/output/dir/
--source path/to/source/dir/" />
</exec>
</target>
...
## View the Results ##
### Webbrowser ###
Open `/path/to/defined/output/index.html`.
### CruiseControl ###
#### config.xml ####
<publishers>
<artifactspublisher dir="path/to/output" dest="artifacts/${project.name}" subdirectory="PhpCbIdentifier" />
...
</publishers>
#### main.jsp ####
<cruisecontrol:tab name="PHP_CodeBrowser" label="PHP_CodeBrowser">
<cruisecontrol:artifactsLink>
<iframe src="<%=request.getContextPath() %>/<%= artifacts_url %>/PhpCbIdentifier/index.html" class="tab-content">
</iframe>
</cruisecontrol:artifactsLink>
</cruisecontrol:tab>
### Jenkins/Hudson ###
Have a look at the [standard template for Jenkins jobs for PHP projects](https://github.com/sebastianbergmann/php-jenkins-template) to see how PHP_CodeBrowser can be used together with Jenkins.
## Contact Information ##
If you have any questions you may get in contact with: Elger Thiele <elger DOT thiele AT mayflower DOT de> or Thorsten Rinne <thorsten DOT rinne AT mayflower DOT de>

View File

@@ -0,0 +1,57 @@
#!/usr/bin/env php
<?php
/**
* PHP_CodeBrowser
*
* PHP Version 5.2.6
*
* Copyright (c) 2007-2009, Mayflower GmbH
* 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 Mayflower GmbH 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.
*
* @category PHP_CodeBrowser
* @package PHP_CodeBrowser
* @author Elger Thiele <elger.thiele@mayflower.de>
* @copyright 2007-2009 Mayflower GmbH
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version SVN: $Id$
* @link http://www.phpunit.de/
* @since File available since 0.1.0
*/
if (file_exists(__DIR__ . '/../../../autoload.php')) {
include_once __DIR__ . '/../../../autoload.php';
} else {
include_once __DIR__ . '/../vendor/autoload.php';
}
$app = new PHPCodeBrowser\Application('PHP_CodeBrowser', '1.1.4');
$app->run();

View File

@@ -0,0 +1,49 @@
@echo off
REM PHP_CodeBrowser shell script Wrapper for WIN
REM Bash file called from the command line
REM
REM Copyright (c) 2007-2009, Mayflower GmbH
REM All rights reserved.
REM
REM Redistribution and use in source and binary forms, with or without
REM modification, are permitted provided that the following conditions
REM are met:
REM
REM * Redistributions of source code must retain the above copyright
REM notice, this list of conditions and the following disclaimer.
REM
REM * Redistributions in binary form must reproduce the above copyright
REM notice, this list of conditions and the following disclaimer in
REM the documentation and/or other materials provided with the
REM distribution.
REM
REM * Neither the name of Mayflower GmbH nor the names of his
REM contributors may be used to endorse or promote products derived
REM from this software without specific prior written permission.
REM
REM THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
REM "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
REM LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
REM FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
REM COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
REM INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
REM BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
REM LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
REM CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
REM LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
REM ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
REM POSSIBILITY OF SUCH DAMAGE.
REM
REM @category PHP_CodeBrowser
REM @package PHP_CodeBrowser
REM @subpackage bin
REM @author Elger Thiele <elger.thiele@mayflower.de>
REM @copyright 2007-2009 Mayflower GmbH
REM @license http://www.opensource.org/licenses/bsd-license.php BSD License
REM @version SVN: $Id: phpcb 5182 2009-09-03 12:34:35Z elger $
REM @link http://www.phpunit.de/
REM @since File available since 0.1.0
set PHPBIN=@php_bin@
"@php_bin@" "@bin_dir@\phpcb" %*

View File

@@ -0,0 +1,31 @@
{
"alias": "phpcb.phar",
"chmod": "0755",
"compactors": [
"Herrera\\Box\\Compactor\\Json",
"Herrera\\Box\\Compactor\\Php"
],
"directories": ["src/", "vendor", "templates"],
"extract": true,
"files": [
"LICENSE"
],
"finder": [
{
"name": "*.php",
"exclude": [
"phpunit",
"phpunit-test-case",
"Tester",
"Tests",
"tests"
],
"in": "vendor"
}
],
"git-commit": "git-commit",
"git-version": "git-version",
"main": "bin/phpcb",
"output": "phpcb-@git-version@.phar",
"stub": true
}

View File

@@ -0,0 +1,79 @@
<project name="PHP_CodeBrowser" default="build" basedir=".">
<target name="clean">
<!-- Clean up -->
<delete dir="${basedir}/build"/>
<!-- Create build directories -->
<mkdir dir="${basedir}/build/api"/>
<mkdir dir="${basedir}/build/code-browser"/>
<mkdir dir="${basedir}/build/coverage"/>
<mkdir dir="${basedir}/build/logs"/>
<mkdir dir="${basedir}/build/pdepend"/>
</target>
<!-- Run unit tests and generate junit.xml and clover.xml -->
<target name="phpunit">
<exec executable="vendor/bin/phpunit" failonerror="true"/>
</target>
<!-- Generate jdepend.xml and software metrics charts -->
<target name="pdepend">
<exec executable="vendor/bin/pdepend">
<arg line="--jdepend-xml='${basedir}/build/logs/jdepend.xml'
--jdepend-chart='${basedir}/build/pdepend/dependencies.svg'
--overview-pyramid='${basedir}/build/pdepend/overview-pyramid.svg'
src" />
</exec>
</target>
<!-- Generate pmd.xml -->
<target name="phpmd">
<exec executable="vendor/bin/phpmd">
<arg line="src xml codesize,design,naming,unusedcode --reportfile '${basedir}/build/logs/pmd.xml'" />
</exec>
</target>
<!-- Generate pmd-cpd.xml -->
<target name="phpcpd">
<exec executable="vendor/bin/phpcpd">
<arg line="--log-pmd '${basedir}/build/logs/pmd-cpd.xml' src" />
</exec>
</target>
<!-- Generate checkstyle.xml -->
<target name="phpcs">
<exec executable="vendor/bin/phpcs">
<arg value="--report=checkstyle" />
<arg value="--report-file=${basedir}/build/logs/checkstyle.xml" />
<arg value="--standard=PSR2" />
<arg value="--extensions=php" />
<arg path="${basedir}/src" />
</exec>
</target>
<!-- Generate API documentation -->
<target name="phpdoc">
<exec executable="phpdoc">
<arg line="-d src -t build/api -i Autoload.php" />
</exec>
</target>
<target name="phpcb">
<exec executable="${basedir}/bin/phpcb">
<arg line="--log '${basedir}/build/logs'
--source '${basedir}/src'
--output '${basedir}/build/code-browser'" />
</exec>
</target>
<target name="build">
<antcall target="clean"/>
<antcall target="pdepend"/>
<antcall target="phpmd"/>
<antcall target="phpcpd"/>
<antcall target="phpcs"/>
<!-- <antcall target="phpdoc"/> -->
<antcall target="phpunit"/>
<antcall target="phpcb"/>
</target>
</project>

View File

@@ -0,0 +1,29 @@
{
"name": "mayflower/php-codebrowser",
"description": "A code browser that augments the code with information from various QA tools.",
"license": "BSD-3-Clause",
"homepage": "https://github.com/Mayflower/PHP_CodeBrowser",
"authors": [
{
"name": "Robin Gloster",
"email": "robin.gloster@mayflower.de",
"role": "developer"
}
],
"require": {
"phpunit/php-file-iterator": "~1.4",
"monolog/monolog": "~1.7",
"symfony/console": "~2.1|~3.0|~4.0"
},
"require-dev": {
"phpunit/phpunit": "5.7.*",
"phpmd/phpmd": "1.5.*",
"squizlabs/php_codesniffer": "1.*",
"phploc/phploc": "*",
"sebastian/phpcpd": "*"
},
"autoload": {
"psr-0": {"PHPCodeBrowser\\": "src/"}
},
"bin": [ "bin/phpcb" ]
}

View File

@@ -0,0 +1,518 @@
<?xml version="1.0"?>
<package version="2.0" xmlns="http://pear.php.net/dtd/package-2.0"
xmlns:tasks="http://pear.php.net/dtd/tasks-1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0
http://pear.php.net/dtd/tasks-1.0.xsd
http://pear.php.net/dtd/package-2.0
http://pear.php.net/dtd/package-2.0.xsd">
<name>PHP_CodeBrowser</name>
<channel>pear.phpqatools.org</channel>
<summary>A code browser that augments the code with information from various QA tools.</summary>
<description>A code browser that augments the code with information from various QA tools.</description>
<lead>
<name>Simon Kohlmeyer</name>
<user>simon</user>
<email>simon.kohlmeyer@mayflower.de</email>
<active>yes</active>
</lead>
<date>2013-10-06</date>
<version>
<release>1.0.4</release>
<api>1.0.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<license uri="http://www.opensource.org/licenses/bsd-license.php">BSD License</license>
<notes>http://github.com/Mayflower/PHP_CodeBrowser/blob/master/CHANGELOG.markdown</notes>
<contents>
<dir name="/">
<dir name="src">
<dir name="Helper">
<file name="IOHelper.php" role="php">
<tasks:replace from="@package_version@" to="version" type="package-info" />
</file>
</dir> <!-- /Helper -->
<dir name="Plugins">
<file name="ErrorCPD.php" role="php">
<tasks:replace from="@package_version@" to="version" type="package-info" />
</file>
<file name="ErrorCRAP.php" role="php">
<tasks:replace from="@package_version@" to="version" type="package-info" />
</file>
<file name="ErrorCheckstyle.php" role="php">
<tasks:replace from="@package_version@" to="version" type="package-info" />
</file>
<file name="ErrorCoverage.php" role="php">
<tasks:replace from="@package_version@" to="version" type="package-info" />
</file>
<file name="ErrorPMD.php" role="php">
<tasks:replace from="@package_version@" to="version" type="package-info" />
</file>
<file name="ErrorPadawan.php" role="php">
<tasks:replace from="@package_version@" to="version" type="package-info" />
</file>
</dir> <!-- /Plugins -->
<dir name="View">
<file name="ViewAbstract.php" role="php">
<tasks:replace from="@package_version@" to="version" type="package-info" />
</file>
<file name="ViewReview.php" role="php">
<tasks:replace from="@package_version@" to="version" type="package-info" />
</file>
</dir> <!-- /View -->
<file name="Autoload.php" role="php">
<tasks:replace from="@package_version@" to="version" type="package-info" />
</file>
<file name="CLIController.php" role="php">
<tasks:replace from="@package_version@" to="version" type="package-info" />
<tasks:replace from="@php_dir@" to="php_dir" type="pear-config" />
<tasks:replace from="@data_dir@" to="data_dir" type="pear-config" />
<tasks:replace from="@release_date@" to="release_date" type="package-info" />
</file>
<file name="File.php" role="php">
<tasks:replace from="@package_version@" to="version" type="package-info" />
</file>
<file name="Issue.php" role="php">
<tasks:replace from="@package_version@" to="version" type="package-info" />
</file>
<file name="IssueXml.php" role="php">
<tasks:replace from="@package_version@" to="version" type="package-info" />
</file>
<file name="PluginsAbstract.php" role="php">
<tasks:replace from="@package_version@" to="version" type="package-info" />
</file>
<file name="SourceHandler.php" role="php">
<tasks:replace from="@package_version@" to="version" type="package-info" />
</file>
</dir> <!-- /src -->
<dir name="templates">
<dir name="css">
<file name="cruisecontrol.css" role="data" />
<file name="global.css" role="data" />
<file name="review.css" role="data" />
<file name="tree.css" role="data" />
</dir> <!-- /css -->
<dir name="img">
<file name="background.gif" role="data" />
<file name="base.gif" role="data" />
<file name="cd.gif" role="data" />
<file name="empty.gif" role="data" />
<file name="folder.gif" role="data" />
<file name="folderopen.gif" role="data" />
<file name="globe.gif" role="data" />
<file name="imgfolder.gif" role="data" />
<file name="join.gif" role="data" />
<file name="joinbottom.gif" role="data" />
<file name="line.gif" role="data" />
<file name="minus.gif" role="data" />
<file name="minusbottom.gif" role="data" />
<file name="musicfolder.gif" role="data" />
<file name="nolines_minus.gif" role="data" />
<file name="nolines_plus.gif" role="data" />
<file name="page.gif" role="data" />
<file name="page.png" role="data" />
<file name="plus.gif" role="data" />
<file name="plusbottom.gif" role="data" />
<file name="question.gif" role="data" />
<file name="separator.gif" role="data" />
<file name="slider.gif" role="data" />
<file name="tab-active.png" role="data" />
<file name="trash.gif" role="data" />
<file name="treeToggle-collapsed.png" role="data" />
<file name="treeToggle-extended.png" role="data" />
<file name="treeToggle.gif" role="data" />
</dir> <!-- /img -->
<dir name="js">
<dir name="jquery.cluetip">
<dir name="images">
<file name="arrowdown.gif" role="data" />
<file name="arrowleft.gif" role="data" />
<file name="arrowright.gif" role="data" />
<file name="arrowup.gif" role="data" />
<file name="bl.gif" role="data" />
<file name="bl.png" role="data" />
<file name="br.gif" role="data" />
<file name="br.png" role="data" />
<file name="darrowdown.gif" role="data" />
<file name="darrowleft.gif" role="data" />
<file name="darrowright.gif" role="data" />
<file name="darrowup.gif" role="data" />
<file name="itunes.png" role="data" />
<file name="rarrowdown.gif" role="data" />
<file name="rarrowleft.gif" role="data" />
<file name="rarrowright.gif" role="data" />
<file name="rarrowup.gif" role="data" />
<file name="tl.gif" role="data" />
<file name="tl.png" role="data" />
<file name="tr.gif" role="data" />
<file name="tr.png" role="data" />
<file name="wait.gif" role="data" />
</dir> <!-- /images -->
<dir name="lib">
<file name="jquery.bgiframe.min.js" role="data" />
<file name="jquery.hoverIntent.js" role="data" />
</dir> <!-- /lib -->
<file name="jquery.cluetip.css" role="data" />
<file name="jquery.cluetip.min.js" role="data" />
</dir> <!-- /jquery.cluetip -->
<dir name="jquery.jstree">
<dir name="themes">
<dir name="default">
<file name="d.png" role="data" />
<file name="dot_for_ie.gif" role="data" />
<file name="style.css" role="data" />
<file name="throbber.gif" role="data" />
</dir> <!-- /default -->
</dir> <!-- /themes -->
<file name="jquery.jstree.min.js" role="data" />
</dir> <!-- /jquery.jstree -->
<dir name="jquery.sidebar">
<dir name="css">
<dir name="codebrowser">
<file name="inject-bottom.png" role="data" />
<file name="inject-left.png" role="data" />
<file name="inject-right.png" role="data" />
<file name="inject-top.png" role="data" />
<file name="sidebar.css" role="data" />
</dir> <!-- /codebrowser -->
</dir> <!-- /css -->
<file name="jquery.sidebar.js" role="data" />
<file name="jquery-ui-1.7.2.custom.min.js" role="data" />
</dir> <!-- /jquery.sidebar -->
<file name="jquery-1.4.2.min.js" role="data" />
<file name="jquery.history.js" role="data" />
<file name="review.js" role="data" />
<file name="tree.js" role="data" />
</dir> <!-- /js -->
<file name="index.tpl" role="data" />
<file name="noErrors.tpl" role="data" />
<file name="review.tpl" role="data" />
</dir> <!-- /templates -->
<dir name="bin">
<file name="phpcb.bat" role="script">
<tasks:replace from="@bin_dir@" to="bin_dir" type="pear-config" />
<tasks:replace from="@php_bin@" to="php_bin" type="pear-config" />
<tasks:windowseol/>
</file>
<file name="phpcb.php" role="script">
<tasks:replace from="/usr/bin/env php" to="php_bin" type="pear-config" />
<tasks:replace from="@php_bin@" to="php_bin" type="pear-config" />
<tasks:replace from="@php_dir@" to="php_dir" type="pear-config" />
</file>
</dir> <!-- /scripts -->
<file name="CHANGELOG.markdown" role="doc" />
<file name="LICENSE" role="doc" />
<file name="README.markdown" role="doc" />
</dir> <!-- / -->
</contents>
<dependencies>
<required>
<php>
<min>5.2.6</min>
</php>
<pearinstaller>
<min>1.8.1</min>
</pearinstaller>
<package>
<name>Console_CommandLine</name>
<channel>pear.php.net</channel>
<min>1.1.3</min>
</package>
<package>
<name>File_Iterator</name>
<channel>pear.phpunit.de</channel>
<min>1.3.0</min>
</package>
<package>
<name>Log</name>
<channel>pear.php.net</channel>
<min>1.12.1</min>
</package>
<extension>
<name>dom</name>
</extension>
<extension>
<name>pcre</name>
</extension>
<extension>
<name>spl</name>
</extension>
</required>
<optional>
<package>
<name>Text_Highlighter</name>
<channel>pear.php.net</channel>
<min>0.7.1</min>
</package>
<package>
<name>PHPUnit</name>
<channel>pear.phpunit.de</channel>
<min>3.4.0</min>
</package>
<package>
<name>PHP_CodeSniffer</name>
<channel>pear.php.net</channel>
<min>1.2.0</min>
</package>
<package>
<name>PhpDocumentor</name>
<channel>pear.php.net</channel>
<min>1.4.3</min>
</package>
<extension>
<name>mbstring</name>
</extension>
</optional>
</dependencies>
<phprelease>
<installconditions>
<os>
<name>windows</name>
</os>
</installconditions>
<filelist>
<install as="PHP_CodeBrowser/Helper/IOHelper.php" name="src/Helper/IOHelper.php" />
<install as="PHP_CodeBrowser/Plugins/ErrorCPD.php" name="src/Plugins/ErrorCPD.php" />
<install as="PHP_CodeBrowser/Plugins/ErrorCRAP.php" name="src/Plugins/ErrorCRAP.php" />
<install as="PHP_CodeBrowser/Plugins/ErrorCheckstyle.php" name="src/Plugins/ErrorCheckstyle.php" />
<install as="PHP_CodeBrowser/Plugins/ErrorCoverage.php" name="src/Plugins/ErrorCoverage.php" />
<install as="PHP_CodeBrowser/Plugins/ErrorPMD.php" name="src/Plugins/ErrorPMD.php" />
<install as="PHP_CodeBrowser/Plugins/ErrorPadawan.php" name="src/Plugins/ErrorPadawan.php" />
<install as="PHP_CodeBrowser/View/ViewReview.php" name="src/View/ViewReview.php" />
<install as="PHP_CodeBrowser/View/ViewAbstract.php" name="src/View/ViewAbstract.php" />
<install as="PHP_CodeBrowser/Autoload.php" name="src/Autoload.php" />
<install as="PHP_CodeBrowser/CLIController.php" name="src/CLIController.php" />
<install as="PHP_CodeBrowser/File.php" name="src/File.php" />
<install as="PHP_CodeBrowser/Issue.php" name="src/Issue.php" />
<install as="PHP_CodeBrowser/IssueXml.php" name="src/IssueXml.php" />
<install as="PHP_CodeBrowser/PluginsAbstract.php" name="src/PluginsAbstract.php" />
<install as="PHP_CodeBrowser/SourceHandler.php" name="src/SourceHandler.php" />
<install as="phpcb.bat" name="bin/phpcb.bat" />
<install as="phpcb" name="bin/phpcb.php" />
</filelist>
</phprelease>
<phprelease>
<filelist>
<install as="PHP_CodeBrowser/Helper/IOHelper.php" name="src/Helper/IOHelper.php" />
<install as="PHP_CodeBrowser/Plugins/ErrorCPD.php" name="src/Plugins/ErrorCPD.php" />
<install as="PHP_CodeBrowser/Plugins/ErrorCRAP.php" name="src/Plugins/ErrorCRAP.php" />
<install as="PHP_CodeBrowser/Plugins/ErrorCheckstyle.php" name="src/Plugins/ErrorCheckstyle.php" />
<install as="PHP_CodeBrowser/Plugins/ErrorCoverage.php" name="src/Plugins/ErrorCoverage.php" />
<install as="PHP_CodeBrowser/Plugins/ErrorPMD.php" name="src/Plugins/ErrorPMD.php" />
<install as="PHP_CodeBrowser/Plugins/ErrorPadawan.php" name="src/Plugins/ErrorPadawan.php" />
<install as="PHP_CodeBrowser/View/ViewReview.php" name="src/View/ViewReview.php" />
<install as="PHP_CodeBrowser/View/ViewAbstract.php" name="src/View/ViewAbstract.php" />
<install as="PHP_CodeBrowser/Autoload.php" name="src/Autoload.php" />
<install as="PHP_CodeBrowser/CLIController.php" name="src/CLIController.php" />
<install as="PHP_CodeBrowser/File.php" name="src/File.php" />
<install as="PHP_CodeBrowser/Issue.php" name="src/Issue.php" />
<install as="PHP_CodeBrowser/IssueXml.php" name="src/IssueXml.php" />
<install as="PHP_CodeBrowser/PluginsAbstract.php" name="src/PluginsAbstract.php" />
<install as="PHP_CodeBrowser/SourceHandler.php" name="src/SourceHandler.php" />
<install as="phpcb" name="bin/phpcb.php" />
<ignore name="bin/phpcb.bat" />
</filelist>
</phprelease>
<changelog>
<release>
<version>
<release>0.1.0</release>
<api>1.0.0</api>
</version>
<stability>
<release>alpha</release>
<api>alpha</api>
</stability>
<date>2009-11-25</date>
<license uri="http://www.opensource.org/licenses/bsd-license.php">BSD License</license>
<notes>
Initial release of PHP_CodeBrowser
</notes>
</release>
<release>
<version>
<release>0.1.1</release>
<api>1.0.0</api>
</version>
<stability>
<release>alpha</release>
<api>alpha</api>
</stability>
<date>2009-11-30</date>
<license uri="http://www.opensource.org/licenses/bsd-license.php">BSD License</license>
<notes>
- fixed PHP_CodeBrowser error, in case of project does not has any error log files or only empty error log files.
</notes>
</release>
<release>
<version>
<release>0.1.2</release>
<api>1.0.0</api>
</version>
<stability>
<release>alpha</release>
<api>alpha</api>
</stability>
<date>2010-03-23</date>
<license uri="http://www.opensource.org/licenses/bsd-license.php">BSD License</license>
<notes>
- Added additional view if source has no errors or valid XML files
</notes>
</release>
<release>
<version>
<release>0.1.3</release>
<api>1.0.0</api>
</version>
<stability>
<release>alpha</release>
<api>alpha</api>
</stability>
<date>2010-04-16</date>
<license uri="http://www.opensource.org/licenses/bsd-license.php">BSD License</license>
<notes>
- Fixed filename mismatch
- Improved execution time output
</notes>
</release>
<release>
<version>
<release>0.1.4</release>
<api>1.0.0</api>
</version>
<stability>
<release>alpha</release>
<api>alpha</api>
</stability>
<date>2010-06-30</date>
<license uri="http://www.opensource.org/licenses/bsd-license.php">BSD License</license>
<notes>
- Fixed missing line numbers bug in PMD plugin
- Fixed bug in PMD plugin (Issue #5)
- Now using Sebastian Bergmann's PHP_Timer utility
</notes>
</release>
<release>
<version>
<release>0.9.0</release>
<api>1.0.0</api>
</version>
<stability>
<release>beta</release>
<api>beta</api>
</stability>
<date>2010-08-12</date>
<license uri="http://www.opensource.org/licenses/bsd-license.php">BSD License</license>
<notes>
- Added support for CRAP when using logs from PHPUnit 3.5
- Improved performance
- Now using jQuery as JavaScript framework
- Added --exclude and --excludePCRE option
- Allowed multiple --source options
</notes>
</release>
<release>
<version>
<release>0.9.1</release>
<api>1.0.0</api>
</version>
<stability>
<release>beta</release>
<api>beta</api>
</stability>
<date>2010-09-02</date>
<license uri="http://www.opensource.org/licenses/bsd-license.php">BSD License</license>
<notes>
- Fixed various Windows-related issues.
- Added error/warning count to the file tree.
- Added a commandline switch to debug exclude options.
- Made XHTML output W3C-compliant.
</notes>
</release>
<release>
<version>
<release>1.0.0</release>
<api>1.0.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<date>2010-12-13</date>
<license uri="http://www.opensource.org/licenses/bsd-license.php">BSD License</license>
<notes>
- Added --ignore option.
- Fixed a few bugs.
- Improved windows support.
</notes>
</release>
<release>
<version>
<release>1.0.2</release>
<api>1.0.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<date>2012-01-16</date>
<license uri="http://www.opensource.org/licenses/bsd-license.php">BSD License</license>
<notes>
- Fixed some bugs.
- Allow custom extensions for php files.
</notes>
</release>
<release>
<version>
<release>1.0.3</release>
<api>1.0.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<date>2012-04-23</date>
<license uri="http://www.opensource.org/licenses/bsd-license.php">BSD License</license>
<notes>
- If mbstring is available, we'll now try to detect file encodings
- Allow the exclusion of files without errors
</notes>
</release>
<release>
<version>
<release>1.0.4</release>
<api>1.0.0</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<date>2013-10-06</date>
<license uri="http://www.opensource.org/licenses/bsd-license.php">BSD License</license>
<notes>
- Fix invalid XML errors
</notes>
</release>
</changelog>
</package>

View File

@@ -0,0 +1,53 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
backupStaticAttributes="false"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
syntaxCheck="false"
bootstrap="./vendor/autoload.php"
>
<testsuites>
<testsuite name="PHP_CodeBrowser">
<directory>./src/PHPCodeBrowser/Tests</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory>./src</directory>
<exclude>
<directory>./src/PHPCodeBrowser/Tests</directory>
</exclude>
</whitelist>
</filter>
<!--<filter>-->
<!--<whitelist>-->
<!--<directory suffix='.php'>src</directory>-->
<!--</whitelist>-->
<!--</filter>-->
<logging>
<log type="coverage-html" target="build/coverage" title="PHP_CodeBrowser"
charset="UTF-8" yui="true" highlight="true"
lowUpperBound="35" highLowerBound="70"/>
<log type="coverage-clover" target="build/logs/clover.xml"/>
<log type="junit" target="build/logs/junit.xml" logIncompleteSkipped="false"/>
</logging>
<php>
<!--TODO: Remove this when E_STRICT stops crashing the tests -->
<!--<ini name="error_reporting" value="E_ALL"/>-->
</php>
<filter>
<whitelist>
<directory>src</directory>
</whitelist>
</filter>
</phpunit>

View File

@@ -0,0 +1,101 @@
<?php
/**
* Application
*
* PHP Version 5.3.0
*
* Copyright (c) 2007-2014, Mayflower GmbH
* 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 Mayflower GmbH 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.
*
* @category PHP_CodeBrowser
* @package PHP_CodeBrowser
* @author Robin Gloster <robin.gloster@mayflower.de>
* @copyright 2007-2010 Mayflower GmbH
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version SVN: $Id$
* @link http://www.phpunit.de/
* @since File available since 1.1
*/
namespace PHPCodeBrowser;
use PHPCodeBrowser\Command\RunCommand;
use Symfony\Component\Console\Application as BaseApplication;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
/**
* Class Application
* @package PHPCodeBrowser
*/
class Application extends BaseApplication
{
/**
* Gets the name of the command based on input.
*
* @param InputInterface $input
* @return string The command name
*/
protected function getCommandName(InputInterface $input)
{
return 'phpcb';
}
/**
* Gets the default commands that should always be available.
*
* @return Command[] An array of default Command instances
*/
protected function getDefaultCommands()
{
// Adds HelpCommand for --help
$defaultCommands = parent::getDefaultCommands();
$defaultCommands[] = new RunCommand();
return $defaultCommands;
}
/**
* Gets the InputDefinition related to this Application.
*
* @return InputDefinition The InputDefinition instance
*/
public function getDefinition()
{
$inputDefinition = parent::getDefinition();
// clear out the normal first argument, which is the command name
$inputDefinition->setArguments();
return $inputDefinition;
}
}

View File

@@ -0,0 +1,326 @@
<?php
/**
* Cli controller
*
* PHP Version 5.3.2
*
* Copyright (c) 2007-2010, Mayflower GmbH
* 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 Mayflower GmbH 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.
*
* @category PHP_CodeBrowser
* @package PHP_CodeBrowser
* @author Elger Thiele <elger.thiele@mayflower.de>
* @author Simon Kohlmeyer <simon.kohlmeyer@mayflower.de>
* @copyright 2007-2010 Mayflower GmbH
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version SVN: $Id$
* @link http://www.phpunit.de/
* @since File available since 0.1.0
*/
namespace PHPCodeBrowser;
use File_Iterator_Factory;
use Monolog\Logger;
use PHPCodeBrowser\Helper\IOHelper;
use PHPCodeBrowser\View\ViewReview;
if (!defined('PHPCB_ROOT_DIR')) {
define('PHPCB_ROOT_DIR', dirname(__FILE__) . '/../');
}
if (!defined('PHPCB_TEMPLATE_DIR')) {
define('PHPCB_TEMPLATE_DIR', dirname(__FILE__) . '/../../templates');
}
/**
* CLIController
*
* @category PHP_CodeBrowser
* @package PHP_CodeBrowser
* @author Elger Thiele <elger.thiele@mayflower.de>
* @author Michel Hartmann <michel.hartmann@mayflower.de>
* @author Simon Kohlmeyer <simon.kohlmeyer@mayflower.de>
* @copyright 2007-2010 Mayflower GmbH
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version Release: @package_version@
* @link http://www.phpunit.de/
* @since Class available since 0.1.0
*/
class CLIController
{
/**
* Path to the Cruise Control input xml file
*
* @var string
*/
private $logDir;
/**
* Path to the code browser html output folder
*
* @var string
*/
private $htmlOutputDir;
/**
* Path to the project source code files
*
* @var string
*/
private $projectSource;
/**
* array of PCREs. Matching files will not appear in the output.
*
* @var array
*/
private $excludeExpressions;
/**
* array of glob patterns. Matching files will not appear in the output.
*
* @var array
*/
private $excludePatterns;
/**
* The error plugin classes
*
* @var array
*/
private $registeredPlugins;
/**
* The IOHelper used for filesystem interaction.
*
* @var IOHelper
*/
private $ioHelper;
/**
* Pear Log object where debug output should go to.
*
* @var Logger
*/
private $debugLog;
/**
* Plugin-specific options. Formatted like
* array(
* 'ErrorCRAP' => array(
* 'threshold' => 2
* )
* )
*
* @var array
*/
private $pluginOptions = array();
/**
* File extensions that we take as php files.
*
* @var array
*/
private $phpSuffixes;
/**
* We want to exclude files with no issues
*
* @var boolean
*/
private $excludeOK;
/**
* The constructor
*
* Standard setters are initialized
*
* @param string $logPath The (path-to) xml log files. Can be null.
* @param array $projectSource The project sources. Can be null.
* @param string $htmlOutputDir The html output dir, where new files will be created
* @param array $excludeExpressions A list of PCREs. Files matching will not appear in the output.
* @param array $excludePatterns A list of glob patterns. Files matching will not appear in the output.
* @param array $pluginOptions array of arrays with plugin-specific options
* @param IOHelper $ioHelper The IOHelper object to be used for filesystem interaction.
* @param Logger $debugLog
* @param array $phpSuffixes
* @param bool $excludeOK
*/
public function __construct(
$logPath,
array $projectSource,
$htmlOutputDir,
array $excludeExpressions,
array $excludePatterns,
array $pluginOptions,
$ioHelper,
Logger $debugLog,
array $phpSuffixes,
$excludeOK = false
) {
$this->logDir = $logPath;
$this->projectSource = $projectSource;
$this->htmlOutputDir = $htmlOutputDir;
$this->excludeExpressions = $excludeExpressions;
$this->excludePatterns = $excludePatterns;
foreach ($pluginOptions as $plugin => $options) {
$this->pluginOptions["Error$plugin"] = $options;
}
$this->ioHelper = $ioHelper;
$this->debugLog = $debugLog;
$this->registeredPlugins = array();
$this->phpSuffixes = $phpSuffixes;
$this->excludeOK = $excludeOK;
}
/**
* Setter/adder method for the used plugin classes.
* For each plugin to use, add it to this array
*
* @param mixed $classNames Definition of plugin classes
*
* @return void
*/
public function addErrorPlugins($classNames)
{
foreach ((array) $classNames as $className) {
$this->registeredPlugins[] = $className;
}
}
/**
* Main execute function for PHP_CodeBrowser.
*
* Following steps are resolved:
* 1. Clean-up output directory
* 2. Merge xml log files
* 3. Generate XML file via error list from plugins
* 4. Save the ErrorList as XML file
* 5. Generate HTML output from XML
* 6. Copy resources (css, js, images) from template directory to output
*
* @return void
*/
public function run()
{
// clear and create output directory
if (is_dir($this->htmlOutputDir)) {
$this->ioHelper->deleteDirectory($this->htmlOutputDir);
} elseif (is_file($this->htmlOutputDir)) {
$this->ioHelper->deleteFile($this->htmlOutputDir);
}
$this->ioHelper->createDirectory($this->htmlOutputDir);
// init needed classes
$viewReview = new ViewReview(
PHPCB_TEMPLATE_DIR,
$this->htmlOutputDir,
$this->ioHelper,
$this->phpSuffixes
);
$sourceHandler = new SourceHandler($this->debugLog);
if (isset($this->logDir)) {
$issueXml = new IssueXml();
// merge xml files
$issueXml->addDirectory($this->logDir);
// conversion of XML file cc to cb format
foreach ($this->registeredPlugins as $className) {
if (array_key_exists($className, $this->pluginOptions)) {
$plugin = new $className(
$issueXml,
$this->pluginOptions[$className]
);
} else {
$plugin = new $className($issueXml);
}
$sourceHandler->addPlugin($plugin);
}
}
if (isset($this->projectSource)) {
foreach ($this->projectSource as $source) {
if (is_dir($source)) {
$factory = new File_Iterator_Factory;
$suffixes = array_merge(
$this->phpSuffixes,
array('php','js','css', 'html')
);
$sourceHandler->addSourceFiles(
$factory->getFileIterator(
$source,
$suffixes
)
);
} else {
$sourceHandler->addSourceFile($source);
}
}
}
array_walk(
$this->excludeExpressions,
array($sourceHandler, 'excludeMatchingPCRE')
);
array_walk(
$this->excludePatterns,
array($sourceHandler, 'excludeMatchingPattern')
);
$files = $sourceHandler->getFiles();
if (!$files) {
$viewReview->copyNoErrorsIndex();
} else {
// Get the path prefix all files have in common
$commonPathPrefix = $sourceHandler->getCommonPathPrefix();
foreach ($files as $file) {
$viewReview->generate(
$file->getIssues(),
$file->name(),
$commonPathPrefix,
$this->excludeOK
);
}
// Copy needed resources (eg js libraries) to output directory
$viewReview->copyResourceFolders();
$viewReview->generateIndex($files, $this->excludeOK);
}
}
}

View File

@@ -0,0 +1,316 @@
<?php
/**
* RunCommand
*
* PHP Version 5.3.0
*
* Copyright (c) 2007-2014, Mayflower GmbH
* 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 Mayflower GmbH 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.
*
* @category PHP_CodeBrowser
* @package PHP_CodeBrowser
* @author Robin Gloster <robin.gloster@mayflower.de>
* @copyright 2007-2010 Mayflower GmbH
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version SVN: $Id$
* @link http://www.phpunit.de/
* @since File available since 1.1
*/
namespace PHPCodeBrowser\Command;
use Exception;
use Monolog\Handler\NullHandler;
use Monolog\Logger;
use PHPCodeBrowser\CLIController;
use PHPCodeBrowser\Helper\IOHelper;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
/**
* Class RunCommand
* @package PHPCodeBrowser\Command
*/
class RunCommand extends Command
{
protected function configure()
{
$plugins = array_map(
function ($class) {
return '"' . substr($class, strlen('Error')) . '"';
},
$this->getAvailablePlugins()
);
$this->setName('phpcb')
->setHelp(
'A Code browser for PHP files with syntax highlighting and colored error-sections '
. 'found by quality assurance tools like PHPUnit, PHPMD or PHP_CodeSniffer.'
)->addOption(
'log',
'l',
InputOption::VALUE_REQUIRED,
'The path to the xml log files, e.g. generated from PHPUnit. Either this or --source must be given'
)->addOption(
'extensions',
'S',
InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY,
'PHP file extensions to include. Can be given multiple times'
)->addOption(
'output',
'o',
InputOption::VALUE_REQUIRED,
'Path to the output folder where generated files should be stored'
)->addOption(
'source',
's',
InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY,
'Path to the project source code. Can either be a directory or a single file. Parse '
. 'complete source directory if set, else only files found in logs. Either this or'
. ' --log must be given. Can be given multiple times'
)->addOption(
'ignore',
'i',
InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY,
'Files or directories that will be ignored during the parsing process. Can be given multiple times'
)->addOption(
'exclude',
'e',
InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY,
'Excludes all files matching the given glob pattern. This is done after pulling the '
. 'files in the source dir in if one is given. Can be given multiple times. Note'
. ' that the match is run against absolute file names'
)->addOption(
'excludePCRE',
'E',
InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY,
'Works like -e but takes PCRE instead of glob patterns'
)->addOption(
'debugExcludes',
null,
InputOption::VALUE_NONE,
'Print which files are excluded by which expressions and patterns'
)->addOption(
'excludeOK',
null,
InputOption::VALUE_NONE,
'Exclude files with no issues from the report'
)->addOption(
'disablePlugin',
null,
InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY,
'Disable single Plugins. Can be one of ' . implode(', ', $plugins)
)->addOption(
'crapThreshold',
null,
InputOption::VALUE_REQUIRED,
'The minimum value for CRAP errors to be recognized. Defaults to 0. Regardless '
. 'of this setting, values below 30 will be considered notices, those above warnings'
);
}
/**
* Executes the current command.
*
* @param InputInterface $input An InputInterface instance
* @param OutputInterface $output
*
* @return null|integer null or 0 if everything went fine, or an error code
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$this->checkErrors($input);
$extensions = $this->handleBackwardCompatibility($input->getOption('extensions'));
$ignore = $this->handleBackwardCompatibility($input->getOption('ignore'));
$excludePCRE = $input->getOption('excludePCRE');
$excludePCRE = $this->convertIgnores($ignore, $excludePCRE);
$logger = new Logger('PHPCodeBrowser');
if (!$input->getOption('debugExcludes')) {
$logger->pushHandler(new NullHandler());
}
// init new CLIController
$controller = new CLIController(
$input->getOption('log'),
$input->getOption('source'),
$input->getOption('output'),
$excludePCRE,
$input->getOption('exclude'),
array('CRAP' => array('threshold' => $input->getOption('crapThreshold'))),
new IOHelper(),
$logger,
array_merge($extensions, array('php')),
(bool) $input->getOption('excludeOK')
);
$plugins = $this->getAvailablePlugins();
$plugins = $this->disablePlugins($input->getOption('disablePlugin'), $plugins);
$controller->addErrorPlugins($plugins);
try {
$controller->run();
} catch (Exception $e) {
error_log(
<<<HERE
[Error] {$e->getMessage()}
{$e->getTraceAsString()}
HERE
);
}
return 0;
}
/**
* @param InputInterface $input
* @throws \InvalidArgumentException if errors are found
*/
protected function checkErrors(InputInterface $input)
{
if (!$input->getOption('log')) {
if (!$input->getOption('source')) {
throw new \InvalidArgumentException('Missing log or source argument.');
}
} elseif (!file_exists($input->getOption('log'))) {
throw new \InvalidArgumentException('Log directory does not exist.');
} elseif (!is_dir($input->getOption('log'))) {
throw new \InvalidArgumentException('Log argument must be a directory, a file was given.');
}
if ($input->getOption('source')) {
foreach ($input->getOption('source') as $s) {
if (!file_exists($s)) {
throw new \InvalidArgumentException("Source '$s' does not exist");
}
}
}
if (!$input->getOption('output')) {
throw new \InvalidArgumentException('Missing output argument.');
} elseif (file_exists($input->getOption('output')) && !is_dir($input->getOption('output'))) {
throw new \InvalidArgumentException('Output argument must be a directory, a file was given.');
}
}
/**
* Returns a list of available plugins.
*
* Currently hard-coded.
*
* @return string[] Class names of error plugins
*/
protected function getAvailablePlugins()
{
return array(
'PHPCodeBrowser\\Plugins\\ErrorCheckstyle',
'PHPCodeBrowser\\Plugins\\ErrorPMD',
'PHPCodeBrowser\\Plugins\\ErrorCPD',
'PHPCodeBrowser\\Plugins\\ErrorPadawan',
'PHPCodeBrowser\\Plugins\\ErrorCoverage',
'PHPCodeBrowser\\Plugins\\ErrorCRAP'
);
}
/**
* @param array $disabledPlugins
* @param array $plugins
*
* @return array
*/
protected function disablePlugins(array $disabledPlugins, array $plugins)
{
$disabledPlugins = array_map(
function ($param) {
return strtolower($param);
},
$disabledPlugins
);
foreach ($plugins as $pluginKey => $plugin) {
$name = substr($plugin, strlen('Error'));
if (in_array(strtolower($name), $disabledPlugins)) {
// Remove it from the plugins list
unset($plugins[$pluginKey]);
}
}
return $plugins;
}
/**
* Convert the --ignore arguments to patterns
*
* @param array $ignored
* @param $excludePCRE
* @return array
*/
protected function convertIgnores(array $ignored, $excludePCRE)
{
$dirSep = preg_quote(DIRECTORY_SEPARATOR, '/');
foreach ($ignored as $ignore) {
$ig = realpath($ignore);
if (!$ig) {
error_log("[Warning] $ignore does not exists");
} else {
$ig = preg_quote($ig, '/');
$excludePCRE[] = "/^$ig($dirSep|$)/";
}
}
return $excludePCRE;
}
/**
* This converts comma-separated options into an array
*
* @param array $option
* @return array
*/
private function handleBackwardCompatibility(array $option)
{
if (count($option) == 1 && strpos($option[0], ',') !== false) {
$option = explode(',', $option[0]);
error_log('Usage of comma-separated options is deprecated, specify them one-by-one.', E_DEPRECATED);
}
return $option;
}
}

View File

@@ -0,0 +1,256 @@
<?php
/**
* File
*
* PHP Version 5.3.0
*
* Copyright (c) 2007-2010, Mayflower GmbH
* 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 Mayflower GmbH 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.
*
* @category PHP_CodeBrowser
* @package PHP_CodeBrowser
* @author Simon Kohlmeyer <simon.kohlmeyer@mayflower.de>
* @copyright 2007-2010 Mayflower GmbH
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version SVN: $Id$
* @link http://www.phpunit.de/
* @since File available since 0.2.0
*/
namespace PHPCodeBrowser;
use PHPCodeBrowser\Helper\IOHelper;
/**
* File
*
* An object of this class represents a single source file
* with it's issues, if any.
*
* @category PHP_CodeBrowser
* @package PHP_CodeBrowser
* @author Simon Kohlmeyer <simon.kohlmeyer@mayflower.de>
* @copyright 2007-2010 Mayflower GmbH
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version Release: @package_version@
* @link http://github.com/mayflowergmbh
* @since Class available since 0.2.0
*/
class File
{
/**
* Filename.
*
* @var string
*/
private $name;
/**
* Issues associated with this file.
*
* @var Issue[]
*/
private $issues;
/**
* Default constructor.
*
* @param string $name The name of the file.
* @param Issue[] $issues
*/
public function __construct($name, array $issues = array())
{
if (DIRECTORY_SEPARATOR !== '/')
{
$name = str_replace('/', DIRECTORY_SEPARATOR, $name);
}
$this->name = $name;
$this->issues = $issues;
}
/**
* Add an issue for this file.
*
* @param Issue $issue The issue to add.
* @throws \InvalidArgumentException
*/
public function addIssue(Issue $issue)
{
if ($issue->fileName !== $this->name) {
throw new \InvalidArgumentException(
'Tried to add issue to wrong file.'
);
}
$this->issues[] = $issue;
}
/**
* Gets an array containing the issues for this file.
*
* @return Issue[] The issues.
*/
public function getIssues()
{
return $this->issues;
}
/**
* Returns the absolute name of this file.
*
* @return string
*/
public function name()
{
return $this->name;
}
/**
* Returns the basename of this file.
*
* @return string
*/
public function basename()
{
return basename($this->name);
}
/**
* Returns the dirName of this file.
*
* @return string
*/
public function dirName()
{
return dirname($this->name);
}
/**
* Returns the number of issues this file has.
*
* @return Integer
*/
public function getIssueCount()
{
return count($this->issues);
}
/**
* Returns the number of errors this file has.
*
* @return Integer
*/
public function getErrorCount()
{
$count = 0;
foreach ($this->issues as $issue) {
if (strcasecmp($issue->severity, 'error') === 0) {
$count += 1;
}
}
return $count;
}
/**
* Returns the number of issues this file has that are not errors.
*
* @return Integer
*/
public function getWarningCount()
{
return $this->getIssueCount() - $this->getErrorCount();
}
/**
* Merges the issues from two file objects representing the same file.
*
* @param File $file The file to merge with.
* @throws \InvalidArgumentException
*/
public function mergeWith(File $file)
{
if ($this->name !== $file->name) {
throw new \InvalidArgumentException(
'Tried to merge different files'
);
}
$this->issues = array_merge($this->issues, $file->issues);
}
/**
* Sorts an array of Files. Key value association will be preserved.
*
* @param File[] $files The files to sort.
*/
public static function sort(array &$files)
{
uasort($files, 'PHPCodeBrowser\File::internalSort');
}
/**
* Sorting function used in File::sort()
*/
protected static function internalSort(File $first, File $second)
{
$first = $first->name();
$second = $second->name();
$prefix = IOHelper::getCommonPathPrefix(array($first, $second));
$prefixLength = strlen($prefix);
$first = substr($first, $prefixLength);
$second = substr($second, $prefixLength);
$firstIsInSubDir = (substr_count($first, DIRECTORY_SEPARATOR) !== 0);
$secondIsInSubDir = (substr_count($second, DIRECTORY_SEPARATOR) !== 0);
if ($firstIsInSubDir) {
if ($secondIsInSubDir) {
// both are subdirectories
return strcmp($first, $second);
} else {
// a lies in a subDir of the dir in which b lies,
// so b comes later.
return -1;
}
} else {
if ($secondIsInSubDir) {
// b lies in a subDir of the dir in which a lies,
// so a comes later.
return 1;
} else {
// both are files
return strcmp($first, $second);
}
}
}
}

View File

@@ -0,0 +1,277 @@
<?php
/**
* Input and output helper
*
* PHP Version 5.2.6
*
* Copyright (c) 2007-2009, Mayflower GmbH
* 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 Mayflower GmbH 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.
*
* @category PHP_CodeBrowser
* @package PHP_CodeBrowser
* @author Elger Thiele <elger.thiele@mayflower.de>
* @copyright 2007-2009 Mayflower GmbH
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version SVN: $Id$
* @link http://www.phpunit.de/
* @since File available since 0.1.0
*/
namespace PHPCodeBrowser\Helper;
use DirectoryIterator;
/**
* IOHelper
*
* Input output helper class provides several methods for writing and
* reading files or directories.
*
* @category PHP_CodeBrowser
* @package PHP_CodeBrowser
* @author Elger Thiele <elger.thiele@mayflower.de>
* @author Christopher Weckerle <christopher.weckerle@mayflower.de>
* @copyright 2007-2009 Mayflower GmbH
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version Release: @package_version@
* @link http://www.phpunit.de/
* @since Class available since 0.1.0
*/
class IOHelper
{
/**
* Creates a file with given name and content.
* If directories to file do not exists they will be created.
*
* @param string $fileName The filename
* @param string $fileContent The content of the file
*
* @return void
*/
public function createFile($fileName, $fileContent)
{
$realName = basename($fileName);
$path = substr($fileName, 0, - 1 * (strlen($realName)));
if (!empty($path)) {
self::createDirectory($path);
}
file_put_contents(realpath($path) . '/' . $realName, $fileContent);
}
/**
* Delete a file. The filename could inherit a absolute or relative
* path-to-file,
* e.g. foo/bar/myFile.php
*
* @param string $fileName The (path-to) filename
*
* @return void
*/
public function deleteFile($fileName)
{
if (file_exists($fileName)) {
unlink($fileName);
}
}
/**
* Copy a file from a source to target dir. The source could inherit an
* absolute or relative path-to-file.
*
* @param string $fileSource The source file
* @param string $sourceFolder The target folder
*
* @return void
* @throws \Exception
*/
public function copyFile($fileSource, $sourceFolder)
{
if (!file_exists($fileSource)) {
throw new \Exception('File ' . $fileSource . ' does not exists!');
}
$fileName = basename($fileSource);
self::createFile(
$sourceFolder . '/' . $fileName,
self::loadFile($fileSource)
);
}
/**
* Return the content of a given file.
*
* @param string $fileName The file the content should be read in
*
* @return string
* @throws \Exception
*/
public function loadFile($fileName)
{
if (!file_exists($fileName)) {
throw new \Exception('File ' . $fileName . ' does not exist!');
}
return trim(file_get_contents($fileName));
}
/**
* Create a directory and its inherit path to directory if not present,
* e.g. path/that/does/not/exist/myFolder/
*
* @param string $target The target folder to create
*
* @return void
*/
public function createDirectory($target)
{
$target = rtrim($target, DIRECTORY_SEPARATOR);
if (!is_dir($target))
{
mkdir($target, 0777, true);
}
}
/**
* Delete a directory within all its items.
* Note that the given directory $source will be deleted as well.
*
* @param string $source The directory to delete.
*
* @throws \Exception
* @return void
*/
public function deleteDirectory($source)
{
$iterator = new DirectoryIterator($source);
while ($iterator->valid()) {
$src = realpath($source . '/' . $iterator->current());
// delete file
if ($iterator->isFile()) {
self::deleteFile($src);
}
// delete folder recursive
if (! $iterator->isDot() && $iterator->isDir()) {
self::deleteDirectory($src);
}
$iterator->next();
}
unset($iterator);
// delete the source root folder as well
if (!rmdir($source)) {
throw new \Exception('Could not delete directory ' . $source);
}
}
/**
* Copy a directory within all its items.
*
* @param string $source The source directory
* @param string $target The target to create
* @param array $exclude List of files / folders that should not be copyed
*
* @return void
*/
public function copyDirectory($source, $target, $exclude = array())
{
// first check for target itself
self::createDirectory($target);
$iterator = new DirectoryIterator($source);
while ($iterator->valid()) {
$item = $iterator->current();
// create new file
if ($iterator->isFile()) {
self::copyFile($source . '/' . $item, $target);
}
// create folder recursive
if (!$iterator->isDot()
&& $iterator->isDir()
&& !in_array($item, $exclude)
) {
self::copyDirectory(
$source . '/' . $item,
$target . '/' . $item
);
}
$iterator->next();
}
}
/**
* Get the prefix all paths in an array of paths have in common.
* @param array $fileNames
* @return string
*/
public static function getCommonPathPrefix(array $fileNames)
{
if (empty($fileNames)) {
return '/';
}
$prefix = dirname(array_shift($fileNames));
foreach ($fileNames as $filename) {
$prefix = self::getCurrentCommonPathPrefix($prefix, $filename);
}
if (substr($prefix, -1, 1) !== DIRECTORY_SEPARATOR) {
$prefix .= DIRECTORY_SEPARATOR;
}
return $prefix;
}
/**
* Get the part of currentPrefix that currentPrefix and path have in common.
* @param string $currentPrefix
* @param string $path
* @return string
*/
protected static function getCurrentCommonPathPrefix($currentPrefix, $path)
{
if (strpos($path, $currentPrefix . DIRECTORY_SEPARATOR) === 0
|| $currentPrefix == DIRECTORY_SEPARATOR
|| $currentPrefix == ''
|| $currentPrefix == '.'
|| preg_match('/^[A-Z]\:\\\\$/', $currentPrefix) === 1) {
return $currentPrefix;
}
return self::getCurrentCommonPathPrefix(dirname($currentPrefix), $path);
}
}

View File

@@ -0,0 +1,138 @@
<?php
/**
* Plugin Abstract
*
* PHP Version 5.3.0
*
* Copyright (c) 2007-2010, Mayflower GmbH
* 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 Mayflower GmbH 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.
*
* @category PHP_CodeBrowser
* @package PHP_CodeBrowser
* @author Elger Thiele <elger.thiele@mayflower.de>
* @author Michel Hartmann <michel.hartmann@mayflower.de>
* @copyright 2007-2010 Mayflower GmbH
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version SVN: $Id$
* @link http://www.phpunit.de/
* @since File available since 0.1.2
*/
namespace PHPCodeBrowser;
/**
* Issue
*
* Object Model for issues.
* This object is used for working with common issues types.
*
* @category PHP_CodeBrowser
* @package PHP_CodeBrowser
* @author Elger Thiele <elger.thiele@mayflower.de>
* @author Michel Hartmann <michel.hartmann@mayflower.de>
* @copyright 2007-2010 Mayflower GmbH
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version Release: @package_version@
* @link http://github.com/mayflowergmbh
* @since Class available since 0.1.2
*/
class Issue
{
/**
* Source file name.
*
* @var string
*/
public $fileName;
/**
* Starting Line of the Issue.
*
* @var string
*/
public $lineStart;
/**
* Ending Line of the Issue.
*
* @var string
*/
public $lineEnd;
/**
* Name of the Plugin that found the Issue.
* It is also used for CSS class definitions.
*
* @var string
*/
public $foundBy;
/**
* Issue Description text.
*
* @var string
*/
public $description;
/**
* Severity of the issue.
*
* @var string
*/
public $severity;
/**
* Default constructor
*
* @param string $fileName The source file name the issue was found in.
* @param Integer $lineStart The starting line of the issue.
* @param Integer $lineEnd The ending line of registered issue.
* @param string $foundBy The plugin name definition.
* @param string $description The description of the issue.
* @param string $severity
*/
public function __construct(
$fileName,
$lineStart,
$lineEnd,
$foundBy,
$description,
$severity
) {
$this->fileName = $fileName;
$this->lineStart = $lineStart;
$this->lineEnd = $lineEnd;
$this->foundBy = $foundBy;
$this->description = $description;
$this->severity = $severity;
}
}

View File

@@ -0,0 +1,183 @@
<?php
/**
* Issue XML Document
*
* PHP Version 5.3.2
*
* Copyright (c) 2007-2009, Mayflower GmbH
* 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 Mayflower GmbH 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.
*
* @category PHP_CodeBrowser
* @package PHP_CodeBrowser
* @author Elger Thiele <elger.thiele@mayflower.de>
* @author Michel Hartmann <michel.hartmann@mayflower.de>
* @copyright 2007-2010 Mayflower GmbH
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version SVN: $Id$
* @link http://www.phpunit.de/
* @since File available since 0.1.0
*/
namespace PHPCodeBrowser;
use \DOMDocument;
use \DOMNode;
use \DOMNodeList;
use \DOMXPath;
/**
* IssueXML
*
* This class is a wrapper around DOMDocument to provide additional features
* like simple xpath queries.
* It is used to merge issue XML files and execute plugins
* against it to retrieve the issues from them.
*
* @category PHP_CodeBrowser
* @package PHP_CodeBrowser
* @author Elger Thiele <elger.thiele@mayflower.de>
* @author Michel Hartmann <michel.hartmann@mayflower.de>
* @copyright 2007-2010 Mayflower GmbH
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version Release: @package_version@
* @link http://www.phpunit.de/
* @since Class available since 0.1.0
*/
class IssueXml extends DOMDocument
{
/**
*
*
* @var \DOMXPath
*/
protected $xpath;
/**
* Do not preserve white spaces.
* @see DOMDocument
*
* @var Boolean
*/
public $preserveWhiteSpace = false;
/**
* Provide nice output.
*
* @var Boolean
*/
public $formatOutput = true;
/**
* Default constructor
*
* @param string $version The version definition for DomDocument
* @param string $encoding The used encoding for DomDocument
*/
public function __construct($version = '1.0', $encoding = 'UTF-8')
{
parent::__construct($version, $encoding);
$this->appendChild(
$this->createElement('codebrowser')
);
}
/**
* Parses directory for XML report files, generating a single DomDocument
* inheriting all files and issues.
*
* @param string $directory The path to directory where xml files are stored
*
* @return IssueXml This object
*/
public function addDirectory($directory)
{
$factory = new \File_Iterator_Factory();
$iterator = $factory->getFileIterator($directory, 'xml');
foreach ($iterator as $current) {
$realFileName = realpath($current);
$xml = new DOMDocument('1.0', 'UTF-8');
$xml->validateOnParse = true;
if (@$xml->load(realpath($current))) {
$this->addXMLFile($xml);
} else {
error_log(
"[Warning] Could not read file '$realFileName'. "
. 'Make sure it contains valid xml.'
);
}
unset($xml);
}
if (!$this->documentElement->hasChildNodes()) {
error_log("[Warning] No valid log files found in '$directory'");
}
return $this;
}
/**
* Add xml file to merge
*
* @param DOMDocument $domDocument The DOMDocument to merge.
*
* @return void
*/
public function addXMLFile(DOMDocument $domDocument)
{
foreach ($domDocument->childNodes as $node) {
$this->documentElement->appendChild($this->importNode($node, true));
}
}
/**
* Perform a XPath-Query on the document.
* @see DOMXPath::query
*
* @param string $expression Xpath expression to query for.
* @param DOMNode $contextNode Node to use as context (optional)
*
* @return DOMNodeList List of all matching nodes.
*/
public function query($expression, DOMNode $contextNode = null)
{
if (!isset($this->xpath)) {
$this->xpath = new DOMXPath($this);
}
if ($contextNode) {
$result = $this->xpath->query($expression, $contextNode);
} else {
$result = $this->xpath->query($expression);
}
return $result;
}
}

View File

@@ -0,0 +1,172 @@
<?php
/**
* Copy paste detection
*
* PHP Version 5.2.6
*
* Copyright (c) 2007-2009, Mayflower GmbH
* 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 Mayflower GmbH 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.
*
* @category PHP_CodeBrowser
* @package PHP_CodeBrowser
* @subpackage Plugins
* @author Elger Thiele <elger.thiele@mayflower.de>
* @author Michel Hartmann <michel.hartmann@mayflower.de>
* @copyright 2007-2010 Mayflower GmbH
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version SVN: $Id$
* @link http://www.phpunit.de/
* @since File available since 0.1.0
*/
namespace PHPCodeBrowser\Plugins;
use DOMElement;
use DOMNode;
use DOMNodeList;
use Exception;
use PHPCodeBrowser\Issue;
use PHPCodeBrowser\PluginsAbstract;
/**
* ErrorCPD
*
* @category PHP_CodeBrowser
* @package PHP_CodeBrowser
* @subpackage Plugins
* @author Elger Thiele <elger.thiele@mayflower.de>
* @author Michel Hartmann <michel.hartmann@mayflower.de>
* @copyright 2007-2010 Mayflower GmbH
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version Release: @package_version@
* @link http://www.phpunit.de/
* @since Class available since 0.1.0
*/
class ErrorCPD extends PluginsAbstract
{
public $pluginName = 'pmd-cpd';
/**
* Mapper method for this plugin.
*
* @param DOMNode $element The XML plugin node with its errors
* @param string $filename
*
* @return array
*/
public function mapIssues(DOMNode $element, $filename)
{
$parentNode = $element->parentNode;
$files = $this->issueXml->query(
'file[@path="'.$filename.'"]',
$parentNode
);
$lineCount = (int)$parentNode->getAttribute('lines');
$result = array();
foreach ($files as $file) {
$result[] = new Issue(
$file->getAttribute('path'),
(int) $file->getAttribute('line'),
(int) $file->getAttribute('line') + $lineCount,
'Duplication',
htmlentities(
$this->getCpdDescription($parentNode->childNodes, $file)
),
'notice'
);
}
return $result;
}
/**
* @return array
*/
public function getFilesWithIssues()
{
$fileNames = array();
$nodes = $this->issueXml->query(
'/*/'.$this->pluginName.'/*/file[@path]'
);
foreach ($nodes as $node) {
$fileNames[] = $node->getAttribute('path');
}
return array_unique($fileNames);
}
/**
* Get all DOMNodes that represent issues for a specific file.
*
* @param string $filename Name of the file to get nodes for.
* @return DOMNodeList
*/
protected function getIssueNodes($filename)
{
return $this->issueXml->query(
'/*/'.$this->pluginName.'/*/file[@path="'.$filename.'"]'
);
}
/**
* We need another version of getDescription, as we need $allNodes
* to find duplicates.
*/
protected function getCpdDescription(DOMNodeList $allNodes, DOMNode $currentNode)
{
$source = array();
foreach ($allNodes as $node) {
if ($node instanceof DOMElement
&& !$node->isSameNode($currentNode)) {
$source[] = sprintf(
'%s (%d)',
$node->getAttribute('path'),
$node->getAttribute('line')
);
}
}
return "Copy paste from:\n".implode("\n", $source);
}
/**
* Make sure this is never called.
* @codeCoverageIgnoreStart
* This cannot be called because of other overridden methods in this class.
*/
protected function getDescription(DOMElement $element)
{
throw new Exception('ErrorCPD does not support getDescription()!');
}
//@codeCoverageIgnoreEnd
}

View File

@@ -0,0 +1,174 @@
<?php
/**
* CRAP
*
* PHP Version 5.3.2
*
* Copyright (c) 2007-2010, Mayflower GmbH
* 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 Mayflower GmbH 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.
*
* @category PHP_CodeBrowser
* @package PHP_CodeBrowser
* @subpackage Plugins
* @author Simon Kohlmeyer <simon.kohlmeyer@mayflower.de>
* @copyright 2007-2010 Mayflower GmbH
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version SVN: $Id$
* @link http://www.phpunit.de/
* @since File available since 0.2.0
*/
namespace PHPCodeBrowser\Plugins;
use DOMElement;
use DOMNode;
use DOMNodeList;
use PHPCodeBrowser\Issue;
use PHPCodeBrowser\PluginsAbstract;
/**
* ErrorCRAP
*
* @category PHP_CodeBrowser
* @package PHP_CodeBrowser
* @subpackage Plugins
* @author Simon Kohlmeyer <simon.kohlmeyer@mayflower.de>
* @copyright 2007-2010 Mayflower GmbH
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version Release: @package_version@
* @link http://www.phpunit.de/
* @since Class available since 0.2.0
*/
class ErrorCRAP extends PluginsAbstract
{
/**
* Name of this plugin.
* Used to read issues from XML.
* @var string
*/
public $pluginName = 'coverage';
/**
* Name of the attribute that holds the number of the first line
* of the issue.
* @var string
*/
protected $lineStartAttr = 'num';
/**
* Name of the attribute that holds the number of the last line
* of the issue.
* @var string
*/
protected $lineEndAttr = 'num';
/**
* Default string to use as source for issue.
* @var string
*/
protected $source = 'CRAP';
/**
* The detailed mapper method for each single plugin, returning an array
* of Issue objects.
* This method provides a default behaviour an can be overloaded to
* implement special behavior for other plugins.
*
* @param DomNode $element The XML plugin node with its errors
* @param string $filename Name of the file to return issues for.
*
* @return array array of issue objects.
*/
public function mapIssues(DomNode $element, $filename)
{
$errorList = array();
foreach ($element->childNodes as $child) {
if ($child instanceof DOMElement
&& 'line' === $child->nodeName
&& 'method' === $child->getAttribute('type')) {
$crap = $child->getAttribute('crap');
if (!$crap) {
continue;
}
if (!array_key_exists('threshold', $this->options)
|| $crap > $this->options['threshold']) {
$errorList[] = new Issue(
$filename,
$this->getLineStart($child),
$this->getLineEnd($child),
$this->getSource(),
$crap,
$crap >= 30 ? 'Error' : 'Notice'
);
}
}
}
return $errorList;
}
/**
* Get an array with all files that have issues.
*
* @return array
*/
public function getFilesWithIssues()
{
$fileNames = array();
$issueNodes = $this->issueXml->query(
'/*/'.$this->pluginName.'/*/file[@name]'
);
foreach ($issueNodes as $node) {
$fileNames[] = $node->getAttribute('name');
}
return array_unique($fileNames);
}
/**
* Get all DOMNodes that represent issues for a specific file.
*
* @param string $filename Name of the file to get nodes for.
* @return DOMNodeList
*/
protected function getIssueNodes($filename)
{
return $this->issueXml->query(
'/*/'.$this->pluginName.'/*/file[@name="'.$filename.'"]'
);
}
}

View File

@@ -0,0 +1,110 @@
<?php
/**
* Checkstyle
*
* PHP Version 5.2.6
*
* Copyright (c) 2007-2010, Mayflower GmbH
* 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 Mayflower GmbH 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.
*
* @category PHP_CodeBrowser
* @package PHP_CodeBrowser
* @subpackage Plugins
* @author Elger Thiele <elger.thiele@mayflower.de>
* @author Michel Hartmann <michel.hartmann@mayflower.de>
* @copyright 2007-2010 Mayflower GmbH
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version SVN: $Id$
* @link http://www.phpunit.de/
* @since File available since 0.1.0
*/
namespace PHPCodeBrowser\Plugins;
use PHPCodeBrowser\PluginsAbstract;
/**
* ErrorCheckstyle
*
* @category PHP_CodeBrowser
* @package PHP_CodeBrowser
* @subpackage Plugins
* @author Elger Thiele <elger.thiele@mayflower.de>
* @author Christopher Weckerle <christopher.weckerle@mayflower.de>
* @author Michel Hartmann <michel.hartmann@mayflower.de>
* @copyright 2007-2010 Mayflower GmbH
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version Release: @package_version@
* @link http://www.phpunit.de/
* @since Class available since 0.1.0
*/
class ErrorCheckstyle extends PluginsAbstract
{
/**
* Name of this plugin.
* Used to read issues from XML.
* @var string
*/
public $pluginName = 'checkstyle';
/**
* Name of the attribute that holds the number of the first line
* of the issue.
* @var string
*/
protected $lineStartAttr = 'line';
/**
* Name of the attribute that holds the number of the last line
* of the issue.
* @var string
*/
protected $lineEndAttr = 'line';
/**
* Name of the attribute that holds message of the issue.
* @var string
*/
protected $descriptionAttr = 'message';
/**
* Name of the attribute that holds severity of the issue.
* @var string
*/
protected $severityAttr = 'severity';
/**
* Default string to use as source for issue.
* @var string
*/
protected $source = 'Checkstyle';
}

View File

@@ -0,0 +1,200 @@
<?php
/**
* Coverage
*
* PHP Version 5.3.2
*
* Copyright (c) 2007-2010, Mayflower GmbH
* 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 Mayflower GmbH 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.
*
* @category PHP_CodeBrowser
* @package PHP_CodeBrowser
* @subpackage Plugins
* @author Elger Thiele <elger.thiele@mayflower.de>
* @author Michel Hartmann <michel.hartmann@mayflower.de>
* @copyright 2007-2010 Mayflower GmbH
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version SVN: $Id$
* @link http://www.phpunit.de/
* @since File available since 0.1.0
*/
namespace PHPCodeBrowser\Plugins;
use DOMElement;
use DOMNode;
use DOMNodeList;
use PHPCodeBrowser\Issue;
use PHPCodeBrowser\PluginsAbstract;
/**
* ErrorCoverage
*
* @category PHP_CodeBrowser
* @package PHP_CodeBrowser
* @subpackage Plugins
* @author Elger Thiele <elger.thiele@mayflower.de>
* @author Michel Hartmann <michel.hartmann@mayflower.de>
* @copyright 2007-2010 Mayflower GmbH
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version Release: @package_version@
* @link http://www.phpunit.de/
* @since Class available since 0.1.0
*/
class ErrorCoverage extends PluginsAbstract
{
/**
* Name of this plugin.
* Used to read issues from XML.
* @var string
*/
public $pluginName = 'coverage';
/**
* Name of the attribute that holds the number of the first line
* of the issue.
* @var string
*/
protected $lineStartAttr = 'num';
/**
* Name of the attribute that holds the number of the last line
* of the issue.
* @var string
*/
protected $lineEndAttr = 'num';
/**
* Default string to use as source for issue.
* @var string
*/
protected $source = 'Coverage';
/**
* The detailed mapper method for each single plugin, returning an array
* of Issue objects.
* This method provides a default behaviour an can be overloaded to
* implement special behavior for other plugins.
*
* @param DomNode $element The XML plugin node with its errors
* @param string $filename Name of the file to return issues for.
*
* @return array array of issue objects.
*/
public function mapIssues(DomNode $element, $filename)
{
$errorList = array();
$children = $element->childNodes;
$childCount = $children->length;
for ($next = 0; $next < $childCount; $next++) {
$child = $children->item($next);
if ($this->representsUncoveredLOC($child)) {
$begin = $child->getAttribute('num');
$end = $begin;
$next += 1;
while ($next < $childCount) {
$child = $children->item($next);
if (!$child instanceof DOMElement) {
$next += 1;
continue;
}
if (!$this->representsUncoveredLOC($child)) {
break;
}
$end = $child->getAttribute('num');
$next += 1;
}
$errorList[] = new Issue(
$filename,
$begin,
$end,
'Coverage',
'Not covered',
'Notice'
);
}
}
return $errorList;
}
/**
* Check if the given object is a DOMElement representing an
* uncovered line of code.
*/
private function representsUncoveredLOC($elem)
{
return ($elem instanceof DOMElement
&& 0 === (int) $elem->getAttribute('count')
&& 'line' === $elem->nodeName
&& 'stmt' === $elem->getAttribute('type'));
}
/**
* Get an array with all files that have issues.
*
* @return array
*/
public function getFilesWithIssues()
{
$fileNames = array();
$issueNodes = $this->issueXml->query(
'/*/'.$this->pluginName.'/*//file[@name]'
);
foreach ($issueNodes as $node) {
$fileNames[] = $node->getAttribute('name');
}
return array_unique($fileNames);
}
/**
* Get all DOMNodes that represent issues for a specific file.
*
* @param string $filename Name of the file to get nodes for.
* @return DOMNodeList
*/
protected function getIssueNodes($filename)
{
return $this->issueXml->query(
'/*/'.$this->pluginName.'/*//file[@name="'.$filename.'"]'
);
}
}

View File

@@ -0,0 +1,126 @@
<?php
/**
* PMD
*
* PHP Version 5.2
*
* Copyright (c) 2007-2010, Mayflower GmbH
* 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 Mayflower GmbH 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.
*
* @category PHP_CodeBrowser
* @package PHP_CodeBrowser
* @subpackage Plugins
* @author Elger Thiele <elger.thiele@mayflower.de>
* @author Michel Hartmann <michel.hartmann@mayflower.de>
* @copyright 2007-2010 Mayflower GmbH
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @link http://www.phpunit.de/
* @since File available since 0.1.0
*/
namespace PHPCodeBrowser\Plugins;
use DOMElement;
use PHPCodeBrowser\PluginsAbstract;
/**
* ErrorPMD
*
* @category PHP_CodeBrowser
* @package PHP_CodeBrowser
* @subpackage Plugins
* @author Elger Thiele <elger.thiele@mayflower.de>
* @author Christopher Weckerle <christopher.weckerle@mayflower.de>
* @author Michel Hartmann <michel.hartmann@mayflower.de>
* @copyright 2007-2010 Mayflower GmbH
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version Release: @package_version@
* @link http://www.phpunit.de/
* @since Class available since 0.1.0
*/
class ErrorPMD extends PluginsAbstract
{
/**
* Name of this plugin.
* Used to read issues from XML.
* @var string
*/
public $pluginName = 'pmd';
/**
* Name of the attribute that holds the number of the first line
* of the issue.
* @var string
*/
protected $lineStartAttr = 'beginline';
/**
* Name of the attribute that holds the number of the last line
* of the issue.
* @var string
*/
protected $lineEndAttr = 'endline';
/**
* Default string to use as source for issue.
* @var string
*/
protected $source = 'PMD';
/**
* Get the severity of an issue.
* Always return 'error'.
*
* @param DOMElement $element
* @return string
*/
protected function getSeverity(DOMElement $element)
{
return 'error';
}
/**
* Get the description of an issue.
* Use the textContent of the element.
*
* @param DOMElement $element
* @return string
*/
protected function getDescription(DOMElement $element)
{
return str_replace(
'&#10;',
'',
htmlentities($element->textContent)
);
}
}

View File

@@ -0,0 +1,110 @@
<?php
/**
* Padawan
*
* PHP Version 5.2.6
*
* Copyright (c) 2007-2010, Mayflower GmbH
* 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 Mayflower GmbH 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.
*
* @category PHP_CodeBrowser
* @package PHP_CodeBrowser
* @subpackage Plugins
* @author Elger Thiele <elger.thiele@mayflower.de>
* @author Michel Hartmann <michel.hartmann@mayflower.de>
* @copyright 2007-2009 Mayflower GmbH
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version SVN: $Id$
* @link http://www.phpunit.de/
* @since File available since 0.1.0
*/
namespace PHPCodeBrowser\Plugins;
use PHPCodeBrowser\PluginsAbstract;
/**
* ErrorPadawan
*
* @category PHP_CodeBrowser
* @package PHP_CodeBrowser
* @subpackage Plugins
* @author Elger Thiele <elger.thiele@mayflower.de>
* @author Christopher Weckerle <christopher.weckerle@mayflower.de>
* @author Michel Hartmann <michel.hartmann@mayflower.de>
* @copyright 2007-2010 Mayflower GmbH
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version Release: @package_version@
* @link http://www.phpunit.de/
* @since Class available since 0.1.0
*/
class ErrorPadawan extends PluginsAbstract
{
/**
* The name of the plugin.
*
* @var string
*/
public $pluginName = 'padawan';
/**
* Name of the attribute that holds the number of the first line
* of the issue.
* @var string
*/
protected $lineStartAttr = 'line';
/**
* Name of the attribute that holds the number of the last line
* of the issue.
* @var string
*/
protected $lineEndAttr = 'line';
/**
* Name of the attribute that holds message of the issue.
* @var string
*/
protected $descriptionAttr = 'message';
/**
* Name of the attribute that holds severity of the issue.
* @var string
*/
protected $severityAttr = 'severity';
/**
* Default string to use as source for issue.
* @var string
*/
protected $source = 'Padawan';
}

View File

@@ -0,0 +1,302 @@
<?php
/**
* Plugin Abstract
*
* PHP Version 5.3.0
*
* Copyright (c) 2007-2010, Mayflower GmbH
* 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 Mayflower GmbH 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.
*
* @category PHP_CodeBrowser
* @package PHP_CodeBrowser
* @author Elger Thiele <elger.thiele@mayflower.de>
* @author Michel Hartmann <michel.hartmann@mayflower.de>
* @copyright 2007-2010 Mayflower GmbH
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version SVN: $Id$
* @link http://www.phpunit.de/
* @since File available since 0.1.0
*/
namespace PHPCodeBrowser;
use \DOMNode;
use \DOMElement;
use \DOMNodeList;
/**
* PluginsAbstract
*
* @category PHP_CodeBrowser
* @package PHP_CodeBrowser
* @author Elger Thiele <elger.thiele@mayflower.de>
* @author Michel Hartmann <michel.hartmann@mayflower.de>
* @copyright 2007-2010 Mayflower GmbH
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version Release: @package_version@
* @link http://www.phpunit.de/
* @since Class available since 0.1.0
*/
abstract class PluginsAbstract
{
/**
* The name of the plugin.
* This should be the name that is written to the XML error files by
* cruisecontrol.
*
* @var string
*/
public $pluginName;
/**
* The IssueXml object
*
* @var IssueXml
*/
protected $issueXml;
/**
* Name of the attribute that holds the number of the first line
* of the issue.
*
* @var string
*/
protected $lineStartAttr;
/**
* Name of the attribute that holds the number of the last line
* of the issue.
*
* @var string
*/
protected $lineEndAttr;
/**
* Name of the attribute that holds message of the issue.
*
* @var string
*/
protected $descriptionAttr;
/**
* Name of the attribute that holds severity of the issue.
*
* @var string
*/
protected $severityAttr;
/**
* Default string to use as source for issue.
*
* @var string
*/
protected $source;
/**
* Plugin-specific options.
*
* @var array
*/
protected $options;
/**
* Default Constructor
*
* @param IssueXml $issueXml The cc XML document.
* @param array $options Optional plugin-specific options.
*/
public function __construct(IssueXml $issueXml, $options = array())
{
$this->issueXml = $issueXml;
$this->options = $options;
}
/**
* Gets a list of File objects, including their issues.
*
* @return File[] List of files with issues.
*/
public function getFileList()
{
$files = array();
foreach ($this->getFilesWithIssues() as $name) {
$files[] = new File($name, $this->getIssuesByFile($name));
}
return $files;
}
/**
* Parse the cc XML file for defined error type, e.g. "pmd" and map this
* error to the Issue objects format.
*
* @param string $filename Name of the file to parse the errors for.
*
* @return array
*/
public function getIssuesByFile($filename)
{
$issues = array();
foreach ($this->getIssueNodes($filename) as $issueNode) {
$issues = array_merge(
$issues,
$this->mapIssues($issueNode, $filename)
);
}
return $issues;
}
/**
* Get an array with all files that have issues.
*
* @return array
*/
public function getFilesWithIssues()
{
$fileNames = array();
$issueNodes = $this->issueXml->query(
sprintf('/*/%s/file[@name]', $this->pluginName)
);
foreach ($issueNodes as $node) {
$fileNames[] = $node->getAttribute('name');
}
return array_unique($fileNames);
}
/**
* The detailed mapper method for each single plugin, returning an array
* of issue objects.
* This method provides a default behaviour an can be overloaded to
* implement special behavior for other plugins.
*
* @param DomNode $element The XML plugin node with its errors
* @param string $filename Name of the file to return issues for.
*
* @return array array of issue objects.
*/
public function mapIssues(DomNode $element, $filename)
{
$errorList = array();
foreach ($element->childNodes as $child) {
if (!($child instanceof DOMElement)) {
continue;
}
$errorList[] = new Issue(
$filename,
$this->getLineStart($child),
$this->getLineEnd($child),
$this->getSource(),
$this->getDescription($child),
$this->getSeverity($child)
);
}
return $errorList;
}
/**
* Get all DOMNodes that represent issues for a specific file.
*
* @param string $filename Name of the file to get nodes for.
*
* @return DOMNodeList
*/
protected function getIssueNodes($filename)
{
return $this->issueXml->query(
sprintf('/*/%s/file[@name="%s"]', $this->pluginName, $filename)
);
}
/**
* Default method for retrieving the first line of an issue.
* @see self::mapIssues
*
* @param DOMElement $element
*
* @return Integer
*/
protected function getLineStart(DOMElement $element)
{
return (int) $element->getAttribute($this->lineStartAttr);
}
/**
* Default method for retrieving the last line of an issue.
* @see self::mapIssues
*
* @param DOMElement $element
*
* @return Integer
*/
protected function getLineEnd(DOMElement $element)
{
return (int) $element->getAttribute($this->lineEndAttr);
}
/**
* Default method for retrieving the source of an issue.
* @see self::mapIssues
*
* @return string
*/
protected function getSource()
{
return $this->source;
}
/**
* Default method for retrieving the description of an issue.
* @see self::mapIssues
*
* @param DOMElement $element
*
* @return string
*/
protected function getDescription(DOMElement $element)
{
return htmlentities($element->getAttribute($this->descriptionAttr));
}
/**
* Default method for retrieving the severity of an issue.
* @see self::mapIssues
*
* @param DOMElement $element
*
* @return string
*/
protected function getSeverity(DOMElement $element)
{
return htmlentities($element->getAttribute($this->severityAttr));
}
}

View File

@@ -0,0 +1,224 @@
<?php
/**
* Source handler
*
* PHP Version 5.3.0
*
* Copyright (c) 2007-2010, Mayflower GmbH
* 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 Mayflower GmbH 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.
*
* @category PHP_CodeBrowser
* @package PHP_CodeBrowser
* @author Elger Thiele <elger.thiele@mayflower.de>
* @author Michel Hartmann <michel.hartmann@mayflower.de>
* @author Simon Kohlmeyer <simon.kohlmeyer@mayflower.de>
* @copyright 2007-2010 Mayflower GmbH
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version SVN: $Id$
* @link http://www.phpunit.de/
* @since File available since 0.2.0
*/
namespace PHPCodeBrowser;
use Exception;
use Monolog\Logger;
use PHPCodeBrowser\Helper\IOHelper;
use SplFileInfo;
/**
* SourceHandler
*
* This class manages lists of source files and their issues.
* For providing these lists the prior generated IssueXml is parsed.
*
* @category PHP_CodeBrowser
* @package PHP_CodeBrowser
* @author Elger Thiele <elger.thiele@mayflower.de>
* @author Christopher Weckerle <christopher.weckerle@mayflower.de>
* @author Michel Hartmann <michel.hartmann@mayflower.de>
* @author Simon Kohlmeyer <simon.kohlmeyer@mayflower.de>
* @copyright 2007-2010 Mayflower GmbH
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version Release: @package_version@
* @link http://www.phpunit.de/
* @since Class available since 0.2.0
*/
class SourceHandler
{
/**
* Files to be included in the report
*
* @var File[]
*/
protected $files = array();
/**
* Pear Log object where debug output should go to.
*
* @var Logger
*/
protected $debugLog;
/**
* Default constructor
*
* @param Logger $debugLog
* @param array $plugins The plugins to get issues from.
*/
public function __construct (Logger $debugLog, array $plugins = array())
{
$this->debugLog = $debugLog;
array_walk($plugins, array($this, 'addPlugin'));
}
/**
* Add a new plugin to the handler.
*
* @param PluginsAbstract $plugin The plugin to add.
*/
public function addPlugin(PluginsAbstract $plugin)
{
foreach ($plugin->getFileList() as $file) {
if (array_key_exists($file->name(), $this->files)) {
$this->files[$file->name()]->mergeWith($file);
} else {
$this->files[$file->name()] = $file;
}
}
}
/**
* Add source files to the list.
*
* @param SplFileInfo[]|string[]|\AppendIterator $files The files to add
*/
public function addSourceFiles($files)
{
foreach ($files as $f) {
$this->addSourceFile($f);
}
}
/**
* Add a source file.
*
* @param string|SplFileInfo $file The file to add
* @throws \Exception
*/
public function addSourceFile($file)
{
if (is_string($file)) {
$filename = $file;
$file = realpath($file);
} else {
$filename = $file->getPathName();
$file = $file->getRealPath();
}
if (!$file) {
throw new Exception("$filename is no regular file");
}
if (!array_key_exists($file, $this->files)) {
$this->files[$file] = new File($file);
}
}
/**
* Retrieves the parent directory all files have in common.
*
* @return string
*/
public function getCommonPathPrefix()
{
return IOHelper::getCommonPathPrefix(array_keys($this->files));
}
/**
* Returns a sorted array of the files that should be in the report.
*
* @return File[] of File
*/
public function getFiles()
{
File::sort($this->files);
return $this->files;
}
/**
* Get a unique list of all file names with issues.
*
* @return array
*/
public function getFilesWithIssues()
{
return array_keys($this->files);
}
/**
* Remove all files that match the given PCRE.
*
* @param string $expr The PCRE specifying which files to remove.
* @return void.
*/
public function excludeMatchingPCRE($expr)
{
foreach (array_keys($this->files) as $filename) {
if (preg_match($expr, $filename)) {
$this->debugLog->debug(
"Excluding $filename, it matches PCRE $expr"
);
unset($this->files[$filename]);
}
}
}
/**
* Remove all files that match the given shell wildcard pattern
* as accepted by fnmatch().
*
* @param string $pattern The pattern.
* @return void.
*/
public function excludeMatchingPattern($pattern)
{
foreach (array_keys($this->files) as $filename) {
if (fnmatch($pattern, $filename)) {
$this->debugLog->debug(
"Excluding $filename, it matches pattern $pattern"
);
unset($this->files[$filename]);
}
}
}
}

View File

@@ -0,0 +1,201 @@
<?php
/**
* Test case
*
* Copyright (c) 2007-2009, Mayflower GmbH
* 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 Mayflower GmbH 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.
*
* @category PHP_CodeBrowser
* @package PHP_CodeBrowser
* @subpackage PHPUnit
* @author Elger Thiele <elger.thiele@mayflower.de>
* @copyright 2007-2009 Mayflower GmbH
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version SVN: $Id$
* @link http://www.phpunit.de/
* @since File available since 0.1.0
*/
namespace PHPCodeBrowser\Tests;
/**
* AbstractTests
*
* @category PHP_CodeBrowser
* @package PHP_CodeBrowser
* @subpackage PHPUnit
* @author Elger Thiele <elger.thiele@mayflower.de>
* @copyright 2007-2009 Mayflower GmbH
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version Release: @package_version@
* @link http://www.phpunit.de/
* @since Class available since 0.1.0
*/
class AbstractTestCase extends \PHPUnit_Framework_TestCase
{
/**
* Merged cruisecontrol XML error file
*
* @var string
*/
protected static $ccXMLFile;
/**
* PHP_CodeBrowser error file
*
* @var string
*/
protected static $xmlFile;
/**
* Basic XML file with valid headers
*
* @var string
*/
protected static $xmlBasic;
/**
* Path information for a dummy TXT file
*
* @var string
*/
protected static $testFile;
/**
* Path information for a dummy XML file
*
* @var string
*/
protected static $testXML;
/**
* File of serialized error list
*
* @var string
*/
protected static $serializedErrors;
/**
* Path information for generated XML test file
*
* @var string
*/
protected static $generatedXMLTest;
/**
* Global setup method for all test cases. Basic variables are initialized.
*
* @return void
*/
protected function setUp()
{
parent::setUp();
if (!defined('PHPCB_SOURCE_DIR')) {
define('PHPCB_SOURCE_DIR', realpath(dirname(__FILE__) . '/../'));
}
if (!defined('PHPCB_TEST_DIR')) {
define(
'PHPCB_TEST_DIR',
realpath(PHPCB_SOURCE_DIR) . DIRECTORY_SEPARATOR . 'Tests' . DIRECTORY_SEPARATOR . 'testData'
);
}
if (!defined('PHPCB_TEST_LOGS')) {
define('PHPCB_TEST_LOGS', PHPCB_TEST_DIR . '/logs');
}
if (!defined('PHPCB_TEST_OUTPUT')) {
define('PHPCB_TEST_OUTPUT', PHPCB_TEST_DIR . DIRECTORY_SEPARATOR . 'output');
}
self::$xmlBasic = PHPCB_TEST_LOGS . '/basic.xml';
if (is_dir(PHPCB_TEST_OUTPUT)) {
$this->cleanUp(PHPCB_TEST_OUTPUT);
rmdir(PHPCB_TEST_OUTPUT);
}
mkdir(PHPCB_TEST_OUTPUT);
}
/**
* Global tear down method for all test cases.
* Cleaning up generated data and output.
*
* @return void
*/
protected function tearDown()
{
parent::tearDown();
$this->cleanUp(PHPCB_TEST_OUTPUT);
rmdir(PHPCB_TEST_OUTPUT);
}
/**
* Load the cb error list
*
* @return array List of cb errors
*/
protected function getSerializedErrors()
{
return unserialize(file_get_contents(self::$serializedErrors));
}
/**
* Cleanup the test directory output folder
*
* @param string $dir The directory to clean up
*
* @return void
*/
protected function cleanUp($dir)
{
$iterator = new \DirectoryIterator($dir);
while ($iterator->valid()) {
// delete file
if ($iterator->isFile()) {
unlink($dir . '/' . $iterator->current());
}
// delete folder recursive
if (! $iterator->isDot() && $iterator->isDir()) {
$this->cleanUp($dir . '/' . $iterator->current());
rmdir($dir . '/' . $iterator->current());
}
$iterator->next();
}
unset($iterator);
}
}

View File

@@ -0,0 +1,27 @@
<?php
namespace PHPCodeBrowser\Tests;
use PHPCodeBrowser\Application;
/**
* Class ApplicationTest
* @package PHPCodeBrowser\Tests
*/
class ApplicationTest extends \PHPUnit_Framework_TestCase
{
/**
* @var Application
*/
private $application;
protected function setUp()
{
$this->application = new Application();
}
public function testCommand()
{
$this->assertInstanceOf('PHPCodeBrowser\\Command\\RunCommand', $this->application->get('phpcb'));
}
}

View File

@@ -0,0 +1,107 @@
<?php
/**
* Test case
*
* Copyright (c) 2007-2010, Mayflower GmbH
* 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 Mayflower GmbH 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.
*
* @category PHP_CodeBrowser
* @package PHP_CodeBrowser
* @subpackage PHPUnit
* @author Simon Kohlmeyer <simon.kohlmeyer@mayflower.de
* @copyright 2007-2010 Mayflower GmbH
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version SVN: $Id$
* @link http://www.phpunit.de/
* @since File available since 0.1.0
*/
namespace PHPCodeBrowser\Tests;
use Monolog\Logger;
use PHPCodeBrowser\CLIController;
use PHPCodeBrowser\Helper\IOHelper;
/**
* CLIControllerTest
*
* @category PHP_CodeBrowser
* @package PHP_CodeBrowser
* @subpackage PHPUnit
* @author Simon Kohlmeyer <simon.kohlmeyer@mayflower.de>
* @copyright 2007-2010 Mayflower GmbH
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version Release: @package_version@
* @link http://www.phpunit.de/
* @since Class available since 0.1.0
*/
class CLIControllerTest extends AbstractTestCase
{
/**
* Run a full system test based on phpcs output.
*
* @return void
*/
public function testMain()
{
$controller = new CLIController(
null,
array(PHPCB_SOURCE_DIR),
PHPCB_TEST_OUTPUT,
array(),
array(),
array(),
new IOHelper(),
new Logger('PHPCodeBrowser'),
array('php')
);
$controller->addErrorPlugins(
array(
'ErrorCheckstyle',
'ErrorPMD',
'ErrorCPD',
'ErrorPadawan',
'ErrorCoverage',
'ErrorCRAP'
)
);
$controller->run();
$this->assertFileExists(PHPCB_TEST_OUTPUT . '/index.html');
$this->assertFileExists(PHPCB_TEST_OUTPUT . '/CLIController.php.html');
$this->assertFileExists(PHPCB_TEST_OUTPUT . '/css');
}
}

View File

@@ -0,0 +1,306 @@
<?php
/**
* Test case
*
* Copyright (c) 2007-2010, Mayflower GmbH
* 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 Mayflower GmbH 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.
*
* @category PHP_CodeBrowser
* @package PHP_CodeBrowser
* @subpackage PHPUnit
* @author Simon Kohlmeyer <simon.kohlmeyer@mayflower.de
* @copyright 2007-2010 Mayflower GmbH
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version SVN: $Id$
* @link http://www.phpunit.de/
* @since File available since 0.1.0
*/
namespace PHPCodeBrowser\Tests;
use PHPCodeBrowser\File;
use PHPCodeBrowser\Issue;
/**
* FileTest
*
* @category PHP_CodeBrowser
* @package PHP_CodeBrowser
* @subpackage PHPUnit
* @author Simon Kohlmeyer <simon.kohlmeyer@mayflower.de>
* @copyright 2007-2010 Mayflower GmbH
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version Release: @package_version@
* @link http://www.phpunit.de/
* @since Class available since 0.1.0
*/
class FileTest extends AbstractTestCase
{
/**
* File object to test
*
* @var File
*/
protected $file;
/**
* Some issues to work with.
*
* @var Issue[]
*/
protected $issues;
/**
* Constructor. Initialize some values.
*/
public function __construct()
{
$this->issues = array(
new Issue('/some/file/name.php', 39, 39, 'Checkstyle', 'm3', 'error'),
new Issue('/some/file/name.php', 50, 52, 'Checkstyle', 'm4', 'warning'),
new Issue('/some/file/name.php', 40, 40, 'Checkstyle', 'm4', 'error')
);
}
/**
* (non-PHPDoc)
* @see AbstractTests#setUp()
*/
protected function setUp()
{
parent::setUp();
$this->file = new File('/some/file/name.php');
}
/**
* Test constructor if variables are stored properly
*
* @return void
*/
public function testInstantiation()
{
$this->assertEquals('/some/file/name.php', $this->file->name());
$this->file = new File('/some/file/name.php', $this->issues);
$this->assertEquals('/some/file/name.php', $this->file->name());
$this->assertEquals($this->issues, $this->file->getIssues());
}
/**
* Test if adding issues works.
*
* @return void
*/
public function testIssueAdding()
{
$this->file->addIssue($this->issues[0]);
$this->assertEquals(
array($this->issues[0]),
$this->file->getIssues()
);
}
/**
* Tries to add invalid issue to file.
*
* @return void
*/
public function testAddingIssueToWrongFile()
{
$issue = new Issue('/the/wrong/file/name.php', 39, 39, 'Checkstyle', 'm3', 'error');
try {
$this->file->addIssue($issue);
$this->fail();
} catch (\InvalidArgumentException $e) {
// Expected
}
}
/**
* Test the basename function
*
* @return void
*/
public function testBasename()
{
$this->assertEquals('name.php', $this->file->basename());
}
/**
* Test the dirName function
*
* @return void
*/
public function testDirName()
{
$this->assertEquals('/some/file', $this->file->dirName());
}
/**
* Test if the issue count is returned correctly
*
* @return void
*/
public function testIssueCount()
{
$this->assertEquals(0, $this->file->getIssueCount());
$this->file->addIssue($this->issues[0]);
$this->assertEquals(1, $this->file->getIssueCount());
$this->file = new File(
'/some/file/name.php',
array($this->issues[0])
);
$this->assertEquals(1, $this->file->getIssueCount());
$this->file->addIssue($this->issues[1]);
$this->assertEquals(2, $this->file->getIssueCount());
}
/**
* Test the errorCount function
*
* @return void
*/
public function testErrorCount()
{
$this->file = new File('/some/file/name.php', $this->issues);
$this->assertEquals(2, $this->file->getErrorCount());
}
/**
* Test the warningCount function
*
* @return void
*/
public function testEarningCount()
{
$this->file = new File('/some/file/name.php', $this->issues);
$this->assertEquals(1, $this->file->getWarningCount());
}
/**
* Test the mergeWith function
*
* @return void
*/
public function testMergeWith()
{
$this->file = new File(
'/some/file/name.php',
array($this->issues[0], $this->issues[1])
);
$otherFile = new File(
'/some/file/name.php',
array($this->issues[2])
);
$this->file->mergeWith($otherFile);
$this->assertEquals(2, $this->file->getErrorCount());
$this->assertEquals(1, $this->file->getWarningCount());
$this->assertEquals(
array_values($this->issues),
array_values($this->file->getIssues())
);
}
/**
* Try to merge with a non-compatible file.
*
* @return void
*/
public function testMergeWithDifferentFile()
{
try {
$this->file->mergeWith(new File('/the/wrong/file/name.php'));
$this->fail();
} catch (\InvalidArgumentException $e) {
// Expected
}
}
/**
* Test the sort function.
*
* @return void.
*/
public function testSort()
{
$sorted = array(
new File("src/Helper/IOHelper.php"),
new File("src/Plugins/ErrorCPD.php"),
new File("src/Plugins/ErrorCheckstyle.php"),
new File("src/Plugins/ErrorCoverage.php"),
new File("src/Plugins/ErrorPMD.php"),
new File("src/Plugins/ErrorPadawan.php"),
new File("src/Util/Autoloader.php"),
new File("src/Util/Logger.php"),
new File("src/View/ViewAbstract.php"),
new File("src/View/ViewReview.php"),
new File("src/CLIController.php"),
new File("src/File.php"),
new File("src/Issue.php"),
new File("src/IssueXml.php"),
new File("src/PluginsAbstract.php"),
new File("src/SourceHandler.php"),
new File("src/SourceIterator.php")
);
$mixed = array(
new File("src/PluginsAbstract.php"),
new File("src/Plugins/ErrorCheckstyle.php"),
new File("src/CLIController.php"),
new File("src/Plugins/ErrorPadawan.php"),
new File("src/SourceIterator.php"),
new File("src/SourceHandler.php"),
new File("src/Issue.php"),
new File("src/View/ViewReview.php"),
new File("src/File.php"),
new File("src/Util/Autoloader.php"),
new File("src/Helper/IOHelper.php"),
new File("src/IssueXml.php"),
new File("src/Plugins/ErrorCoverage.php"),
new File("src/View/ViewAbstract.php"),
new File("src/Util/Logger.php"),
new File("src/Plugins/ErrorPMD.php"),
new File("src/Plugins/ErrorCPD.php"),
);
File::sort($mixed);
$mixed = array_values($mixed);
$this->assertEquals($sorted, $mixed);
}
}

View File

@@ -0,0 +1,258 @@
<?php
/**
* Test case
*
* Copyright (c) 2007-2010, Mayflower GmbH
* 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 Mayflower GmbH 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.
*
* @category PHP_CodeBrowser
* @package PHP_CodeBrowser
* @subpackage PHPUnit
* @author Simon Kohlmeyer <simon.kohlmeyer@mayflower.de
* @copyright 2007-2010 Mayflower GmbH
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version SVN: $Id$
* @link http://www.phpunit.de/
* @since File available since 0.1.0
*/
namespace PHPCodeBrowser\Tests\Helper;
use PHPCodeBrowser\Helper\IOHelper;
use PHPCodeBrowser\Tests\AbstractTestCase;
/**
* IOHelperTest
*
* @category PHP_CodeBrowser
* @package PHP_CodeBrowser
* @subpackage PHPUnit
* @author Simon Kohlmeyer <simon.kohlmeyer@mayflower.de>
* @copyright 2007-2010 Mayflower GmbH
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version Release: @package_version@
* @link http://www.phpunit.de/
* @since Class available since 0.1.0
*/
class IOHelperTest extends AbstractTestCase
{
/**
* The IOHelper object under test.
*
* @var IOHelper
*/
protected $ioHelper;
/**
* (non-PHPDoc)
* @see AbstractTestCase::setUp()
*/
protected function setUp()
{
parent::setUp();
$this->ioHelper = new IOHelper();
}
/**
* Test createFile function without creating a path
*
* @return void
*/
public function testFileCreation()
{
$filename = PHPCB_TEST_OUTPUT . '/tmpfile';
$content = 'Lorem ipsum';
if (file_exists($filename)) {
unlink($filename);
}
$this->ioHelper->createFile($filename, $content);
$this->assertTrue(file_exists($filename));
$this->assertEquals($content, file_get_contents($filename));
unlink($filename);
}
/**
* Test createFile function with creating a path
*
* @return void
*/
public function testCreationOfFileWithPath()
{
$dirName = PHPCB_TEST_OUTPUT . '/tmpdir';
$filename = $dirName . '/tmpfile';
$content = 'Lorem ipsum';
if (file_exists($filename)) {
unlink($filename);
rmdir($dirName);
} elseif (file_exists($dirName)) {
rmdir($dirName);
}
$this->ioHelper->createFile($filename, $content);
$this->assertTrue(file_exists($dirName));
$this->assertTrue(file_exists($filename));
$this->assertEquals($content, file_get_contents($filename));
unlink($filename);
rmdir($dirName);
}
/**
* Test deleteFile function
*
* @return void
*/
public function testFileDeletion()
{
$filename = PHPCB_TEST_OUTPUT . '/tmpfile';
if (!file_exists($filename)) {
file_put_contents($filename, 'Lorem ipsum');
}
$this->ioHelper->deleteFile($filename);
$this->assertFalse(file_exists($filename));
}
/**
* Test deleteDirectory function
*
* @return void
*/
public function testDirectoryDeletion()
{
$dir = PHPCB_TEST_OUTPUT . '/dir';
$file = $dir . '/file';
$subDir = $dir . '/subDir';
mkdir($dir);
mkdir($subDir);
touch($file);
$this->ioHelper->deleteDirectory($dir);
$this->assertFileNotExists($dir);
}
/**
* Test copyFile function
*
* @return void
*/
public function testCopyFile()
{
$srcFile = PHPCB_TEST_OUTPUT . '/tmpfile';
$dstDir = PHPCB_TEST_OUTPUT . '/tmpdir';
$dstFile = $dstDir . '/tmpfile';
$content = 'Lorem ipsum';
if (file_exists($srcFile)) {
unlink($srcFile);
}
if (file_exists($dstFile)) {
rmdir($dstFile);
}
file_put_contents($srcFile, $content);
$this->ioHelper->copyFile($srcFile, $dstDir);
$this->assertTrue(file_exists($srcFile));
$this->assertTrue(file_exists($dstDir));
$this->assertTrue(file_exists($dstFile));
$this->assertEquals($content, file_get_contents($dstFile));
$this->assertEquals($content, file_get_contents($srcFile));
unlink($dstFile);
rmdir($dstDir);
unlink($srcFile);
}
/**
* Test loadFile function for non-existent file.
*
* @return void
*/
public function testLoadFileWithNonexistentFile()
{
$sourceFile = PHPCB_TEST_OUTPUT . '/doesNotExist';
if (file_exists($sourceFile)) {
unlink(PHPCB_TEST_OUTPUT . '/doesNotExist');
}
try {
$this->ioHelper->loadFile($sourceFile);
$this->fail();
} catch (\Exception $e) {
// expected
}
}
/**
* Test copyFile function for non-existent source file
*
* @return void
*/
public function testCopyFileNonExisting()
{
$file = PHPCB_TEST_OUTPUT . '/tmpfile';
$dstDir = PHPCB_TEST_OUTPUT . '/tmpdir';
if (file_exists($file)) {
unlink($file);
}
try {
$this->ioHelper->copyFile($file, $dstDir);
} catch (\Exception $e) {
return;
}
$this->fail('Expected exception was not thrown.');
}
/**
* Test getCommonPathPrefix with empty file list.
*
* @return void
*/
public function testGetCommonPathPrefixForNoFiles()
{
$this->assertEquals(
'/',
$this->ioHelper->getCommonPathPrefix(array())
);
}
}

View File

@@ -0,0 +1,114 @@
<?php
/**
* Test case
*
* Copyright (c) 2007-2010, Mayflower GmbH
* 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 Mayflower GmbH 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.
*
* @category PHP_CodeBrowser
* @package PHP_CodeBrowser
* @subpackage PHPUnit
* @author Simon Kohlmeyer <simon.kohlmeyer@mayflower.de
* @copyright 2007-2010 Mayflower GmbH
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version SVN: $Id$
* @link http://www.phpunit.de/
* @since File available since 0.1.0
*/
namespace PHPCodeBrowser\Tests;
use PHPCodeBrowser\Issue;
/**
* IssueTest
*
* @category PHP_CodeBrowser
* @package PHP_CodeBrowser
* @subpackage PHPUnit
* @author Simon Kohlmeyer <simon.kohlmeyer@mayflower.de>
* @copyright 2007-2010 Mayflower GmbH
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version Release: @package_version@
* @link http://www.phpunit.de/
* @since Class available since 0.1.0
*/
class IssueTest extends AbstractTestCase
{
/**
* Issue object to test
*
* @var Issue
*/
protected $issue;
/**
* (non-PHPDoc)
* @see tests/cbAbstractTests#setUp()
*/
protected function setUp()
{
parent::setUp();
$this->issue = new Issue(
'testFileName',
23,
27,
'testFinder',
'testDescription',
'notice'
);
}
/**
* (non-PHPDoc)
* @see tests/cbAbstractTests#tearDown()
*/
protected function tearDown()
{
parent::tearDown();
}
/**
* Test constructor if variables are stored properly
*
* @return void
*/
public function testInstantiation()
{
$this->assertTrue($this->issue->fileName === 'testFileName');
$this->assertTrue($this->issue->lineStart === 23);
$this->assertTrue($this->issue->lineEnd === 27);
$this->assertTrue($this->issue->foundBy === 'testFinder');
$this->assertTrue($this->issue->description === 'testDescription');
$this->assertTrue($this->issue->severity === 'notice');
}
}

View File

@@ -0,0 +1,150 @@
<?php
/**
* Test case
*
* Copyright (c) 2007-2010, Mayflower GmbH
* 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 Mayflower GmbH 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.
*
* @category PHP_CodeBrowser
* @package PHP_CodeBrowser
* @subpackage PHPUnit
* @author Simon Kohlmeyer <simon.kohlmeyer@mayflower.de
* @copyright 2007-2010 Mayflower GmbH
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version SVN: $Id$
* @link http://www.phpunit.de/
* @since File available since 0.9.0
*/
namespace PHPCodeBrowser\Tests\Plugins;
use DOMDocument;
use PHPCodeBrowser\File;
use PHPCodeBrowser\Issue;
use PHPCodeBrowser\IssueXml;
use PHPCodeBrowser\Plugins\ErrorCPD;
use PHPCodeBrowser\Tests\AbstractTestCase;
/**
* ErrorCPDTest
*
* @category PHP_CodeBrowser
* @package PHP_CodeBrowser
* @subpackage PHPUnit
* @author Simon Kohlmeyer <simon.kohlmeyer@mayflower.de>
* @copyright 2007-2010 Mayflower GmbH
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version Release: @package_version@
* @link http://www.phpunit.de/
* @since Class available since 0.9.0
*/
class ErrorCPDTest extends AbstractTestCase
{
/**
* The object to test.
*
* @var ErrorCPD
*/
protected $errorCPD;
/**
* The xml string to test the plugin against.
*
* @var string
*/
protected $testXml = <<<HERE
<?xml version="1.0" encoding="UTF-8"?>
<pmd-cpd version="phpcpd 1.3.1">
<duplication lines="1" tokens="2">
<file path="/original/file" line="23"/>
<file path="/copied/file" line="42"/>
<codefragment>
echo 'Some code here';
</codefragment>
</duplication>
</pmd-cpd>
HERE;
/**
* (non-PHPDoc)
* @see tests/cbAbstractTests#setUp()
*/
protected function setUp()
{
parent::setUp();
$issueXML = new IssueXML();
$xml = new DOMDocument('1.0', 'UTF-8');
$xml->loadXML($this->testXml);
$issueXML->addXMLFile($xml);
$this->errorCPD = new ErrorCPD($issueXML);
}
/**
* Test getFileList
*
* @return void
*/
public function testGettingFileList()
{
$expected = array(
new File(
'/original/file',
array(
new Issue(
'/original/file',
23,
24,
'Duplication',
"Copy paste from:\n/copied/file (42)\n (0)",
'notice'
)
)
),
new File(
'/copied/file',
array(
new Issue(
'/copied/file',
42,
43,
'Duplication',
"Copy paste from:\n/original/file (23)\n (0)",
'notice'
)
)
)
);
$actual = $this->errorCPD->getFileList();
$this->assertEquals($expected, $actual);
}
}

View File

@@ -0,0 +1,213 @@
<?php
/**
* Test case
*
* Copyright (c) 2007-2010, Mayflower GmbH
* 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 Mayflower GmbH 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.
*
* @category PHP_CodeBrowser
* @package PHP_CodeBrowser
* @subpackage PHPUnit
* @author Simon Kohlmeyer <simon.kohlmeyer@mayflower.de
* @copyright 2007-2010 Mayflower GmbH
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version SVN: $Id$
* @link http://www.phpunit.de/
* @since File available since 0.9.0
*/
namespace PHPCodeBrowser\Tests\Plugins;
use DOMDocument;
use PHPCodeBrowser\File;
use PHPCodeBrowser\Issue;
use PHPCodeBrowser\IssueXml;
use PHPCodeBrowser\Plugins\ErrorCRAP;
use PHPCodeBrowser\Tests\AbstractTestCase;
/**
* ErrorCRAPTest
*
* @category PHP_CodeBrowser
* @package PHP_CodeBrowser
* @subpackage PHPUnit
* @author Simon Kohlmeyer <simon.kohlmeyer@mayflower.de>
* @copyright 2007-2010 Mayflower GmbH
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version Release: @package_version@
* @link http://www.phpunit.de/
* @since Class available since 0.9.0
*/
class ErrorCRAPTest extends AbstractTestCase
{
/**
* The object to test.
*
* @var ErrorCRAP
*/
protected $errorCrap;
/**
* The xml string to test the plugin against.
*
* @var string
*/
protected $testXml = <<<HERE
<?xml version="1.0" encoding="UTF-8"?>
<coverage generated="1279366386">
<project timestamp="1279366386">
<file name="/test/file">
<class name="Class"
namespace="global"
fullPackage="Full_Package"
category="Category"
package="Package">
</class>
<line num="50" type="stmt" count="1"/>
<line num="143" type="method" name="method_1" crap="1" count="3"/>
<line num="144" type="stmt" count="3"/>
<line num="145" type="stmt" count="3"/>
<line num="162" type="method" name="method_2" crap="100" count="3"/>
<line num="164" type="stmt" count="3"/>
<line num="165" type="stmt" count="3"/>
</file>
<file name="/has/no/crap">
<class name="NoCrapClass"
namespace="global"
fullPackage="Full_Package"
category="Category"
package="Package">
</class>
<line num="50" type="stmt" count="1"/>
<line num="143" type="method" name="method_1" count="3"/>
<line num="144" type="stmt" count="3"/>
<line num="145" type="stmt" count="3"/>
<line num="162" type="method" name="method_2" count="3"/>
<line num="164" type="stmt" count="3"/>
<line num="165" type="stmt" count="3"/>
</file>
</project>
</coverage>
HERE;
/**
* (non-PHPDoc)
* @see tests/cbAbstractTests#setUp()
*/
protected function setUp()
{
parent::setUp();
$issueXML = new IssueXML();
$xml = new DOMDocument('1.0', 'UTF-8');
$xml->loadXML($this->testXml);
$issueXML->addXMLFile($xml);
$this->errorCrap = new ErrorCRAP($issueXML);
}
/**
* Test getFileList
*
* @return void
*/
public function testGettingFileList()
{
$expected = array(
new File(
'/test/file',
array(
new Issue(
'/test/file',
143,
143,
'CRAP',
'1',
'Notice'
),
new Issue(
'/test/file',
162,
162,
'CRAP',
'100',
'Error'
)
)
),
new File(
'/has/no/crap',
array()
)
);
$actual = $this->errorCrap->getFileList();
$this->assertEquals($expected, $actual);
}
/**
* Test getFileList with limit set
*
* @return void
*/
public function testGetFileListWithLimit()
{
$issueXML = new IssueXML();
$xml = new DOMDocument('1.0', 'UTF-8');
$xml->loadXML($this->testXml);
$issueXML->addXMLFile($xml);
$this->errorCrap = new ErrorCRAP(
$issueXML,
array('threshold' => 30)
);
$expected = array(
new File(
'/test/file',
array(
new Issue(
'/test/file',
162,
162,
'CRAP',
'100',
'Error'
)
)
),
new File(
'/has/no/crap',
array()
)
);
$actual = $this->errorCrap->getFileList();
$this->assertEquals($expected, $actual);
}
}

View File

@@ -0,0 +1,177 @@
<?php
/**
* Test case
*
* Copyright (c) 2007-2010, Mayflower GmbH
* 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 Mayflower GmbH 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.
*
* @category PHP_CodeBrowser
* @package PHP_CodeBrowser
* @subpackage PHPUnit
* @author Simon Kohlmeyer <simon.kohlmeyer@mayflower.de
* @copyright 2007-2010 Mayflower GmbH
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version SVN: $Id$
* @link http://www.phpunit.de/
* @since File available since 0.9.0
*/
namespace PHPCodeBrowser\Tests\Plugins;
use DOMDocument;
use PHPCodeBrowser\File;
use PHPCodeBrowser\Issue;
use PHPCodeBrowser\IssueXml;
use PHPCodeBrowser\Plugins\ErrorCheckstyle;
use PHPCodeBrowser\Tests\AbstractTestCase;
/**
* ErrorCheckstyleTest
*
* @category PHP_CodeBrowser
* @package PHP_CodeBrowser
* @subpackage PHPUnit
* @author Simon Kohlmeyer <simon.kohlmeyer@mayflower.de>
* @copyright 2007-2010 Mayflower GmbH
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version Release: @package_version@
* @link http://www.phpunit.de/
* @since Class available since 0.9.0
*/
class ErrorCheckstyleTest extends AbstractTestCase
{
/**
* The object to test.
*
* @var ErrorCheckstyle
*/
protected $errorCheckstyle;
/**
* The xml string to test the plugin against.
*
* @var string
*/
protected $testXml = <<<HERE
<?xml version="1.0" encoding="UTF-8"?>
<checkstyle version="1.2.2">
<file name="/some/file">
<error line="117"
column="32"
severity="error"
message="Message 1"
source="Source3"/>
<error line="121"
column="88"
severity="warning"
message="Message 2"
source="Source2"/>
</file>
<file name="/other/file">
<error line="48"
column="67"
severity="error"
message="Message 3"
source="Source1"/>
</file>
<file name="/no/violations">
</file>
</checkstyle>
HERE;
/**
* (non-PHPDoc)
* @see tests/cbAbstractTests#setUp()
*/
protected function setUp()
{
parent::setUp();
$issueXML = new IssueXML();
$xml = new DOMDocument('1.0', 'UTF-8');
$xml->validateOnParse = true;
$xml->loadXML($this->testXml);
$issueXML->addXMLFile($xml);
$this->errorCheckstyle = new ErrorCheckstyle($issueXML);
}
/**
* Test getFileList
*
* @return void
*/
public function testGettingFileList()
{
$expected = array(
new File(
'/some/file',
array(
new Issue(
'/some/file',
117,
117,
'Checkstyle',
'Message 1',
'error'
),
new Issue(
'/some/file',
121,
121,
'Checkstyle',
'Message 2',
'warning'
)
)
),
new File(
'/other/file',
array(
new Issue(
'/other/file',
48,
48,
'Checkstyle',
'Message 3',
'error'
)
)
),
new File(
'/no/violations',
array()
)
);
$actual = $this->errorCheckstyle->getFileList();
$this->assertEquals($expected, $actual);
}
}

View File

@@ -0,0 +1,180 @@
<?php
/**
* Test case
*
* Copyright (c) 2007-2010, Mayflower GmbH
* 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 Mayflower GmbH 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.
*
* @category PHP_CodeBrowser
* @package PHP_CodeBrowser
* @subpackage PHPUnit
* @author Simon Kohlmeyer <simon.kohlmeyer@mayflower.de
* @copyright 2007-2010 Mayflower GmbH
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version SVN: $Id$
* @link http://www.phpunit.de/
* @since File available since 0.9.0
*/
namespace PHPCodeBrowser\Tests\Plugins;
use DOMDocument;
use PHPCodeBrowser\File;
use PHPCodeBrowser\Issue;
use PHPCodeBrowser\IssueXml;
use PHPCodeBrowser\Plugins\ErrorCoverage;
use PHPCodeBrowser\Tests\AbstractTestCase;
/**
* ErrorCoverageTest
*
* @category PHP_CodeBrowser
* @package PHP_CodeBrowser
* @subpackage PHPUnit
* @author Simon Kohlmeyer <simon.kohlmeyer@mayflower.de>
* @copyright 2007-2010 Mayflower GmbH
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version Release: @package_version@
* @link http://www.phpunit.de/
* @since Class available since 0.9.0
*/
class ErrorCoverageTest extends AbstractTestCase
{
/**
* The object to test.
*
* @var ErrorCoverage
*/
protected $errorCoverage;
/**
* The xml string to test the plugin against.
*
* @var string
*/
protected $testXml = <<<HERE
<?xml version="1.0" encoding="UTF-8"?>
<coverage generated="1279365369">
<project timestamp="1279365369">
<file name="/partly/tested">
<line num="1" type="stmt" count="1"/>
<line num="2" type="stmt" count="1"/>
<line num="3" type="stmt" count="2"/>
<line num="4" type="stmt" count="2"/>
<line num="5" type="stmt" count="1"/>
<line num="10" type="stmt" count="0"/>
<line num="11" type="stmt" count="0"/>
<line num="12" type="stmt" count="0"/>
<line num="13" type="stmt" count="0"/>
<line num="14" type="stmt" count="0"/>
<line num="21" type="stmt" count="2"/>
<line num="22" type="stmt" count="2"/>
</file>
<file name="/totally/tested">
<line num="212" type="stmt" count="2"/>
<line num="213" type="stmt" count="2"/>
<line num="215" type="stmt" count="2"/>
<line num="216" type="stmt" count="2"/>
</file>
<file name="/not/tested">
<line num="212" type="stmt" count="0"/>
<line num="213" type="stmt" count="0"/>
<line num="214" type="stmt" count="0"/>
<line num="216" type="stmt" count="0"/>
<line num="219" type="stmt" count="0"/>
<line num="220" type="stmt" count="0"/>
<line num="221" type="stmt" count="0"/>
<line num="224" type="stmt" count="0"/>
<line num="225" type="stmt" count="0"/>
</file>
</project>
</coverage>
HERE;
/**
* (non-PHPDoc)
* @see tests/cbAbstractTests#setUp()
*/
protected function setUp()
{
parent::setUp();
$issueXML = new IssueXML();
$xml = new DOMDocument('1.0', 'UTF-8');
$xml->loadXML($this->testXml);
$issueXML->addXMLFile($xml);
$this->errorCoverage = new ErrorCoverage($issueXML);
}
/**
* Test getFileList
*
* @return void
*/
public function testGettingFileList()
{
$expected = array(
new File(
'/partly/tested',
array(
new Issue(
'/partly/tested',
10,
14,
'Coverage',
'Not covered',
'Notice'
)
)
),
new File(
'/totally/tested',
array()
),
new File(
'/not/tested',
array(
new Issue(
'/not/tested',
212,
225,
'Coverage',
'Not covered',
'Notice'
)
)
)
);
$actual = $this->errorCoverage->getFileList();
$this->assertEquals($expected, $actual);
}
}

View File

@@ -0,0 +1,178 @@
<?php
/**
* Test case
*
* Copyright (c) 2007-2010, Mayflower GmbH
* 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 Mayflower GmbH 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.
*
* @category PHP_CodeBrowser
* @package PHP_CodeBrowser
* @subpackage PHPUnit
* @author Simon Kohlmeyer <simon.kohlmeyer@mayflower.de
* @copyright 2007-2010 Mayflower GmbH
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version SVN: $Id$
* @link http://www.phpunit.de/
* @since File available since 0.9.0
*/
namespace PHPCodeBrowser\Tests\Plugins;
use DOMDocument;
use PHPCodeBrowser\File;
use PHPCodeBrowser\Issue;
use PHPCodeBrowser\IssueXml;
use PHPCodeBrowser\Plugins\ErrorPMD;
use PHPCodeBrowser\Tests\AbstractTestCase;
/**
* ErrorPMDTest
*
* @category PHP_CodeBrowser
* @package PHP_CodeBrowser
* @subpackage PHPUnit
* @author Simon Kohlmeyer <simon.kohlmeyer@mayflower.de>
* @copyright 2007-2010 Mayflower GmbH
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version Release: @package_version@
* @link http://www.phpunit.de/
* @since Class available since 0.9.0
*/
class ErrorPMDTest extends AbstractTestCase
{
/**
* The object to test.
*
* @var ErrorPMD
*/
protected $errorPmd;
/**
* The xml string to test the plugin against.
*
* @var string
*/
protected $testXml = <<<HERE
<?xml version="1.0" encoding="UTF-8" ?>
<pmd version="0.2.6" timestamp="2010-07-17T02:38:00-07:00">
<file name="/some/file">
<violation beginline="3"
endline="4"
rule="Rule1"
ruleset="Ruleset 1"
priority="1">Description 1</violation>
<violation beginline="5"
endline="5"
rule="Rule2"
ruleset="Ruleset 1"
class="SomeClass"
method="someMethod"
priority="3">Description 2</violation>
</file>
<file name="/other/file">
<violation beginline="15"
endline="15"
rule="The third rule"
ruleset="Ruleset two"
priority="3">Description 3</violation>
</file>
<file name="/has/no/violation">
</file>
</pmd>
HERE;
/**
* (non-PHPDoc)
* @see tests/cbAbstractTests#setUp()
*/
protected function setUp()
{
parent::setUp();
$issueXML = new IssueXML();
$xml = new DOMDocument('1.0', 'UTF-8');
$xml->loadXML($this->testXml);
$issueXML->addXMLFile($xml);
$this->errorPmd = new ErrorPMD($issueXML);
}
/**
* Test getFileList
*
* @return void
*/
public function testGettingFileList()
{
$expected = array(
new File(
'/some/file',
array(
new Issue(
'/some/file',
3,
4,
'PMD',
'Description 1',
'error'
),
new Issue(
'/some/file',
5,
5,
'PMD',
'Description 2',
'error'
)
)
),
new File(
'/other/file',
array(
new Issue(
'/other/file',
15,
15,
'PMD',
'Description 3',
'error'
)
)
),
new File(
'/has/no/violation',
array()
)
);
$actual = $this->errorPmd->getFileList();
$this->assertEquals($expected, $actual);
}
}

View File

@@ -0,0 +1,298 @@
<?php
/**
* Test case
*
* Copyright (c) 2007-2010, Mayflower GmbH
* 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 Mayflower GmbH 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.
*
* @category PHP_CodeBrowser
* @package PHP_CodeBrowser
* @subpackage PHPUnit
* @author Simon Kohlmeyer <simon.kohlmeyer@mayflower.de
* @copyright 2007-2010 Mayflower GmbH
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version SVN: $Id$
* @link http://www.phpunit.de/
* @since File available since 0.1.0
*/
namespace PHPCodeBrowser\Tests;
use Exception;
use Monolog\Handler\NullHandler;
use Monolog\Logger;
use PHPCodeBrowser\File;
use PHPCodeBrowser\Issue;
use PHPCodeBrowser\IssueXml;
use PHPCodeBrowser\Plugins\ErrorCheckstyle;
use PHPCodeBrowser\Plugins\ErrorPMD;
use PHPCodeBrowser\SourceHandler;
use SplFileInfo;
/**
* SourceHandlerTest
*
* @category PHP_CodeBrowser
* @package PHP_CodeBrowser
* @subpackage PHPUnit
* @author Simon Kohlmeyer <simon.kohlmeyer@mayflower.de>
* @copyright 2007-2010 Mayflower GmbH
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version Release: @package_version@
* @link http://www.phpunit.de/
* @since Class available since 0.1.0
*/
class SourceHandlerTest extends AbstractTestCase
{
/**
* SourceHandler object to test
*
* @var SourceHandler
*/
protected $sourceHandler;
/**
* Plugin array populated with example files.
* TODO: Mock this
*
* @var array of PluginsAbstract
*/
protected $plugins;
/**
* @var Logger
*/
private $logger;
/**
* Initializes common values.
*/
public function __construct()
{
$xmlStrings = array(
<<<HERE
<?xml version="1.0" encoding="UTF-8"?>
<pmd version="0.2.6" timestamp="2010-08-12T00:00:00+02:000">
<file name='/a/nother/dir/src.php'>
<violation beginline="291" endline="291" rule="ExitExpression"
ruleset="Design Rules"
externalInfoUrl="http://example.com" priority="1">descr</violation>
</file>
</pmd>
HERE
,
<<<HERE
<?xml version="1.0" encoding="UTF-8"?>
<checkstyle version="1.2.0RC3">
<file name="/a/dir/source.php">
<error line="37" column="1" severity="error"
message="m1" source="PEAR.Commenting.FileCommentSniff"/>
</file>
<file name="/a/nother/dir/src.php">
<error line="39" column="1" severity="error"
message="m3" source="PEAR.Commenting.FileCommentSniff"/>
<error line="40" column="1" severity="error"
message="m4" source="PEAR.Commenting.FileCommentSniff"/>
</file>
</checkstyle>
HERE
);
$issueXML = new IssueXml();
foreach ($xmlStrings as $xmlString) {
$xml = new \DOMDocument('1.0', 'UTF-8');
$xml->validateOnParse = true;
$xml->loadXML($xmlString);
$issueXML->addXMLFile($xml);
}
$this->plugins = array(
new ErrorCheckstyle($issueXML),
new ErrorPMD($issueXML)
);
}
/**
* (non-PHPDoc)
* @see AbstractTests#setUp()
*/
protected function setUp()
{
parent::setUp();
$this->logger = new Logger('PHPCodeBrowser');
$this->logger->pushHandler(new NullHandler());
$this->sourceHandler = new SourceHandler($this->logger);
array_walk(
$this->plugins,
array($this->sourceHandler, 'addPlugin')
);
}
/**
* Test the constructor.
*
* @return void.
*/
public function testInstantiation()
{
$sourceHandler = new SourceHandler(
$this->logger,
$this->plugins
);
$this->assertEquals($this->sourceHandler, $sourceHandler);
}
/**
* Test getFiles.
*
* @return void
*/
public function testGetFiles()
{
$expected = array(
'/a/nother/dir/src.php' => new File(
'/a/nother/dir/src.php',
array(
new Issue('/a/nother/dir/src.php', 39, 39, 'Checkstyle', 'm3', 'error'),
new Issue('/a/nother/dir/src.php', 40, 40, 'Checkstyle', 'm4', 'error'),
new Issue('/a/nother/dir/src.php', 291, 291, 'PMD', 'descr', 'error')
)
),
'/a/dir/source.php' => new File(
'/a/dir/source.php',
array(
new Issue('/a/dir/source.php', 37, 37, 'Checkstyle', 'm1', 'error')
)
)
);
File::sort($expected);
$actual = $this->sourceHandler->getFiles();
$this->assertEquals($expected, $actual);
}
/**
* Test getFilesWithIssues
*
* @return void
*/
public function testGetFilesWithIssues()
{
$expectedFiles = array (
'/a/dir/source.php',
'/a/nother/dir/src.php'
);
$actualFiles = $this->sourceHandler->getFilesWithIssues();
$this->assertEquals($expectedFiles, $actualFiles);
}
/**
* Test addSourceFiles
*
* @return void
*/
public function testAddSourceFiles()
{
$this->sourceHandler->addSourceFiles(
array(new SplFileInfo(__FILE__), __FILE__)
);
$this->assertContains(__FILE__, array_keys($this->sourceHandler->getFiles()));
}
/**
* Test if addSourceFile chokes on non-existent files.
*
* @return void
*/
public function testAddSourceFilesWithNonExisting()
{
try {
$this->sourceHandler->addSourceFiles(
array(new SplFileInfo('/i/do/not/exist'))
);
} catch (Exception $e) {
//expected
return;
}
$this->fail('Expected Exception was not thrown');
}
/**
* Test getCommonPathPrefix
*
* @return void
*/
public function testGetCommonPathPrefix()
{
$expected = '/a/';
$actual = $this->sourceHandler->getCommonPathPrefix();
$this->assertEquals($expected, $actual);
}
/**
* Test excludeMatchingPCRE
*
* @return void
*/
public function testExcludeMatchingPCRE()
{
$expected = array(
'/a/dir/source.php' => new File(
'/a/dir/source.php',
array(
new Issue('/a/dir/source.php', 37, 37, 'Checkstyle', 'm1', 'error')
)
)
);
$this->sourceHandler->excludeMatchingPCRE('/^\/a.*src\.php$/');
$this->assertEquals($expected, $this->sourceHandler->getFiles());
}
/**
* Test excludeMatchingPattern
*
* @return void
*/
public function testExcludeMatchingPattern()
{
$expected = array(
'/a/dir/source.php' => new File(
'/a/dir/source.php',
array(
new Issue('/a/dir/source.php', 37, 37, 'Checkstyle', 'm1', 'error')
)
)
);
$this->sourceHandler->excludeMatchingPattern('*src.php');
$this->assertEquals($expected, $this->sourceHandler->getFiles());
}
}

View File

@@ -0,0 +1,291 @@
<?php
/**
* Test case
*
* Copyright (c) 2007-2010, Mayflower GmbH
* 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 Mayflower GmbH 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.
*
* @category PHP_CodeBrowser
* @package PHP_CodeBrowser
* @subpackage PHPUnit
* @author Simon Kohlmeyer <simon.kohlmeyer@mayflower.de
* @copyright 2007-2010 Mayflower GmbH
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version SVN: $Id$
* @link http://www.phpunit.de/
* @since File available since 0.1.0
*/
namespace PHPCodeBrowser\Tests\View;
use PHPCodeBrowser\File;
use PHPCodeBrowser\Issue;
use PHPCodeBrowser\Tests\AbstractTestCase;
use PHPCodeBrowser\View\ViewReview;
/**
* ViewReviewTest
*
* @category PHP_CodeBrowser
* @package PHP_CodeBrowser
* @subpackage PHPUnit
* @author Simon Kohlmeyer <simon.kohlmeyer@mayflower.de>
* @copyright 2007-2010 Mayflower GmbH
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version Release: @package_version@
* @link http://www.phpunit.de/
* @since Class available since 0.1.0
*/
class ViewReviewTest extends AbstractTestCase
{
/**
* The ViewReview object to test.
*
* @var ViewReview
*/
protected $viewReview;
/**
* IOHelper mock to simulate filesystem interaction.
*
* @var \PHPUnit_Framework_MockObject_MockObject
*/
protected $ioMock;
/**
* (non-PHPDoc)
* @see tests/cbAbstractTests#setUp()
*/
protected function setUp()
{
parent::setUp();
$this->ioMock = $this->createMock('PHPCodeBrowser\Helper\IOHelper');
$this->viewReview = new ViewReview(
PHPCB_ROOT_DIR . '/../templates/',
PHPCB_TEST_OUTPUT,
$this->ioMock
);
}
/**
* Test the generate method without any issues
*
* @return void
*/
public function testGenerateNoIssues()
{
$expectedFile = PHPCB_TEST_OUTPUT . DIRECTORY_SEPARATOR . basename(__FILE__) . '.html';
$this->ioMock->expects($this->once())
->method('loadFile')
->with($this->equalTo(__FILE__))
->will($this->returnValue(file_get_contents(__FILE__)));
$this->ioMock->expects($this->once())
->method('createFile')
->with($this->equalTo($expectedFile));
$this->viewReview->generate(
array(),
__FILE__,
dirname(__FILE__) . DIRECTORY_SEPARATOR
);
}
/**
* Test the generate method with an issue
*
* @return void
*/
public function testGenerate()
{
$issueList = array(
new Issue(
__FILE__,
80,
85,
'finder',
'description',
'severe'
)
);
$expectedFile = PHPCB_TEST_OUTPUT . DIRECTORY_SEPARATOR . basename(__FILE__) . '.html';
$this->ioMock->expects($this->once())
->method('loadFile')
->with($this->equalTo(__FILE__))
->will($this->returnValue(file_get_contents(__FILE__)));
$this->ioMock->expects($this->once())
->method('createFile')
->with($this->equalTo($expectedFile));
$this->viewReview->generate(
$issueList,
__FILE__,
dirname(__FILE__) . DIRECTORY_SEPARATOR
);
}
/**
* Test the generate method with multiple errors on one line.
*
* @return void
*/
public function testGenerateMultiple()
{
$issueList = array(
new Issue(__FILE__, 80, 80, 'finder', 'description', 'severe'),
new Issue(__FILE__, 80, 80, 'other finder', 'other description', 'more severe')
);
$expectedFile = PHPCB_TEST_OUTPUT . DIRECTORY_SEPARATOR . basename(__FILE__) . '.html';
$this->ioMock->expects($this->once())
->method('loadFile')
->with($this->equalTo(__FILE__))
->will($this->returnValue(file_get_contents(__FILE__)));
$this->ioMock->expects($this->once())
->method('createFile')
->with($this->equalTo($expectedFile));
$this->viewReview->generate(
$issueList,
__FILE__,
dirname(__FILE__) . DIRECTORY_SEPARATOR
);
}
/**
* Try to test highlighting with Text_Highlighter
*
* @return void
*/
public function testGenerateWithTextHighlighter()
{
if (!class_exists('Text_Highlighter')) {
$this->markTestIncomplete();
}
$html = <<< EOT
<html>
<head>
<title>Title</title>
</head>
<body>
<p>Body</p>
</body>
</html>
EOT;
$prefix = '/dir/';
$fileName = $prefix . 'file.html';
$expectedFile = PHPCB_TEST_OUTPUT . '/file.html.html';
$this->ioMock->expects($this->once())
->method('loadFile')
->with($this->equalTo($fileName))
->will($this->returnValue($html));
$this->ioMock->expects($this->once())
->method('createFile')
->with($this->equalTo($expectedFile));
$issues = array(
new Issue($fileName, 5, 5, 'finder', 'description', 'severity')
);
$this->viewReview->generate($issues, $fileName, $prefix);
}
/**
* Test highlighting of unknown code files.
*
* @return void
*/
public function testGenerateUnknownType()
{
$expectedFile = PHPCB_TEST_OUTPUT . DIRECTORY_SEPARATOR . basename(self::$xmlBasic) . '.html';
$this->ioMock->expects($this->once())
->method('createFile')
->with($this->equalTo($expectedFile));
$issueList = array(
new Issue(self::$xmlBasic, 5, 5, 'finder', 'description', 'severity')
);
$this->viewReview->generate(
$issueList,
self::$xmlBasic,
dirname(self::$xmlBasic) . DIRECTORY_SEPARATOR
);
}
/**
* Test if the resource folders are copied.
*
* @return void
*/
public function testCopyResourceFolders()
{
$this->ioMock->expects($this->exactly(3))
->method('copyDirectory')
->with(
$this->matchesRegularExpression(
'|^' . realpath(dirname(__FILE__) . '/../../../templates/') . '|'
)
);
$this->viewReview->copyResourceFolders();
}
/**
* Test the generateIndex function
*
* @return void
*/
public function testGenerateIndex()
{
$files = array(
"s/A/somefile.php" => new File("s/A/somefile.php"),
"s/file.php" => new File("s/file.php"),
"s/B/anotherfile.php" => new File("s/B/anotherfile.php")
);
$this->ioMock->expects($this->once())
->method('createFile')
->with(
$this->logicalAnd(
$this->stringEndsWith('index.html')
)
);
$this->viewReview->generateIndex($files);
}
}

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="utf-8"?><codebrowser/>

View File

@@ -0,0 +1,327 @@
<?php
/**
* View Abstract
*
* PHP Version 5.3.0
*
* Copyright (c) 2007-2010, Mayflower GmbH
* 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 Mayflower GmbH 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.
*
* @category PHP_CodeBrowser
* @package PHP_CodeBrowser
* @author Elger Thiele <elger.thiele@mayflower.de>
* @author Jan Mergler <jan.mergler@mayflower.de>
* @author Simon Kohlmeyer <simon.kohlmeyer@mayflower.de>
* @copyright 2007-2010 Mayflower GmbH
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version SVN: $Id$
* @link http://www.phpunit.de/
* @since File available since 0.1.0
*/
namespace PHPCodeBrowser\View;
use Exception;
use PHPCodeBrowser\File;
use PHPCodeBrowser\Helper\IOHelper;
/**
* ViewAbstract
*
* This class is generating the highlighted and formatted html view for file.
*
* @category PHP_CodeBrowser
* @package PHP_CodeBrowser
* @author Elger Thiele <elger.thiele@mayflower.de>
* @author Jan Mergler <jan.mergler@mayflower.de>
* @author Simon Kohlmeyer <simon.kohlmeyer@mayflower.de>
* @copyright 2007-2010 Mayflower GmbH
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version Release: @package_version@
* @link http://www.phpunit.de/
* @since Class available since 0.1.0
*/
class ViewAbstract
{
/**
* Template directory
*
* @var string
*/
protected $templateDir;
/**
* Output directory
*
* @var string
*/
protected $outputDir;
/**
* Available resource folders
*
* @var array
*/
protected $resourceFolders = array('css', 'js', 'img');
/**
* IOHelper for filesystem interaction.
*
* @var IOHelper
*/
protected $ioHelper;
/**
* Default Constructor
*
* @param string $templateDir The directory containing the templates.
* @param string $outputDir The directory where the reviews should be.
* @param IOHelper $ioHelper The IOHelper object to use for I/O.
* @throws Exception
*/
public function __construct($templateDir, $outputDir, IOHelper $ioHelper)
{
$this->templateDir = $templateDir;
if (!$this->templateDir) {
throw new Exception(
"Specified template directory '$templateDir' does not exist"
);
}
$this->outputDir = $outputDir;
if (!$this->outputDir) {
throw new Exception(
"Specified output directory '$outputDir' does not exist"
);
}
$this->outputDir .= DIRECTORY_SEPARATOR;
$this->ioHelper = $ioHelper;
}
/**
* Copy needed resources to output directory
*
* @return void
* @throws Exception
* @see IOHelper->copyFile
*/
public function copyResourceFolders()
{
foreach ($this->resourceFolders as $folder) {
$this->ioHelper->copyDirectory(
$this->templateDir . DIRECTORY_SEPARATOR . $folder,
$this->outputDir . DIRECTORY_SEPARATOR . $folder
);
}
}
/**
* Copy the noErrors file as index.html to indicate that no
* source files were found
*
* @return void
*/
public function copyNoErrorsIndex()
{
$this->ioHelper->createFile(
$this->outputDir . '/index.html',
$this->render('noErrors', array())
);
}
/**
* Creates a javascript-filled index.html
*
* @param array $fileList
* @param bool $excludeOK
*
* @return void
*/
public function generateIndex(array $fileList, $excludeOK = false)
{
//we want to exclude files without issues
if ($excludeOK) {
$fileList = array_filter($fileList, array('PHPCodeBrowser\\View\\ViewAbstract', 'hasFileAnyIssues'));
}
$data['treeList'] = $this->getTreeListHtml($fileList);
$data['fileList'] = $fileList;
$this->ioHelper->createFile(
$this->outputDir . '/index.html',
$this->render('index', $data)
);
}
/**
* Has the file any issues?
*
* @param File $file
* @return boolean
*/
public static function hasFileAnyIssues(File $file)
{
$issues = $file->getIssues();
return !empty($issues);
}
/**
* Convert a list of files to a html fragment for jstree.
*
* @param File[] $fileList The files, format: array('name' => File).
* @param string $hrefPrefix The prefix to put before all href= tags.
*
* @return string The html fragment.
*/
protected function getTreeListHtml(array $fileList, $hrefPrefix = '')
{
/*
* In this method, all directories have a trailing DIRECTORY_SEPARATOR.
* This is important so that $curDir doesn't become empty if we go
* up to the root directory ('/' on linux)
*/
$curDir = IOHelper::getCommonPathPrefix(array_keys($fileList));
$preLen = strlen($curDir);
$indentStep = 4;
$indent = $indentStep;
$ret = '<ul>' . PHP_EOL;
foreach ($fileList as $name => $file) {
$dir = dirname($name) . DIRECTORY_SEPARATOR;
// Go back until the file is somewhere below curDir
while (strpos($dir, $curDir) !== 0) {
// chop off one subDir from $curDir
$curDir = substr(
$curDir,
0,
strrpos($curDir, DIRECTORY_SEPARATOR, -2) + 1
);
$ret .= str_pad(' ', $indent);
$ret .= '</ul>' . PHP_EOL;
$indent -= $indentStep;
$ret .= str_pad(' ', $indent);
$ret .= '</li>' . PHP_EOL;
}
if ($dir !== $curDir) {
// File is in a subDir of current directory
// relDir has no leading or trailing slash.
$relDir = substr($dir, strlen($curDir), -1);
$relDirs = explode(DIRECTORY_SEPARATOR, $relDir);
foreach ($relDirs as $dirName) {
$curDir .= $dirName . DIRECTORY_SEPARATOR;
// Check how many errors/warnings are in this dir.
//TODO: Optimize this. Counts get recalculated for subDirs.
$errors = 0;
$warnings = 0;
foreach (array_keys($fileList) as $fName) {
if (strncmp($fName, $curDir, strlen($curDir)) === 0) {
$errors += $fileList[$fName]->getErrorCount();
$warnings += $fileList[$fName]->getWarningCount();
}
}
$count = '';
if ($errors != 0 || $warnings != 0) {
$count .= '(<span class="errorCount">';
$count .= $errors;
$count .= '</span>|<span class="warningCount">';
$count .= $warnings . '</span>)';
}
$ret .= str_pad(' ', $indent);
$ret .= "<li><a class='treeDir'>$dirName $count</a>"
. PHP_EOL;
$indent += $indentStep;
$ret .= str_pad(' ', $indent);
$ret .= '<ul>' . PHP_EOL;
}
}
$name = str_replace('\\', '/', $name);
$shortName = substr($name, $preLen);
$fileName = basename($name);
$count = '';
if ($file->getErrorCount() != 0 || $file->getWarningCount() != 0) {
$count .= '(<span class="errorCount">';
$count .= $file->getErrorCount();
$count .= '</span>|<span class="warningCount">';
$count .= $file->getWarningCount();
$count .= '</span>)';
}
$ret .= str_pad(' ', $indent);
$ret .= '<li class="php"><a class="fileLink" href="';
$ret .= $hrefPrefix . $shortName . '.html">';
$ret .= "$fileName $count</a></li>" . PHP_EOL;
}
while ($indent > $indentStep) {
$indent -= $indentStep;
$ret .= str_pad(' ', $indent);
$ret .= '</ul>' . PHP_EOL;
$indent -= $indentStep;
$ret .= str_pad(' ', $indent);
$ret .= '</li>' . PHP_EOL;
}
$ret .= '</ul>' . PHP_EOL;
return $ret;
}
/**
* Render a template.
*
* Defined template is parsed and filled with data.
* Rendered content is read from output buffer.
*
* @param string $templateName Template file to use for rendering
* @param array $data Given data set to use for rendering
*
* @return string HTML files as string from output buffer
*/
protected function render($templateName, $data)
{
$filePath = $this->templateDir . DIRECTORY_SEPARATOR
. $templateName . '.tpl';
extract($data, EXTR_SKIP);
ob_start();
include($filePath);
$contents = ob_get_contents();
ob_end_clean();
return $contents;
}
}

View File

@@ -0,0 +1,432 @@
<?php
/**
* View Review
*
* PHP Version 5.3.0
*
* Copyright (c) 2007-2010, Mayflower GmbH
* 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 Mayflower GmbH 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.
*
* @category PHP_CodeBrowser
* @package PHP_CodeBrowser
* @author Elger Thiele <elger.thiele@mayflower.de>
* @author Jan Mergler <jan.mergler@mayflower.de>
* @author Simon Kohlmeyer <simon.kohlmeyer@mayflower.de>
* @copyright 2007-2010 Mayflower GmbH
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version SVN: $Id$
* @link http://www.phpunit.de/
* @since File available since 0.1.0
*/
namespace PHPCodeBrowser\View;
use DOMDocument;
use DOMElement;
use DOMXPath;
use PHPCodeBrowser\Helper\IOHelper;
/**
* ViewReview
*
* This class is generating the highlighted and formatted html view for file.
*
* @category PHP_CodeBrowser
* @package PHP_CodeBrowser
* @author Elger Thiele <elger.thiele@mayflower.de>
* @author Jan Mergler <jan.mergler@mayflower.de>
* @author Simon Kohlmeyer <simon.kohlmeyer@mayflower.de>
* @copyright 2007-2010 Mayflower GmbH
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version Release: @package_version@
* @link http://www.phpunit.de/
* @since Class available since 0.1.0
*/
class ViewReview extends ViewAbstract
{
/**
* Highlight mapping.
*
* @var array
*/
protected $phpHighlightColorMap;
/**
* Suffixes for php files.
*
* @var array
*/
protected $phpSuffixes;
/**
* Default constructor
*
* Highlighting strings are set.
*
* @param string $templateDir The directory containing the templates.
* @param string $outputDir The directory where the reviews should be.
* @param IOHelper $ioHelper The IOHelper object to use for I/O.
* @param array $phpSuffixes The array with extensions of php files.
*/
public function __construct($templateDir, $outputDir, $ioHelper, $phpSuffixes = array('php'))
{
parent::__construct($templateDir, $outputDir, $ioHelper);
$this->phpHighlightColorMap = array(
ini_get('highlight.string') => 'string',
ini_get('highlight.comment') => 'comment',
ini_get('highlight.keyword') => 'keyword',
ini_get('highlight.default') => 'default',
ini_get('highlight.html') => 'html',
);
$this->phpSuffixes = $phpSuffixes;
}
/**
* Generating the Html code browser view for a given file.
*
* Issue list for each file will be marked in source code.
* Source code is highlighted.
* Generated Html source code is be saved as Html.
*
* @param array $issueList The issue list for given file
* @param $fileName
* @param string $commonPathPrefix The prefix path all given files have
* in common
* @param bool $excludeOK
*
* @return void
*
* @see self::_formatIssues
* @see self::_formatSourceCode
* @see self::_generateJSCode
*/
public function generate(array $issueList, $fileName, $commonPathPrefix, $excludeOK = false)
{
$issues = $this->formatIssues($issueList);
$shortFilename = substr($fileName, strlen($commonPathPrefix));
$data['issues'] = $issueList;
$data['filepath'] = $shortFilename;
$data['source'] = $this->formatSourceCode($fileName, $issues);
$depth = substr_count($shortFilename, DIRECTORY_SEPARATOR);
$data['csspath'] = str_repeat('../', $depth - 1 >= 0 ? $depth - 1 : 0);
//we want to exclude files without issues and there are no issues in this one
if ($excludeOK && !$data['issues']) {
return;
}
$this->ioHelper->createFile(
$this->outputDir . $shortFilename . '.html',
$this->render('review', $data)
);
}
/**
* Source code is highlighted an formatted.
*
* Besides highlighting, whole lines will be marked with different colors
* and JQuery functions (like tooltips) are integrated.
*
* @param string $filename The file to format
* @param array $outputIssues Sorted issueList by line number
*
* @return string Html formatted string
*/
private function formatSourceCode($filename, $outputIssues)
{
$sourceDom = $this->highlightCode($filename);
$xpath = new DOMXPath($sourceDom);
$lines = $xpath->query('//ol/li');
// A shortcut to prevent possible trouble with log(0)
// Note that this is exactly what will happen anyways.
if ($lines->length === 0) {
return $sourceDom->saveHTML();
}
$lineNumber = 0;
$linePlaces = floor(log($lines->length, 10)) + 1;
/** @var $line DOMElement:: */
foreach ($lines as $line) {
++$lineNumber;
$line->setAttribute('id', 'line_' . $lineNumber);
$lineClasses = array(
($lineNumber % 2) ? 'odd' : 'even'
);
if (isset($outputIssues[$lineNumber])) {
$lineClasses[] = 'hasIssues';
$message = '|';
foreach ($outputIssues[$lineNumber] as $issue) {
$message .= sprintf(
'
<div class="tooltip">
<div class="title %s">%s</div>
<div class="text">%s</div>
</div>
',
$issue->foundBy,
$issue->foundBy,
$issue->description
);
}
$line->setAttribute('title', utf8_encode($message));
}
// Add line number
$nuSpan = $sourceDom->createElement('span');
$nuSpan->setAttribute('class', 'lineNumber');
for ($i = 0; $i < $linePlaces - strlen($lineNumber); $i++) {
$nuSpan->appendChild($sourceDom->createEntityReference('nbsp'));
}
$nuSpan->appendChild($sourceDom->createTextNode($lineNumber));
$nuSpan->appendChild($sourceDom->createEntityReference('nbsp'));
$line->insertBefore($nuSpan, $line->firstChild);
//create anchor for the new line
$anchor = $sourceDom->createElement('a');
$anchor->setAttribute('name', 'line_' . $lineNumber);
$line->appendChild($anchor);
// set li css class depending on line errors
switch ($tmp = (isset($outputIssues[$lineNumber])
? count($outputIssues[$lineNumber])
: 0)) {
case 0:
break;
case 1:
$lineClasses[] = $outputIssues[$lineNumber][0]->foundBy;
break;
case 1 < $tmp:
$lineClasses[] = 'moreErrors';
break;
// This can't happen, count always returns >= 0
// @codeCoverageIgnoreStart
default:
break;
// @codeCoverageIgnoreEnd
}
$line->setAttribute('class', implode(' ', $lineClasses));
}
return $sourceDom->saveHTML();
}
/**
* Highlighter method for PHP source code
*
* The source code is highlighted by PHP native method.
* Afterwords a DOMDocument will be generated with each
* line in a separate node.
*
* @param string $sourceCode The PHP source code
*
* @return DOMDocument
*/
protected function highlightPhpCode($sourceCode)
{
$code = highlight_string($sourceCode, true);
if (extension_loaded('mbstring') && !mb_check_encoding($code, 'UTF-8')) {
$detectOrder = mb_detect_order();
$detectOrder[] = 'iso-8859-1';
$encoding = mb_detect_encoding($code, $detectOrder, true);
if ($encoding === false) {
error_log('Error detecting file encoding');
}
$code = mb_convert_encoding(
$code,
'UTF-8',
$encoding
);
}
$sourceDom = new DOMDocument();
$sourceDom->loadHTML('<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>' . $code);
//fetch <code>-><span>->children from php generated html
$sourceElements = $sourceDom->getElementsByTagname('code')->item(0)
->childNodes->item(0)->childNodes;
//create target dom
$targetDom = new DOMDocument();
$targetNode = $targetDom->createElement('ol');
$targetNode->setAttribute('class', 'code');
$targetDom->appendChild($targetNode);
$li = $targetDom->createElement('li');
$targetNode->appendChild($li);
// iterate through all <span> elements
foreach ($sourceElements as $sourceElement) {
if (!$sourceElement instanceof DOMElement) {
$span = $targetDom->createElement('span');
$span->nodeValue = htmlspecialchars($sourceElement->wholeText);
$li->appendChild($span);
continue;
}
if ('br' === $sourceElement->tagName) {
// create new li and new line
$li = $targetDom->createElement('li');
$targetNode->appendChild($li);
continue;
}
$elementClass = $this->mapPhpColors(
$sourceElement->getAttribute('style')
);
foreach ($sourceElement->childNodes as $sourceChildElement) {
if ($sourceChildElement instanceof DOMElement
&& 'br' === $sourceChildElement->tagName) {
// create new li and new line
$li = $targetDom->createElement('li');
$targetNode->appendChild($li);
} else {
// append content to current li element
$span = $targetDom->createElement('span');
$span->nodeValue = htmlspecialchars(
$sourceChildElement->textContent
);
$span->setAttribute('class', $elementClass);
$li->appendChild($span);
}
}
}
return $targetDom;
}
/**
* Return colors defined in ini files.
*
* @param string $style The given style name, e.g. "comment"
*
* @return string
*/
protected function mapPhpColors($style)
{
$color = substr($style, 7);
return $this->phpHighlightColorMap[$color];
}
/**
* Highlighting source code of given file.
*
* Php code is using native php highlighter.
* If PEAR Text_Highlighter is installed all defined files in $highlightMap
* will be highlighted as well.
*
* @param string $file The filename / real path to file
*
* @return DOMDocument Html representation of parsed source code
*/
protected function highlightCode($file)
{
$sourceCode = $this->ioHelper->loadFile($file);
$extension = pathinfo($file, PATHINFO_EXTENSION);
if (in_array($extension, $this->phpSuffixes)) {
return $this->highlightPhpCode($sourceCode);
} else {
$sourceCode = preg_replace(
'/^.*$/m',
'<li>$0</li>',
htmlentities($sourceCode)
);
$sourceCode = preg_replace('/ /', '&nbsp;', $sourceCode);
$sourceCode = '<div class="code"><ol class="code">'
. $sourceCode.'</ol></div>';
$sourceCode = $this->stripInvalidXml($sourceCode);
$doc = new DOMDocument();
$doc->loadHTML($sourceCode);
return $doc;
}
}
/**
* Sorting a list of issues combining issues matching same line number
* for each file.
*
* @param array $issueList List of issues
*
* @return array
*/
private function formatIssues($issueList)
{
$outputIssues = array();
foreach ($issueList as $issue) {
for ($i = $issue->lineStart; $i <= $issue->lineEnd; $i++) {
$outputIssues[$i][] = $issue;
}
}
return $outputIssues;
}
/**
* Removes invalid XML
*
* @access private
* @param string $value
* @return string
*/
private function stripInvalidXml($value)
{
$ret = "";
$current = null;
if (empty($value)) {
return $ret;
}
$length = strlen($value);
for ($i=0; $i < $length; $i++) {
$current = ord($value{$i});
if (($current == 0x9)
|| ($current == 0xA)
|| ($current == 0xD)
|| (($current >= 0x20) && ($current <= 0xD7FF))
|| (($current >= 0xE000) && ($current <= 0xFFFD))
|| (($current >= 0x10000) && ($current <= 0x10FFFF))
) {
$ret .= chr($current);
} else {
$ret .= " ";
}
}
return $ret;
}
}

View File

@@ -0,0 +1,229 @@
html {
height: 100%;
width: 100%;
}
body.codebrowser {
margin: 0;
padding: 0;
border: 0;
width: 100%;
font-family: Arial,Helvetica,sans-serif;
font-size: 12px;
background-color: #fff;
}
.codebrowser .test {
color: blue;
}
.codebrowser a {
color: #2e3436;
padding: 2px;
text-decoration: none;
}
.codebrowser a:hover {
text-decoration: underline;
}
/** start Tooltip Styles **/
.codebrowser .prototip {
width: 300px;
position: absolute;
}
.codebrowser .prototip .effectWrapper {
position: relative;
}
.codebrowser .prototip .tooltip {
position: relative;
}
.codebrowser .prototip .toolbar {
position: relative;
display: block;
}
.codebrowser .prototip .tooltip .title, .tooltip .message {
border: 5px solid #808080;
padding: 5px;
width: 100%;
}
.codebrowser .prototip .tooltip .title {
color: #808080;
font: italic 17px Georgia, serif;
display: block;
border-bottom: none;
}
.codebrowser .tooltip .message {
border-top: none;
color: #fff;
font: 11px Arial, Helvetica, sans-serif;
display: block;
background-color: #808080;
}
/** end Tooltip Styles **/
.codebrowser .header {
padding: 5px 5px 10px 20px;
}
.codebrowser .filepath {
background-color: #fff;
color: #555753;
font-size: 1.5em;
font-weight: bold;
padding: 5px 20px 5px 30px;
background-image: url(./../img/page.gif);
background-repeat: no-repeat;
background-position: 4px center;
margin: 5px;
}
.codebrowser .sourcecode {
padding: 0px;
margin: 0px;
width: 98%;
}
.codebrowser .filelist {
margin: 5px;
}
.codebrowser .filelist td {
background-color: #ffffff;
padding: 5px;
}
.codebrowser .filelist table {
background-color: #fff;
border: none;
}
.codebrowser .filelist a {
background-image: url(./../img/page.gif);
background-position: center left;
background-repeat: no-repeat;
padding-left: 20px;
}
.codebrowser .tree {
margin-top: 10px;
margin-left: 5px;
}
.codebrowser .filelist tr.file {
background-color: #F3F3F0;
}
.codebrowser ol.code li.transparent {
background-color: transparent;
}
.codebrowser ol.code li code {
font: 1.2em courier, monospace;
color: #c30;
white-space: pre;
padding-left: 0.5em;
}
.codebrowser .code .comment {
color: #939399;
}
.codebrowser .code .default {
color: #44c;
}
.codebrowser .code .keyword {
color: #373;
}
.codebrowser .code .string {
color: #c30;
}
.dTreeNode a img {
margin-left: -2px;
}
.codebrowser .dtree {
font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;
font-size: 11px;
font-weight: bold;
color: #555753;
white-space: nowrap;
}
.codebrowser .dtree img {
border: 0px;
vertical-align: middle;
}
.codebrowser .dtree a {
color: #437610;
font-weight: normal;
text-decoration: none;
}
.codebrowser .dtree a.node, .dtree a.nodeSel {
white-space: nowrap;
padding: 1px 2px 1px 2px;
}
.codebrowser .dtree a.node:hover, .dtree a.nodeSel:hover {
color: #ffffff;
background: transparent url(./../img/tab-active.png) repeat-x scroll 0 0 ;
text-decoration: none;
padding: 3px;
}
.codebrowser .dtree a.nodeSel {
background-color: #c0d2ec;
}
.codebrowser .dtree .clip {
overflow: hidden;
}
/** Sidebar Styles **/
.codebrowser #sideBar {
position: fixed;
width: auto;
height: auto;
top: 80px;
right: 0px;
background-image:url(./../img/background.gif);
background-position:top left;
background-repeat:repeat-y;
text-align: left;
}
.codebrowser #sideBarTab {
float: left;
height: 137px;
width: 28px;
background-image:url(./../img/slider.gif);
background-repeat: no-repeat;
}
.codebrowser #sideBarContents {
float: left;
overflow: hidden !important;
width: 600px;
height: 400px;
}
.codebrowser #sideBarContentsInner {
width: 580px;
overflow: auto;
height: 380px;
margin: 10px;
}

View File

@@ -0,0 +1,49 @@
/* List borders */
ol, ul {
border: 1px solid #D3D3D0;
}
li:first-child {
border-top: none;
}
li {
border-top: 1px solid #E7E7E7;
}
/* Table borders */
table {
border-collapse: collapse;
}
tr:first-child {
border-left: none;
border-right: none;
}
tr {
border: 1px solid #E7E7E7;
border-top: none;
}
/* Alternating Colors */
li.even,
tr.even {
background-color: #F9F9F9;
}
#review li.white, /* This is here because the htmlstill uses this tag */
li.odd,
tr.odd {
background-color: #FFFFFF;
}
/* Global Colors */
.errorCount {
color: red;
}
.warningCount {
color: blue;
}

View File

@@ -0,0 +1,208 @@
#review ol {
width: 99%;
margin: 15px;
padding: 0;
font-family: monospace;
font-size: 12px;
line-height: 20px;
color: #939399;
text-align: left;
height: 99%;
list-style: none;
}
#review ol li {
white-space: nowrap;
margin: 0;
padding: 0 0 0 1%;
color: #4E4E4E;
}
#review ol li.moreErrors {
background-color: #FFB380;
}
/* Error type colors */
#cluetip .Coverage,
#sidebar .Coverage,
#review .Coverage {
background-color: #BFE4FF;
}
#cluetip .Duplication,
#sidebar .Duplication,
#review .Duplication {
background-color: #FFBFDC;
}
#cluetip .Checkstyle,
#sidebar .Checkstyle,
#review .Checkstyle {
background-color: #FFF2BF;
}
#cluetip .Padawan,
#sidebar .Padawan,
#review .Padawan {
background-color: #E6FF80;
}
#cluetip .CRAP,
#sidebar .CRAP,
#review .CRAP {
background-color: #FFBFEF;
}
#cluetip .PMD,
#sidebar .PMD,
#review .PMD {
background-color: #FFCC80;
}
#cluetip .ZendCodeAnalyzer,
#sidebar .ZendCodeAnalyzer,
#review .ZendCodeAnalyzer {
background-color: #D5BFFF;
}
#cluetip .EfferentCoupling,
#sidebar .EfferentCoupling,
#review .EfferentCoupling {
background-color: #CCFF99;
}
/**
* tooltips
*/
/* global */
#cluetip{
background-color:#F9F9F9;
filter: alpha(opacity=87);
-moz-opacity:0.87;
opacity:0.87;
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
-moz-box-shadow:0px 0px 5px #000;
-webkit-box-shadow:0px 0px 5px #000;
box-shadow:0px 0px 5px #000;
padding: 10px;
/* IE8 and below */
border: 1px solid black \9;
}
#cluetip-close img {
border: 0;
}
#cluetip-title {
overflow: hidden;
display: none;
height: 0px;
}
#cluetip-title #cluetip-close {
float: right;
position: relative;
}
#cluetip-waitimage {
width: 43px;
height: 11px;
position: absolute;
background-image: url(../js/jquery.cluetip/images/wait.gif);
}
.cluetip-arrows {
display: none;
position: absolute;
top: 0;
left: -11px;
height: 22px;
width: 11px;
background-repeat: no-repeat;
background-position: 0 0;
}
#cluetip-extra {
display: none;
}
#cluetip-inner{
background-color: #F9F9F9;
}
/***************************************
=cluetipClass: 'default'
-------------------------------------- */
.cluetip-default {
background-color: #d9d9c2;
}
.cluetip-default #cluetip-outer {
position: relative;
margin: 0;
background-color: #d9d9c2;
}
.cluetip-default h3#cluetip-title {
display: none;
}
.cluetip-default #cluetip-title a {
color: #d9d9c2;
font-size: 0.95em;
}
.cluetip-default #cluetip-inner {
padding: 0px;
}
.cluetip-default div#cluetip-close {
text-align: right;
margin: 0 5px 5px;
color: #900;
}
.tooltip {
padding-bottom: 3px;
}
.tooltip .title{
font-size: medium;
height: 20px;
line-height: 20px;
vertical-align: middle;
width: 100%;
padding: 3px;
}
.tooltip .text{
padding: 3px;
border-bottom: 1px solid #E7E7E7;
font-size: 12px;
}
/**
* Sidebar
*/
#sidebar {
width: 560px;
height: 360px;
overflow:auto;
}
#sidebar table {
background-color:#E7E7E7;
border-spacing:1px;
color:#666666;
}
#sidebar table td {
vertical-align: top;
}
#sidebar table tr.head td {
background-color: #fff;
height: 25px;
border-bottom: solid 1px #BABDB6;
color:black;
}
#sidebar table tr {
text-align:left;
}
#sidebar table tr.odd {
border-top:1px solid #FFFFFF;
}

View File

@@ -0,0 +1,53 @@
.jstree ol,
.jstree ul,
.jstree li {
border: none;
}
.jstree li.php a .jstree-icon {
background-repeat: repeat;
background-image: url(../img/page.gif);
}
.jstree a {
cursor: pointer;
}
#treeContainer {
float: left;
}
#tree {
float: left;
padding-right: 5px;
display: none;
}
#treeToggle {
display: inline-block;
min-height: 200px;
-moz-opacity:0.87;
opacity:0.87;
-moz-border-radius-bottomright: 10px;
-webkit-border-bottom-right-radius: 10px;
-moz-box-shadow: 1px 1px 3px #000000;
-webkit-box-shadow: 1px 1px 3px #000000;
box-shadow:0px 0px 5px #000;
background-color: #F9F9F9;
background-position: center center;
background-repeat: no-repeat;
padding: 16px;
/* IE8 and below. */
border: 1px solid black \9;
}
#treeHeader {
font-weight: bold;
color: #555753;
white-space: nowrap;
}
#treeHeader .jstree-icon {
background-image: url("../img/base.gif");
background-position: 0 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 239 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 372 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 376 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 622 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 633 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 861 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 870 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 613 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 538 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 822 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 994 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 181 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 294 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 284 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -0,0 +1,109 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="stylesheet" type="text/css" href="js/jquery.sidebar/css/codebrowser/sidebar.css" />
<link rel="stylesheet" type="text/css" href="css/cruisecontrol.css" />
<link rel="stylesheet" type="text/css" href="css/global.css" />
<link rel="stylesheet" type="text/css" href="css/review.css" />
<link rel="stylesheet" type="text/css" href="css/tree.css" />
<script type="text/javascript" src="js/jquery-1.4.2.min.js"></script>
<script type="text/javascript" src="js/jquery.jstree/jquery.jstree.min.js"></script>
<script type="text/javascript" src="js/jquery.sidebar/jquery-ui-1.7.2.custom.min.js"></script>
<script type="text/javascript" src="js/jquery.sidebar/jquery.sidebar.js"></script>
<script type="text/javascript" src="js/jquery.cluetip/lib/jquery.hoverIntent.js"></script>
<script type="text/javascript" src="js/jquery.cluetip/lib/jquery.bgiframe.min.js"></script>
<script type="text/javascript" src="js/jquery.cluetip/jquery.cluetip.min.js"></script>
<script type="text/javascript" src="js/jquery.history.js"></script>
<script type="text/javascript" src="js/review.js"></script>
<script type="text/javascript" src="js/tree.js"></script>
<title>PHP CodeBrowser</title>
</head>
<body class="codebrowser">
<div id="treeContainer">
<div id="tree">
<div id="treeHeader">
<a href="index.html" class='fileLink'>CodeBrowser</a>
</div>
<?php echo $treeList; ?>
</div>
<div id="treeToggle" style="background-image: url('img/treeToggle-extended.png');"></div>
</div>
<div id="contentBox" style="display: inline-block; margin: 15px;">
<div id="fileList">
<table border="0" cellspacing="2" cellpadding="3">
<?php
$oddrow = true;
$preLen = strlen(PHPCodeBrowser\Helper\IOHelper::getCommonPathPrefix(array_keys($fileList)));
// Find out which types of errors have been found
$occuringErrorTypes = array (
'CPD' => false,
'CRAP' => false,
'Checkstyle' => false,
'Coverage' => false,
'PMD' => false,
'Padawan' => false
);
foreach ($fileList as $file) {
/** @var $file PHPCodeBrowser\File */
foreach ($file->getIssues() as $issue) {
$occuringErrorTypes[$issue->foundBy] = true;
}
}
$occuringErrorTypes = array_keys(array_filter($occuringErrorTypes));
// Print the tables head
echo ' <tr class="head">';
echo ' <th><strong>File</strong></th>' . PHP_EOL;
echo ' <th width="50px" align="center"><strong>Errors'
. '</strong></th>' . PHP_EOL;
echo ' <th width="50px" align="center"><strong>Warnings'
. '</strong></th>' . PHP_EOL;
foreach ($occuringErrorTypes as $errorType) {
echo " <th width='70px' align='center'><strong>"
. "$errorType</strong></th>" . PHP_EOL;
}
echo ' </tr>' . PHP_EOL;
// Print the file table
/** @var $f PHPCodeBrowser\File */
foreach ($fileList as $filename => $f) {
$tag = $oddrow ? 'odd' : 'even';
$oddrow = !$oddrow;
$shortName = substr($filename, $preLen);
$shortName = str_replace('\\', '/', $shortName);
$errors = $f->getErrorCount();
$warnings = $f->getWarningCount();
$counts = array_fill_keys($occuringErrorTypes, 0);
foreach ($f->getIssues() as $issue) {
$counts[$issue->foundBy] += 1;
}
echo " <tr class='$tag'>" . PHP_EOL;
echo " <td><a class='fileLink' "
. "href='./$shortName.html'>$shortName</a></td>" . PHP_EOL;
echo " <td align='center'><span class='errorCount'>"
. "$errors</span></td>" . PHP_EOL;
echo " <td align='center'>"
. "<span class='warningCount'>$warnings</span></td>" . PHP_EOL;
foreach ($counts as $count) {
echo " <td align='center'>$count</td>" . PHP_EOL;
}
echo " </tr>" . PHP_EOL;
}
?>
</table>
</div>
</div>
</body>
</html>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,154 @@
/*!
* jQuery JavaScript Library v1.4.2
* http://jquery.com/
*
* Copyright 2010, John Resig
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* Includes Sizzle.js
* http://sizzlejs.com/
* Copyright 2010, The Dojo Foundation
* Released under the MIT, BSD, and GPL Licenses.
*
* Date: Sat Feb 13 22:33:48 2010 -0500
*/
(function(A,w){function ma(){if(!c.isReady){try{s.documentElement.doScroll("left")}catch(a){setTimeout(ma,1);return}c.ready()}}function Qa(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function X(a,b,d,f,e,j){var i=a.length;if(typeof b==="object"){for(var o in b)X(a,o,b[o],f,e,d);return a}if(d!==w){f=!j&&f&&c.isFunction(d);for(o=0;o<i;o++)e(a[o],b,f?d.call(a[o],o,e(a[o],b)):d,j);return a}return i?
e(a[0],b):w}function J(){return(new Date).getTime()}function Y(){return false}function Z(){return true}function na(a,b,d){d[0].type=a;return c.event.handle.apply(b,d)}function oa(a){var b,d=[],f=[],e=arguments,j,i,o,k,n,r;i=c.data(this,"events");if(!(a.liveFired===this||!i||!i.live||a.button&&a.type==="click")){a.liveFired=this;var u=i.live.slice(0);for(k=0;k<u.length;k++){i=u[k];i.origType.replace(O,"")===a.type?f.push(i.selector):u.splice(k--,1)}j=c(a.target).closest(f,a.currentTarget);n=0;for(r=
j.length;n<r;n++)for(k=0;k<u.length;k++){i=u[k];if(j[n].selector===i.selector){o=j[n].elem;f=null;if(i.preType==="mouseenter"||i.preType==="mouseleave")f=c(a.relatedTarget).closest(i.selector)[0];if(!f||f!==o)d.push({elem:o,handleObj:i})}}n=0;for(r=d.length;n<r;n++){j=d[n];a.currentTarget=j.elem;a.data=j.handleObj.data;a.handleObj=j.handleObj;if(j.handleObj.origHandler.apply(j.elem,e)===false){b=false;break}}return b}}function pa(a,b){return"live."+(a&&a!=="*"?a+".":"")+b.replace(/\./g,"`").replace(/ /g,
"&")}function qa(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function ra(a,b){var d=0;b.each(function(){if(this.nodeName===(a[d]&&a[d].nodeName)){var f=c.data(a[d++]),e=c.data(this,f);if(f=f&&f.events){delete e.handle;e.events={};for(var j in f)for(var i in f[j])c.event.add(this,j,f[j][i],f[j][i].data)}}})}function sa(a,b,d){var f,e,j;b=b&&b[0]?b[0].ownerDocument||b[0]:s;if(a.length===1&&typeof a[0]==="string"&&a[0].length<512&&b===s&&!ta.test(a[0])&&(c.support.checkClone||!ua.test(a[0]))){e=
true;if(j=c.fragments[a[0]])if(j!==1)f=j}if(!f){f=b.createDocumentFragment();c.clean(a,b,f,d)}if(e)c.fragments[a[0]]=j?f:1;return{fragment:f,cacheable:e}}function K(a,b){var d={};c.each(va.concat.apply([],va.slice(0,b)),function(){d[this]=a});return d}function wa(a){return"scrollTo"in a&&a.document?a:a.nodeType===9?a.defaultView||a.parentWindow:false}var c=function(a,b){return new c.fn.init(a,b)},Ra=A.jQuery,Sa=A.$,s=A.document,T,Ta=/^[^<]*(<[\w\W]+>)[^>]*$|^#([\w-]+)$/,Ua=/^.[^:#\[\.,]*$/,Va=/\S/,
Wa=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Xa=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,P=navigator.userAgent,xa=false,Q=[],L,$=Object.prototype.toString,aa=Object.prototype.hasOwnProperty,ba=Array.prototype.push,R=Array.prototype.slice,ya=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(a==="body"&&!b){this.context=s;this[0]=s.body;this.selector="body";this.length=1;return this}if(typeof a==="string")if((d=Ta.exec(a))&&
(d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:s;if(a=Xa.exec(a))if(c.isPlainObject(b)){a=[s.createElement(a[1])];c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=sa([d[1]],[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}return c.merge(this,a)}else{if(b=s.getElementById(d[2])){if(b.id!==d[2])return T.find(a);this.length=1;this[0]=b}this.context=s;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=s;a=s.getElementsByTagName(a);return c.merge(this,
a)}else return!b||b.jquery?(b||T).find(a):c(b).find(a);else if(c.isFunction(a))return T.ready(a);if(a.selector!==w){this.selector=a.selector;this.context=a.context}return c.makeArray(a,this)},selector:"",jquery:"1.4.2",length:0,size:function(){return this.length},toArray:function(){return R.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){var f=c();c.isArray(a)?ba.apply(f,a):c.merge(f,a);f.prevObject=this;f.context=this.context;if(b===
"find")f.selector=this.selector+(this.selector?" ":"")+d;else if(b)f.selector=this.selector+"."+b+"("+d+")";return f},each:function(a,b){return c.each(this,a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(s,c);else Q&&Q.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(R.apply(this,arguments),"slice",R.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this,
function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject||c(null)},push:ba,sort:[].sort,splice:[].splice};c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,j,i,o;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b<d;b++)if((e=arguments[b])!=null)for(j in e){i=a[j];o=e[j];if(a!==o)if(f&&o&&(c.isPlainObject(o)||c.isArray(o))){i=i&&(c.isPlainObject(i)||
c.isArray(i))?i:c.isArray(o)?[]:{};a[j]=c.extend(f,i,o)}else if(o!==w)a[j]=o}return a};c.extend({noConflict:function(a){A.$=Sa;if(a)A.jQuery=Ra;return c},isReady:false,ready:function(){if(!c.isReady){if(!s.body)return setTimeout(c.ready,13);c.isReady=true;if(Q){for(var a,b=0;a=Q[b++];)a.call(s,c);Q=null}c.fn.triggerHandler&&c(s).triggerHandler("ready")}},bindReady:function(){if(!xa){xa=true;if(s.readyState==="complete")return c.ready();if(s.addEventListener){s.addEventListener("DOMContentLoaded",
L,false);A.addEventListener("load",c.ready,false)}else if(s.attachEvent){s.attachEvent("onreadystatechange",L);A.attachEvent("onload",c.ready);var a=false;try{a=A.frameElement==null}catch(b){}s.documentElement.doScroll&&a&&ma()}}},isFunction:function(a){return $.call(a)==="[object Function]"},isArray:function(a){return $.call(a)==="[object Array]"},isPlainObject:function(a){if(!a||$.call(a)!=="[object Object]"||a.nodeType||a.setInterval)return false;if(a.constructor&&!aa.call(a,"constructor")&&!aa.call(a.constructor.prototype,
"isPrototypeOf"))return false;var b;for(b in a);return b===w||aa.call(a,b)},isEmptyObject:function(a){for(var b in a)return false;return true},error:function(a){throw a;},parseJSON:function(a){if(typeof a!=="string"||!a)return null;a=c.trim(a);if(/^[\],:{}\s]*$/.test(a.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,"")))return A.JSON&&A.JSON.parse?A.JSON.parse(a):(new Function("return "+
a))();else c.error("Invalid JSON: "+a)},noop:function(){},globalEval:function(a){if(a&&Va.test(a)){var b=s.getElementsByTagName("head")[0]||s.documentElement,d=s.createElement("script");d.type="text/javascript";if(c.support.scriptEval)d.appendChild(s.createTextNode(a));else d.text=a;b.insertBefore(d,b.firstChild);b.removeChild(d)}},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,b,d){var f,e=0,j=a.length,i=j===w||c.isFunction(a);if(d)if(i)for(f in a){if(b.apply(a[f],
d)===false)break}else for(;e<j;){if(b.apply(a[e++],d)===false)break}else if(i)for(f in a){if(b.call(a[f],f,a[f])===false)break}else for(d=a[0];e<j&&b.call(d,e,d)!==false;d=a[++e]);return a},trim:function(a){return(a||"").replace(Wa,"")},makeArray:function(a,b){b=b||[];if(a!=null)a.length==null||typeof a==="string"||c.isFunction(a)||typeof a!=="function"&&a.setInterval?ba.call(b,a):c.merge(b,a);return b},inArray:function(a,b){if(b.indexOf)return b.indexOf(a);for(var d=0,f=b.length;d<f;d++)if(b[d]===
a)return d;return-1},merge:function(a,b){var d=a.length,f=0;if(typeof b.length==="number")for(var e=b.length;f<e;f++)a[d++]=b[f];else for(;b[f]!==w;)a[d++]=b[f++];a.length=d;return a},grep:function(a,b,d){for(var f=[],e=0,j=a.length;e<j;e++)!d!==!b(a[e],e)&&f.push(a[e]);return f},map:function(a,b,d){for(var f=[],e,j=0,i=a.length;j<i;j++){e=b(a[j],j,d);if(e!=null)f[f.length]=e}return f.concat.apply([],f)},guid:1,proxy:function(a,b,d){if(arguments.length===2)if(typeof b==="string"){d=a;a=d[b];b=w}else if(b&&
!c.isFunction(b)){d=b;b=w}if(!b&&a)b=function(){return a.apply(d||this,arguments)};if(a)b.guid=a.guid=a.guid||b.guid||c.guid++;return b},uaMatch:function(a){a=a.toLowerCase();a=/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version)?[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||!/compatible/.test(a)&&/(mozilla)(?:.*? rv:([\w.]+))?/.exec(a)||[];return{browser:a[1]||"",version:a[2]||"0"}},browser:{}});P=c.uaMatch(P);if(P.browser){c.browser[P.browser]=true;c.browser.version=P.version}if(c.browser.webkit)c.browser.safari=
true;if(ya)c.inArray=function(a,b){return ya.call(b,a)};T=c(s);if(s.addEventListener)L=function(){s.removeEventListener("DOMContentLoaded",L,false);c.ready()};else if(s.attachEvent)L=function(){if(s.readyState==="complete"){s.detachEvent("onreadystatechange",L);c.ready()}};(function(){c.support={};var a=s.documentElement,b=s.createElement("script"),d=s.createElement("div"),f="script"+J();d.style.display="none";d.innerHTML=" <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";
var e=d.getElementsByTagName("*"),j=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!j)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(j.getAttribute("style")),hrefNormalized:j.getAttribute("href")==="/a",opacity:/^0.55$/.test(j.style.opacity),cssFloat:!!j.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:s.createElement("select").appendChild(s.createElement("option")).selected,
parentNode:d.removeChild(d.appendChild(s.createElement("div"))).parentNode===null,deleteExpando:true,checkClone:false,scriptEval:false,noCloneEvent:true,boxModel:null};b.type="text/javascript";try{b.appendChild(s.createTextNode("window."+f+"=1;"))}catch(i){}a.insertBefore(b,a.firstChild);if(A[f]){c.support.scriptEval=true;delete A[f]}try{delete b.test}catch(o){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function k(){c.support.noCloneEvent=
false;d.detachEvent("onclick",k)});d.cloneNode(true).fireEvent("onclick")}d=s.createElement("div");d.innerHTML="<input type='radio' name='radiotest' checked='checked'/>";a=s.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var k=s.createElement("div");k.style.width=k.style.paddingLeft="1px";s.body.appendChild(k);c.boxModel=c.support.boxModel=k.offsetWidth===2;s.body.removeChild(k).style.display="none"});a=function(k){var n=
s.createElement("div");k="on"+k;var r=k in n;if(!r){n.setAttribute(k,"return;");r=typeof n[k]==="function"}return r};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=j=null}})();c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var G="jQuery"+J(),Ya=0,za={};c.extend({cache:{},expando:G,noData:{embed:true,object:true,
applet:true},data:function(a,b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var f=a[G],e=c.cache;if(!f&&typeof b==="string"&&d===w)return null;f||(f=++Ya);if(typeof b==="object"){a[G]=f;e[f]=c.extend(true,{},b)}else if(!e[f]){a[G]=f;e[f]={}}a=e[f];if(d!==w)a[b]=d;return typeof b==="string"?a[b]:a}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var d=a[G],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{if(c.support.deleteExpando)delete a[c.expando];
else a.removeAttribute&&a.removeAttribute(c.expando);delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this,a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===w){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===w&&this.length)f=c.data(this[0],a);return f===w&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this,
a,b)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d);return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b===
w)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var Aa=/[\n\t]/g,ca=/\s+/,Za=/\r/g,$a=/href|src|style/,ab=/(button|input)/i,bb=/(button|input|object|select|textarea)/i,
cb=/^(a|area)$/i,Ba=/radio|checkbox/;c.fn.extend({attr:function(a,b){return X(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(n){var r=c(this);r.addClass(a.call(this,n,r.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ca),d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1)if(e.className){for(var j=" "+e.className+" ",
i=e.className,o=0,k=b.length;o<k;o++)if(j.indexOf(" "+b[o]+" ")<0)i+=" "+b[o];e.className=c.trim(i)}else e.className=a}return this},removeClass:function(a){if(c.isFunction(a))return this.each(function(k){var n=c(this);n.removeClass(a.call(this,k,n.attr("class")))});if(a&&typeof a==="string"||a===w)for(var b=(a||"").split(ca),d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1&&e.className)if(a){for(var j=(" "+e.className+" ").replace(Aa," "),i=0,o=b.length;i<o;i++)j=j.replace(" "+b[i]+" ",
" ");e.className=c.trim(j)}else e.className=""}return this},toggleClass:function(a,b){var d=typeof a,f=typeof b==="boolean";if(c.isFunction(a))return this.each(function(e){var j=c(this);j.toggleClass(a.call(this,e,j.attr("class"),b),b)});return this.each(function(){if(d==="string")for(var e,j=0,i=c(this),o=b,k=a.split(ca);e=k[j++];){o=f?o:!i.hasClass(e);i[o?"addClass":"removeClass"](e)}else if(d==="undefined"||d==="boolean"){this.className&&c.data(this,"__className__",this.className);this.className=
this.className||a===false?"":c.data(this,"__className__")||""}})},hasClass:function(a){a=" "+a+" ";for(var b=0,d=this.length;b<d;b++)if((" "+this[b].className+" ").replace(Aa," ").indexOf(a)>-1)return true;return false},val:function(a){if(a===w){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value||{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var j=b?d:0;for(d=b?d+1:e.length;j<d;j++){var i=
e[j];if(i.selected){a=c(i).val();if(b)return a;f.push(a)}}return f}if(Ba.test(b.type)&&!c.support.checkOn)return b.getAttribute("value")===null?"on":b.value;return(b.value||"").replace(Za,"")}return w}var o=c.isFunction(a);return this.each(function(k){var n=c(this),r=a;if(this.nodeType===1){if(o)r=a.call(this,k,n.val());if(typeof r==="number")r+="";if(c.isArray(r)&&Ba.test(this.type))this.checked=c.inArray(n.val(),r)>=0;else if(c.nodeName(this,"select")){var u=c.makeArray(r);c("option",this).each(function(){this.selected=
c.inArray(c(this).val(),u)>=0});if(!u.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return w;if(f&&b in c.attrFn)return c(a)[b](d);f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==w;b=f&&c.props[b]||b;if(a.nodeType===1){var j=$a.test(b);if(b in a&&f&&!j){if(e){b==="type"&&ab.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed");
a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:bb.test(a.nodeName)||cb.test(a.nodeName)&&a.href?0:w;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText=""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&j?a.getAttribute(b,2):a.getAttribute(b);return a===null?w:a}return c.style(a,b,d)}});var O=/\.(.*)$/,db=function(a){return a.replace(/[^\w\s\.\|`]/g,
function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){if(a.setInterval&&a!==A&&!a.frameElement)a=A;var e,j;if(d.handler){e=d;d=e.handler}if(!d.guid)d.guid=c.guid++;if(j=c.data(a)){var i=j.events=j.events||{},o=j.handle;if(!o)j.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem,arguments):w};o.elem=a;b=b.split(" ");for(var k,n=0,r;k=b[n++];){j=e?c.extend({},e):{handler:d,data:f};if(k.indexOf(".")>-1){r=k.split(".");
k=r.shift();j.namespace=r.slice(0).sort().join(".")}else{r=[];j.namespace=""}j.type=k;j.guid=d.guid;var u=i[k],z=c.event.special[k]||{};if(!u){u=i[k]=[];if(!z.setup||z.setup.call(a,f,r,o)===false)if(a.addEventListener)a.addEventListener(k,o,false);else a.attachEvent&&a.attachEvent("on"+k,o)}if(z.add){z.add.call(a,j);if(!j.handler.guid)j.handler.guid=d.guid}u.push(j);c.event.global[k]=true}a=null}}},global:{},remove:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){var e,j=0,i,o,k,n,r,u,z=c.data(a),
C=z&&z.events;if(z&&C){if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(e in C)c.event.remove(a,e+b)}else{for(b=b.split(" ");e=b[j++];){n=e;i=e.indexOf(".")<0;o=[];if(!i){o=e.split(".");e=o.shift();k=new RegExp("(^|\\.)"+c.map(o.slice(0).sort(),db).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(r=C[e])if(d){n=c.event.special[e]||{};for(B=f||0;B<r.length;B++){u=r[B];if(d.guid===u.guid){if(i||k.test(u.namespace)){f==null&&r.splice(B--,1);n.remove&&n.remove.call(a,u)}if(f!=
null)break}}if(r.length===0||f!=null&&r.length===1){if(!n.teardown||n.teardown.call(a,o)===false)Ca(a,e,z.handle);delete C[e]}}else for(var B=0;B<r.length;B++){u=r[B];if(i||k.test(u.namespace)){c.event.remove(a,n,u.handler,B);r.splice(B--,1)}}}if(c.isEmptyObject(C)){if(b=z.handle)b.elem=null;delete z.events;delete z.handle;c.isEmptyObject(z)&&c.removeData(a)}}}}},trigger:function(a,b,d,f){var e=a.type||a;if(!f){a=typeof a==="object"?a[G]?a:c.extend(c.Event(e),a):c.Event(e);if(e.indexOf("!")>=0){a.type=
e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===8)return w;a.result=w;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(f=c.data(d,"handle"))&&f.apply(d,b);f=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+e]&&d["on"+e].apply(d,b)===false)a.result=false}catch(j){}if(!a.isPropagationStopped()&&
f)c.event.trigger(a,b,f,true);else if(!a.isDefaultPrevented()){f=a.target;var i,o=c.nodeName(f,"a")&&e==="click",k=c.event.special[e]||{};if((!k._default||k._default.call(d,a)===false)&&!o&&!(f&&f.nodeName&&c.noData[f.nodeName.toLowerCase()])){try{if(f[e]){if(i=f["on"+e])f["on"+e]=null;c.event.triggered=true;f[e]()}}catch(n){}if(i)f["on"+e]=i;c.event.triggered=false}}},handle:function(a){var b,d,f,e;a=arguments[0]=c.event.fix(a||A.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive;
if(!b){d=a.type.split(".");a.type=d.shift();f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)")}e=c.data(this,"events");d=e[a.type];if(e&&d){d=d.slice(0);e=0;for(var j=d.length;e<j;e++){var i=d[e];if(b||f.test(i.namespace)){a.handler=i.handler;a.data=i.data;a.handleObj=i;i=i.handler.apply(this,arguments);if(i!==w){a.result=i;if(i===false){a.preventDefault();a.stopPropagation()}}if(a.isImmediatePropagationStopped())break}}}return a.result},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
fix:function(a){if(a[G])return a;var b=a;a=c.Event(b);for(var d=this.props.length,f;d;){f=this.props[--d];a[f]=b[f]}if(!a.target)a.target=a.srcElement||s;if(a.target.nodeType===3)a.target=a.target.parentNode;if(!a.relatedTarget&&a.fromElement)a.relatedTarget=a.fromElement===a.target?a.toElement:a.fromElement;if(a.pageX==null&&a.clientX!=null){b=s.documentElement;d=s.body;a.pageX=a.clientX+(b&&b.scrollLeft||d&&d.scrollLeft||0)-(b&&b.clientLeft||d&&d.clientLeft||0);a.pageY=a.clientY+(b&&b.scrollTop||
d&&d.scrollTop||0)-(b&&b.clientTop||d&&d.clientTop||0)}if(!a.which&&(a.charCode||a.charCode===0?a.charCode:a.keyCode))a.which=a.charCode||a.keyCode;if(!a.metaKey&&a.ctrlKey)a.metaKey=a.ctrlKey;if(!a.which&&a.button!==w)a.which=a.button&1?1:a.button&2?3:a.button&4?2:0;return a},guid:1E8,proxy:c.proxy,special:{ready:{setup:c.bindReady,teardown:c.noop},live:{add:function(a){c.event.add(this,a.origType,c.extend({},a,{handler:oa}))},remove:function(a){var b=true,d=a.origType.replace(O,"");c.each(c.data(this,
"events").live||[],function(){if(d===this.origType.replace(O,""))return b=false});b&&c.event.remove(this,a.origType,oa)}},beforeunload:{setup:function(a,b,d){if(this.setInterval)this.onbeforeunload=d;return false},teardown:function(a,b){if(this.onbeforeunload===b)this.onbeforeunload=null}}}};var Ca=s.removeEventListener?function(a,b,d){a.removeEventListener(b,d,false)}:function(a,b,d){a.detachEvent("on"+b,d)};c.Event=function(a){if(!this.preventDefault)return new c.Event(a);if(a&&a.type){this.originalEvent=
a;this.type=a.type}else this.type=a;this.timeStamp=J();this[G]=true};c.Event.prototype={preventDefault:function(){this.isDefaultPrevented=Z;var a=this.originalEvent;if(a){a.preventDefault&&a.preventDefault();a.returnValue=false}},stopPropagation:function(){this.isPropagationStopped=Z;var a=this.originalEvent;if(a){a.stopPropagation&&a.stopPropagation();a.cancelBubble=true}},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=Z;this.stopPropagation()},isDefaultPrevented:Y,isPropagationStopped:Y,
isImmediatePropagationStopped:Y};var Da=function(a){var b=a.relatedTarget;try{for(;b&&b!==this;)b=b.parentNode;if(b!==this){a.type=a.data;c.event.handle.apply(this,arguments)}}catch(d){}},Ea=function(a){a.type=a.data;c.event.handle.apply(this,arguments)};c.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){c.event.special[a]={setup:function(d){c.event.add(this,b,d&&d.selector?Ea:Da,a)},teardown:function(d){c.event.remove(this,b,d&&d.selector?Ea:Da)}}});if(!c.support.submitBubbles)c.event.special.submit=
{setup:function(){if(this.nodeName.toLowerCase()!=="form"){c.event.add(this,"click.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="submit"||d==="image")&&c(b).closest("form").length)return na("submit",this,arguments)});c.event.add(this,"keypress.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="text"||d==="password")&&c(b).closest("form").length&&a.keyCode===13)return na("submit",this,arguments)})}else return false},teardown:function(){c.event.remove(this,".specialSubmit")}};
if(!c.support.changeBubbles){var da=/textarea|input|select/i,ea,Fa=function(a){var b=a.type,d=a.value;if(b==="radio"||b==="checkbox")d=a.checked;else if(b==="select-multiple")d=a.selectedIndex>-1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},fa=function(a,b){var d=a.target,f,e;if(!(!da.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Fa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data",
e);if(!(f===w||e===f))if(f!=null||e){a.type="change";return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:fa,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return fa.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return fa.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a,
"_change_data",Fa(a))}},setup:function(){if(this.type==="file")return false;for(var a in ea)c.event.add(this,a+".specialChange",ea[a]);return da.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return da.test(this.nodeName)}};ea=c.event.special.change.filters}s.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this,f)}c.event.special[b]={setup:function(){this.addEventListener(a,
d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,f,e){if(typeof d==="object"){for(var j in d)this[b](j,f,d[j],e);return this}if(c.isFunction(f)){e=f;f=w}var i=b==="one"?c.proxy(e,function(k){c(this).unbind(k,i);return e.apply(this,arguments)}):e;if(d==="unload"&&b!=="one")this.one(d,f,e);else{j=0;for(var o=this.length;j<o;j++)c.event.add(this[j],d,i,f)}return this}});c.fn.extend({unbind:function(a,b){if(typeof a==="object"&&
!a.preventDefault)for(var d in a)this.unbind(d,a[d]);else{d=0;for(var f=this.length;d<f;d++)c.event.remove(this[d],a,b)}return this},delegate:function(a,b,d,f){return this.live(b,d,f,a)},undelegate:function(a,b,d){return arguments.length===0?this.unbind("live"):this.die(b,null,d,a)},trigger:function(a,b){return this.each(function(){c.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0]){a=c.Event(a);a.preventDefault();a.stopPropagation();c.event.trigger(a,b,this[0]);return a.result}},
toggle:function(a){for(var b=arguments,d=1;d<b.length;)c.proxy(a,b[d++]);return this.click(c.proxy(a,function(f){var e=(c.data(this,"lastToggle"+a.guid)||0)%d;c.data(this,"lastToggle"+a.guid,e+1);f.preventDefault();return b[e].apply(this,arguments)||false}))},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}});var Ga={focus:"focusin",blur:"focusout",mouseenter:"mouseover",mouseleave:"mouseout"};c.each(["live","die"],function(a,b){c.fn[b]=function(d,f,e,j){var i,o=0,k,n,r=j||this.selector,
u=j?this:c(this.context);if(c.isFunction(f)){e=f;f=w}for(d=(d||"").split(" ");(i=d[o++])!=null;){j=O.exec(i);k="";if(j){k=j[0];i=i.replace(O,"")}if(i==="hover")d.push("mouseenter"+k,"mouseleave"+k);else{n=i;if(i==="focus"||i==="blur"){d.push(Ga[i]+k);i+=k}else i=(Ga[i]||i)+k;b==="live"?u.each(function(){c.event.add(this,pa(i,r),{data:f,selector:r,handler:e,origType:i,origHandler:e,preType:n})}):u.unbind(pa(i,r),e)}}return this}});c.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error".split(" "),
function(a,b){c.fn[b]=function(d){return d?this.bind(b,d):this.trigger(b)};if(c.attrFn)c.attrFn[b]=true});A.attachEvent&&!A.addEventListener&&A.attachEvent("onunload",function(){for(var a in c.cache)if(c.cache[a].handle)try{c.event.remove(c.cache[a].handle.elem)}catch(b){}});(function(){function a(g){for(var h="",l,m=0;g[m];m++){l=g[m];if(l.nodeType===3||l.nodeType===4)h+=l.nodeValue;else if(l.nodeType!==8)h+=a(l.childNodes)}return h}function b(g,h,l,m,q,p){q=0;for(var v=m.length;q<v;q++){var t=m[q];
if(t){t=t[g];for(var y=false;t;){if(t.sizcache===l){y=m[t.sizset];break}if(t.nodeType===1&&!p){t.sizcache=l;t.sizset=q}if(t.nodeName.toLowerCase()===h){y=t;break}t=t[g]}m[q]=y}}}function d(g,h,l,m,q,p){q=0;for(var v=m.length;q<v;q++){var t=m[q];if(t){t=t[g];for(var y=false;t;){if(t.sizcache===l){y=m[t.sizset];break}if(t.nodeType===1){if(!p){t.sizcache=l;t.sizset=q}if(typeof h!=="string"){if(t===h){y=true;break}}else if(k.filter(h,[t]).length>0){y=t;break}}t=t[g]}m[q]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
e=0,j=Object.prototype.toString,i=false,o=true;[0,0].sort(function(){o=false;return 0});var k=function(g,h,l,m){l=l||[];var q=h=h||s;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g||typeof g!=="string")return l;for(var p=[],v,t,y,S,H=true,M=x(h),I=g;(f.exec(""),v=f.exec(I))!==null;){I=v[3];p.push(v[1]);if(v[2]){S=v[3];break}}if(p.length>1&&r.exec(g))if(p.length===2&&n.relative[p[0]])t=ga(p[0]+p[1],h);else for(t=n.relative[p[0]]?[h]:k(p.shift(),h);p.length;){g=p.shift();if(n.relative[g])g+=p.shift();
t=ga(g,t)}else{if(!m&&p.length>1&&h.nodeType===9&&!M&&n.match.ID.test(p[0])&&!n.match.ID.test(p[p.length-1])){v=k.find(p.shift(),h,M);h=v.expr?k.filter(v.expr,v.set)[0]:v.set[0]}if(h){v=m?{expr:p.pop(),set:z(m)}:k.find(p.pop(),p.length===1&&(p[0]==="~"||p[0]==="+")&&h.parentNode?h.parentNode:h,M);t=v.expr?k.filter(v.expr,v.set):v.set;if(p.length>0)y=z(t);else H=false;for(;p.length;){var D=p.pop();v=D;if(n.relative[D])v=p.pop();else D="";if(v==null)v=h;n.relative[D](y,v,M)}}else y=[]}y||(y=t);y||k.error(D||
g);if(j.call(y)==="[object Array]")if(H)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&E(h,y[g])))l.push(t[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&l.push(t[g]);else l.push.apply(l,y);else z(y,l);if(S){k(S,q,l,m);k.uniqueSort(l)}return l};k.uniqueSort=function(g){if(B){i=o;g.sort(B);if(i)for(var h=1;h<g.length;h++)g[h]===g[h-1]&&g.splice(h--,1)}return g};k.matches=function(g,h){return k(g,null,null,h)};k.find=function(g,h,l){var m,q;if(!g)return[];
for(var p=0,v=n.order.length;p<v;p++){var t=n.order[p];if(q=n.leftMatch[t].exec(g)){var y=q[1];q.splice(1,1);if(y.substr(y.length-1)!=="\\"){q[1]=(q[1]||"").replace(/\\/g,"");m=n.find[t](q,h,l);if(m!=null){g=g.replace(n.match[t],"");break}}}}m||(m=h.getElementsByTagName("*"));return{set:m,expr:g}};k.filter=function(g,h,l,m){for(var q=g,p=[],v=h,t,y,S=h&&h[0]&&x(h[0]);g&&h.length;){for(var H in n.filter)if((t=n.leftMatch[H].exec(g))!=null&&t[2]){var M=n.filter[H],I,D;D=t[1];y=false;t.splice(1,1);if(D.substr(D.length-
1)!=="\\"){if(v===p)p=[];if(n.preFilter[H])if(t=n.preFilter[H](t,v,l,p,m,S)){if(t===true)continue}else y=I=true;if(t)for(var U=0;(D=v[U])!=null;U++)if(D){I=M(D,t,U,v);var Ha=m^!!I;if(l&&I!=null)if(Ha)y=true;else v[U]=false;else if(Ha){p.push(D);y=true}}if(I!==w){l||(v=p);g=g.replace(n.match[H],"");if(!y)return[];break}}}if(g===q)if(y==null)k.error(g);else break;q=g}return v};k.error=function(g){throw"Syntax error, unrecognized expression: "+g;};var n=k.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
CLASS:/\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(g){return g.getAttribute("href")}},
relative:{"+":function(g,h){var l=typeof h==="string",m=l&&!/\W/.test(h);l=l&&!m;if(m)h=h.toLowerCase();m=0;for(var q=g.length,p;m<q;m++)if(p=g[m]){for(;(p=p.previousSibling)&&p.nodeType!==1;);g[m]=l||p&&p.nodeName.toLowerCase()===h?p||false:p===h}l&&k.filter(h,g,true)},">":function(g,h){var l=typeof h==="string";if(l&&!/\W/.test(h)){h=h.toLowerCase();for(var m=0,q=g.length;m<q;m++){var p=g[m];if(p){l=p.parentNode;g[m]=l.nodeName.toLowerCase()===h?l:false}}}else{m=0;for(q=g.length;m<q;m++)if(p=g[m])g[m]=
l?p.parentNode:p.parentNode===h;l&&k.filter(h,g,true)}},"":function(g,h,l){var m=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p=h=h.toLowerCase();q=b}q("parentNode",h,m,g,p,l)},"~":function(g,h,l){var m=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p=h=h.toLowerCase();q=b}q("previousSibling",h,m,g,p,l)}},find:{ID:function(g,h,l){if(typeof h.getElementById!=="undefined"&&!l)return(g=h.getElementById(g[1]))?[g]:[]},NAME:function(g,h){if(typeof h.getElementsByName!=="undefined"){var l=[];
h=h.getElementsByName(g[1]);for(var m=0,q=h.length;m<q;m++)h[m].getAttribute("name")===g[1]&&l.push(h[m]);return l.length===0?null:l}},TAG:function(g,h){return h.getElementsByTagName(g[1])}},preFilter:{CLASS:function(g,h,l,m,q,p){g=" "+g[1].replace(/\\/g,"")+" ";if(p)return g;p=0;for(var v;(v=h[p])!=null;p++)if(v)if(q^(v.className&&(" "+v.className+" ").replace(/[\t\n]/g," ").indexOf(g)>=0))l||m.push(v);else if(l)h[p]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()},
CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,l,m,q,p){h=g[1].replace(/\\/g,"");if(!p&&n.attrMap[h])g[1]=n.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,l,m,q){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,h);else{g=k.filter(g[3],h,l,true^q);l||m.push.apply(m,
g);return false}else if(n.match.POS.test(g[0])||n.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,l){return!!k(l[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)},
text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}},
setFilters:{first:function(g,h){return h===0},last:function(g,h,l,m){return h===m.length-1},even:function(g,h){return h%2===0},odd:function(g,h){return h%2===1},lt:function(g,h,l){return h<l[3]-0},gt:function(g,h,l){return h>l[3]-0},nth:function(g,h,l){return l[3]-0===h},eq:function(g,h,l){return l[3]-0===h}},filter:{PSEUDO:function(g,h,l,m){var q=h[1],p=n.filters[q];if(p)return p(g,l,h,m);else if(q==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(q==="not"){h=
h[3];l=0;for(m=h.length;l<m;l++)if(h[l]===g)return false;return true}else k.error("Syntax error, unrecognized expression: "+q)},CHILD:function(g,h){var l=h[1],m=g;switch(l){case "only":case "first":for(;m=m.previousSibling;)if(m.nodeType===1)return false;if(l==="first")return true;m=g;case "last":for(;m=m.nextSibling;)if(m.nodeType===1)return false;return true;case "nth":l=h[2];var q=h[3];if(l===1&&q===0)return true;h=h[0];var p=g.parentNode;if(p&&(p.sizcache!==h||!g.nodeIndex)){var v=0;for(m=p.firstChild;m;m=
m.nextSibling)if(m.nodeType===1)m.nodeIndex=++v;p.sizcache=h}g=g.nodeIndex-q;return l===0?g===0:g%l===0&&g/l>=0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var l=h[1];g=n.attrHandle[l]?n.attrHandle[l](g):g[l]!=null?g[l]:g.getAttribute(l);l=g+"";var m=h[2];h=h[4];return g==null?m==="!=":m===
"="?l===h:m==="*="?l.indexOf(h)>=0:m==="~="?(" "+l+" ").indexOf(h)>=0:!h?l&&g!==false:m==="!="?l!==h:m==="^="?l.indexOf(h)===0:m==="$="?l.substr(l.length-h.length)===h:m==="|="?l===h||l.substr(0,h.length+1)===h+"-":false},POS:function(g,h,l,m){var q=n.setFilters[h[2]];if(q)return q(g,l,h,m)}}},r=n.match.POS;for(var u in n.match){n.match[u]=new RegExp(n.match[u].source+/(?![^\[]*\])(?![^\(]*\))/.source);n.leftMatch[u]=new RegExp(/(^(?:.|\r|\n)*?)/.source+n.match[u].source.replace(/\\(\d+)/g,function(g,
h){return"\\"+(h-0+1)}))}var z=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g};try{Array.prototype.slice.call(s.documentElement.childNodes,0)}catch(C){z=function(g,h){h=h||[];if(j.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var l=0,m=g.length;l<m;l++)h.push(g[l]);else for(l=0;g[l];l++)h.push(g[l]);return h}}var B;if(s.documentElement.compareDocumentPosition)B=function(g,h){if(!g.compareDocumentPosition||
!h.compareDocumentPosition){if(g==h)i=true;return g.compareDocumentPosition?-1:1}g=g.compareDocumentPosition(h)&4?-1:g===h?0:1;if(g===0)i=true;return g};else if("sourceIndex"in s.documentElement)B=function(g,h){if(!g.sourceIndex||!h.sourceIndex){if(g==h)i=true;return g.sourceIndex?-1:1}g=g.sourceIndex-h.sourceIndex;if(g===0)i=true;return g};else if(s.createRange)B=function(g,h){if(!g.ownerDocument||!h.ownerDocument){if(g==h)i=true;return g.ownerDocument?-1:1}var l=g.ownerDocument.createRange(),m=
h.ownerDocument.createRange();l.setStart(g,0);l.setEnd(g,0);m.setStart(h,0);m.setEnd(h,0);g=l.compareBoundaryPoints(Range.START_TO_END,m);if(g===0)i=true;return g};(function(){var g=s.createElement("div"),h="script"+(new Date).getTime();g.innerHTML="<a name='"+h+"'/>";var l=s.documentElement;l.insertBefore(g,l.firstChild);if(s.getElementById(h)){n.find.ID=function(m,q,p){if(typeof q.getElementById!=="undefined"&&!p)return(q=q.getElementById(m[1]))?q.id===m[1]||typeof q.getAttributeNode!=="undefined"&&
q.getAttributeNode("id").nodeValue===m[1]?[q]:w:[]};n.filter.ID=function(m,q){var p=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&p&&p.nodeValue===q}}l.removeChild(g);l=g=null})();(function(){var g=s.createElement("div");g.appendChild(s.createComment(""));if(g.getElementsByTagName("*").length>0)n.find.TAG=function(h,l){l=l.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var m=0;l[m];m++)l[m].nodeType===1&&h.push(l[m]);l=h}return l};g.innerHTML="<a href='#'></a>";
if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")n.attrHandle.href=function(h){return h.getAttribute("href",2)};g=null})();s.querySelectorAll&&function(){var g=k,h=s.createElement("div");h.innerHTML="<p class='TEST'></p>";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){k=function(m,q,p,v){q=q||s;if(!v&&q.nodeType===9&&!x(q))try{return z(q.querySelectorAll(m),p)}catch(t){}return g(m,q,p,v)};for(var l in g)k[l]=g[l];h=null}}();
(function(){var g=s.createElement("div");g.innerHTML="<div class='test e'></div><div class='test'></div>";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){n.order.splice(1,0,"CLASS");n.find.CLASS=function(h,l,m){if(typeof l.getElementsByClassName!=="undefined"&&!m)return l.getElementsByClassName(h[1])};g=null}}})();var E=s.compareDocumentPosition?function(g,h){return!!(g.compareDocumentPosition(h)&16)}:
function(g,h){return g!==h&&(g.contains?g.contains(h):true)},x=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},ga=function(g,h){var l=[],m="",q;for(h=h.nodeType?[h]:h;q=n.match.PSEUDO.exec(g);){m+=q[0];g=g.replace(n.match.PSEUDO,"")}g=n.relative[g]?g+"*":g;q=0;for(var p=h.length;q<p;q++)k(g,h[q],l);return k.filter(m,l)};c.find=k;c.expr=k.selectors;c.expr[":"]=c.expr.filters;c.unique=k.uniqueSort;c.text=a;c.isXMLDoc=x;c.contains=E})();var eb=/Until$/,fb=/^(?:parents|prevUntil|prevAll)/,
gb=/,/;R=Array.prototype.slice;var Ia=function(a,b,d){if(c.isFunction(b))return c.grep(a,function(e,j){return!!b.call(e,j,e)===d});else if(b.nodeType)return c.grep(a,function(e){return e===b===d});else if(typeof b==="string"){var f=c.grep(a,function(e){return e.nodeType===1});if(Ua.test(b))return c.filter(b,f,!d);else b=c.filter(b,f)}return c.grep(a,function(e){return c.inArray(e,b)>=0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f<e;f++){d=b.length;
c.find(a,this[f],b);if(f>0)for(var j=d;j<b.length;j++)for(var i=0;i<d;i++)if(b[i]===b[j]){b.splice(j--,1);break}}return b},has:function(a){var b=c(a);return this.filter(function(){for(var d=0,f=b.length;d<f;d++)if(c.contains(this,b[d]))return true})},not:function(a){return this.pushStack(Ia(this,a,false),"not",a)},filter:function(a){return this.pushStack(Ia(this,a,true),"filter",a)},is:function(a){return!!a&&c.filter(a,this).length>0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,j=
{},i;if(f&&a.length){e=0;for(var o=a.length;e<o;e++){i=a[e];j[i]||(j[i]=c.expr.match.POS.test(i)?c(i,b||this.context):i)}for(;f&&f.ownerDocument&&f!==b;){for(i in j){e=j[i];if(e.jquery?e.index(f)>-1:c(f).is(e)){d.push({selector:i,elem:f});delete j[i]}}f=f.parentNode}}return d}var k=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(n,r){for(;r&&r.ownerDocument&&r!==b;){if(k?k.index(r)>-1:c(r).is(a))return r;r=r.parentNode}return null})},index:function(a){if(!a||typeof a===
"string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),a);return this.pushStack(qa(a[0])||qa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode",
d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")?
a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);eb.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):e;if((this.length>1||gb.test(f))&&fb.test(a))e=e.reverse();return this.pushStack(e,a,R.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===w||a.nodeType!==1||!c(a).is(d));){a.nodeType===
1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var Ja=/ jQuery\d+="(?:\d+|null)"/g,V=/^\s+/,Ka=/(<([\w:]+)[^>]*?)\/>/g,hb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,La=/<([\w:]+)/,ib=/<tbody/i,jb=/<|&#?\w+;/,ta=/<script|<object|<embed|<option|<style/i,ua=/checked\s*(?:[^=]|=\s*.checked.)/i,Ma=function(a,b,d){return hb.test(d)?
a:b+"></"+d+">"},F={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]};F.optgroup=F.option;F.tbody=F.tfoot=F.colgroup=F.caption=F.thead;F.th=F.td;if(!c.support.htmlSerialize)F._default=[1,"div<div>","</div>"];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d=
c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==w)return this.empty().append((this[0]&&this[0].ownerDocument||s).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this},
wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})},
prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,
this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,f;(f=this[d])!=null;d++)if(!a||c.filter(a,[f]).length){if(!b&&f.nodeType===1){c.cleanData(f.getElementsByTagName("*"));c.cleanData([f])}f.parentNode&&f.parentNode.removeChild(f)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild);
return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Ja,"").replace(/=([^="'>\s]+\/)>/g,'="$1">').replace(V,"")],f)[0]}else return this.cloneNode(true)});if(a===true){ra(this,b);ra(this.find("*"),b.find("*"))}return b},html:function(a){if(a===w)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Ja,
""):null;else if(typeof a==="string"&&!ta.test(a)&&(c.support.leadingWhitespace||!V.test(a))&&!F[(La.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Ka,Ma);try{for(var b=0,d=this.length;b<d;b++)if(this[b].nodeType===1){c.cleanData(this[b].getElementsByTagName("*"));this[b].innerHTML=a}}catch(f){this.empty().append(a)}}else c.isFunction(a)?this.each(function(e){var j=c(this),i=j.html();j.empty().append(function(){return a.call(this,e,i)})}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&
this[0].parentNode){if(c.isFunction(a))return this.each(function(b){var d=c(this),f=d.html();d.replaceWith(a.call(this,b,f))});if(typeof a!=="string")a=c(a).detach();return this.each(function(){var b=this.nextSibling,d=this.parentNode;c(this).remove();b?c(b).before(a):c(d).append(a)})}else return this.pushStack(c(c.isFunction(a)?a():a),"replaceWith",a)},detach:function(a){return this.remove(a,true)},domManip:function(a,b,d){function f(u){return c.nodeName(u,"table")?u.getElementsByTagName("tbody")[0]||
u.appendChild(u.ownerDocument.createElement("tbody")):u}var e,j,i=a[0],o=[],k;if(!c.support.checkClone&&arguments.length===3&&typeof i==="string"&&ua.test(i))return this.each(function(){c(this).domManip(a,b,d,true)});if(c.isFunction(i))return this.each(function(u){var z=c(this);a[0]=i.call(this,u,b?z.html():w);z.domManip(a,b,d)});if(this[0]){e=i&&i.parentNode;e=c.support.parentNode&&e&&e.nodeType===11&&e.childNodes.length===this.length?{fragment:e}:sa(a,this,o);k=e.fragment;if(j=k.childNodes.length===
1?(k=k.firstChild):k.firstChild){b=b&&c.nodeName(j,"tr");for(var n=0,r=this.length;n<r;n++)d.call(b?f(this[n],j):this[n],n>0||e.cacheable||this.length>1?k.cloneNode(true):k)}o.length&&c.each(o,Qa)}return this}});c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var f=[];d=c(d);var e=this.length===1&&this[0].parentNode;if(e&&e.nodeType===11&&e.childNodes.length===1&&d.length===1){d[b](this[0]);
return this}else{e=0;for(var j=d.length;e<j;e++){var i=(e>0?this.clone(true):this).get();c.fn[b].apply(c(d[e]),i);f=f.concat(i)}return this.pushStack(f,a,d.selector)}}});c.extend({clean:function(a,b,d,f){b=b||s;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||s;for(var e=[],j=0,i;(i=a[j])!=null;j++){if(typeof i==="number")i+="";if(i){if(typeof i==="string"&&!jb.test(i))i=b.createTextNode(i);else if(typeof i==="string"){i=i.replace(Ka,Ma);var o=(La.exec(i)||["",
""])[1].toLowerCase(),k=F[o]||F._default,n=k[0],r=b.createElement("div");for(r.innerHTML=k[1]+i+k[2];n--;)r=r.lastChild;if(!c.support.tbody){n=ib.test(i);o=o==="table"&&!n?r.firstChild&&r.firstChild.childNodes:k[1]==="<table>"&&!n?r.childNodes:[];for(k=o.length-1;k>=0;--k)c.nodeName(o[k],"tbody")&&!o[k].childNodes.length&&o[k].parentNode.removeChild(o[k])}!c.support.leadingWhitespace&&V.test(i)&&r.insertBefore(b.createTextNode(V.exec(i)[0]),r.firstChild);i=r.childNodes}if(i.nodeType)e.push(i);else e=
c.merge(e,i)}}if(d)for(j=0;e[j];j++)if(f&&c.nodeName(e[j],"script")&&(!e[j].type||e[j].type.toLowerCase()==="text/javascript"))f.push(e[j].parentNode?e[j].parentNode.removeChild(e[j]):e[j]);else{e[j].nodeType===1&&e.splice.apply(e,[j+1,0].concat(c.makeArray(e[j].getElementsByTagName("script"))));d.appendChild(e[j])}return e},cleanData:function(a){for(var b,d,f=c.cache,e=c.event.special,j=c.support.deleteExpando,i=0,o;(o=a[i])!=null;i++)if(d=o[c.expando]){b=f[d];if(b.events)for(var k in b.events)e[k]?
c.event.remove(o,k):Ca(o,k,b.handle);if(j)delete o[c.expando];else o.removeAttribute&&o.removeAttribute(c.expando);delete f[d]}}});var kb=/z-?index|font-?weight|opacity|zoom|line-?height/i,Na=/alpha\([^)]*\)/,Oa=/opacity=([^)]*)/,ha=/float/i,ia=/-([a-z])/ig,lb=/([A-Z])/g,mb=/^-?\d+(?:px)?$/i,nb=/^-?\d/,ob={position:"absolute",visibility:"hidden",display:"block"},pb=["Left","Right"],qb=["Top","Bottom"],rb=s.defaultView&&s.defaultView.getComputedStyle,Pa=c.support.cssFloat?"cssFloat":"styleFloat",ja=
function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){return X(this,a,b,true,function(d,f,e){if(e===w)return c.curCSS(d,f);if(typeof e==="number"&&!kb.test(f))e+="px";c.style(d,f,e)})};c.extend({style:function(a,b,d){if(!a||a.nodeType===3||a.nodeType===8)return w;if((b==="width"||b==="height")&&parseFloat(d)<0)d=w;var f=a.style||a,e=d!==w;if(!c.support.opacity&&b==="opacity"){if(e){f.zoom=1;b=parseInt(d,10)+""==="NaN"?"":"alpha(opacity="+d*100+")";a=f.filter||c.curCSS(a,"filter")||"";f.filter=
Na.test(a)?a.replace(Na,b):b}return f.filter&&f.filter.indexOf("opacity=")>=0?parseFloat(Oa.exec(f.filter)[1])/100+"":""}if(ha.test(b))b=Pa;b=b.replace(ia,ja);if(e)f[b]=d;return f[b]},css:function(a,b,d,f){if(b==="width"||b==="height"){var e,j=b==="width"?pb:qb;function i(){e=b==="width"?a.offsetWidth:a.offsetHeight;f!=="border"&&c.each(j,function(){f||(e-=parseFloat(c.curCSS(a,"padding"+this,true))||0);if(f==="margin")e+=parseFloat(c.curCSS(a,"margin"+this,true))||0;else e-=parseFloat(c.curCSS(a,
"border"+this+"Width",true))||0})}a.offsetWidth!==0?i():c.swap(a,ob,i);return Math.max(0,Math.round(e))}return c.curCSS(a,b,d)},curCSS:function(a,b,d){var f,e=a.style;if(!c.support.opacity&&b==="opacity"&&a.currentStyle){f=Oa.test(a.currentStyle.filter||"")?parseFloat(RegExp.$1)/100+"":"";return f===""?"1":f}if(ha.test(b))b=Pa;if(!d&&e&&e[b])f=e[b];else if(rb){if(ha.test(b))b="float";b=b.replace(lb,"-$1").toLowerCase();e=a.ownerDocument.defaultView;if(!e)return null;if(a=e.getComputedStyle(a,null))f=
a.getPropertyValue(b);if(b==="opacity"&&f==="")f="1"}else if(a.currentStyle){d=b.replace(ia,ja);f=a.currentStyle[b]||a.currentStyle[d];if(!mb.test(f)&&nb.test(f)){b=e.left;var j=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;e.left=d==="fontSize"?"1em":f||0;f=e.pixelLeft+"px";e.left=b;a.runtimeStyle.left=j}}return f},swap:function(a,b,d){var f={};for(var e in b){f[e]=a.style[e];a.style[e]=b[e]}d.call(a);for(e in b)a.style[e]=f[e]}});if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b=
a.offsetWidth,d=a.offsetHeight,f=a.nodeName.toLowerCase()==="tr";return b===0&&d===0&&!f?true:b>0&&d>0&&!f?false:c.curCSS(a,"display")==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var sb=J(),tb=/<script(.|\s)*?\/script>/gi,ub=/select|textarea/i,vb=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,N=/=\?(&|$)/,ka=/\?/,wb=/(\?|&)_=.*?(&|$)/,xb=/^(\w+:)?\/\/([^\/?#]+)/,yb=/%20/g,zb=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!==
"string")return zb.call(this,a);else if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var e=a.slice(f,a.length);a=a.slice(0,f)}f="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b==="object"){b=c.param(b,c.ajaxSettings.traditional);f="POST"}var j=this;c.ajax({url:a,type:f,dataType:"html",data:b,complete:function(i,o){if(o==="success"||o==="notmodified")j.html(e?c("<div />").append(i.responseText.replace(tb,"")).find(e):i.responseText);d&&j.each(d,[i.responseText,o,i])}});return this},
serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ub.test(this.nodeName)||vb.test(this.type))}).map(function(a,b){a=c(this).val();return a==null?null:c.isArray(a)?c.map(a,function(d){return{name:b.name,value:d}}):{name:b.name,value:a}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),
function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:f})},getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:f})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href,
global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:A.XMLHttpRequest&&(A.location.protocol!=="file:"||!A.ActiveXObject)?function(){return new A.XMLHttpRequest}:function(){try{return new A.ActiveXObject("Microsoft.XMLHTTP")}catch(a){}},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},etag:{},ajax:function(a){function b(){e.success&&
e.success.call(k,o,i,x);e.global&&f("ajaxSuccess",[x,e])}function d(){e.complete&&e.complete.call(k,x,i);e.global&&f("ajaxComplete",[x,e]);e.global&&!--c.active&&c.event.trigger("ajaxStop")}function f(q,p){(e.context?c(e.context):c.event).trigger(q,p)}var e=c.extend(true,{},c.ajaxSettings,a),j,i,o,k=a&&a.context||e,n=e.type.toUpperCase();if(e.data&&e.processData&&typeof e.data!=="string")e.data=c.param(e.data,e.traditional);if(e.dataType==="jsonp"){if(n==="GET")N.test(e.url)||(e.url+=(ka.test(e.url)?
"&":"?")+(e.jsonp||"callback")+"=?");else if(!e.data||!N.test(e.data))e.data=(e.data?e.data+"&":"")+(e.jsonp||"callback")+"=?";e.dataType="json"}if(e.dataType==="json"&&(e.data&&N.test(e.data)||N.test(e.url))){j=e.jsonpCallback||"jsonp"+sb++;if(e.data)e.data=(e.data+"").replace(N,"="+j+"$1");e.url=e.url.replace(N,"="+j+"$1");e.dataType="script";A[j]=A[j]||function(q){o=q;b();d();A[j]=w;try{delete A[j]}catch(p){}z&&z.removeChild(C)}}if(e.dataType==="script"&&e.cache===null)e.cache=false;if(e.cache===
false&&n==="GET"){var r=J(),u=e.url.replace(wb,"$1_="+r+"$2");e.url=u+(u===e.url?(ka.test(e.url)?"&":"?")+"_="+r:"")}if(e.data&&n==="GET")e.url+=(ka.test(e.url)?"&":"?")+e.data;e.global&&!c.active++&&c.event.trigger("ajaxStart");r=(r=xb.exec(e.url))&&(r[1]&&r[1]!==location.protocol||r[2]!==location.host);if(e.dataType==="script"&&n==="GET"&&r){var z=s.getElementsByTagName("head")[0]||s.documentElement,C=s.createElement("script");C.src=e.url;if(e.scriptCharset)C.charset=e.scriptCharset;if(!j){var B=
false;C.onload=C.onreadystatechange=function(){if(!B&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){B=true;b();d();C.onload=C.onreadystatechange=null;z&&C.parentNode&&z.removeChild(C)}}}z.insertBefore(C,z.firstChild);return w}var E=false,x=e.xhr();if(x){e.username?x.open(n,e.url,e.async,e.username,e.password):x.open(n,e.url,e.async);try{if(e.data||a&&a.contentType)x.setRequestHeader("Content-Type",e.contentType);if(e.ifModified){c.lastModified[e.url]&&x.setRequestHeader("If-Modified-Since",
c.lastModified[e.url]);c.etag[e.url]&&x.setRequestHeader("If-None-Match",c.etag[e.url])}r||x.setRequestHeader("X-Requested-With","XMLHttpRequest");x.setRequestHeader("Accept",e.dataType&&e.accepts[e.dataType]?e.accepts[e.dataType]+", */*":e.accepts._default)}catch(ga){}if(e.beforeSend&&e.beforeSend.call(k,x,e)===false){e.global&&!--c.active&&c.event.trigger("ajaxStop");x.abort();return false}e.global&&f("ajaxSend",[x,e]);var g=x.onreadystatechange=function(q){if(!x||x.readyState===0||q==="abort"){E||
d();E=true;if(x)x.onreadystatechange=c.noop}else if(!E&&x&&(x.readyState===4||q==="timeout")){E=true;x.onreadystatechange=c.noop;i=q==="timeout"?"timeout":!c.httpSuccess(x)?"error":e.ifModified&&c.httpNotModified(x,e.url)?"notmodified":"success";var p;if(i==="success")try{o=c.httpData(x,e.dataType,e)}catch(v){i="parsererror";p=v}if(i==="success"||i==="notmodified")j||b();else c.handleError(e,x,i,p);d();q==="timeout"&&x.abort();if(e.async)x=null}};try{var h=x.abort;x.abort=function(){x&&h.call(x);
g("abort")}}catch(l){}e.async&&e.timeout>0&&setTimeout(function(){x&&!E&&g("timeout")},e.timeout);try{x.send(n==="POST"||n==="PUT"||n==="DELETE"?e.data:null)}catch(m){c.handleError(e,x,null,m);d()}e.async||g();return x}},handleError:function(a,b,d,f){if(a.error)a.error.call(a.context||a,b,d,f);if(a.global)(a.context?c(a.context):c.event).trigger("ajaxError",[b,a,f])},active:0,httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status===
1223||a.status===0}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),f=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(f)c.etag[b]=f;return a.status===304||a.status===0},httpData:function(a,b,d){var f=a.getResponseHeader("content-type")||"",e=b==="xml"||!b&&f.indexOf("xml")>=0;a=e?a.responseXML:a.responseText;e&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b===
"json"||!b&&f.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&f.indexOf("javascript")>=0)c.globalEval(a);return a},param:function(a,b){function d(i,o){if(c.isArray(o))c.each(o,function(k,n){b||/\[\]$/.test(i)?f(i,n):d(i+"["+(typeof n==="object"||c.isArray(n)?k:"")+"]",n)});else!b&&o!=null&&typeof o==="object"?c.each(o,function(k,n){d(i+"["+k+"]",n)}):f(i,o)}function f(i,o){o=c.isFunction(o)?o():o;e[e.length]=encodeURIComponent(i)+"="+encodeURIComponent(o)}var e=[];if(b===w)b=c.ajaxSettings.traditional;
if(c.isArray(a)||a.jquery)c.each(a,function(){f(this.name,this.value)});else for(var j in a)d(j,a[j]);return e.join("&").replace(yb,"+")}});var la={},Ab=/toggle|show|hide/,Bb=/^([+-]=)?([\d+-.]+)(.*)$/,W,va=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b){if(a||a===0)return this.animate(K("show",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");
this[a].style.display=d||"";if(c.css(this[a],"display")==="none"){d=this[a].nodeName;var f;if(la[d])f=la[d];else{var e=c("<"+d+" />").appendTo("body");f=e.css("display");if(f==="none")f="block";e.remove();la[d]=f}c.data(this[a],"olddisplay",f)}}a=0;for(b=this.length;a<b;a++)this[a].style.display=c.data(this[a],"olddisplay")||"";return this}},hide:function(a,b){if(a||a===0)return this.animate(K("hide",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");!d&&d!=="none"&&c.data(this[a],
"olddisplay",c.css(this[a],"display"))}a=0;for(b=this.length;a<b;a++)this[a].style.display="none";return this}},_toggle:c.fn.toggle,toggle:function(a,b){var d=typeof a==="boolean";if(c.isFunction(a)&&c.isFunction(b))this._toggle.apply(this,arguments);else a==null||d?this.each(function(){var f=d?a:c(this).is(":hidden");c(this)[f?"show":"hide"]()}):this.animate(K("toggle",3),a,b);return this},fadeTo:function(a,b,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,d)},
animate:function(a,b,d,f){var e=c.speed(b,d,f);if(c.isEmptyObject(a))return this.each(e.complete);return this[e.queue===false?"each":"queue"](function(){var j=c.extend({},e),i,o=this.nodeType===1&&c(this).is(":hidden"),k=this;for(i in a){var n=i.replace(ia,ja);if(i!==n){a[n]=a[i];delete a[i];i=n}if(a[i]==="hide"&&o||a[i]==="show"&&!o)return j.complete.call(this);if((i==="height"||i==="width")&&this.style){j.display=c.css(this,"display");j.overflow=this.style.overflow}if(c.isArray(a[i])){(j.specialEasing=
j.specialEasing||{})[i]=a[i][1];a[i]=a[i][0]}}if(j.overflow!=null)this.style.overflow="hidden";j.curAnim=c.extend({},a);c.each(a,function(r,u){var z=new c.fx(k,j,r);if(Ab.test(u))z[u==="toggle"?o?"show":"hide":u](a);else{var C=Bb.exec(u),B=z.cur(true)||0;if(C){u=parseFloat(C[2]);var E=C[3]||"px";if(E!=="px"){k.style[r]=(u||1)+E;B=(u||1)/z.cur(true)*B;k.style[r]=B+E}if(C[1])u=(C[1]==="-="?-1:1)*u+B;z.custom(B,u,E)}else z.custom(B,u,"")}});return true})},stop:function(a,b){var d=c.timers;a&&this.queue([]);
this.each(function(){for(var f=d.length-1;f>=0;f--)if(d[f].elem===this){b&&d[f](true);d.splice(f,1)}});b||this.dequeue();return this}});c.each({slideDown:K("show",1),slideUp:K("hide",1),slideToggle:K("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(a,b){c.fn[a]=function(d,f){return this.animate(b,d,f)}});c.extend({speed:function(a,b,d){var f=a&&typeof a==="object"?a:{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};f.duration=c.fx.off?0:typeof f.duration===
"number"?f.duration:c.fx.speeds[f.duration]||c.fx.speeds._default;f.old=f.complete;f.complete=function(){f.queue!==false&&c(this).dequeue();c.isFunction(f.old)&&f.old.call(this)};return f},easing:{linear:function(a,b,d,f){return d+f*a},swing:function(a,b,d,f){return(-Math.cos(a*Math.PI)/2+0.5)*f+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]||
c.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style)this.elem.style.display="block"},cur:function(a){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];return(a=parseFloat(c.css(this.elem,this.prop,a)))&&a>-10000?a:parseFloat(c.curCSS(this.elem,this.prop))||0},custom:function(a,b,d){function f(j){return e.step(j)}this.startTime=J();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start;
this.pos=this.state=0;var e=this;f.elem=this.elem;if(f()&&c.timers.push(f)&&!W)W=setInterval(c.fx.tick,13)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(a){var b=J(),d=true;if(a||b>=this.options.duration+this.startTime){this.now=
this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var f in this.options.curAnim)if(this.options.curAnim[f]!==true)d=false;if(d){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;a=c.data(this.elem,"olddisplay");this.elem.style.display=a?a:this.options.display;if(c.css(this.elem,"display")==="none")this.elem.style.display="block"}this.options.hide&&c(this.elem).hide();if(this.options.hide||this.options.show)for(var e in this.options.curAnim)c.style(this.elem,
e,this.options.orig[e]);this.options.complete.call(this.elem)}return false}else{e=b-this.startTime;this.state=e/this.options.duration;a=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||a](this.state,e,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=c.timers,b=0;b<a.length;b++)a[b]()||a.splice(b--,1);a.length||
c.fx.stop()},stop:function(){clearInterval(W);W=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){c.style(a.elem,"opacity",a.now)},_default:function(a){if(a.elem.style&&a.elem.style[a.prop]!=null)a.elem.style[a.prop]=(a.prop==="width"||a.prop==="height"?Math.max(0,a.now):a.now)+a.unit;else a.elem[a.prop]=a.now}}});if(c.expr&&c.expr.filters)c.expr.filters.animated=function(a){return c.grep(c.timers,function(b){return a===b.elem}).length};c.fn.offset="getBoundingClientRect"in s.documentElement?
function(a){var b=this[0];if(a)return this.each(function(e){c.offset.setOffset(this,a,e)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);var d=b.getBoundingClientRect(),f=b.ownerDocument;b=f.body;f=f.documentElement;return{top:d.top+(self.pageYOffset||c.support.boxModel&&f.scrollTop||b.scrollTop)-(f.clientTop||b.clientTop||0),left:d.left+(self.pageXOffset||c.support.boxModel&&f.scrollLeft||b.scrollLeft)-(f.clientLeft||b.clientLeft||0)}}:function(a){var b=
this[0];if(a)return this.each(function(r){c.offset.setOffset(this,a,r)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);c.offset.initialize();var d=b.offsetParent,f=b,e=b.ownerDocument,j,i=e.documentElement,o=e.body;f=(e=e.defaultView)?e.getComputedStyle(b,null):b.currentStyle;for(var k=b.offsetTop,n=b.offsetLeft;(b=b.parentNode)&&b!==o&&b!==i;){if(c.offset.supportsFixedPosition&&f.position==="fixed")break;j=e?e.getComputedStyle(b,null):b.currentStyle;
k-=b.scrollTop;n-=b.scrollLeft;if(b===d){k+=b.offsetTop;n+=b.offsetLeft;if(c.offset.doesNotAddBorder&&!(c.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(b.nodeName))){k+=parseFloat(j.borderTopWidth)||0;n+=parseFloat(j.borderLeftWidth)||0}f=d;d=b.offsetParent}if(c.offset.subtractsBorderForOverflowNotVisible&&j.overflow!=="visible"){k+=parseFloat(j.borderTopWidth)||0;n+=parseFloat(j.borderLeftWidth)||0}f=j}if(f.position==="relative"||f.position==="static"){k+=o.offsetTop;n+=o.offsetLeft}if(c.offset.supportsFixedPosition&&
f.position==="fixed"){k+=Math.max(i.scrollTop,o.scrollTop);n+=Math.max(i.scrollLeft,o.scrollLeft)}return{top:k,left:n}};c.offset={initialize:function(){var a=s.body,b=s.createElement("div"),d,f,e,j=parseFloat(c.curCSS(a,"marginTop",true))||0;c.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"});b.innerHTML="<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";
a.insertBefore(b,a.firstChild);d=b.firstChild;f=d.firstChild;e=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=f.offsetTop!==5;this.doesAddBorderForTableAndCells=e.offsetTop===5;f.style.position="fixed";f.style.top="20px";this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15;f.style.position=f.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==j;a.removeChild(b);
c.offset.initialize=c.noop},bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.curCSS(a,"marginTop",true))||0;d+=parseFloat(c.curCSS(a,"marginLeft",true))||0}return{top:b,left:d}},setOffset:function(a,b,d){if(/static/.test(c.curCSS(a,"position")))a.style.position="relative";var f=c(a),e=f.offset(),j=parseInt(c.curCSS(a,"top",true),10)||0,i=parseInt(c.curCSS(a,"left",true),10)||0;if(c.isFunction(b))b=b.call(a,
d,e);d={top:b.top-e.top+j,left:b.left-e.left+i};"using"in b?b.using.call(a,d):f.css(d)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),f=/^body|html$/i.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.curCSS(a,"marginTop",true))||0;d.left-=parseFloat(c.curCSS(a,"marginLeft",true))||0;f.top+=parseFloat(c.curCSS(b[0],"borderTopWidth",true))||0;f.left+=parseFloat(c.curCSS(b[0],"borderLeftWidth",true))||0;return{top:d.top-
f.top,left:d.left-f.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||s.body;a&&!/^body|html$/i.test(a.nodeName)&&c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(f){var e=this[0],j;if(!e)return null;if(f!==w)return this.each(function(){if(j=wa(this))j.scrollTo(!a?f:c(j).scrollLeft(),a?f:c(j).scrollTop());else this[d]=f});else return(j=wa(e))?"pageXOffset"in j?j[a?"pageYOffset":
"pageXOffset"]:c.support.boxModel&&j.document.documentElement[d]||j.document.body[d]:e[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();c.fn["inner"+b]=function(){return this[0]?c.css(this[0],d,false,"padding"):null};c.fn["outer"+b]=function(f){return this[0]?c.css(this[0],d,false,f?"margin":"border"):null};c.fn[d]=function(f){var e=this[0];if(!e)return f==null?null:this;if(c.isFunction(f))return this.each(function(j){var i=c(this);i[d](f.call(this,j,i[d]()))});return"scrollTo"in
e&&e.document?e.document.compatMode==="CSS1Compat"&&e.document.documentElement["client"+b]||e.document.body["client"+b]:e.nodeType===9?Math.max(e.documentElement["client"+b],e.body["scroll"+b],e.documentElement["scroll"+b],e.body["offset"+b],e.documentElement["offset"+b]):f===w?c.css(e,d):this.css(d,typeof f==="string"?f:f+"px")}});A.jQuery=A.$=c})(window);

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 853 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 901 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 241 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 235 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 232 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 241 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 606 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 672 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 731 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 432 B

Some files were not shown because too many files have changed in this diff Show More