Form.php 9.47 KB
Newer Older
1 2
<?php

3
namespace Drupal\simple_sitemap\Form;
4

5 6
use Drupal\Core\StringTranslation\StringTranslationTrait;

7
/**
8 9
 * Class Form
 * @package Drupal\simple_sitemap\Form
10 11
 */
class Form {
12
  use StringTranslationTrait;
13

gbyte.co's avatar
gbyte.co committed
14 15 16 17
  const PRIORITY_DEFAULT = 0.5;
  const PRIORITY_HIGHEST = 10;
  const PRIORITY_DIVIDER = 10;

18
  private $generator;
19
  private $currentUser;
20 21 22 23
  private $formState;

  public $alteringForm = TRUE;
  public $entityCategory = NULL;
24 25
  public $entityTypeId;
  public $bundleName;
26
  public $instanceId;
27

28 29 30 31 32 33 34 35 36 37 38 39
  private static $allowedFormOperations = [
    'default',
    'edit',
    'add',
    'register'
  ];

  private static $valuesToCheck = [
    'simple_sitemap_index_content',
    'simple_sitemap_priority',
    'simple_sitemap_regenerate_now'
  ];
40

41 42
  /**
   * Form constructor.
43 44 45
   *
   * @param $generator
   * @param $current_user
46
   */
47
  public function __construct($generator, $current_user) {
48
    $this->generator = $generator;
49
    $this->currentUser = $current_user;
50
  }
51

52 53 54 55
  /**
   * @param $form_state
   * @return $this
   */
56
  public function processForm($form_state) {
57
    $this->formState = $form_state;
gbyte.co's avatar
gbyte.co committed
58
    if (!is_null($this->formState)) {
59
      $this->getEntityDataFromFormEntity();
gbyte.co's avatar
gbyte.co committed
60 61
      $this->assertAlteringForm();
    }
62
    return $this;
63 64
  }

65 66 67 68
  /**
   * @param $entity_category
   * @return $this
   */
69 70
  public function setEntityCategory($entity_category) {
    $this->entityCategory = $entity_category;
71
    return $this;
72 73
  }

74 75 76 77
  /**
   * @param $entity_type_id
   * @return $this
   */
78 79
  public function setEntityTypeId($entity_type_id) {
    $this->entityTypeId = $entity_type_id;
80
    return $this;
81 82
  }

83 84 85 86
  /**
   * @param $bundle_name
   * @return $this
   */
87 88
  public function setBundleName($bundle_name) {
    $this->bundleName = $bundle_name;
89
    return $this;
90 91
  }

92 93 94 95
  /**
   * @param $instance_id
   * @return $this
   */
96 97
  public function setInstanceId($instance_id) {
    $this->instanceId = $instance_id;
98
    return $this;
99 100
  }

gbyte.co's avatar
gbyte.co committed
101 102 103
  private function assertAlteringForm() {

    // Do not alter the form if user lacks certain permissions.
104
    if (!$this->currentUser->hasPermission('administer sitemap settings'))
gbyte.co's avatar
gbyte.co committed
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
      $this->alteringForm = FALSE;

    // Do not alter the form if it is irrelevant to sitemap generation.
    elseif (empty($this->entityCategory))
      $this->alteringForm = FALSE;

    // Do not alter the form if entity is not enabled in sitemap settings.
    elseif (!$this->generator->entityTypeIsEnabled($this->entityTypeId))
      $this->alteringForm = FALSE;

    // Do not alter the form, if sitemap is disabled for the entity type of this
    // entity instance.
    elseif ($this->entityCategory == 'instance'
      && !$this->generator->bundleIsIndexed($this->entityTypeId, $this->bundleName))
      $this->alteringForm = FALSE;
  }

122 123 124
  /**
   * @param $form_fragment
   */
gbyte.co's avatar
gbyte.co committed
125
  public function displayRegenerateNow(&$form_fragment) {
126
    $form_fragment['simple_sitemap_regenerate_now'] = [
127
      '#type' => 'checkbox',
128 129
      '#title' => $this->t('Regenerate sitemap after hitting <em>Save</em>'),
      '#description' => $this->t('This setting will regenerate the whole sitemap including the above changes.'),
130
      '#default_value' => FALSE,
131
    ];
132
    if ($this->generator->getSetting('cron_generate')) {
133
      $form_fragment['simple_sitemap_regenerate_now']['#description'] .= '</br>' . $this->t('Otherwise the sitemap will be regenerated on the next cron run.');
134 135
    }
  }
136 137 138 139 140 141

