xmlsitemap.xmlsitemap.inc 8.87 KB
Newer Older
1
2
<?php

3
4
5
6
7
/**
 * @file
 * XML sitemap integration functions for xmlsitemap.module.
 */

8
9
10
11
class XMLSitemapException extends Exception {}

class XMLSitemapGenerationException extends XMLSitemapException {}

12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/**
 * Extended class for writing XML sitemap files.
 */
class XMLSitemapWriter extends XMLWriter {
  protected $uri = NULL;
  protected $sitemapElementCount = 0;
  protected $linkCountFlush = 500;
  protected $sitemap = NULL;
  protected $sitemap_page = NULL;
  protected $rootElement = 'urlset';

  /**
   * Constructor.
   *
   * @param $sitemap
   *   The sitemap array.
   * @param $page
   *   The current page of the sitemap being generated.
   */
31
  function __construct(stdClass $sitemap, $page) {
32
33
34
35
36
37
38
    $this->sitemap = $sitemap;
    $this->sitemap_page = $page;
    $this->uri = xmlsitemap_sitemap_get_file($sitemap, $page);
    $this->openUri($this->uri);
  }

  public function openUri($uri) {
39
    $return = parent::openUri($uri);
40
    if (!$return) {
41
      throw new XMLSitemapGenerationException(t('Could not open file @file for writing.', array('@file' => $uri)));
42
43
44
45
46
47
    }
    return $return;
  }

  public function startDocument($version = '1.0', $encoding = 'UTF-8', $standalone = NULL) {
    $this->setIndent(FALSE);
48
49
50
51
    $result = parent::startDocument($version, $encoding);
    if (!$result) {
      throw new XMLSitemapGenerationException(t('Unknown error occurred while writing to file @file.', array('@file' => $this->uri)));
    }
52
53
54
55
    if (variable_get('xmlsitemap_xsl', 1)) {
      $this->writeXSL();
    }
    $this->startElement($this->rootElement, TRUE);
56
    return $result;
57
58
59
60
61
62
  }

  /**
   * Add the XML stylesheet to the XML page.
   */
  public function writeXSL() {
63
    $this->writePi('xml-stylesheet', 'type="text/xsl" href="' . url('sitemap.xsl', $this->sitemap->uri['options']) . '"');
64
65
66
67
68
69
70
71
72
73
74
75
    $this->writeRaw(PHP_EOL);
  }

  /**
   * Return an array of attributes for the root element of the XML.
   */
  public function getRootAttributes() {
    $attributes['xmlns'] = 'http://www.sitemaps.org/schemas/sitemap/0.9';
    if (variable_get('xmlsitemap_developer_mode', 0)) {
      $attributes['xmlns:xsi'] = 'http://www.w3.org/2001/XMLSchema-instance';
      $attributes['xsi:schemaLocation'] = 'http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd';
    }
76
77
78

    drupal_alter('xmlsitemap_root_attributes', $attributes, $this->sitemap);

79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
    return $attributes;
  }

  public function generateXML() {
    return xmlsitemap_generate_chunk($this->sitemap, $this, $this->sitemap_page);
  }

  public function startElement($name, $root = FALSE) {
    parent::startElement($name);

    if ($root) {
      foreach ($this->getRootAttributes() as $name => $value) {
        $this->writeAttribute($name, $value);
      }
      $this->writeRaw(PHP_EOL);
    }
  }

  /**
   * Write an full XML sitemap element tag.
   *
   * @param $name
   *   The element name.
   * @param $element
   *   An array of the elements properties and values.
   */
  public function writeSitemapElement($name, array &$element) {
    $this->writeElement($name, $element);
    $this->writeRaw(PHP_EOL);

    // After a certain number of elements have been added, flush the buffer
    // to the output file.
    $this->sitemapElementCount++;
    if (($this->sitemapElementCount % $this->linkCountFlush) == 0) {
      $this->flush();
    }
  }

  /**
   * Write full element tag including support for nested elements.
   *
   * @param $name
   *   The element name.
   * @param $content
   *   The element contents or an array of the elements' sub-elements.
   */
125
  public function writeElement($name, $content = '') {
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
    if (is_array($content)) {
      $this->startElement($name);
      foreach ($content as $sub_name => $sub_content) {
        $this->writeElement($sub_name, $sub_content);
      }
      $this->endElement();
    }
    else {
      parent::writeElement($name, $content);
    }
  }

  public function getURI() {
    return $this->uri;
  }

  public function getSitemapElementCount() {
    return $this->sitemapElementCount;
  }

  public function endDocument() {
    $return = parent::endDocument();

149
    if (!$return) {
150
      throw new XMLSitemapGenerationException(t('Unknown error occurred while writing to file @file.', array('@file' => $this->uri)));
151
152
153
154
155
156
157
158
159
160
161
162
163
164
    }

    //if (xmlsitemap_var('gz')) {
    //  $file_gz = $file . '.gz';
    //  file_put_contents($file_gz, gzencode(file_get_contents($file), 9));
    //}

    return $return;
  }
}

class XMLSitemapIndexWriter extends XMLSitemapWriter {
  protected $rootElement = 'sitemapindex';

165
  function __construct(stdClass $sitemap, $page = 'index') {
166
167
168
169
170
171
172
173
174
    parent::__construct($sitemap, 'index');
  }

