simple_sitemap.module 9.45 KB
Newer Older
Pawel G's avatar
Pawel G committed
1
<?php
Pawel G's avatar
Pawel G committed
2

3 4 5 6
/**
 * @file
 * Main module file containing hooks.
 */
Pawel G's avatar
Pawel G committed
7

Pawel G's avatar
Pawel G committed
8
use Drupal\Core\Form\FormStateInterface;
Pawel G's avatar
Pawel G committed
9 10
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Routing\RouteMatchInterface;
11
use Drupal\system\MenuInterface;
12
use Drupal\language\ConfigurableLanguageInterface;
13 14 15 16
use Drupal\simple_sitemap\Plugin\Field\SimplesitemapIndexItem;
use Drupal\simple_sitemap\Plugin\Field\SimplesitemapPriorityItem;
use Drupal\simple_sitemap\Plugin\Field\SimplesitemapChangefreqItem;
use Drupal\simple_sitemap\Plugin\Field\SimplesitemapIncludeImagesItem;
17

18
/**
Pawel G's avatar
Pawel G committed
19 20 21 22 23
 *Implements hook_help.
 *
 * @param $route_name
 * @param \Drupal\Core\Routing\RouteMatchInterface $route_match
 * @return \Drupal\Component\Render\MarkupInterface|null
24
 */
Pawel G's avatar
Pawel G committed
25
function simple_sitemap_help($route_name, RouteMatchInterface $route_match) {
26
  return $route_name === 'help.page.simple_sitemap' ?
27
    check_markup(file_get_contents(dirname(__FILE__) . "/README.md")) : NULL;
28 29
}

30 31
/**
 * Implements hook_form_alter.
32 33
 *
 * Adds sitemap settings to entity types that are supported via plugins.
Pawel G's avatar
Pawel G committed
34 35 36 37
 *
 * @param $form
 * @param \Drupal\Core\Form\FormStateInterface $form_state
 * @param $form_id
38
 */
Pawel G's avatar
Pawel G committed
39
function simple_sitemap_form_alter(&$form, FormStateInterface $form_state, $form_id) {
40

41
  /** @var Drupal\simple_sitemap\Form\FormHelper $f */
Pawel G's avatar
Pawel G committed
42 43
  $f = \Drupal::service('simple_sitemap.form_helper');
  if (!$f->processForm($form_state)) {
44
    return;
Pawel G's avatar
Pawel G committed
45
  }
Pawel G's avatar
Pawel G committed
46 47 48 49 50

  $form['simple_sitemap'] = [
    '#type' => 'details',
    '#group' => isset($form['additional_settings']) ? 'additional_settings' : 'advanced',
    '#title' => t('Simple XML sitemap'),
Pawel G's avatar
Pawel G committed
51
    '#description' => $f->getEntityCategory() === 'instance' ? t('Settings for this entity can be overridden here.') : '',
Pawel G's avatar
Pawel G committed
52
  ];
53

Pawel G's avatar
Pawel G committed
54
  // Attach some js magic to forms.
Pawel G's avatar
Pawel G committed
55
  // todo: JS not working on comment entity form, hence disabling.
Pawel G's avatar
Pawel G committed
56
  if ($f->getEntityTypeId() !== 'comment' || $f->getEntityCategory() !== 'instance') {
Pawel G's avatar
Pawel G committed
57
    $form['#attached']['library'][] = 'simple_sitemap/form';
Pawel G's avatar
Pawel G committed
58
  }
59

Pawel G's avatar
Pawel G committed
60 61 62
  // Only attach fieldset summary js to 'additional settings' vertical tabs.
  if (isset($form['additional_settings'])) {
    $form['#attached']['library'][] = 'simple_sitemap/fieldsetSummaries';
63
  }
64

Pawel G's avatar
Pawel G committed
65
  $f->displayEntitySettings($form['simple_sitemap'])
Pawel G's avatar
Pawel G committed
66 67
  // todo: do not show setting when creating new bundle.
    ->displayRegenerateNow($form['simple_sitemap']);
68

69
  // Add submission handler.
70
  if (isset($form['actions']['submit']['#submit'])) {
71
    foreach (array_keys($form['actions']) as $action) {
Pawel G's avatar
Pawel G committed
72
      if ($action !== 'preview'
73 74
        && isset($form['actions'][$action]['#type'])
        && $form['actions'][$action]['#type'] === 'submit') {
75 76 77
        $form['actions'][$action]['#submit'][] = 'simple_sitemap_entity_form_submit';
      }
    }
78
  }
Pawel G's avatar
Pawel G committed
79 80
  // Fix for account page rendering other submit handlers not usable.
  else {
Pawel G's avatar
Pawel G committed
81
    $form['#submit'][] = 'simple_sitemap_entity_form_submit';
82
  }
Pawel G's avatar
Pawel G committed
83 84
}

