json_table-1.0.6/src/Plugin/Field/FieldFormatter/JsonChartFormatter.php

src/Plugin/Field/FieldFormatter/JsonChartFormatter.php
<?php

namespace Drupal\json_table\Plugin\Field\FieldFormatter;

use Drupal\Component\Utility\Html;
use Drupal\Core\Entity\EntityDisplayRepositoryInterface;
use Drupal\Core\Field\Attribute\FieldFormatter;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\FormatterBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Plugin implementation of the 'json_formatter' formatter.
 */
#[FieldFormatter(
  id: 'json_chart_formatter',
  label: new TranslatableMarkup('Json Chart'),
  field_types: [
    'json',
  ],
)]
class JsonChartFormatter extends FormatterBase {

  /**
   * Entity display service.
   *
   * @var \Drupal\Core\Entity\EntityDisplayRepositoryInterface
   */
  protected EntityDisplayRepositoryInterface $entityDisplayRepository;

  /**
   * Construct a JsonChartFormatter object.
   *
   * @param string $plugin_id
   *   The plugin_id for the plugin instance.
   * @param mixed $plugin_definition
   *   The plugin implementation definition.
   * @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
   *   Defines an interface for entity field definitions.
   * @param array $settings
   *   The formatter settings.
   * @param string $label
   *   The formatter label display setting.
   * @param string $view_mode
   *   The view mode.
   * @param array $third_party_settings
   *   Any third party settings.
   * @param \Drupal\Core\Entity\EntityDisplayRepositoryInterface $entity_display_repository
   *   Entity display service.
   */
  public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, $label, $view_mode, array $third_party_settings, EntityDisplayRepositoryInterface $entity_display_repository) {
    parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $label, $view_mode, $third_party_settings);
    $this->entityDisplayRepository = $entity_display_repository;
  }

  /**
   * {@inheritDoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new self(
      $plugin_id,
      $plugin_definition,
      $configuration['field_definition'],
      $configuration['settings'],
      $configuration['label'],
      $configuration['view_mode'],
      $configuration['third_party_settings'],
      // Add any services you want to inject here.
      $container->get('entity_display.repository')
    );
  }

  /**
   * {@inheritdoc}
   */
  public static function defaultSettings() {
    return [
      'mode' => 'googleCharts',
      'chart_type' => 'LineChart',
      'chart_width' => 900,
      'chart_height' => 300,
      'header' => '',
    ] + parent::defaultSettings();
  }

  /**
   * {@inheritdoc}
   */
  public function settingsForm(array $form, FormStateInterface $form_state) {
    $form['mode'] = [
      '#type' => 'select',
      '#options' => [
        'googleCharts' => $this->t('Google chart'),
        'chartjs' => $this->t('Chart js'),
      ],
      '#default_value' => $this->getSetting('mode'),
    ];
    $form['chart_type'] = [
      '#title' => $this->t('Chart type'),
      '#description' => '<a href="https://developers-dot-devsite-v2-prod.appspot.com/chart/interactive/docs/gallery" target="_blank">' . $this->t('Google charts') . '</a>' .
      ' Or <a href="https://www.chartjs.org/docs/latest/samples/information.html" target="_blank">' . $this->t('ChartJs') . '</a>',
      '#type' => 'select',
      '#default_value' => $this->getSetting('chart_type'),
      '#options' => $this->googleChartsOption(),
      '#empty_option' => $this->t('Default Line Chart'),
    ];
    $form['chart_width'] = [
      '#title' => $this->t('Chart width'),
      '#type' => 'number',
      '#default_value' => $this->getSetting('chart_width'),
    ];
    $form['chart_height'] = [
      '#title' => $this->t('Chart height'),
      '#type' => 'number',
      '#default_value' => $this->getSetting('chart_height'),
    ];
    $form['header'] = [
      '#title' => $this->t('Header'),
      '#type' => 'textarea',
      '#default_value' => $this->getSetting('header'),
      '#description' => $this->t('Separated par ,'),
    ];
    // Needed to avoid errors notified as log message.
    if (isset($form['#after_build'])) {
      $form['#after_build'] = NULL;
    }
    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function settingsSummary() {
    $summary = [];
    $summary['mode'] = $this->t('Mode: @mode', ['@mode' => $this->getSetting('mode')]);
    $summary['chart_type'] = $this->t('Type: @type', ['@type' => $this->getSetting('chart_type')]);
    $summary['chart_width'] = $this->t('Chart width: @width', ['@width' => $this->getSetting('chart_width')]);
    $summary['chart_height'] = $this->t('Chart height: @height', ['@height' => $this->getSetting('chart_height')]);
    return $summary;
  }

  /**
   * {@inheritDoc}
   */
  public function viewElements(FieldItemListInterface $items, $langcode) {
    $field_name = $items->getName();
    $setting = $this->getSettings();
    $options = $this->googleChartsOption($setting['chart_type']);
    $mode = $this->getSetting('mode');
    $fieldName = $this->fieldDefinition->getLabel();
    $description = $this->fieldDefinition->getDescription();
    $entity = $items->getEntity();
    $form_display = $this->entityDisplayRepository->getFormDisplay(
      $entity->getEntityTypeId(),
      $entity->bundle(),
      $form_mode = 'default'
    );
    $widgetSettings = $form_display->getComponent($field_name)['settings'];
    $header = [];
    $widgetHeader = $setting['header'];
    if (empty($widgetHeader) && !empty($widgetSettings['header'])) {
      $widgetHeader = $widgetSettings['header'];
    }
    if (!empty($widgetHeader)) {
      $checkJson = json_decode($widgetHeader, TRUE);
      if (!$checkJson) {
        $header = str_replace([
          "\r\n",
          "\r",
          "\t",
          ',',
          ';',
        ], PHP_EOL, $widgetHeader);
        $header = explode(PHP_EOL, $header);
      }
      elseif (is_array($checkJson)) {
        $header = $checkJson;
      }
    }
    $options['url'] = FALSE;
    if (!empty($setting['caption'])) {
      $options['title'] = $setting['caption'];
    }
    $setting['options'] = $options;
    $elements['#attached'] = [
      'drupalSettings' => [
        $mode => [$field_name => $setting],
      ],
    ];
    if (!empty($items)) {
      switch ($mode) {
        case 'googleCharts':
          $elements['#attached']['library'] = ['json_table/googleCharts'];
          break;

        case 'chartjs':
          $elements['#attached']['library'] = ['json_table/chartjs'];
          break;

        default:
          $elements = [];
      }
    }
    if (is_numeric($setting['chart_width'])) {
      $setting['chart_width'] .= 'px';
    }
    if (is_numeric($setting['chart_height'])) {
      $setting['chart_height'] .= 'px';
    }
    if (empty($setting['chart_width'])) {
      $setting['chart_width'] = '100%';
    }

    foreach ($items as $delta => $item) {
      $value = $item->value;
      if (empty($value)) {
        continue;
      }
      $id = Html::getUniqueId($field_name . '-' . $delta);
      $elements[$delta] = [
        '#theme' => 'json_table_chart',
        '#settings' => $setting,
        '#id_field_name' => $field_name,
        '#langcode' => $langcode,
        '#attributes' => [
          'data-json-field' => $field_name,
          'data-delta' => $delta,
          'class' => [$mode, $field_name],
          'id' => $id,
        ],
      ];
      $value = json_decode($value, JSON_OBJECT_AS_ARRAY);
      if (!empty($value)) {
        foreach ($value as $key => $row) {
          foreach ($row as $col => $val) {
            if (is_numeric($val)) {
              $value[$key][$col] = $val + 0;
            }
          }
          $value[$key] = is_array($value[$key]) ? array_values($value[$key]) : [];
        }
      }
      switch ($mode) {
        case 'googleCharts':
          if (!empty($header)) {
            array_unshift($value, $header);
          }
          $elements['#attached']['drupalSettings'][$mode][$id]['data'] = $value;
          break;

        case 'chartjs':
          if (empty($header)) {
            $header = array_shift($value);
          }
          // Support 20 colors.
          $color = ['#000', '#FF6384', '#36A2EB', '#FFCE56', '#4BC0C0',
            '#9966FF', '#FF9F40', '#33FF99', '#FF66B2', '#C9CBFF', '#66C2A5',
            '#FF6666', '#FC8D62', '#8DA0CB', '#E78AC3', '#A6D854', '#808080',
            '#4D4D4D', '#E0E0E0', '#FFD700', '#00FF00',
          ];
          $opacity = explode(',', 'FF,F2,E6,D9,CC,BF,B3,A6,99,8C,80,73,66,59,4D,40,33,26,1A,0D,00');
          $chartJsOption = $this->chartJsOption($setting['chart_type']);
          $labels = $datasets = [];
          if (!empty($value)) {
            $labels = array_column($value, 0);
            foreach ($header as $delta => $label) {
              if ($delta) {
                $datasets[] = [
                  'label' => $label,
                  'data' => array_column($value, $delta),
                  'backgroundColor' => $color[$delta] ?? $color[0] . $opacity[$delta] ?? $opacity[0],
                ];
              }
            }
          }
          $elements['#attached']['drupalSettings'][$mode][$id]['data'] = [
            'type' => $chartJsOption['type'],
            'labels' => $labels,
            'datasets' => $datasets,
            'title' => $fieldName,
            'subtitle' => $description,
          ];
          break;
      }
    }
    return $elements;
  }

  /**
   * {@inheritDoc}
   */
  private function googleChartsOption($option = FALSE) {
    $options = [
      'BarChart' => [
        'title' => $this->t('Bar'),
        'option' => [
          'bar' => ['groupWidth' => "95%"],
          'legend' => ['position' => "none"],
        ],
      ],
      'BubbleChart' => [
        'title' => $this->t('Bubble'),
        'option' => [
          'bubble' => ['textStyle' => ['fontSize' => 11]],
        ],
      ],
      'LineChart' => [
        'title' => $this->t('Line'),
        'option' => [
          'legend' => ['position' => "bottom"],
          'curveType' => 'function',
        ],
      ],
      'ColumnChart' => [
        'title' => $this->t('Column'),
        'option' => [
          'bar' => ['groupWidth' => "95%"],
          'legend' => ['position' => "none"],
        ],
      ],
      'ComboChart' => [
        'title' => $this->t('Combo'),
        'option' => [
          'seriesType' => 'bars',
        ],
      ],
      'PieChart' => [
        'title' => $this->t('Pie'),
        'option' => [
          'is3D' => TRUE,
        ],
      ],
      'ScatterChart' => [
        'title' => $this->t('Scatter'),
        'option' => [
          'legend' => ['position' => "none"],
        ],
      ],
      'SteppedAreaChart' => [
        'title' => $this->t('Stepped Area'),
        'option' => [
          'isStacked' => TRUE,
        ],
      ],
      'AreaChart' => [
        'title' => $this->t('Area'),
        'option' => [
          'legend' => ['position' => "top", 'maxLines' => 3],
          'isStacked' => 'relative',
        ],
      ],
      'Histogram' => [
        'title' => $this->t('Histogram'),
        'option' => [
          'legend' => ['position' => "top", 'maxLines' => 3],
          'interpolateNulls' => FALSE,
        ],
      ],
      'CandlestickChart' => [
        'title' => $this->t('Candlestick'),
        'option' => [
          'notHeader' => TRUE,
          'legend' => 'none',
          'bar' => ['groupWidth' => '100%'],
        ],
      ],
    ];
    if ($option) {
      return $options[$option]['option'];
    }
    $titleOptions = [];
    foreach ($options as $type => $option) {
      $titleOptions[$type] = $option['title'];
    }
    return $titleOptions;
  }

  /**
   * {@inheritdoc}
   */
  private function chartJsOption($option) {
    $options = [
      'BarChart' => [
        'type' => 'bar',
        'option' => [
          'indexAxis' => 'y',
        ],
      ],
      'BubbleChart' => [
        'type' => 'bubble',
      ],
      'LineChart' => [
        'type' => 'line',
      ],
      'ColumnChart' => [
        'type' => 'bar',
      ],
      'ComboChart' => [
        'type' => 'doughnut',
      ],
      'PieChart' => [
        'type' => 'pie',
      ],
      'ScatterChart' => [
        'type' => 'scatter',
        'option' => [
          'scales' => [
            'x' => [
              'type' => 'linear',
              'position' => 'bottom',
            ],
          ],
        ],
      ],
      'SteppedAreaChart' => [
        'type' => 'radar',
        'option' => [
          'elements' => [
            'line' => ['borderWidth' => 3],
          ],
        ],
      ],
      'AreaChart' => [
        'type' => 'polarArea',
      ],
    ];
    return $options[$option] ?? $options['BarChart'];
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc