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

3
namespace Drupal\simple_sitemap\Form;
4

5
use Drupal\Core\StringTranslation\StringTranslationTrait;
6
use Drupal\simple_sitemap\EntityHelper;
Pawel G's avatar
Pawel G committed
7 8
use Drupal\simple_sitemap\Simplesitemap;
use Drupal\Core\Session\AccountProxyInterface;
9
use Drupal\Core\Form\FormState;
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
  private $generator;
Pawel G's avatar
Pawel G committed
26 27 28 29

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

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

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

Pawel G's avatar
Pawel G committed
42 43 44
  /**
   * @var bool
   */
45
  public $alteringForm = TRUE;
Pawel G's avatar
Pawel G committed
46 47 48 49

  /**
   * @var string|null
   */
50
  public $entityCategory = NULL;
Pawel G's avatar
Pawel G committed
51 52 53 54

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

  /**
   * @var string
   */
60
  public $bundleName;
Pawel G's avatar
Pawel G committed
61 62 63 64

  /**
   * @var string
   */
65
  public $instanceId;
66

67 68 69 70
  private static $allowedFormOperations = [
    'default',
    'edit',
    'add',
Pawel G's avatar
Pawel G committed
71
    'register',
72 73 74 75 76
  ];

  private static $valuesToCheck = [
    'simple_sitemap_index_content',
    'simple_sitemap_priority',
Pawel G's avatar
Pawel G committed
77
    'simple_sitemap_regenerate_now',
78
  ];
79

80
  /**
81 82 83 84
   * FormHelper constructor.
   * @param \Drupal\simple_sitemap\Simplesitemap $generator
   * @param \Drupal\simple_sitemap\EntityHelper $entityHelper
   * @param \Drupal\Core\Session\AccountProxyInterface $current_user
85
   */
Pawel G's avatar
Pawel G committed
86 87
  public function __construct(
    Simplesitemap $generator,
88
    EntityHelper $entityHelper,
Pawel G's avatar
Pawel G committed
89 90
    AccountProxyInterface $current_user
  ) {
91
    $this->generator = $generator;
92
    $this->entityHelper = $entityHelper;
93
    $this->currentUser = $current_user;
94
  }
Pawel G's avatar
Pawel G committed
95

96
  /**
Pawel G's avatar
Pawel G committed
97
   * @param \Drupal\Core\Form\FormState $form_state
98 99
   * @return $this
   */
100
  public function processForm(FormState $form_state) {
Pawel G's avatar
Pawel G committed
101
    $this->formState = $form_state;
Pawel G's avatar
Pawel G committed
102
    if (!is_null($this->formState)) {
103
      $this->getEntityDataFromFormEntity();
Pawel G's avatar
Pawel G committed
104 105
      $this->assertAlteringForm();
    }
106
    return $this;
107 108
  }

109
  /**
Pawel G's avatar
Pawel G committed
110
   * @param string $entity_category
111 112
   * @return $this
   */
113 114
  public function setEntityCategory($entity_category) {
    $this->entityCategory = $entity_category;
115
    return $this;
116 117
  }

118
  /**
Pawel G's avatar
Pawel G committed
119
   * @param string $entity_type_id
120 121
   * @return $this
   */
122 123
  public function setEntityTypeId($entity_type_id) {
    $this->entityTypeId = $entity_type_id;
124
    return $this;
125 126
  }

127
  /**
Pawel G's avatar
Pawel G committed
128
   * @param string $bundle_name
129 130
   * @return $this
   */
131 132
  public function setBundleName($bundle_name) {
    $this->bundleName = $bundle_name;
133
    return $this;
134 135
  }

136
  /**
Pawel G's avatar
Pawel G committed
137
   * @param string $instance_id
138 139
   * @return $this
   */
140 141
  public function setInstanceId($instance_id) {
    $this->instanceId = $instance_id;
142
    return $this;
143 144
  }

Pawel G's avatar
Pawel G committed
145 146 147
  /**
   *
   */
Pawel G's avatar
Pawel G committed
148 149 150
  private function assertAlteringForm() {

    // Do not alter the form if user lacks certain permissions.
Pawel G's avatar
Pawel G committed
151
    if (!$this->currentUser->hasPermission('administer sitemap settings')) {
Pawel G's avatar
Pawel G committed
152
      $this->alteringForm = FALSE;
Pawel G's avatar
Pawel G committed
153
    }
Pawel G's avatar
Pawel G committed
154 155

    // Do not alter the form if it is irrelevant to sitemap generation.
Pawel G's avatar
Pawel G committed
156
    elseif (empty($this->entityCategory)) {
Pawel G's avatar
Pawel G committed
157
      $this->alteringForm = FALSE;
Pawel G's avatar
Pawel G committed
158
    }
Pawel G's avatar
Pawel G committed
159 160

    // Do not alter the form if entity is not enabled in sitemap settings.
Pawel G's avatar
Pawel G committed
161
    elseif (!$this->generator->entityTypeIsEnabled($this->entityTypeId)) {
Pawel G's avatar
Pawel G committed
162
      $this->alteringForm = FALSE;
Pawel G's avatar
Pawel G committed
163
    }
Pawel G's avatar
Pawel G committed
164 165 166 167

    // Do not alter the form, if sitemap is disabled for the entity type of this
    // entity instance.
    elseif ($this->entityCategory == 'instance'
Pawel G's avatar
Pawel G committed
168
      && !$this->generator->bundleIsIndexed($this->entityTypeId, $this->bundleName)) {
Pawel G's avatar
Pawel G committed
169
      $this->alteringForm = FALSE;
Pawel G's avatar
Pawel G committed
170
    }
Pawel G's avatar
Pawel G committed
171 172
  }

