charts_highstock-1.0.x-dev/src/Plugin/views/field/HighstockValue.php
src/Plugin/views/field/HighstockValue.php
<?php
namespace Drupal\charts_highstock\Plugin\views\field;
use Drupal\charts\ChartViewsFieldInterface;
use Drupal\Component\Datetime\DateTimePlus;
use Drupal\Component\Serialization\Json;
use Drupal\Core\Entity\EntityTypeManager;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\views\Plugin\views\field\FieldPluginBase;
use Drupal\views\ResultRow;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* @file
* Defines Drupal\charts_highstock\Plugin\views\field\HighstockValue.
*/
/**
* Field handler to generate an array with a timestamp and value.
*
* @ingroup views_field_handlers
*
* @ViewsField("field_charts_highstock")
*/
class HighstockValue extends FieldPluginBase implements ContainerFactoryPluginInterface, ChartViewsFieldInterface {
/**
* The entity type manager service.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
*/
protected $entityTypeManager;
/**
* Highstock Value constructor.
*
* @param array $configuration
* The plugin configurations.
* @param $plugin_id
* The plugin id.
* @param $plugin_definition
* The plugin definition.
* @param \Drupal\Core\Entity\EntityTypeManager $entityTypeManager
* The entity type manager service.
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManager $entityTypeManager) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->entityTypeManager = $entityTypeManager;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static($configuration, $plugin_id, $plugin_definition,
$container->get('entity_type.manager')
);
}
/**
* Sets the initial field data at zero.
*/
public function query() {
}
/**
* {@inheritdoc}
*/
protected function defineOptions() {
$options = parent::defineOptions();
$options['timestamp'] = ['default' => []];
$options['value'] = ['default' => []];
$options['value_set_precision'] = ['default' => FALSE];
$options['value_precision'] = ['default' => 0];
$options['value_decimal'] = ['default' => '.'];
$options['value_separator'] = ['default' => ','];
$options['value_source'] = ['default' => 'entity'];
return $options;
}
/**
* {@inheritdoc}
*/
public function buildOptionsForm(&$form, FormStateInterface $form_state) {
parent::buildOptionsForm($form, $form_state);
$all_fields = $this->displayHandler->getFieldLabels();
// Remove any field that have been excluded from the display from the list.
foreach ($all_fields as $key => $field) {
$exclude = $this->view->display_handler->handlers['field'][$key]->options['exclude'];
if ($exclude) {
unset($all_fields[$key]);
}
}
// Offer to include only those fields that follow this one.
$field_options = array_slice($all_fields, 0, array_search($this->options['id'], array_keys($all_fields)));
$form['timestamp'] = [
'#type' => 'select',
'#title' => $this->t('Timestamp Provider'),
'#description' => $this->t('Field that outputs a timestamp value.'),
'#options' => $field_options,
'#default_value' => $this->options['timestamp'],
];
$form['value'] = [
'#type' => 'select',
'#title' => $this->t('Value Provider'),
'#description' => $this->t('Field that outputs a value.'),
'#options' => $field_options,
'#default_value' => $this->options['value'],
];
$form['value_source'] = [
'#type' => 'select',
'#title' => $this->t('Value provider source'),
'#options' => [
'entity' => $this->t('Entity'),
'views' => $this->t('Views'),
],
'#default_value' => $this->options['value_source'] ?? 'entity',
'#description' => $this->t('Where the value provider source should be extracted from. If from entity, it means that any views rewrite from the views value provider won\'t be taken into account.'),
];
$form['value_set_precision'] = [
'#type' => 'checkbox',
'#title' => $this->t('Round'),
'#description' => $this->t('If checked, the value provider will be rounded.'),
'#default_value' => $this->options['value_set_precision'],
];
$form['value_precision'] = [
'#type' => 'number',
'#title' => $this->t('Precision'),
'#default_value' => $this->options['value_precision'],
'#min' => 0,
'#max' => 10,
'#description' => $this->t('Specify how many digits to print after the decimal point of the value provider.'),
'#states' => [
'visible' => [
':input[name="options[value_set_precision]"]' => ['checked' => TRUE],
],
],
];
$form['value_decimal'] = [
'#type' => 'textfield',
'#title' => $this->t('Decimal point'),
'#default_value' => $this->options['value_decimal'],
'#description' => $this->t('What single character to use as a decimal point for value provider.'),
'#size' => 2,
];
$form['value_separator'] = [
'#type' => 'select',
'#title' => $this->t('Thousands marker'),
'#options' => [
'' => $this->t('- None -'),
',' => $this->t('Comma'),
' ' => $this->t('Space'),
'.' => $this->t('Decimal'),
'\'' => $this->t('Apostrophe'),
],
'#default_value' => $this->options['value_separator'],
'#description' => $this->t('What single character to use as the thousands separator.'),
];
}
/**
* {@inheritdoc}
*/
public function getValue(ResultRow $values, $field = NULL) {
parent::getValue($values, $field);
// $is_aggregated = $this->displayHandler->useGroupBy();
$timestamp_field = $this->options['timestamp'] ?? '';
$timestamp = $timestamp_field ? $this->view->field[$timestamp_field]->getValue($values) : NULL;
if (!is_numeric($timestamp)) {
return NULL;
}
$value_field = $this->options['value'] ?? NULL;
$value = NULL;
if ($value_field) {
$source = $this->options['value_source'] ?? 'entity';
$value = $source === 'entity' ?
($values->_entity->{$value_field}->value ?? NULL) :
(string)($this->view->field[$value_field]->advancedRender($values));
}
if (!is_numeric($value)) {
return NULL;
}
return Json::encode([
Json::decode($timestamp),
Json::decode($this->formatNumber($value)),
]);
}
private function formatNumber($value) {
$value = $value ?? 0;
if (!is_numeric($value)) {
return $value;
}
if (!empty($this->options['value_set_precision'])) {
$precision = $this->options['value_precision'];
}
elseif ($decimal_position = strpos($value, '.')) {
$precision = strlen($value) - $decimal_position - 1;
}
else {
$precision = 0;
}
$value = round($value, $precision);
if ($value == 0 || $value == 0.0) {
return $value;
}
return number_format($value, $precision, $this->options['value_decimal'], $this->options['value_separator']);
}
/**
* Set the data type for the chart field to be an array.
*
* @return string
* The data type.
*/
public function getChartFieldDataType(): string {
return 'array';
}
}
