aggrid-8.x-1.x-dev/src/Plugin/Field/FieldFormatter/HtmlFormatterType.php
src/Plugin/Field/FieldFormatter/HtmlFormatterType.php
<?php
namespace Drupal\aggrid\Plugin\Field\FieldFormatter;
use Drupal\aggrid\AggridConfigHelpers;
use Drupal\aggrid\AggridSuppression;
use Drupal\Component\Utility\Html;
use Drupal\Core\Field\FieldItemInterface;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\FormatterBase;
use Drupal\Core\Form\FormStateInterface;
/**
* Plugin implementation of the 'html_formatter_type' formatter.
*
* @FieldFormatter(
* id = "html_formatter_type",
* label = @Translation("HTML grid view mode"),
* field_types = {
* "aggrid"
* }
* )
*/
class HtmlFormatterType extends FormatterBase {
/**
* Complimentary suppression for aggrid item.
*
* @var boolean
*/
protected $suppComplimentary;
/**
* Complimentary suppression for aggrid item.
*
* @var array
*/
protected $rowSuppression;
/**
* {@inheritdoc}
*/
public static function defaultSettings() {
return [
'suppression_override' => false,
// Implement default settings.
] + parent::defaultSettings();
}
/**
* {@inheritdoc}
*/
public function settingsForm(array $form, FormStateInterface $form_state) {
$form = parent::settingsForm($form, $form_state);
$form['suppression_override'] = [
'#type' => 'checkbox',
'#title' => $this->t('Suppression override'),
'#description' => $this->t('If enabled, suppression will be ignored'),
'#default_value' => $this->getSetting('suppression_override'),
];
return $form;
}
/**
* {@inheritdoc}
*/
public function settingsSummary() {
$summary = [];
// Implement settings summary.
if ($override = $this->getSetting('suppression_override') ? 'Yes' : 'No') {
$summary[] = $this->t('Suppression override: @suppover', ['@suppover' => $override]);
}
return $summary;
}
/**
* {@inheritdoc}
*/
public function createAggridRowData($rowSettings, $columns, $headers, $rowData) {
$aggridSuppression = new AggridSuppression();
// Get configuration for suppression setting
$settings = $this->getSettings();
// Default override
$suppOverride = false;
// Get suppression override setting
if (!empty($settings['suppression_override'])) {
$suppOverride = $settings['suppression_override'];
}
// Clear any previous suppression
$this->rowSuppression = [];
// Cycle through suppression multiple times
if (is_array($rowData)) {
for ($i = 0; $i < 4; $i++) {
$processSuppression = $aggridSuppression->processSuppression($rowSettings, $headers, $rowData, $suppOverride, $this->suppComplimentary);
$rowData = $processSuppression['rowData'];
$this->rowSuppression = $processSuppression['rowSuppression'];
}
}
// HTML rendering
$table_render = '';
$spanSkip[][] = 0;
if (is_array($rowData)) {
for ($i = 0; $i < count($rowData); $i++) {
// Each row... then each cell in each row.
$table_render .= '<tr>';
$colCount = -1;
foreach ($headers as $field) {
$colCount++;
// Loop and look for cell data.
$colSpan = 1;
$rowSpan = 1;
$cellClass = "";
// Check if a spanCount exists for item. If not, create it.
if (!isset($spanSkip[$i][$colCount])) {
$spanSkip[$i][$colCount] = 0;
}
// If it exists, do it
if (($spanSkip[$i][$colCount] == 0
|| $spanSkip[$i][$colCount] == '')) {
// Has data, put it to cell.
// Get the colspan and rowspan.
if (isset($rowSettings[$i][$field]['colSpan'])) {
$colSpan = $rowSettings[$i][$field]['colSpan'];
}
if (isset($rowSettings[$i][$field]['rowSpan'])) {
$rowSpan = $rowSettings[$i][$field]['rowSpan'];
}
if ($rowSpan == '' || $rowSpan == NULL) {
$rowSpan = 1;
}
if ($colSpan == '' || $colSpan == NULL) {
$colSpan = 1;
}
// Loop span and set skips.
for ($si = 0; $si < $rowSpan; $si++) {
$rowNum = $i + $si;
for ($sc = 0; $sc < $colSpan; $sc++) {
$colNum = $colCount + $sc;
$spanSkip[$rowNum][$colNum] = 1;
}
}
$cellClass = '';
// Get the class, switch the name from just aggrid to aggrid-html.
if (isset($rowSettings[$i][$field]['cellClass'])) {
$cellClass = str_replace('aggrid-', 'aggrid-html', $rowSettings[$i][$field]['cellClass']);
}
// Get the class, switch the name from just aggrid to aggrid-html.
if (isset($rowSettings[$i][$field]['formatType'])
&& $rowSettings[$i][$field]['formatType'] != '') {
$cellClass = $cellClass . ' aggrid-html-ftype-' . $rowSettings[$i][$field]['formatType'];
}
// Check if this cell item is actually a label. If so, define as a row for scope (accessibility).
if (strpos($cellClass, 'aggrid-htmlcell-label') !== false) {
$cellScope = 'scope="row"';
} else {
$cellScope = '';
}
// Check settings
if (isset($columns[0][$field])
&& $columns[0][$field]['viewHide']) {
$cellClass = $cellClass . ' aggrid-htmlcell-viewhide';
}
// Check if field/cell exists. If not, blank it as default.
if (isset($rowData[$i]->$field)) {
$cellData = $rowData[$i]->$field;
}
else {
$cellData = "";
}
// Finally, display the cell.
$table_render .= '<td ' . $cellScope . ' rowspan="' . $rowSpan . '" colspan="' . $colSpan . '" class="' . $cellClass . '">' . $cellData . '</td>';
} elseif ($spanSkip[$i][$colCount] > 0) {
// No need to render the cell.
} else {
// No data, just a blank cell.
$table_render .= '<td></td>';
}
}
// Close up the row.
$table_render .= '</tr>';
}
}
return $table_render;
}
/**
* {@inheritdoc}
*/
public function viewElements(FieldItemListInterface $items, $langcode) {
$elements = [];
// Set the agGrid Configuration Helpers
$aggridConfigHelpers = new AggridConfigHelpers();
foreach ($items as $delta => $item) {
$field_name = $this->fieldDefinition->getName();
$item_id = Html::getUniqueId("ht-$field_name-$delta");
$aggridDefault = $aggridConfigHelpers->getDefaults($items[$delta]->aggrid_id);
if (empty($aggridDefault)) {
$elements[$delta]['container'] = [
'#plain_text' => $this->t('Missing ag-Grid Config Entity'),
'#prefix' => '<div class="aggrid-widget-missing">',
'#suffix' => '</div>',
];
}
else {
if ($items[$delta]->value == '' || $items[$delta]->value == '{}') {
$aggridValue = $aggridDefault['default']->rowData;
}
else {
$aggridValue = json_decode($items[$delta]->value);
}
$pinnedTopRowData = @$aggridDefault['addOptions']->pinnedTopRowData;
$pinnedBottomRowData = @$aggridDefault['addOptions']->pinnedBottomRowData;
$aggridRowSettings = $aggridDefault['aggridRowSettings'];
// Set complimentary suppression variable
// Check to see if complimentary is enabled on the default row and rowDefault
if (isset($aggridRowSettings['default']['rowDefault']['valueSuppression']['complimentary'])) {
$this->suppComplimentary = true;
}
else {
$this->suppComplimentary = false;
}
// Set the row data
$rowData = $aggridValue;
// Get header information
$getHeaders = $aggridConfigHelpers->getHeaders($aggridDefault['default']->columnDefs);
// Set the variables from header information
$rowIndex = $getHeaders['rowIndex'];
$colIndex = $getHeaders['colIndex'];
$headers = $getHeaders['headers'];
$columns = $getHeaders['columns'];
// Data Header Settings.
$dataHeaderSettings[][][] = "";
$dataHeaderSettings = $aggridConfigHelpers->getRowSettings($aggridRowSettings, $headers, $columns, 'dh-');
// Run the headers again for colSpan
// Get header information
$getHeaders = $aggridConfigHelpers->getHeaders($aggridDefault['default']->columnDefs, $dataHeaderSettings);
// Set the variables from header information
$headers = $getHeaders['headers'];
$columns = $getHeaders['columns'];
// Build table.
$table_render = '';
$table_render .= '<table id="' . $item_id . '-table" class="aggrid-html-widget"><thead>';
// Get the header rows.
for ($y = 1; $y <= $rowIndex; $y++) {
// Each header row and each column cell with spanning.
$table_render .= '<tr>';
for ($x = 1; $x <= $colIndex; $x++) {
if (!array_key_exists($x, $columns[$y])) {
$table_render .= '<th id="'. $item_id .'-h' . $y . 'c' . $x .'"></th>';
}
else {
foreach ($columns[$y][$x] as $count => $value) {
// Set variables for columns
$colClass = [];
$field = $columns[$y][$x][$count]['field'];
// Check settings
if (isset($columns[0][$field])
&& $columns[0][$field]['viewHide']) {
$colClass[] = 'aggrid-htmlcell-viewhide';
}
// Render the header
$table_render .= '<th scope="col" id="'. $item_id .'-h' . $y . 'c' . $x .'" class="'. implode(' ', $colClass) .'" colspan="' . $columns[$y][$x][$count]['colspan'] . '" data-width="' . $columns[$y][$x][$count]['width'] . '" data-minWidth="' . $columns[$y][$x][$count]['minWidth'] . '">' . $columns[$y][$x][$count]['headerName'] . '</th>';
}
}
}
$table_render .= '</tr>';
}
// Close up the headers and start on data rows.
$table_render .= '</thead><tbody>';
// Pinned Top Row Settings.
$pinnedTopRowSettings[][][] = "";
$pinnedTopRowSettings = $aggridConfigHelpers->getRowSettings($aggridRowSettings, $headers, $pinnedTopRowData, 't-');
// Pinned Top Rows.
$table_render .= $this->createAggridRowData($pinnedTopRowSettings, $columns, $headers, $pinnedTopRowData);
// (Data) Row Settings.
$rowSettings = $aggridConfigHelpers->getRowSettings($aggridRowSettings, $headers, $rowData, '');
// Data rows.
$table_render .= $this->createAggridRowData($rowSettings, $columns, $headers, $rowData);
// Set the row suppression from after the actual rowData is run
$rowSuppression = $this->rowSuppression;
// Pinned Bottom Row Settings.
$pinnedBottomRowSettings = $aggridConfigHelpers->getRowSettings($aggridRowSettings, $headers, $pinnedBottomRowData, 'b-');
// Pinned Bottom Rows.
$table_render .= $this->createAggridRowData($pinnedBottomRowSettings, $columns, $headers, $pinnedBottomRowData);
// Close up the table.
$table_render .= '</tbody></table>';
$elements[$delta]['container'] = [
'#theme' => 'aggrid_table',
'#title' => $this->fieldDefinition->label(),
'#description' => $this->fieldDefinition->getDescription(),
'#headers' => $headers,
'#rowSettings' => $rowSettings,
'#rowSuppression' => $rowSuppression,
'#rowData' => $rowData,
'#suffix' => $table_render,
'#attached' => [
'library' => [
'aggrid/aggrid.widget',
],
],
];
/*
* Putting this code to the side for now. They're currently working on multiple headers
* for the '#type' => 'table'
*
*
// Loop through header array and dive down max 3 header rows. Squash all down to single row with only the items with fields.
// Header 1
foreach($aggridDefault->columnDefs as $column) {
if (isset($column->children)) { // If children, then dive down for headers, otherwise establish column
foreach ($column->children as $child) {
// Header 2
if (isset($child->children)) {
foreach ($child->children as $subchild) {
if (isset($subchild->field)) {
// Header from row 3
$columns[$column->headerName . ' - ' . $child->headerName . ' - ' . $subchild->headerName] = [];
$columns[$column->headerName . ' - ' . $child->headerName . ' - ' . $subchild->headerName]['field'] = $subchild->field;
}
}
} else {
if (isset($child->field)) {
// Header from row 2
$columns[$column->headerName . ' - ' . $child->headerName] = [];
$columns[$column->headerName . ' - ' . $child->headerName]['field'] = $child->field;
}
}
}
} else {
if (isset($column->field)) {
// Header from row 1
$columns[$column->headerName] = [];
$columns[$column->headerName]['field'] = $column->field;
}
}
}
// Headers
foreach($columns as $column => $value) {
array_push($headers, $column);
}
// Row Data
for ($i = 0; $i < count($rowData); $i++) {
foreach($columns as $column => $value) {
$colField = $columns[$column]['field'];
$tabledata[$i][$columns[$column]['field']] = [
'data' => $rowData[$i]->$colField,
'class' => ['row_' . $columns[$column]['field'], 'col_' . $columns[$column]['field']],
];
}
}
$elements[$delta]['tablefield'] = [
'#type' => 'table',
'#headers' => $headers,
'#rows' => $tabledata,
'#attributes' => [
'id' => [$item_id . '-table'],
'class' => ['aggrid-html-widget'],
],
'#prefix' => '<div id="tablefield-wrapper-' . $delta . '" class="tablefield-wrapper">',
'#suffix' => '</div>',
];
*/
}
}
return $elements;
}
/**
* Generate the output appropriate for one field item.
*
* @param \Drupal\Core\Field\FieldItemInterface $item
* One field item.
*
* @return string
* The textual output generated.
*/
protected function viewValue(FieldItemInterface $item) {
/*
* The text value has no text format assigned to it, so the user input
* should equal the output, including newlines.
*/
return nl2br(Html::escape($item->value));
}
}
