FormHelper.php 14 KB
Newer Older
1 2
<?php

3
namespace Drupal\simple_sitemap\Form;
4

Pawel G's avatar
Pawel G committed
5
use Drupal\Core\Form\FormStateInterface;
6
use Drupal\Core\StringTranslation\StringTranslationTrait;
7
use Drupal\simple_sitemap\EntityHelper;
Pawel G's avatar
Pawel G committed
8 9
use Drupal\simple_sitemap\Simplesitemap;
use Drupal\Core\Session\AccountProxyInterface;
10

11
/**
Pawel G's avatar
Pawel G committed
12
 * Class FormHelper
13
 * @package Drupal\simple_sitemap\Form
14
 */
15
class FormHelper {
16
  use StringTranslationTrait;
17

Pawel G's avatar
Pawel G committed
18 19 20 21
  const PRIORITY_DEFAULT = 0.5;
  const PRIORITY_HIGHEST = 10;
  const PRIORITY_DIVIDER = 10;

Pawel G's avatar
Pawel G committed
22 23 24
  /**
   * @var \Drupal\simple_sitemap\Simplesitemap
   */
25
  protected $generator;
Pawel G's avatar
Pawel G committed
26 27 28 29

  /**
   * @var \Drupal\simple_sitemap\EntityHelper
   */
30
  protected $entityHelper;
Pawel G's avatar
Pawel G committed
31 32 33 34

  /**
   * @var \Drupal\Core\Session\AccountProxyInterface
   */
35
  protected $currentUser;
Pawel G's avatar
Pawel G committed
36 37 38 39

  /**
   * @var \Drupal\Core\Form\FormState
   */
40
  protected $formState;
41

Pawel G's avatar
Pawel G committed
42 43 44
  /**
   * @var string|null
   */
Pawel G's avatar
Pawel G committed
45
  protected $entityCategory;
Pawel G's avatar
Pawel G committed
46 47 48 49

  /**
   * @var string
   */
50
  protected $entityTypeId;
Pawel G's avatar
Pawel G committed
51 52 53 54

  /**
   * @var string
   */
55
  protected $bundleName;
Pawel G's avatar
Pawel G committed
56 57 58 59

  /**
   * @var string
   */
60
  protected $instanceId;
61

62
  protected static $allowedFormOperations = [
63 64 65
    'default',
    'edit',
    'add',
Pawel G's avatar
Pawel G committed
66
    'register',
67 68
  ];

69
  protected static $changefreqValues = [
70 71 72 73 74 75 76 77 78
    'always',
    'hourly',
    'daily',
    'weekly',
    'monthly',
    'yearly',
    'never',
  ];

79
  protected static $valuesToCheck = [
80 81
    'simple_sitemap_index_content',
    'simple_sitemap_priority',
82
    'simple_sitemap_changefreq',
83
    'simple_sitemap_include_images',
Pawel G's avatar
Pawel G committed
84
    'simple_sitemap_regenerate_now',
85
  ];
86

87
  /**
88 89 90 91
   * FormHelper constructor.
   * @param \Drupal\simple_sitemap\Simplesitemap $generator
   * @param \Drupal\simple_sitemap\EntityHelper $entityHelper
   * @param \Drupal\Core\Session\AccountProxyInterface $current_user
92
   */
Pawel G's avatar
Pawel G committed
93 94
  public function __construct(
    Simplesitemap $generator,
95
    EntityHelper $entityHelper,
Pawel G's avatar
Pawel G committed
96 97
    AccountProxyInterface $current_user
  ) {
98
    $this->generator = $generator;
99
    $this->entityHelper = $entityHelper;
100
    $this->currentUser = $current_user;
101
  }
Pawel G's avatar
Pawel G committed
102

103
  /**
Pawel G's avatar
Pawel G committed
104 105
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   * @return bool
106
   */
Pawel G's avatar
Pawel G committed
107
  public function processForm(FormStateInterface $form_state) {
Pawel G's avatar
Pawel G committed
108
    $this->formState = $form_state;
109
    $this->cleanUpFormInfo();
110
    $this->getEntityDataFromFormEntity();
Pawel G's avatar
Pawel G committed
111
    return $this->supports();
112 113
  }

114
  /**
Pawel G's avatar
Pawel G committed
115
   * @param string $entity_category
116 117
   * @return $this
   */
118 119
  public function setEntityCategory($entity_category) {
    $this->entityCategory = $entity_category;
120
    return $this;
121 122
  }

123
  /**
124
   * @return null|string
125
   */
126 127 128 129 130 131 132 133
  public function getEntityCategory() {
    return $this->entityCategory;
  }