  public function getRootAttributes() {
    $attributes['xmlns'] = 'http://www.sitemaps.org/schemas/sitemap/0.9';
    if (variable_get('xmlsitemap_developer_mode', 0)) {
      $attributes['xmlns:xsi'] = 'http://www.w3.org/2001/XMLSchema-instance';
      $attributes['xsi:schemaLocation'] = 'http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/siteindex.xsd';
    }
175
176
177

    drupal_alter('xmlsitemap_root_attributes', $attributes, $this->sitemap);

178
179
180
181
182
183
    return $attributes;
  }

  public function generateXML() {
    $lastmod_format = variable_get('xmlsitemap_lastmod_format', XMLSITEMAP_LASTMOD_MEDIUM);

184
    $url_options = $this->sitemap->uri['options'];
185
186
187
188
189
190
191
    $url_options += array(
      'absolute' => TRUE,
      'base_url' => variable_get('xmlsitemap_base_url', $GLOBALS['base_url']),
      'language' => language_default(),
      'alias' => TRUE,
    );

192
    for ($i = 1; $i <= $this->sitemap->chunks; $i++) {
193
194
195
196
197
198
199
200
201
202
203
      $url_options['query']['page'] = $i;
      $element = array(
        'loc' => url('sitemap.xml', $url_options),
        // @todo Use the actual lastmod value of the chunk file.
        'lastmod' => gmdate($lastmod_format, REQUEST_TIME),
      );
      $this->writeSitemapElement('sitemap', $element);
    }
  }
}

204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
/**
 * Implements hook_xmlsitemap_link_info().
 */
function xmlsitemap_xmlsitemap_link_info() {
  return array(
    'frontpage' => array(
      'label' => t('Frontpage'),
      'xmlsitemap' => array(
        'settings callback' => 'xmlsitemap_link_frontpage_settings',
      ),
    ),
  );
}

/**
 * XML sitemap link type settings callback for frontpage link entity.
 */
function xmlsitemap_link_frontpage_settings(&$form) {
222
  module_load_include('admin.inc', 'xmlsitemap');
223
  if (user_access('administer site configuration')) {
224
    $form['#description'] = t('The front page path can be changed in the <a href="@url-frontpage">site information configuration</a>.', array('@url-frontpage' => url('admin/config/system/site-information')));
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
  }
  $form['xmlsitemap_frontpage_priority'] = array(
    '#type' => 'select',
    '#title' => t('Priority'),
    '#options' => xmlsitemap_get_priority_options(),
    '#default_value' => variable_get('xmlsitemap_frontpage_priority', 1.0),
  );
  $form['xmlsitemap_frontpage_changefreq'] = array(
    '#type' => 'select',
    '#title' => t('Change frequency'),
    '#options' => xmlsitemap_get_changefreq_options(),
    '#default_value' => variable_get('xmlsitemap_frontpage_changefreq', XMLSITEMAP_FREQUENCY_DAILY),
  );
  return $form;
}

/**
 * Implements hook_xmlsitemap_link_alter().
 */
function xmlsitemap_xmlsitemap_link_alter(&$link) {
  // Alter the frontpage priority.
246
  if ($link['type'] == 'frontpage' || $link['loc'] == '' || $link['loc'] == variable_get('site_frontpage', 'node')) {
247
248
    $link['priority'] = variable_get('xmlsitemap_frontpage_priority', 1.0);
    $link['changefreq'] = variable_get('xmlsitemap_frontpage_changefreq', XMLSITEMAP_FREQUENCY_DAILY);
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
  }
}

/**
 * Implements hook_xmlsitemap_links().
 */
function xmlsitemap_xmlsitemap_links() {
  // Frontpage link.
  $links[] = array(
    'type' => 'frontpage',
    'id' => 0,
    'loc' => '',
  );
  return $links;
}

265
266
267
/**
 * Implements hook_xmlsitemap_sitemap_operations().
 */
268
269
270
function xmlsitemap_xmlsitemap_sitemap_operations() {
  $operations['update'] = array(
    'label' => t('Update cached files'),
271
    'action past' => t('Updated'),
272
273
274
275
276
    'callback' => 'xmlsitemap_sitemap_multiple_update',
  );
  return $operations;
}

277
/**
278
 * XML sitemap operation callback; regenerate sitemap files using the batch API.
279
280
281
282
283
284
 *
 * @param $smids
 *   An array of XML sitemap IDs.
 *
 * @see xmlsitemap_regenerate_batch()
 */
285
286
287
288
289
function xmlsitemap_sitemap_multiple_update(array $smids) {
  module_load_include('generate.inc', 'xmlsitemap');
  $batch = xmlsitemap_regenerate_batch($smids);
  batch_set($batch);
}
290
291
292
293
294

/**
 * Implements hook_query_TAG_alter().
 */
function xmlsitemap_query_xmlsitemap_link_bundle_access_alter(QueryAlterableInterface $query) {
295
  if ($query instanceof EntityFieldQuery && $entity = $query->getMetaData('entity')) {
296
    $info = $query->getMetaData('entity_info');
297
298
299
300
    $bundle = $query->getMetaData('bundle');
    if (empty($bundle)) {
      $bundle = xmlsitemap_get_link_type_enabled_bundles($entity);
    }
301
    $query->entityCondition('bundle', $bundle, is_array($bundle) ? 'IN' : '=');
302
303
  }
}