accessibility_scanner-8.x-1.0-alpha8/src/Plugin/CaptureResponse/AxeCoreCliCaptureResponse.php
src/Plugin/CaptureResponse/AxeCoreCliCaptureResponse.php
<?php
namespace Drupal\accessibility_scanner\Plugin\CaptureResponse;
use Drupal\Core\Url;
use Drupal\Component\Serialization\Json;
use Drupal\web_page_archive\Plugin\CaptureResponseInterface;
use Drupal\web_page_archive\Plugin\CaptureResponse\UriCaptureResponse;
/**
* The @axe-core/cli capture response.
*/
class AxeCoreCliCaptureResponse extends UriCaptureResponse {
/**
* {@inheritdoc}
*/
public static function getId() {
return 'wpa_axecore_cli_capture_response';
}
/**
* {@inheritdoc}
*/
public function renderable(array $options = []) {
return (isset($options['mode']) && $options['mode'] == 'full') ?
$this->renderFull($options) : $this->renderPreview($options);
}
/**
* Renders "preview" mode.
*/
private function renderPreview(array $options) {
$contents = $this->retrieveFileContents();
$route_params = [
'web_page_archive_run_revision' => $options['vid'],
'delta' => $options['delta'],
];
$render = [
'#theme' => 'wpa-axecore-cli-preview',
'#summary' => $this->generateSummary($contents),
'#url' => $this->captureUrl,
'#view_button' => [
'#type' => 'link',
'#url' => Url::fromRoute('entity.web_page_archive.modal', $route_params),
'#title' => $this->t('View Detailed Report'),
'#attributes' => [
'class' => ['button', 'use-ajax'],
'data-dialog-type' => 'modal',
'data-dialog-options' => Json::encode(['width' => 1280]),
],
],
];
return $render;
}
/**
* Retrieves file contents.
*/
public function retrieveFileContents() {
if (!empty($this->content) && file_exists($this->content)) {
$contents = file_get_contents($this->content);
return Json::decode($contents);
}
return '';
}
/**
* Summarize contents.
*/
public function generateSummary($contents) {
$ret = [
'tags' => !empty($contents[0]['toolOptions']['runOnly']['values']) ? implode(', ', $contents[0]['toolOptions']['runOnly']['values']) : '',
];
$types = ['violations', 'inapplicable', 'incomplete', 'passes'];
$severities = ['critical', 'serious', 'moderate', 'minor'];
foreach ($types as $type) {
$ret["num_distinct_{$type}"] = 0;
$ret["num_total_{$type}"] = 0;
foreach ($severities as $severity) {
$ret["num_distinct_{$type}_{$severity}"] = 0;
$ret["num_total_{$type}_{$severity}"] = 0;
}
if (!empty($contents[0][$type])) {
foreach ($contents[0][$type] as $instance) {
$ret["num_distinct_{$type}"]++;
$ret["num_total_{$type}"] += count($instance['nodes']);
if (in_array($instance['impact'], $severities)) {
$ret["num_distinct_{$type}_{$instance['impact']}"]++;
$ret["num_total_{$type}_{$instance['impact']}"] += count($instance['nodes']);
}
}
}
}
// If there are no violations then we are "passing".
$ret['is_passing'] = empty($ret['num_total_violations']);
return $ret;
}
/**
* Helper method to retrieve information about a particular report key.
*
* @param string $key
* The key to lookup.
*
* @return array|null
* Key/value pair containing "type" and "label" values for respective key.
*/
protected function getKeyInfo($key) {
$labels = [
'url' => [
'type' => 'string',
'label' => $this->t('URL'),
],
'tags' => [
'type' => 'string',
'label' => $this->t('Tags'),
],
'num_distinct_violations' => [
'type' => 'integer',
'label' => $this->t('Distinct Violations (All)'),
],
'num_total_violations' => [
'type' => 'integer',
'label' => $this->t('Total Violations (All)'),
],
'num_distinct_violations_critical' => [
'type' => 'integer',
'label' => $this->t('Distinct Violations (Critical)'),
],
'num_total_violations_critical' => [
'type' => 'integer',
'label' => $this->t('Total Violations (Critical)'),
],
'num_distinct_violations_serious' => [
'type' => 'integer',
'label' => $this->t('Distinct Violations (Serious)'),
],
'num_total_violations_serious' => [
'type' => 'integer',
'label' => $this->t('Total Violations (Serious)'),
],
'num_distinct_violations_moderate' => [
'type' => 'integer',
'label' => $this->t('Distinct Violations (Moderate)'),
],
'num_total_violations_moderate' => [
'type' => 'integer',
'label' => $this->t('Total Violations (Moderate)'),
],
'num_distinct_violations_minor' => [
'type' => 'integer',
'label' => $this->t('Distinct Violations (Minor)'),
],
'num_total_violations_minor' => [
'type' => 'integer',
'label' => $this->t('Total Violations (Minor)'),
],
'num_distinct_inapplicable' => [
'type' => 'integer',
'label' => $this->t('Inapplicable Rules'),
],
'num_distinct_incomplete' => [
'type' => 'integer',
'label' => $this->t('Distinct Incomplete'),
],
'num_total_incomplete' => [
'type' => 'integer',
'label' => $this->t('Total Incomplete'),
],
'num_distinct_passes' => [
'type' => 'integer',
'label' => $this->t('Distinct Passes'),
],
'num_total_passes' => [
'type' => 'integer',
'label' => $this->t('Total Passes'),
],
'is_passing' => [
'type' => 'boolean',
'label' => $this->t('Passing?'),
],
];
if (isset($labels[$key])) {
return $labels[$key];
}
}
/**
* {@inheritdoc}
*/
public function getReportData() {
$contents = $this->retrieveFileContents();
$raw_data = ['url' => $this->getCaptureUrl()] + $this->generateSummary($contents);
$report_data = [];
foreach ($raw_data as $raw_key => $raw_value) {
$info = $this->getKeyInfo($raw_key);
// We don't want to bombard the report with a bunch of unnecessary data,
// so let's only display the columns that we've defined a key for.
if (!isset($info)) {
continue;
}
$label = $info['label']->__toString();
if ($info['type'] == 'boolean') {
$report_data[$label] = $raw_value ? $this->t('Yes')->__toString() : $this->t('No')->__toString();
}
elseif ($info['type'] == 'integer') {
$report_data[$label] = intval($raw_value);
}
else {
$report_data[$label] = $raw_value;
}
}
return $report_data;
}
/**
* Retrieves aggregate report data.
*
* @return array
* Report data.
*/
public function getAggregateReportData() {
$contents = $this->retrieveFileContents();
foreach ($contents as $item) {
// Determine tags used.
$tags = !empty($item['toolOptions']['runOnly']['values']) ? $item['toolOptions']['runOnly']['values'] : [];
$tags = array_combine($tags, $tags);
$types = ['incomplete', 'violations'];
$severities = [
'#all_severities',
'critical',
'serious',
'moderate',
'minor',
];
// Initial counts.
foreach ($types as $type) {
foreach ($severities as $severity) {
$report_data['#all_tags'][$type][$severity]['distinct'] = 0;
$report_data['#all_tags'][$type][$severity]['total'] = 0;
foreach ($tags as $tag) {
$report_data[$tag][$type][$severity]['distinct'] = 0;
$report_data[$tag][$type][$severity]['total'] = 0;
}
}
}
// Determine counts.
foreach ($types as $type) {
if (!empty($item[$type])) {
foreach ($item[$type] as $details) {
$count = count($details['nodes']);
foreach ($details['tags'] as $tag) {
if (isset($tags[$tag])) {
$report_data[$tag][$type][$details['impact']]['distinct']++;
$report_data[$tag][$type]['#all_severities']['distinct']++;
$report_data[$tag][$type][$details['impact']]['total'] += $count;
$report_data[$tag][$type]['#all_severities']['total'] += $count;
}
}
$report_data['#all_tags'][$type][$details['impact']]['distinct']++;
$report_data['#all_tags'][$type]['#all_severities']['distinct']++;
$report_data['#all_tags'][$type][$details['impact']]['total'] += $count;
$report_data['#all_tags'][$type]['#all_severities']['total'] += $count;
}
}
}
}
return $report_data;
}
/**
* Renders full mode.
*/
private function renderFull(array $options) {
$contents = $this->retrieveFileContents();
$render = [
'#theme' => 'wpa-axecore-cli-full-report',
'#summary' => $this->generateSummary($contents),
'#results' => $contents[0],
'#url' => $this->captureUrl,
];
return $render;
}
/**
* {@inheritdoc}
*/
public static function compare(CaptureResponseInterface $a, CaptureResponseInterface $b, array $compare_utilities, array $tags = [], array $data = []) {
$tags[] = '@axe-core/cli';
return parent::compare($a, $b, $compare_utilities, $tags, $data);
}
}