  /**
 * @param string $entity_type_id
 * @return $this
 */
134 135
  public function setEntityTypeId($entity_type_id) {
    $this->entityTypeId = $entity_type_id;
136
    return $this;
137 138
  }

139 140 141 142 143 144 145
  /**
   * @return string
   */
  public function getEntityTypeId() {
    return $this->entityTypeId;
  }

146
  /**
Pawel G's avatar
Pawel G committed
147
   * @param string $bundle_name
148 149
   * @return $this
   */
150 151
  public function setBundleName($bundle_name) {
    $this->bundleName = $bundle_name;
152
    return $this;
153 154
  }

155 156 157 158 159 160 161
  /**
   * @return string
   */
  public function getBundleName() {
    return $this->bundleName;
  }

162
  /**
Pawel G's avatar
Pawel G committed
163
   * @param string $instance_id
164 165
   * @return $this
   */
166 167
  public function setInstanceId($instance_id) {
    $this->instanceId = $instance_id;
168
    return $this;
169 170
  }

171 172 173 174 175 176 177
  /**
   * @return string
   */
  public function getInstanceId() {
    return $this->instanceId;
  }

Pawel G's avatar
Pawel G committed
178
  /**
Pawel G's avatar
Pawel G committed
179
   * @return bool
Pawel G's avatar
Pawel G committed
180
   */
Pawel G's avatar
Pawel G committed
181
  protected function supports() {
Pawel G's avatar
Pawel G committed
182 183

    // Do not alter the form if user lacks certain permissions.
Pawel G's avatar
Pawel G committed
184
    if (!$this->currentUser->hasPermission('administer sitemap settings')) {
Pawel G's avatar
Pawel G committed
185
      return FALSE;
Pawel G's avatar
Pawel G committed
186
    }
Pawel G's avatar
Pawel G committed
187 188

    // Do not alter the form if it is irrelevant to sitemap generation.
189
    elseif (empty($this->getEntityCategory())) {
Pawel G's avatar
Pawel G committed
190
      return FALSE;
Pawel G's avatar
Pawel G committed
191
    }
Pawel G's avatar
Pawel G committed
192 193

    // Do not alter the form if entity is not enabled in sitemap settings.
194
    elseif (!$this->generator->entityTypeIsEnabled($this->getEntityTypeId())) {
Pawel G's avatar
Pawel G committed
195
      return FALSE;
Pawel G's avatar
Pawel G committed
196
    }
Pawel G's avatar
Pawel G committed
197 198 199

    // Do not alter the form, if sitemap is disabled for the entity type of this
    // entity instance.
Pawel G's avatar
Pawel G committed
200
    elseif ($this->getEntityCategory() === 'instance'
201
      && !$this->generator->bundleIsIndexed($this->getEntityTypeId(), $this->getBundleName())) {
Pawel G's avatar
Pawel G committed
202
      return FALSE;
Pawel G's avatar
Pawel G committed
203
    }
Pawel G's avatar
Pawel G committed
204 205

    return TRUE;
Pawel G's avatar
Pawel G committed
206 207
  }

208
  /**
Pawel G's avatar
Pawel G committed
209
   * @param array $form_fragment
210
   */
Pawel G's avatar
Pawel G committed
211
  public function displayRegenerateNow(&$form_fragment) {
Pawel G's avatar
Pawel G committed
212
    $form_fragment['simple_sitemap_regenerate_now'] = [
213
      '#type' => 'checkbox',
214 215
      '#title' => $this->t('Regenerate sitemap after hitting <em>Save</em>'),
      '#description' => $this->t('This setting will regenerate the whole sitemap including the above changes.'),
216
      '#default_value' => FALSE,
Pawel G's avatar
Pawel G committed
217
    ];
Pawel G's avatar
Pawel G committed
218
    if ($this->generator->getSetting('cron_generate')) {
219
      $form_fragment['simple_sitemap_regenerate_now']['#description'] .= '</br>' . $this->t('Otherwise the sitemap will be regenerated during a future cron run.');
220 221
    }
  }
222 223

