GeofieldItem.php 7.49 KB
Newer Older
1 2
<?php

3
namespace Drupal\geofield\Plugin\Field\FieldType;
4

plopesc's avatar
plopesc committed
5
use Drupal\Core\Field\FieldDefinitionInterface;
6
use Drupal\Core\Form\FormStateInterface;
7 8 9
use Drupal\Core\Field\FieldItemBase;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\TypedData\DataDefinition;
10
use Drupal\Component\Plugin\Exception\PluginException;
11 12 13 14 15 16 17 18

/**
 * Plugin implementation of the 'geofield' field type.
 *
 * @FieldType(
 *   id = "geofield",
 *   label = @Translation("Geofield"),
 *   description = @Translation("This field stores geospatial information."),
19
 *   default_widget = "geofield_latlon",
20
 *   default_formatter = "geofield_default"
21 22
 * )
 */
23
class GeofieldItem extends FieldItemBase {
24 25 26 27

  /**
   * {@inheritdoc}
   */
itamair's avatar
itamair committed
28
  public static function defaultStorageSettings() {
29
    return [
30
      'backend' => 'geofield_backend_default',
itamair's avatar
itamair committed
31
    ] + parent::defaultStorageSettings();
32 33
  }

34 35 36 37 38 39 40 41 42
  /**
   * {@inheritdoc}
   */
  public static function defaultFieldSettings() {
    return [
      'backend' => 'geofield_backend_default',
    ] + parent::defaultFieldSettings();
  }

43 44 45
  /**
   * {@inheritdoc}
   */
46
  public static function schema(FieldStorageDefinitionInterface $field) {
47
    /* @var \Drupal\geofield\Plugin\GeofieldBackendManager $backend_manager */
itamair's avatar
itamair committed
48 49
    $backend_manager = \Drupal::service('plugin.manager.geofield_backend');
    $backend_plugin = NULL;
50

51 52 53 54 55
    try {
      /* @var \Drupal\geofield\Plugin\GeofieldBackendPluginInterface $backend_plugin */
      if (!empty($field->getSetting('backend')) && $backend_manager->getDefinition($field->getSetting('backend')) != NULL) {
        $backend_plugin = $backend_manager->createInstance($field->getSetting('backend'));
      }
itamair's avatar
itamair committed
56
    }
57 58 59 60 61 62 63 64
    catch (\Exception $e) {
      watchdog_exception("geofiedl_backend_manager", $e);
      try {
        $backend_plugin = $backend_manager->createInstance('geofield_backend_default');
      }
      catch (PluginException $e) {
        watchdog_exception("geofiedl_backend_manager", $e);
      }
65
    }
66 67
    return [
      'columns' => [
68
        'value' => isset($backend_plugin) ? $backend_plugin->schema() : [],
69
        'geo_type' => [
70 71 72
          'type' => 'varchar',
          'default' => '',
          'length' => 64,
73 74
        ],
        'lat' => [
75
          'type' => 'numeric',
76
          'precision' => 18,
77
          'scale' => 12,
78
          'not null' => FALSE,
79 80
        ],
        'lon' => [
81
          'type' => 'numeric',
82
          'precision' => 18,
83
          'scale' => 12,
84
          'not null' => FALSE,
85 86
        ],
        'left' => [
87
          'type' => 'numeric',
88
          'precision' => 18,
89
          'scale' => 12,
90
          'not null' => FALSE,
91 92
        ],
        'top' => [
93
          'type' => 'numeric',
94
          'precision' => 18,
95
          'scale' => 12,
96
          'not null' => FALSE,
97 98
        ],
        'right' => [
99
          'type' => 'numeric',
100
          'precision' => 18,
101
          'scale' => 12,
102
          'not null' => FALSE,
103 104
        ],
        'bottom' => [
105
          'type' => 'numeric',
106
          'precision' => 18,
107
          'scale' => 12,
108
          'not null' => FALSE,
109 110
        ],
        'geohash' => [
111 112 113
          'type' => 'varchar',
          'length' => GEOFIELD_GEOHASH_LENGTH,
          'not null' => FALSE,
114 115 116 117 118 119 120 121 122 123
        ],
      ],
      'indexes' => [
        'lat' => ['lat'],
        'lon' => ['lon'],
        'top' => ['top'],
        'bottom' => ['bottom'],
        'left' => ['left'],
        'right' => ['right'],
        'geohash' => ['geohash'],
itamair's avatar
itamair committed
124 125
        'centroid' => ['lat', 'lon'],
        'bbox' => ['top', 'bottom', 'left', 'right'],
126 127
      ],
    ];
128 129 130
  }

  /**
itamair's avatar
itamair committed
131
   * {@inheritdoc}
132
   */
133 134
  public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
    $properties['value'] = DataDefinition::create('string')
Brandonian's avatar
Brandonian committed
135 136
      ->setLabel(t('Geometry'))
      ->addConstraint('GeoType', []);
137 138 139 140 141

    $properties['geo_type'] = DataDefinition::create('string')
      ->setLabel(t('Geometry Type'));

