deprecation_status-8.x-3.x-dev/src/Form/SingleErrorForm.php
src/Form/SingleErrorForm.php
<?php
namespace Drupal\deprecation_status\Form;
use Drupal\Component\Utility\Html;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Url;
use Drupal\Core\Utility\TableSort;
use Drupal\deprecation_status\DataSource;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
class SingleErrorForm extends FormBase {
/**
* Stored sorting criteria.
*
* @type int
*/
protected $column;
/**
* Stored sorting criteria ('asc' or 'desc').
*
* @type string
*/
protected $sort;
/**
* {@inheritdoc}
*/
public function getFormId() {
return 'deprecation_status_single_error_form';
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state, $error_index = NULL) {
$form['#cache']['tags'][] = 'deprecation_status';
$form['error_index'] = [
'#type' => 'value',
'#value' => $error_index,
];
// Read the error in.
$error = '';
$file = fopen(DataSource::getFullPath('errors_detail.csv'), 'r');
$i = 0;
while ($line = fgetcsv($file, 0, ";")) {
// Skip the header row.
if ($i > 0 && (($i - 1) === (int) $error_index)) {
$error = $line;
}
$i++;
}
fclose($file);
// Throw a 404 if this error was not found.
if (empty($error)) {
throw new NotFoundHttpException();
}
$form['error_string'] = [
'#type' => 'item',
'#title' => $this->t('Error details for'),
'#markup' => '<p>' . DataSource::formatError($error[4]) . '<p>',
];
// Add high level summary table.
$columns = [
'total' => 'Occurence count',
'projects' => 'Affected project count',
'top' => 'Occurs in a top X project by usage',
'category' => 'Category',
];
$form['table'] = [
'#type' => 'table',
'#header' => $columns,
'#rows' => [array_slice($error, 0, 4)],
];
$form['filters'] = [
'#type' => 'details',
'#title' => $this->t('Filter projects'),
'#attributes' => ['class' => ['container-inline']],
'#open' => TRUE,
];
$form['filters']['names'] = [
'#title' => 'Names',
'#type' => 'textfield',
'#default_value' => @$_GET['names'],
'#attributes' => ['placeholder' => "Use *, eg. 'commerce*'"],
'#size' => 20,
];
$form['filters']['topx'] = [
'#title' => 'Top X by usage',
'#type' => 'select',
'#options' => [],
'#default_value' => @$_GET['topx'],
'#required' => FALSE,
'#empty_option' => '- No filter -',
];
foreach([50, 100, 200, 500, 1000] as $number) {
$form['filters']['topx']['#options'][$number] = '<= ' . $number;
}
$form['filters']['submit'] = [
'#type' => 'submit',
'#value' => $this->t('Submit'),
];
// Add project listing table.
$columns = [
'project' => 'Project',
'group' => 'Top X by usage',
'occurrences' => 'Occurrences',
];
// Add sorting information to columns.
$i = 0;
foreach ($columns as $name => &$column) {
$column = ['data' => $column, 'field' => $i];
$i++;
}
// Sort by occurrences descending initially.
$columns['occurrences']['sort'] = 'desc';
$form['list'] = [
'#type' => 'table',
'#header' => $columns,
'#rows' => [],
'#empty' => t('No matching projects found. Adjust filters.'),
];
// Parse affected project information into an array.
$projects = [];
$data = explode(', ', $error[5]);
foreach ($data as $item) {
preg_match('!^(.+) \[(.+)\] \\((.+)\\)$!', $item, $details);
$projects[] = [
$details[1],
$details[2],
$details[3],
];
}
$projects = $this->tableFilter($projects);
// Sort the data array based on query tablesort information.
$order = TableSort::getOrder($columns, \Drupal::request());
$this->column = $order['sql'];
$this->sort = TableSort::getSort($columns, \Drupal::request());
uasort($projects, [$this, 'tableSort']);
// Turn project names into links.
foreach($projects as $project) {
list ($machine_name) = explode(' ', $project[0]);
$project[0] = [
'data' => [
'#type' => 'link',
'#title' => $project[0],
'#url' => Url::fromRoute('deprecation_status.project', ['machine_name' => $machine_name]),
],
];
$form['list']['#rows'][] = $project;
}
$form['data_info'] = DataSource::getDataInfo();
return $form;
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
$keys = ['names', 'topx'];
$submitted = $form_state->getValues();
$query = [];
foreach ($keys as $key) {
if (!empty($submitted[$key])) {
$query[$key] = $submitted[$key];
}
}
$form_state->setRedirect('deprecation_status.error', ['error_index' => $submitted['error_index']], ['query' => $query]);
}
/**
* Custom table sorting based on stored sorting criteria.
*/
protected function tableSort($a, $b) {
if ($a[$this->column] == $b[$this->column]) {
return 0;
}
$cmp = ($a[$this->column] < $b[$this->column]) ? -1 : 1;
return ($this->sort == 'desc') ? $cmp * -1 : $cmp;
}
/**
* Custom table filter based on form values.
*/
protected function tableFilter($projects) {
$keys = ['names', 'topx'];
foreach ($keys as $key) {
$$key = @$_GET[$key];
}
// Process peoject name matching for preg_match() later.
$name_list = [];
if (!empty($names)) {
$all_names = explode(',', $names);
foreach($all_names as $one_name) {
$parts = explode('*', trim($one_name));
$processed_parts = [];
foreach ($parts as $part) {
$processed_parts[] = preg_quote($part, '!');
}
$name_list[] = join('.*', $processed_parts);
}
}
$filtered = [];
foreach ($projects as $project) {
$match = TRUE;
if (!empty($name_list) && $match) {
$one_match = FALSE;
foreach($name_list as $name) {
if (preg_match("!^$name$!", $project[0])) {
$one_match = TRUE;
break;
}
}
$match = $one_match;
}
if (!empty($topx) && $match) {
$match = $project[1] <= $topx;
}
if ($match) {
$filtered[] = $project;
}
}
return $filtered;
}
}