  /**
224
   * @param array $form_fragment
225 226 227
   * @param bool $multiple
   * @return $this
   */
228
  public function displayEntitySettings(&$form_fragment, $multiple = FALSE) {
229
    $prefix = $multiple ? $this->getEntityTypeId() . '_' : '';
230

231
    if ($this->getEntityCategory() === 'instance') {
232
      $bundle_settings = $this->generator->getBundleSettings($this->getEntityTypeId(), $this->getBundleName());
Pawel G's avatar
Pawel G committed
233 234 235
      $settings = NULL !== $this->getInstanceId()
        ? $this->generator->getEntityInstanceSettings($this->getEntityTypeId(), $this->getInstanceId())
        : $bundle_settings;
236
    }
237
    else {
238
      $settings = $this->generator->getBundleSettings($this->getEntityTypeId(), $this->getBundleName());
239
    }
240
    Simplesitemap::supplementDefaultSettings('entity', $settings);
Pawel G's avatar
Pawel G committed
241

242
    $bundle_name = !empty($this->getBundleName()) ? $this->getBundleName() : $this->t('undefined');
243

Pawel G's avatar
Pawel G committed
244
    // Index
245 246 247
    if (!$multiple) {
      $form_fragment[$prefix . 'simple_sitemap_index_content'] = [
        '#type' => 'radios',
248
        '#default_value' => (int) $settings['index'],
249
        '#options' => [
Pawel G's avatar
Pawel G committed
250 251 252 253 254 255
          0 => $this->getEntityCategory() === 'instance'
            ? $this->t('Do not index this @bundle entity', ['@bundle' => $bundle_name])
            : $this->t('Do not index entities of this type'),
          1 => $this->getEntityCategory() === 'instance'
            ? $this->t('Index this @bundle entity', ['@bundle' => $bundle_name])
            : $this->t('Index entities of this type'),
Pawel G's avatar
Pawel G committed
256
        ],
257
      ];
Pawel G's avatar
Pawel G committed
258

259
      if ($this->getEntityCategory() === 'instance' && isset($bundle_settings['index'])) {
260
        $form_fragment[$prefix . 'simple_sitemap_index_content']['#options'][(int) $bundle_settings['index']] .= ' <em>(' . $this->t('default') . ')</em>';
261 262 263
      }
    }

Pawel G's avatar
Pawel G committed
264
    // Priority
265 266
    $form_fragment[$prefix . 'simple_sitemap_priority'] = [
      '#type' => 'select',
267
      '#title' => $this->t('Priority'),
268 269 270
      '#description' => $this->getEntityCategory() === 'instance'
        ? $this->t('The priority this @bundle entity will have in the eyes of search engine bots.', ['@bundle' => $bundle_name])
        : $this->t('The priority entities of this type will have in the eyes of search engine bots.'),
Pawel G's avatar
Pawel G committed
271
      '#default_value' => $settings['priority'],
272
      '#options' => $this->getPrioritySelectValues(),
273
    ];
274

275 276
    if ($this->getEntityCategory() === 'instance' && isset($bundle_settings['priority'])) {
      $form_fragment[$prefix . 'simple_sitemap_priority']['#options'][$this->formatPriority($bundle_settings['priority'])] .= ' (' . $this->t('default') . ')';
277
    }
278

Pawel G's avatar
Pawel G committed
279
    // Changefreq
280 281 282
    $form_fragment[$prefix . 'simple_sitemap_changefreq'] = [
      '#type' => 'select',
      '#title' => $this->t('Change frequency'),
283 284 285
      '#description' => $this->getEntityCategory() === 'instance'
      ? $this->t('The frequency with which this @bundle entity changes. Search engine bots may take this as an indication of how often to index it.', ['@bundle' => $bundle_name])
      : $this->t('The frequency with which entities of this type change. Search engine bots may take this as an indication of how often to index them.'),
Pawel G's avatar
Pawel G committed
286
      '#default_value' => $settings['changefreq'],
287 288 289
      '#options' => $this->getChangefreqSelectValues(),
    ];

290 291 292 293
    if ($this->getEntityCategory() === 'instance' && isset($bundle_settings['changefreq'])) {
      $form_fragment[$prefix . 'simple_sitemap_changefreq']['#options'][$bundle_settings['changefreq']] .= ' (' . $this->t('default') . ')';
    }

Pawel G's avatar
Pawel G committed
294
    // Images
295 296 297 298
    $form_fragment[$prefix . 'simple_sitemap_include_images'] = [
      '#type' => 'select',
      '#title' => $this->t('Include images'),
      '#description' => $this->getEntityCategory() === 'instance'
Pawel G's avatar
Pawel G committed
299 300
        ? $this->t('Determines if images referenced by this @bundle entity should be included in the sitemap.', ['@bundle' => $bundle_name])
        : $this->t('Determines if images referenced by entities of this type should be included in the sitemap.'),
301
      '#default_value' => (int) $settings['include_images'],
302 303 304 305
      '#options' => [0 => $this->t('No'), 1 => $this->t('Yes')],
    ];

    if ($this->getEntityCategory() === 'instance' && isset($bundle_settings['include_images'])) {
306
      $form_fragment[$prefix . 'simple_sitemap_include_images']['#options'][(int) $bundle_settings['include_images']] .= ' (' . $this->t('default') . ')';
307 308
    }

Pawel G's avatar
Pawel G committed
309
    return $this;
310 311 312 313 314 315 316
  }