173
  /**
Pawel G's avatar
Pawel G committed
174
   * @param array $form_fragment
175
   */
Pawel G's avatar
Pawel G committed
176
  public function displayRegenerateNow(&$form_fragment) {
Pawel G's avatar
Pawel G committed
177
    $form_fragment['simple_sitemap_regenerate_now'] = [
178
      '#type' => 'checkbox',
179 180
      '#title' => $this->t('Regenerate sitemap after hitting <em>Save</em>'),
      '#description' => $this->t('This setting will regenerate the whole sitemap including the above changes.'),
181
      '#default_value' => FALSE,
Pawel G's avatar
Pawel G committed
182
    ];
Pawel G's avatar
Pawel G committed
183
    if ($this->generator->getSetting('cron_generate')) {
184
      $form_fragment['simple_sitemap_regenerate_now']['#description'] .= '</br>' . $this->t('Otherwise the sitemap will be regenerated on the next cron run.');
185 186
    }
  }
187 188

  /**
189
   * @param array $form_fragment
190 191 192
   * @param bool $multiple
   * @return $this
   */
193
  public function displayEntitySettings(&$form_fragment, $multiple = FALSE) {
194
    $prefix = $multiple ? $this->entityTypeId . '_' : '';
195

196
    if ($this->entityCategory == 'instance') {
Pawel G's avatar
Pawel G committed
197 198
      $bundle_settings = $this->generator->getBundleSettings($this->entityTypeId, $this->bundleName);
      $settings = !is_null($this->instanceId) ? $this->generator->getEntityInstanceSettings($this->entityTypeId, $this->instanceId) : $bundle_settings;
199
    }
200
    else {
Pawel G's avatar
Pawel G committed
201
      $settings = $this->generator->getBundleSettings($this->entityTypeId, $this->bundleName);
202 203 204
    }
    $index = isset($settings['index']) ? $settings['index'] : 0;
    $priority = isset($settings['priority']) ? $settings['priority'] : self::PRIORITY_DEFAULT;
205
    $bundle_name = !empty($this->bundleName) ? $this->bundleName : $this->t('undefined');
206 207 208 209 210 211

    if (!$multiple) {
      $form_fragment[$prefix . 'simple_sitemap_index_content'] = [
        '#type' => 'radios',
        '#default_value' => $index,
        '#options' => [
212 213
          0 => $this->entityCategory == 'instance' ? $this->t('Do not index this @bundle entity', ['@bundle' => $bundle_name]) : $this->t('Do not index entities of this type'),
          1 => $this->entityCategory == 'instance' ? $this->t('Index this @bundle entity', ['@bundle' => $bundle_name]) : $this->t('Index entities of this type'),
Pawel G's avatar
Pawel G committed
214
        ],
215
      ];
216
      if ($this->entityCategory == 'instance' && isset($bundle_settings['index'])) {
217
        $form_fragment[$prefix . 'simple_sitemap_index_content']['#options'][$bundle_settings['index']] .= ' <em>(' . $this->t('Default') . ')</em>';
218 219 220
      }
    }

Pawel G's avatar
Pawel G committed
221
    if ($this->entityCategory == 'instance') {
222
      $priority_description = $this->t('The priority this @bundle entity will have in the eyes of search engine bots.', ['@bundle' => $bundle_name]);
Pawel G's avatar
Pawel G committed
223 224
    }
    else {
225
      $priority_description = $this->t('The priority entities of this type will have in the eyes of search engine bots.');
Pawel G's avatar
Pawel G committed
226
    }
227 228
    $form_fragment[$prefix . 'simple_sitemap_priority'] = [
      '#type' => 'select',
229
      '#title' => $this->t('Priority'),
230 231
      '#description' => $priority_description,
      '#default_value' => $priority,
232
      '#options' => $this->getPrioritySelectValues(),
233
    ];
234
    if ($this->entityCategory == 'instance' && isset($bundle_settings['priority'])) {
235
      $form_fragment[$prefix . 'simple_sitemap_priority']['#options'][$this->formatPriority($bundle_settings['priority'])] .= ' (' . $this->t('Default') . ')';
236
    }
Pawel G's avatar
Pawel G committed
237
    return $this;
238 239 240 241 242 243 244
  }

  /**
   * 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
245
   *   TRUE if this is a bundle or bundle instance form, FALSE otherwise.
246
   */