85
/**
86
 * Form submission handler called in hook_form_alter.
Pawel G's avatar
Pawel G committed
87 88 89
 *
 * @param $form
 * @param \Drupal\Core\Form\FormStateInterface $form_state
90
 */
Pawel G's avatar
Pawel G committed
91
function simple_sitemap_entity_form_submit($form, FormStateInterface &$form_state) {
92

93
  /** @var Drupal\simple_sitemap\Form\FormHelper $f */
Pawel G's avatar
Pawel G committed
94 95 96 97
  $f = \Drupal::service('simple_sitemap.form_helper');
  if (!$f->processForm($form_state)) {
    return;
  }
98

99 100 101 102
  $values = $form_state->getValues();

  // Fix for values appearing in a sub array on a commerce product entity.
  $values = isset($values['simple_sitemap']) ? $values['simple_sitemap'] : $values;
103

104
  // Only make changes in DB if sitemap settings actually changed.
105
  if ($f->valuesChanged($form, $values)) {
106

107
    /** @var \Drupal\simple_sitemap\Simplesitemap $generator */
Pawel G's avatar
Pawel G committed
108
    $generator = \Drupal::service('simple_sitemap.generator');
109

110 111 112 113
    $settings = [
      'index' => $values['simple_sitemap_index_content'],
      'priority' => $values['simple_sitemap_priority'],
      'changefreq' => $values['simple_sitemap_changefreq'],
114
      'include_images' => $values['simple_sitemap_include_images'],
115 116
    ];

117
    switch ($f->getEntityCategory()) {
118 119

      case 'bundle':
120 121 122
        $generator->setBundleSettings(
          $f->getEntityTypeId(),
          !empty($f->getBundleName()) ? $f->getBundleName() : $f->getFormEntityId(),
123
          $settings
124
        );
125 126
        break;

127
      case 'instance':
128 129 130
        $generator->setEntityInstanceSettings(
          $f->getEntityTypeId(),
          !empty($f->getInstanceId()) ? $f->getInstanceId() : $f->getFormEntityId(),
131
          $settings
132
        );
133
        break;
134
    }
135 136 137

    // Regenerate sitemaps according to user setting.
    if ($values['simple_sitemap_regenerate_now']) {
Pawel G's avatar
Pawel G committed
138
      $generator->generateSitemap();
139
    }
140 141 142 143 144 145
  }
}

/**
 * Implements hook_cron.
 */
Pawel G's avatar
Pawel G committed
146
function simple_sitemap_cron() {
147

148
  /** @var \Drupal\simple_sitemap\Simplesitemap $generator */
Pawel G's avatar
Pawel G committed
149 150
  $generator = \Drupal::service('simple_sitemap.generator');
  if ($generator->getSetting('cron_generate')) {
151
    $interval = (int) $generator->getSetting('cron_generate_interval', 0) * 60 * 60;
152 153 154
    $requestTime = \Drupal::service('datetime.time')->getRequestTime();
    if ($interval === 0 || ((\Drupal::state()->get('simple_sitemap.last_cron_generate', 0) + $interval) <= $requestTime)) {
      \Drupal::state()->set('simple_sitemap.last_cron_generate', $requestTime);
155 156
      $generator->generateSitemap('backend');
    }
157
  }
Pawel G's avatar
Pawel G committed
158
}
159

160 161 162 163 164 165 166
/**
 * Implements hook_ENTITY_TYPE_delete().
 *
 * When a language is removed from the system remove it also from settings.
 */
function simple_sitemap_configurable_language_delete(ConfigurableLanguageInterface $language) {

167
  /** @var \Drupal\simple_sitemap\Simplesitemap $generator */
168 169 170 171 172 173 174 175
  $generator = \Drupal::service('simple_sitemap.generator');
  $excluded_languages = $generator->getSetting('excluded_languages');
  if (isset($excluded_languages[$language->id()])) {
    unset($excluded_languages[$language->id()]);
    $generator->saveSetting('excluded_languages', $excluded_languages);
  }
}

176 177 178 179
/**
 * Implements hook_entity_delete().
 *
 * Removes settings of the removed entity.
180 181
 *
 * @param \Drupal\Core\Entity\EntityInterface $entity
182
 */