  /**
   * Checks if this particular form is a bundle form, or a bundle instance form
   * and gathers sitemap settings from the database.
   *
   * @return bool
Pawel G's avatar
Pawel G committed
317
   *   TRUE if this is a bundle or bundle instance form, FALSE otherwise.
318
   */
319
  protected function getEntityDataFromFormEntity() {
Pawel G's avatar
Pawel G committed
320
    if (!$form_entity = $this->getFormEntity()) {
Pawel G's avatar
Pawel G committed
321 322
      return FALSE;
    }
323

Pawel G's avatar
Pawel G committed
324 325 326 327 328 329 330 331 332 333 334 335
    $entity_type_id = $form_entity->getEntityTypeId();
    $sitemap_entity_types = $this->entityHelper->getSupportedEntityTypes();
    if (isset($sitemap_entity_types[$entity_type_id])) {
      $this->setEntityCategory('instance');
    }
    else {
      /**
       * @var \Drupal\Core\Entity\EntityType $sitemap_entity_type
       */
      foreach ($sitemap_entity_types as $sitemap_entity_type) {
        if ($sitemap_entity_type->getBundleEntityType() === $entity_type_id) {
          $this->setEntityCategory('bundle');
336
          break;
Pawel G's avatar
Pawel G committed
337
        }
338
      }
339
    }
Pawel G's avatar
Pawel G committed
340 341

    // Menu fix.
Pawel G's avatar
Pawel G committed
342
    $this->setEntityCategory(NULL === $this->getEntityCategory() && $entity_type_id === 'menu' ? 'bundle' : $this->getEntityCategory());
Pawel G's avatar
Pawel G committed
343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361

    switch ($this->getEntityCategory()) {
      case 'bundle':
        $this->setEntityTypeId($this->entityHelper->getBundleEntityTypeId($form_entity));
        $this->setBundleName($form_entity->id());
        $this->setInstanceId(NULL);
        break;

      case 'instance':
        $this->setEntityTypeId($entity_type_id);
        $this->setBundleName($this->entityHelper->getEntityInstanceBundleName($form_entity));
        // New menu link's id is '' instead of NULL, hence checking for empty.
        $this->setInstanceId(!empty($form_entity->id()) ? $form_entity->id() : NULL);
        break;

      default:
        return FALSE;
    }
    return TRUE;
362 363 364 365 366
  }