247
  private function getEntityDataFromFormEntity() {
248 249
    $form_entity = $this->getFormEntity();
    if ($form_entity !== FALSE) {
250
      $entity_type_id = $form_entity->getEntityTypeId();
251
      $sitemap_entity_types = $this->entityHelper->getSitemapEntityTypes();
252 253
      if (isset($sitemap_entity_types[$entity_type_id])) {
        $this->entityCategory = 'instance';
254 255
      }
      else {
Pawel G's avatar
Pawel G committed
256
        foreach ($sitemap_entity_types as $sitemap_entity) {
257 258 259
          if ($sitemap_entity->getBundleEntityType() == $entity_type_id) {
            $this->entityCategory = 'bundle';
            break;
260 261 262
          }
        }
      }
263

264
      // Menu fix.
265
      $this->entityCategory = is_null($this->entityCategory) && $entity_type_id == 'menu' ? 'bundle' : $this->entityCategory;
266 267 268

      switch ($this->entityCategory) {
        case 'bundle':
269
          $this->entityTypeId = $this->entityHelper->getBundleEntityTypeId($form_entity);
270 271 272 273 274
          $this->bundleName = $form_entity->id();
          $this->instanceId = NULL;
          break;

        case 'instance':
275
          $this->entityTypeId = $entity_type_id;
276
          $this->bundleName = $this->entityHelper->getEntityInstanceBundleName($form_entity);
Pawel G's avatar
Pawel G committed
277 278
          // New menu link's id is '' instead of NULL, hence checking for empty.
          $this->instanceId = !empty($form_entity->id()) ? $form_entity->id() : NULL;
279 280 281 282 283 284
          break;

        default:
          return FALSE;
      }
      return TRUE;
285 286 287 288 289 290 291
    }
    return FALSE;
  }

  /**
   * Gets the object entity of the form if available.
   *
Pawel G's avatar
Pawel G committed
292
   * @return object|false
Pawel G's avatar
Pawel G committed
293 294
   *   Entity or FALSE if non-existent or if form operation is
   *   'delete'.
295 296 297 298 299
   */
  private function getFormEntity() {
    $form_object = $this->formState->getFormObject();
    if (!is_null($form_object)
      && method_exists($form_object, 'getEntity')
300
      && in_array($form_object->getOperation(), self::$allowedFormOperations)) {
301 302 303 304 305 306 307 308 309
      return $form_object->getEntity();
    }
    return FALSE;
  }

  /**
   * Gets new entity Id after entity creation.
   * To be used in an entity form submit.
   *
Pawel G's avatar
Pawel G committed
310
   * @return int
Pawel G's avatar
Pawel G committed
311
   *   Entity ID.
312
   */
Pawel G's avatar
Pawel G committed
313 314
  public function getFormEntityId() {
    return $this->formState->getFormObject()->getEntity()->id();
315 316 317 318 319 320
  }

  /**
   * Checks if simple_sitemap values have been changed after submitting the form.
   * To be used in an entity form submit.
   *
321
   * @param $form
322
   * @param array $values
Pawel G's avatar
Pawel G committed
323
   *
324
   * @return bool
Pawel G's avatar
Pawel G committed
325
   *   TRUE if simple_sitemap form values have been altered by the user.
326
   */
327
  public function valuesChanged($form, array $values) {
Pawel G's avatar
Pawel G committed
328
    foreach (self::$valuesToCheck as $field_name) {
329
      if (isset($values[$field_name]) && $values[$field_name] != $form['simple_sitemap'][$field_name]['#default_value']) {
330 331 332 333 334
        return TRUE;
      }
    }
    return FALSE;
  }
Pawel G's avatar
Pawel G committed
335 336 337 338

  /**
   * Gets the values needed to display the priority dropdown setting.
   *
339
   * @return array
Pawel G's avatar
Pawel G committed
340
   */
341
  public function getPrioritySelectValues() {
Pawel G's avatar
Pawel G committed
342
    $options = [];
Pawel G's avatar
Pawel G committed
343
    foreach (range(0, self::PRIORITY_HIGHEST) as $value) {
344
      $value = $this->formatPriority($value / self::PRIORITY_DIVIDER);
345
      $options[$value] = $value;
Pawel G's avatar
Pawel G committed
346 347 348
    }
    return $options;
  }
349

350
  /**
351
   * @param string $priority
352 353 354
   * @return string
   */
  public function formatPriority($priority) {
Pawel G's avatar
Pawel G committed
355
    return number_format((float) $priority, 1, '.', '');
356 357
  }

358
  /**
359
   * @param string|int $priority
360 361
   * @return bool
   */
362
  public static function isValidPriority($priority) {
363
    return is_numeric($priority) && $priority >= 0 && $priority <= 1;
364
  }
365
}