<?php
/*
Copyright 2008 Josh Heidenreich
This file is part of Pelzini.
Pelzini is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Pelzini is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Pelzini. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* Contains the {@link QualityCheckTransformer} class
*
* @package Transformers
* @author Josh
* @since 0.2
**/
/**
* This is a transformer that does quality checks on the codebase
*
* It checks that the documentation has the required tags. Currently the 'required tags' are only the summary
*
* The documentation is created in a report called the {@link Quality check report}.
**/
class QualityCheckTransformer extends Transformer {
private $offending_items;
private $required_tags;
/**
* Set up the quality check transformer
*
* @param array $required_tags Docblock tags which will be reported if missing
**/
public function __construct
(array $required_tags = null) {
$this->required_tags = $required_tags;
if (empty($this->required_tags)) { $this->required_tags = array('@summary'); }
}
/**
* Transforms the data model before outputting.
*
* This transformer generates a report of objects that do not have good enough documentation
*
* @param array $parser_model The data model to transform
* @return array The new data model, or null if there was an error
**/
public function transform(&$parser_model)
{
$this->offending_items = array();
foreach ($parser_model as $item) {
if ($item instanceof CodeParserItem) {
$this->check_files($item);
}
}
if (count($this->offending_items) == 0) { return null;
}
ksort($this->offending_items);
$report = "The following items have insufficent documentation:";
foreach ($this->offending_items as $type => $items) {
$report .= "\n\n<b>{$type}:</b>\n - ";
$report .= implode("\n - ", $items); }
$document = new ParserDocument();
$document->name = "Quality check report";
$document->description = htmlify_text($report);
$parser_model[] = $document;
return $parser_model;
}
/**
* Checks that a file has high-enough quality documentation
**/
private function check_files($item)
{
$tags = $item->getDocblockTags();
// classes and interfaces
foreach ($item->classes as $sub) {
if ($sub instanceof ParserClass) {
$this->check_class($sub);
} else if ($sub instanceof ParserInterface) {
$this->check_interface($sub);
}
}
// functions
foreach ($item->functions as $sub) {
$this->check_function($sub);
}
// the files
foreach ($this->required_tags as $tag_name) {
if (!isset($tags[$tag_name]) or
$tags[$tag_name] == '') { if ($tag_name == '@summary') {
$tag_name = 'summary';
} else {
$tag_name .= ' tag';
}
$problems[] = "No {$tag_name}";
}
}
$this->offending_items['Files'][] = '{@link ' . $item->name . '}: <i>' . implode(', ', $problems) . '</i>'; }
}
/**
* Checks that a class has high-enough quality documentation
**/
private function check_class($item)
{
$tags = $item->getDocblockTags();
foreach ($this->required_tags as $tag_name) {
if (!isset($tags[$tag_name]) or
$tags[$tag_name] == '') { if ($tag_name == '@summary') {
$tag_name = 'summary';
} else {
$tag_name .= ' tag';
}
$problems[] = "No {$tag_name}";
}
}
$this->offending_items['Classes'][] = '{@link ' . $item->name . '}: <i>' . implode(', ', $problems) . '</i>'; }
foreach ($item->functions as $sub) {
$this->check_function($sub, ' from class {@link ' . $item->name . '}');
}
}
/**
* Checks that an interface has high-enough quality documentation
**/
private function check_interface($item)
{
$tags = $item->getDocblockTags();
foreach ($this->required_tags as $tag_name) {
if (!isset($tags[$tag_name]) or
$tags[$tag_name] == '') { if ($tag_name == '@summary') {
$tag_name = 'summary';
} else {
$tag_name .= ' tag';
}
$problems[] = "No {$tag_name}";
}
}
$this->offending_items['Interfaces'][] = '{@link ' . $item->name . '}: <i>' . implode(', ', $problems) . '</i>'; }
foreach ($item->functions as $sub) {
$this->check_function($sub, ' from interface {@link ' . $item->name . '}');
}
}
/**
* Checks that a function has high-enough quality documentation
**/
private function check_function($item, $from = null)
{
$tags = $item->getDocblockTags();
foreach ($this->required_tags as $tag_name) {
if (!isset($tags[$tag_name]) or
$tags[$tag_name] == '') { if ($tag_name == '@summary') {
$tag_name = 'summary';
} else {
$tag_name .= ' tag';
}
$problems[] = "No {$tag_name}";
}
}
$this->offending_items['Functions'][] = '{@link ' . $item->name . '}' . $from . ': <i>' . implode(', ', $problems) . '</i>'; }
foreach ($item->args as $arg) {
if ($arg->description == '') {
$this->offending_items['Function arguments'][] = '{@link ' . $item->name . '}' . $from . ': <i>No description for ' . $arg->name . '</i>';
}
}
}
}
?>