  /**
   * Gets the object entity of the form if available.
   *
Pawel G's avatar
Pawel G committed
367
   * @return \Drupal\Core\Entity\Entity|false
Pawel G's avatar
Pawel G committed
368 369
   *   Entity or FALSE if non-existent or if form operation is
   *   'delete'.
370
   */
371
  protected function getFormEntity() {
372
    $form_object = $this->formState->getFormObject();
373
    if (NULL !== $form_object
374
      && method_exists($form_object, 'getOperation')
375
      && method_exists($form_object, 'getEntity')
376
      && in_array($form_object->getOperation(), self::$allowedFormOperations)) {
377 378 379 380 381
      return $form_object->getEntity();
    }
    return FALSE;
  }

382 383 384 385 386 387 388 389 390 391 392 393 394
  /**
   * Removes gathered form information from service object.
   *
   * Needed because this service may contain form info from the previous
   * operation when revived from the container.
   */
  protected function cleanUpFormInfo() {
    $this->entityCategory = NULL;
    $this->entityTypeId = NULL;
    $this->bundleName = NULL;
    $this->instanceId = NULL;
  }

395 396 397 398
  /**
   * Gets new entity Id after entity creation.
   * To be used in an entity form submit.
   *
Pawel G's avatar
Pawel G committed
399
   * @return int
Pawel G's avatar
Pawel G committed
400
   *   Entity ID.
401
   */
Pawel G's avatar
Pawel G committed
402 403
  public function getFormEntityId() {
    return $this->formState->getFormObject()->getEntity()->id();
404 405 406 407 408 409
  }

  /**
   * Checks if simple_sitemap values have been changed after submitting the form.
   * To be used in an entity form submit.
   *
410
   * @param $form
411
   * @param array $values
Pawel G's avatar
Pawel G committed
412
   *
413
   * @return bool
Pawel G's avatar
Pawel G committed
414
   *   TRUE if simple_sitemap form values have been altered by the user.
415
   */
416
  public function valuesChanged($form, array $values) {
Pawel G's avatar
Pawel G committed
417
    foreach (self::$valuesToCheck as $field_name) {
418
      if (isset($values[$field_name]) && $values[$field_name] != $form['simple_sitemap'][$field_name]['#default_value']) {
419 420 421 422 423
        return TRUE;
      }
    }
    return FALSE;
  }
Pawel G's avatar
Pawel G committed
424 425 426 427

  /**
   * Gets the values needed to display the priority dropdown setting.
   *
428
   * @return array
429
   *   Select options.
Pawel G's avatar
Pawel G committed
430
   */
431
  public function getPrioritySelectValues() {
Pawel G's avatar
Pawel G committed
432
    $options = [];
Pawel G's avatar
Pawel G committed
433
    foreach (range(0, self::PRIORITY_HIGHEST) as $value) {
434
      $value = $this->formatPriority($value / self::PRIORITY_DIVIDER);
435
      $options[$value] = $value;
Pawel G's avatar
Pawel G committed
436 437 438
    }
    return $options;
  }
439

440 441 442 443 444 445 446
  /**
   * Gets the values needed to display the changefreq dropdown setting.
   *
   * @return array
   *   Select options.
   */
  public function getChangefreqSelectValues() {
Pawel G's avatar
Pawel G committed
447
    $options = ['' => $this->t('- Not specified -')];
448
    foreach (self::$changefreqValues as $setting) {
Pawel G's avatar
Pawel G committed
449
      $options[$setting] = $this->t($setting);
450 451 452 453 454 455 456 457
    }
    return $options;
  }

  /**
   * @return array
   */
  public static function getChangefreqOptions() {
458
    return self::$changefreqValues;
459 460
  }

461
  /**
462
   * @param string $priority
463 464 465
   * @return string
   */
  public function formatPriority($priority) {
Pawel G's avatar
Pawel G committed
466
    return number_format((float) $priority, 1, '.', '');
467 468
  }

469
  /**
470
   * @param string|int $priority
471 472
   * @return bool
   */
473
  public static function isValidPriority($priority) {
474
    return is_numeric($priority) && $priority >= 0 && $priority <= 1;
475
  }
476 477 478 479 480 481

  /**
   * @param string $changefreq
   * @return bool
   */
  public static function isValidChangefreq($changefreq) {
482
    return in_array($changefreq, self::$changefreqValues);
483
  }
484
}