Pawel G's avatar
Pawel G committed
183
function simple_sitemap_entity_delete(EntityInterface $entity) {
184

185
  /** @var \Drupal\simple_sitemap\Simplesitemap $generator */
186 187 188 189
  $generator = \Drupal::service('simple_sitemap.generator');
  $generator->removeEntityInstanceSettings(
    $entity->getEntityTypeId(), $entity->id()
  );
190
}
191 192 193 194 195

/**
 * Implements hook_entity_bundle_delete().
 *
 * Removes settings of the removed bundle.
Pawel G's avatar
Pawel G committed
196 197 198
 *
 * @param string $entity_type_id
 * @param string $bundle
199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
 */
function simple_sitemap_entity_bundle_delete($entity_type_id, $bundle) {
  simple_sitemap_delete_bundle_config($entity_type_id, $bundle);
}

/**
 * Implements hook_menu_delete().
 *
 * Removes settings for the removed menu.
 *
 * @param \Drupal\system\MenuInterface $menu
 */
function simple_sitemap_menu_delete(MenuInterface $menu) {
  simple_sitemap_delete_bundle_config('menu_link_content', $menu->id());
}

/**
 * Helper function used by simple_sitemap_entity_bundle_delete() and
 * simple_sitemap_menu_delete() hooks. This is needed, as menus are technically
 * not bundles.
 *
 * @param string $entity_type_id
 * @param string $bundle
 */
function simple_sitemap_delete_bundle_config($entity_type_id, $bundle) {
224

225
  /** @var \Drupal\simple_sitemap\Simplesitemap $generator */
226 227
  $generator = \Drupal::service('simple_sitemap.generator');
  $deleted_bundle_settings = $generator->getBundleSettings($entity_type_id, $bundle);
228
  if (!empty($deleted_bundle_settings['index'])) {
229 230 231 232

    // Delete bundle settings.
    \Drupal::service('config.factory')->getEditable("simple_sitemap.bundle_settings.$entity_type_id.$bundle")->delete();

233
    $message = 'You may want to <a href="@url">regenerate</a> your XML sitemaps now.';
234
    if ($generator->getSetting('cron_generate')) {
235
      $message .= ' Otherwise the sitemaps will be regenerated during a future cron run.';
236
    }
237
    \Drupal::messenger()->addMessage(t($message, ['@url' => $GLOBALS['base_url'] . '/admin/config/search/simplesitemap']));
238 239
  }
}
240 241 242

/**
 * Implements hook_robotstxt().
243 244 245
 *
 * @todo Use sitemap base URL setting?
 * @todo include non-default sitemaps as well?
246 247 248
 */
function simple_sitemap_robotstxt() {
  return [
249 250
    '# XML sitemaps',
    'Sitemap: ' . $GLOBALS['base_url'] . '/sitemap.xml',
251 252
  ];
}
253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297

/**
 * Implements hook_entity_base_field_info().
 */
function simple_sitemap_entity_base_field_info(\Drupal\Core\Entity\EntityTypeInterface $entity_type) {

  /** @var \Drupal\Core\Entity\ContentEntityTypeInterface[] $entity_types */
  $entity_types = \Drupal::service('simple_sitemap.entity_helper')->getSupportedEntityTypes();
  $fields = [];
  if (isset($entity_types[$entity_type->id()])) {
    $definitions = [
      'simple_sitemap_index' => [
        'type' => 'boolean',
        'name' => 'Indexed in sitemap',
        'class' => SimplesitemapIndexItem::class,
      ],
      'simple_sitemap_priority' => [
        'type' => 'decimal',
        'name' => 'Priority in sitemap',
        'class' => SimplesitemapPriorityItem::class,
      ],
      'simple_sitemap_changefreq' => [
        'type' => 'string',
        'name' => 'Change frequency in sitemap',
        'class' => SimplesitemapChangefreqItem::class,
      ],
      'simple_sitemap_include_images' => [
        'type' => 'boolean',
        'name' => 'Include images in sitemap',
        'class' => SimplesitemapIncludeImagesItem::class,
      ],
    ];

    foreach ($definitions as $id => $definition) {
      $fields[$id] = \Drupal\Core\Field\BaseFieldDefinition::create($definition['type'])
        ->setCardinality(1)
        ->setName($definition['name'])
        ->setComputed(TRUE)
        ->setClass($definition['class']);
    }
  }

  return $fields;
}