  /**
   * @param $form_fragment
   * @param bool $multiple
   * @return $this
   */
gbyte.co's avatar
gbyte.co committed
142
  public function displayEntitySettings(&$form_fragment, $multiple = FALSE) {
143
    $prefix = $multiple ? $this->entityTypeId . '_' : '';
144

145
    if ($this->entityCategory == 'instance') {
146 147
      $bundle_settings = $this->generator->getBundleSettings($this->entityTypeId, $this->bundleName);
      $settings = !is_null($this->instanceId) ? $this->generator->getEntityInstanceSettings($this->entityTypeId, $this->instanceId) : $bundle_settings;
148
    }
149
    else {
150
      $settings = $this->generator->getBundleSettings($this->entityTypeId, $this->bundleName);
151 152 153
    }
    $index = isset($settings['index']) ? $settings['index'] : 0;
    $priority = isset($settings['priority']) ? $settings['priority'] : self::PRIORITY_DEFAULT;
154
    $bundle_name = !empty($this->bundleName) ? $this->bundleName : $this->t('undefined');
155 156 157 158 159 160

    if (!$multiple) {
      $form_fragment[$prefix . 'simple_sitemap_index_content'] = [
        '#type' => 'radios',
        '#default_value' => $index,
        '#options' => [
161 162
          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'),
163 164
        ]
      ];
165
      if ($this->entityCategory == 'instance' && isset($bundle_settings['index'])) {
166
        $form_fragment[$prefix . 'simple_sitemap_index_content']['#options'][$bundle_settings['index']] .= ' <em>(' . $this->t('Default') . ')</em>';
167 168 169
      }
    }

170
    if ($this->entityCategory == 'instance')
171
      $priority_description = $this->t('The priority this @bundle entity will have in the eyes of search engine bots.', ['@bundle' => $bundle_name]);
172
    else
173
      $priority_description = $this->t('The priority entities of this type will have in the eyes of search engine bots.');
174 175
    $form_fragment[$prefix . 'simple_sitemap_priority'] = [
      '#type' => 'select',
176
      '#title' => $this->t('Priority'),
177 178
      '#description' => $priority_description,
      '#default_value' => $priority,
179
      '#options' => $this->getPrioritySelectValues(),
180
    ];
181
    if ($this->entityCategory == 'instance' && isset($bundle_settings['priority'])) {
182
      $form_fragment[$prefix . 'simple_sitemap_priority']['#options'][(string)$bundle_settings['priority']] .= ' (' . $this->t('Default') . ')';
183
    }
184
    return $this;
185 186 187 188 189 190 191 192 193
  }