    $properties['lat'] = DataDefinition::create('float')
plopesc's avatar
plopesc committed
142
      ->setLabel(t('Centroid Latitude'));
143 144

    $properties['lon'] = DataDefinition::create('float')
plopesc's avatar
plopesc committed
145
      ->setLabel(t('Centroid Longitude'));
146 147 148 149 150 151 152 153 154 155 156 157 158

    $properties['left'] = DataDefinition::create('float')
      ->setLabel(t('Left Bounding'));

    $properties['top'] = DataDefinition::create('float')
      ->setLabel(t('Top Bounding'));

    $properties['right'] = DataDefinition::create('float')
      ->setLabel(t('Right Bounding'));

    $properties['bottom'] = DataDefinition::create('float')
      ->setLabel(t('Bottom Bounding'));

Brandonian's avatar
Brandonian committed
159
    $properties['geohash'] = DataDefinition::create('string')
160 161
      ->setLabel(t('Geohash'));

162 163 164
    $properties['latlon'] = DataDefinition::create('string')
      ->setLabel(t('LatLong Pair'));

165
    return $properties;
166 167
  }

168 169 170
  /**
   * {@inheritdoc}
   */
itamair's avatar
itamair committed
171 172 173
  public function fieldSettingsForm(array $form, FormStateInterface $form_state) {
    // Backend plugins need to define requirement/settings methods,
    // allow them to inject data here.
174
    $element = [];
175

itamair's avatar
itamair committed
176
    $backend_manager = \Drupal::service('plugin.manager.geofield_backend');
177

itamair's avatar
itamair committed
178
    $backends = $backend_manager->getDefinitions();
179
    $backend_options = [];
180 181 182 183 184

    foreach ($backends as $id => $backend) {
      $backend_options[$id] = $backend['admin_label'];
    }

185
    $element['backend'] = [
186
      '#type' => 'select',
187
      '#title' => $this->t('Storage Backend'),
188
      '#default_value' => $this->getSetting('backend'),
189
      '#options' => $backend_options,
190
      '#description' => $this->t("Select the Geospatial storage backend you would like to use to store geofield geometry data. If you don't know what this means, select 'Default Backend'."),
191
    ];
192 193 194 195

    return $element;
  }

196 197 198 199
  /**
   * {@inheritdoc}
   */
  public function isEmpty() {
200 201 202 203 204 205 206 207 208
    try {
      $value = $this->get('value')->getValue();
      if (!empty($value)) {
        /* @var \Drupal\geofield\GeoPHP\GeoPHPInterface $geo_php_wrapper */
        // Note: Geofield FieldType doesn't support Dependency Injection yet
        // (https://www.drupal.org/node/2053415).
        $geo_php_wrapper = \Drupal::service('geofield.geophp');
        /* @var \Geometry|null $geometry */
        $geometry = $geo_php_wrapper->load($value);
209
        return $geometry instanceof \Geometry ? $geometry->isEmpty() : TRUE;
210 211 212
      }
    }
    catch (\Exception $e) {
213
      watchdog_exception('geofield get value exception', $e);
214 215
    }
    return TRUE;
216 217 218
  }

  /**
itamair's avatar
itamair committed
219
   * {@inheritdoc}
220 221 222 223 224 225 226 227 228 229
   */
  public function setValue($values, $notify = TRUE) {
    parent::setValue($values);
    $this->populateComputedValues();
  }

  /**
   * Populates computed variables.
   */
  protected function populateComputedValues() {
itamair's avatar
itamair committed
230 231

    /* @var \Geometry $geom */
232
    $geom = \Drupal::service('geofield.geophp')->load($this->value);
233 234

    if (!empty($geom)) {
itamair's avatar
itamair committed
235
      /* @var \Point $centroid */
236 237 238 239
      $centroid = $geom->getCentroid();
      $bounding = $geom->getBBox();

      $this->geo_type = $geom->geometryType();
240 241
      $this->lon = $centroid->getX();
      $this->lat = $centroid->getY();
242 243 244 245
      $this->left = $bounding['minx'];
      $this->top = $bounding['maxy'];
      $this->right = $bounding['maxx'];
      $this->bottom = $bounding['miny'];
246
      $this->geohash = substr($geom->out('geohash'), 0, GEOFIELD_GEOHASH_LENGTH);
247
      $this->latlon = $centroid->getY() . ',' . $centroid->getX();
248 249
    }
  }
250 251 252 253 254 255

  /**
   * {@inheritdoc}
   */
  public function prepareCache() {
  }
plopesc's avatar
plopesc committed
256 257 258 259 260

  /**
   * {@inheritdoc}
   */
  public static function generateSampleValue(FieldDefinitionInterface $field_definition) {
261
    $value = [
plopesc's avatar
plopesc committed
262
      'value' => \Drupal::service('geofield.wkt_generator')->WktGenerateGeometry(),
263
    ];
plopesc's avatar
plopesc committed
264 265 266
    return $value;
  }

267
}