  /**
   * Checks if this particular form is a bundle form, or a bundle instance form
   * and gathers sitemap settings from the database.
   *
   * @return bool
   *  TRUE if this is a bundle or bundle instance form, FALSE otherwise.
   */
194
  private function getEntityDataFromFormEntity() {
195 196
    $form_entity = $this->getFormEntity();
    if ($form_entity !== FALSE) {
197
      $entity_type_id = $form_entity->getEntityTypeId();
198
      $sitemap_entity_types = $this->generator->getSitemapEntityTypes();
199 200
      if (isset($sitemap_entity_types[$entity_type_id])) {
        $this->entityCategory = 'instance';
201 202
      }
      else {
203
        foreach($sitemap_entity_types as $sitemap_entity) {
204 205 206
          if ($sitemap_entity->getBundleEntityType() == $entity_type_id) {
            $this->entityCategory = 'bundle';
            break;
207 208 209
          }
        }
      }
210

211
      // Menu fix.
212
      $this->entityCategory = is_null($this->entityCategory) && $entity_type_id == 'menu' ? 'bundle' : $this->entityCategory;
213 214 215

      switch ($this->entityCategory) {
        case 'bundle':
216
          $this->entityTypeId = $this->generator->getBundleEntityTypeId($form_entity);
217 218 219 220 221
          $this->bundleName = $form_entity->id();
          $this->instanceId = NULL;
          break;

        case 'instance':
222
          $this->entityTypeId = $entity_type_id;
223
          $this->bundleName = $this->generator->getEntityInstanceBundleName($form_entity);
224
          $this->instanceId = !empty($form_entity->id()) ? $form_entity->id() : NULL; // New menu link's id is '' instead of NULL, hence checking for empty.
225 226 227 228 229 230
          break;

        default:
          return FALSE;
      }
      return TRUE;
231 232 233 234 235 236 237
    }
    return FALSE;
  }

  /**
   * Gets the object entity of the form if available.
   *
gbyte.co's avatar
gbyte.co committed
238 239
   * @return object|false
   *  Entity or FALSE if non-existent or if form operation is
240 241 242 243 244 245
   *  'delete'.
   */
  private function getFormEntity() {
    $form_object = $this->formState->getFormObject();
    if (!is_null($form_object)
      && method_exists($form_object, 'getEntity')
246
      && in_array($form_object->getOperation(), self::$allowedFormOperations)) {
247 248 249 250 251 252 253 254 255
      return $form_object->getEntity();
    }
    return FALSE;
  }

  /**
   * Gets new entity Id after entity creation.
   * To be used in an entity form submit.
   *
gbyte.co's avatar
gbyte.co committed
256 257
   * @return int
   *  Entity ID.
258
   */
259 260
  public function getFormEntityId() {
    return $this->formState->getFormObject()->getEntity()->id();
261 262 263 264 265 266
  }

  /**
   * Checks if simple_sitemap values have been changed after submitting the form.
   * To be used in an entity form submit.
   *
267 268
   * @param $form
   * @param $values
269 270 271
   * @return bool
   *  TRUE if simple_sitemap form values have been altered by the user.
   */
272
  public function valuesChanged($form, $values) { //todo make non-static
273
    foreach (self::$valuesToCheck as $field_name) {
274
      if (isset($values[$field_name]) && $values[$field_name] != $form['simple_sitemap'][$field_name]['#default_value']) {
275 276 277 278 279
        return TRUE;
      }
    }
    return FALSE;
  }
gbyte.co's avatar
gbyte.co committed
280 281 282 283

  /**
   * Gets the values needed to display the priority dropdown setting.
   *
284
   * @return array
gbyte.co's avatar
gbyte.co committed
285
   */
286
  public function getPrioritySelectValues() {
287
    $options = [];
gbyte.co's avatar
gbyte.co committed
288
    foreach(range(0, self::PRIORITY_HIGHEST) as $value) {
289
      $value = $this->formatPriority($value / self::PRIORITY_DIVIDER);
290
      $options[$value] = $value;
gbyte.co's avatar
gbyte.co committed
291 292 293
    }
    return $options;
  }
294

295 296 297 298 299
  /**
   * @param $priority
   * @return string
   */
  public function formatPriority($priority) {
300 301 302
    return number_format((float)$priority, 1, '.', '');
  }

303 304 305 306
  /**
   * @param $priority
   * @return bool
   */
307 308 309
  public static function isValidPriority($priority) {
    return !is_numeric($priority) || $priority < 0 || $priority > 1 ? FALSE : TRUE;
  }
310
}