Commit 9309c488 authored by Dave Reid's avatar Dave Reid

by Dave Reid: Generalized and linked rebuilding links with entity info.

parent a4e5fedf
......@@ -104,8 +104,8 @@ function xmlsitemap_settings_form() {
'#weight' => 20,
);
$entites = xmlsitemap_get_link_info(NULL, TRUE);
foreach ($entites as $entity => $entity_info) {
$entities = xmlsitemap_get_link_info(NULL, TRUE);
foreach ($entities as $entity => $entity_info) {
$form[$entity] = array(
'#type' => 'fieldset',
'#title' => $entity_info['label'],
......@@ -201,20 +201,34 @@ function xmlsitemap_rebuild_form() {
}
}
// Build the list of rebuildable entities.
$entities = xmlsitemap_get_link_info();
$callbacks = $options = array();
foreach ($entities as $entity => $info) {
if (empty($info['base table'])) {
if (empty($info['xmlsitemap']['rebuild callback'])) {
// Only show entities which can be rebuilt.
unset($entities[$entity]);
continue;
}
if (!empty($info['object keys']['bundle']) && !xmlsitemap_get_link_type_enabled_bundles($entity)) {
continue;
}
else {
$callbacks[$entity] = $info['xmlsitemap']['rebuild callback'];
$options[$entity] = $info['label'];
}
}
$form['callbacks'] = array(
'#type' => 'value',
'#value' => $callbacks,
);
$form['entities'] = array(
'#type' => 'select',
'#title' => t("Select which link types you would like to rebuild"),
'#description' => t('If no link types are selected, the sitemap files will just be regenerated.'),
'#multiple' => TRUE,
'#options' => drupal_map_assoc(array_keys($entities)),
'#default_value' => xmlsitemap_var('rebuild_needed') || !xmlsitemap_var('developer_mode') ? array_keys($entities) : array(),
'#options' => $options,
'#default_value' => xmlsitemap_var('rebuild_needed') || !xmlsitemap_var('developer_mode') ? array_keys($options) : array(),
'#access' => xmlsitemap_var('developer_mode'),
);
$form['save_custom'] = array(
......@@ -244,7 +258,8 @@ function xmlsitemap_rebuild_form_submit($form, &$form_state) {
variable_set('xmlsitemap_rebuild_needed', TRUE);
module_load_include('inc', 'xmlsitemap');
$batch = xmlsitemap_rebuild_batch($form_state['values']['entities'], $form_state['values']['save_custom']);
$batch = xmlsitemap_rebuild_batch($form_state['values']['entities'], $form_state['values']['callbacks'], $form_state['values']['save_custom']);
batch_set($batch);
$form_state['redirect'] = 'admin/config/search/xmlsitemap';
}
......@@ -366,6 +381,8 @@ function xmlsitemap_add_form_type_options(&$form, $module, $options) {
/**
* Add a link's XML sitemap options to the link's form.
*
* @todo Add changefreq overridability.
*/
function xmlsitemap_add_form_link_options(&$form, $link) {
$form['xmlsitemap'] = array(
......
......@@ -344,7 +344,7 @@ function xmlsitemap_generate_index($handle, &$status, $language) {
/**
* Batch information callback.
*/
function xmlsitemap_rebuild_batch($entities = array(), $save_custom = FALSE) {
function xmlsitemap_rebuild_batch(array $entities, array $callbacks, $save_custom = FALSE) {
$batch = array(
'operations' => array(),
'finished' => 'xmlsitemap_rebuild_batch_finished',
......@@ -352,12 +352,13 @@ function xmlsitemap_rebuild_batch($entities = array(), $save_custom = FALSE) {
'file' => drupal_get_path('module', 'xmlsitemap') . '/xmlsitemap.inc',
);
// Purge any links first.
$batch['operations'][] = array('xmlsitemap_rebuild_batch_clear', array($entities, $save_custom));
$batch['operations'][] = array('xmlsitemap_rebuild_batch_clear', array($entities, (bool) $save_custom));
// Fetch all the sitemap links and save them to the {xmlsitemap} table.
foreach ($entities as $entity) {
$batch['operations'][] = array('xmlsitemap_rebuild_batch_fetch', array($entity));
$batch['operations'][] = array($callbacks[$entity], array($entity));
}
// Generate all the sitemap pages.
......@@ -390,38 +391,40 @@ function xmlsitemap_rebuild_batch_clear(array $entities, $save_custom, &$context
}
/**
* Batch callback; fetch and add the sitemap links for a specific module.
* Batch callback; fetch and add the sitemap links for a specific entity.
*/
function xmlsitemap_rebuild_batch_fetch($module, &$context) {
if (!isset($context['sandbox']['progress'])) {
$context['sandbox']['batch'] = module_hook($module, 'xmlsitemap_links_batch_info');
if ($context['sandbox']['batch']) {
$context['sandbox'] += module_invoke($module, 'xmlsitemap_links_batch_info');
}
else {
$context['sandbox']['links'] = module_invoke($module, 'xmlsitemap_links');
$context['sandbox']['max'] = count($context['sandbox']['links']);
}
$context['sandbox'] += array(
'progress' => 0,
'current' => 0,
);
function xmlsitemap_rebuild_batch_fetch($entity, &$context) {
if (!isset($context['sandbox']['info'])) {
$context['sandbox']['info'] = xmlsitemap_get_link_info($entity);
$context['sandbox']['progress'] = 0;
$context['sandbox']['last_id'] = 0;
}
$info = $context['sandbox']['info'];
if ($context['sandbox']['batch']) {
$links = module_invoke($module, 'xmlsitemap_links', $context['sandbox']['current'], xmlsitemap_var('batch_limit'));
}
else {
$links = array_splice($context['sandbox']['links'], 0, xmlsitemap_var('batch_limit'));
$query = db_select($info['base table']);
$query->addField($info['base table'], $info['object keys']['id']);
$query->condition($info['object keys']['id'], $context['sandbox']['last_id'], '>');
if (!empty($info['object keys']['bundle'])) {
$bundles = xmlsitemap_get_link_type_enabled_bundles($entity);
$query->condition($info['object keys']['bundle'], $bundles);
}
$query->orderBy($info['object keys']['id']);
$query->addTag('xmlsitemap_rebuild');
$query->addMetaData('entity', $entity);
$query->addMetaData('entity_info', $info);
foreach ($links as $link) {
xmlsitemap_save_link($link);
$context['sandbox']['progress']++;
$context['sandbox']['current'] = $link['id'];
$context['message'] = t('Now processing %module link @count.', array('%module' => $module, '@count' => $context['sandbox']['progress']));
if (!isset($context['sandbox']['max'])) {
$context['sandbox']['max'] = $query->countQuery()->execute()->fetchField();
}
$query->range(0, variable_get('xmlsitemap_batch_limit', 100));
$ids = $query->execute()->fetchCol();
$info['xmlsitemap']['process callback']($ids);
$context['sandbox']['last_id'] = end($ids);
$context['sandbox']['progress'] += count($ids);
$context['message'] = t('Now processing %entity @last_id (@progress of @count).', array('%entity' => $entity, '@last_id' => $context['sandbox']['last_id'], '@progress' => $context['sandbox']['progress'], '@count' => $context['sandbox']['max']));
if ($context['sandbox']['progress'] != $context['sandbox']['max']) {
$context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max'];
}
......
......@@ -798,12 +798,16 @@ function xmlsitemap_get_link_info($type = NULL, $reset = FALSE) {
}
}
$link_info = array_merge($link_info, module_invoke_all('xmlsitemap_link_info'));
foreach ($link_info as $key => $info) {
$link_info[$key] += array(
foreach ($link_info as $key => &$info) {
$info += array(
'type' => $key,
'base table' => FALSE,
'bundles' => array(),
'xmlsitemap' => array(),
);
if (!isset($info['xmlsitemap']['rebuild callback']) && !empty($info['base table']) && !empty($info['object keys']['id']) && !empty($info['xmlsitemap']['process callback'])) {
$info['xmlsitemap']['rebuild callback'] = 'xmlsitemap_rebuild_batch_fetch';
}
}
drupal_alter('xmlsitemap_link_info', $link_info);
ksort($link_info);
......@@ -933,6 +937,17 @@ function xmlsitemap_language_load($language = LANGUAGE_NONE) {
return $languages[$language];
}
function xmlsitemap_get_link_type_enabled_bundles($entity_type) {
$bundles = array();
$info = xmlsitemap_get_link_info($entity_type);
foreach ($info['bundles'] as $bundle => $bundle_info) {
if (!empty($bundle_info['xmlsitemap']['status'])) {
$bundles[] = $bundle;
}
}
return $bundles;
}
function xmlsitemap_get_link_type_indexed_status($entity_type, $bundle = '') {
$info = xmlsitemap_get_link_info($entity_type);
$status = array();
......@@ -940,7 +955,7 @@ function xmlsitemap_get_link_type_indexed_status($entity_type, $bundle = '') {
$indexed = db_select('xmlsitemap');
$indexed->condition('type', $entity_type);
$indexed->condition('subtype', $bundle);
$visible = $indexed;
$visible = clone $indexed;
$visible->condition('status', 1);
$visible->condition('access', 1);
......@@ -949,7 +964,7 @@ function xmlsitemap_get_link_type_indexed_status($entity_type, $bundle = '') {
$total = db_select($info['base table']);
$total->addField('xmlsitemap', $info['object keys']['id']);
if (!empty($info['object keys']['bundle']) && db_column_exists($info['base table'], $info['object keys']['bundle'])) {
if (!empty($info['object keys']['bundle'])) {
$total->condition($info['object keys']['bundle'], $bundle);
}
$status['total'] = $total->countQuery()->execute()->fetchField();
......
......@@ -7,7 +7,9 @@
function xmlsitemap_node_entity_info_alter(&$entity_info) {
$entity_info['node']['label'] = t('Content');
$entity_info['node']['bundle label'] = t('Content type');
$entity_info['node']['xmlsitemap'] = array();
$entity_info['node']['xmlsitemap'] = array(
'process callback' => 'xmlsitemap_node_xmlsitemap_process_node_links',
);
foreach (node_type_get_names() as $type => $name) {
$entity_info['node']['bundles'][$type]['xmlsitemap'] = array(
'priority' => variable_get('xmlsitemap_node_priority_' . $type, 0.5),
......@@ -29,13 +31,23 @@ function xmlsitemap_node_cron() {
* Implements hook_xmlsitemap_index_links().
*/
function xmlsitemap_node_xmlsitemap_index_links($limit) {
if ($types = xmlsitemap_node_get_types()) {
if ($types = xmlsitemap_get_link_type_enabled_bundles('node')) {
$nids = db_query_range("SELECT n.nid FROM {node} n LEFT JOIN {xmlsitemap} x ON x.type = 'node' AND n.nid = x.id WHERE x.id IS NULL AND n.type IN (:types) ORDER BY n.nid DESC", 0, $limit, array(':types' => $types))->fetchCol();
$nodes = node_load_multiple($nids);
foreach ($nodes as $node) {
$link = xmlsitemap_node_create_link($node);
xmlsitemap_save_link($link);
}
xmlsitemap_node_xmlsitemap_process_node_links($nids);
}
}
/**
* Process node sitemap links.
*
* @param $nids
* An array of node IDs.
*/
function xmlsitemap_node_xmlsitemap_process_node_links(array $nids) {
$nodes = node_load_multiple($nids);
foreach ($nodes as $node) {
$link = xmlsitemap_node_create_link($node);
xmlsitemap_save_link($link);
}
}
......@@ -100,6 +112,25 @@ function xmlsitemap_node_node_type_delete($info) {
//xmlsitemap_link_delete_multiple(array('type' => 'node', 'subtype' => $info->type));
}
/**
* Implements hook_field_extra_fields().
*/
function xmlsitemap_node_field_extra_fields() {
$extras = array();
$bundles = xmlsitemap_get_link_type_enabled_bundles('node');
foreach (node_type_get_names() as $type => $name) {
if (!in_array($type, $bundles)) {
continue;
}
$extras['node'][$type]['xmlsitemap'] = array(
'label' => t('XML sitemap'),
'description' => t('XML sitemap module element'),
'weight' => 30,
);
}
return $extras;
}
/**
* Implements hook_form_FORM_ID_alter().
*
......@@ -167,64 +198,6 @@ function xmlsitemap_node_form_alter(&$form, $form_state, $form_id) {
}
}
/**
* Implements hook_xmlsitemap_links().
*/
function xmlsitemap_node_xmlsitemap_links($offset = 0, $limit = 0) {
$links = array();
if ($types = xmlsitemap_node_get_types()) {
$sql = "SELECT n.nid FROM {node} n WHERE n.nid > :offset AND n.type IN (:types) ORDER BY n.nid";
$args = array(':offset' => $offset, ':types' => $types);
$nids = ($limit ? db_query_range($sql, 0, $limit, $args)->fetchCol() : db_query($sql, $args)->fetchCol());
$nodes = node_load_multiple($nids);
foreach ($nodes as $node) {
$links[] = xmlsitemap_node_create_link($node);
}
}
return $links;
}
/**
* Implements hook_xmlsitemap_links_batch_info().
*/
function xmlsitemap_node_xmlsitemap_links_batch_info() {
$types = xmlsitemap_node_get_types();
return array(
'max' => $types ? db_query("SELECT COUNT(n.nid) FROM {node} n WHERE n.type IN (:types)", array(':types' => $types))->fetchField() : 0,
);
}
/**
* Fetch an array of node types to be included in the sitemap.
*/
function xmlsitemap_node_get_types() {
$node_types = array_keys(node_type_get_names());
foreach ($node_types as $index => $node_type) {
if (!variable_get('xmlsitemap_node_status_' . $node_type, 0)) {
unset($node_types[$index]);
}
}
return $node_types;
}
/**
* Implements hook_field_extra_fields().
*/
function xmlsitemap_node_field_extra_fields() {
$extras = array();
foreach (xmlsitemap_node_get_types() as $type) {
$extras['node'][$type]['xmlsitemap'] = array(
'label' => t('XML sitemap'),
'description' => t('XML sitemap module element'),
'weight' => 30,
);
}
return $extras;
}
/**
* Fetch all the timestamps for when a node was changed.
*
......
......@@ -6,7 +6,9 @@
*/
function xmlsitemap_taxonomy_entity_info_alter(&$entity_info) {
$entity_info['taxonomy_term']['bundle label'] = t('Vocabulary name');
$entity_info['taxonomy_term']['xmlsitemap'] = array();
$entity_info['taxonomy_term']['xmlsitemap'] = array(
'process callback' => 'xmlsitemap_taxonomy_xmlsitemap_process_taxonomy_term_links',
);
foreach (taxonomy_vocabulary_get_names() as $machine_name => $vocabulary) {
$entity_info['taxonomy_term']['bundles'][$machine_name]['xmlsitemap'] = array(
'priority' => variable_get('xmlsitemap_taxonomy_priority_' . $vocabulary->vid, 0.5),
......@@ -43,44 +45,24 @@ function xmlsitemap_taxonomy_cron() {
* Implements hook_xmlsitemap_index_links().
*/
function xmlsitemap_taxonomy_xmlsitemap_index_links($limit) {
if ($vids = xmlsitemap_taxonomy_get_vids()) {
if ($vids = xmlsitemap_get_link_type_enabled_bundles('taxonomy_term')) {
$tids = db_query_range("SELECT t.tid FROM {taxonomy_term_data} t LEFT JOIN {xmlsitemap} x ON x.type = 'taxonomy_term' AND t.tid = x.id WHERE x.id IS NULL AND t.vid IN (:vids) ORDER BY t.tid DESC", 0, $limit, array(':vids' => $vids))->fetchCol();
$terms = taxonomy_term_load_multiple($tids);
foreach ($terms as $term) {
$link = xmlsitemap_taxonomy_create_link($term);
xmlsitemap_save_link($link);
}
xmlsitemap_taxonomy_xmlsitemap_process_taxonomy_term_links($tids);
}
}
/**
* Implements hook_xmlsitemap_links().
* Process taxonomy term sitemap links.
*
* @param $tids
* An array of taxonomy term IDs.
*/
function xmlsitemap_taxonomy_xmlsitemap_links($offset = 0, $limit = 0) {
$links = array();
if ($vids = xmlsitemap_taxonomy_get_vids()) {
$sql = "SELECT t.tid FROM {taxonomy_term_data} t WHERE t.tid > :tid AND t.vid IN (:vids) ORDER BY t.tid";
$args = array(':tid' => $offset, ':vids' => $vids);
$tids = ($limit ? db_query_range($sql, 0, $limit, $args)->fetchCol() : db_query($sql, $args)->fetchCol());
$terms = taxonomy_term_load_multiple($tids);
foreach ($terms as $term) {
$links[] = xmlsitemap_taxonomy_create_link($term);
}
function xmlsitemap_taxonomy_xmlsitemap_process_taxonomy_term_links(array $tids) {
$terms = taxonomy_term_load_multiple($tids);
foreach ($terms as $term) {
$link = xmlsitemap_taxonomy_create_link($term);
xmlsitemap_save_link($link);
}
return $links;
}
/**
* Implements hook_xmlsitemap_links_batch_info().
*/
function xmlsitemap_taxonomy_xmlsitemap_links_batch_info() {
$vids = xmlsitemap_taxonomy_get_vids();
return array(
'max' => $vids ? db_query("SELECT COUNT(t.tid) FROM {taxonomy_term_data} t WHERE t.vid IN (:vids)", array(':vids' => $vids))->fetchField() : 0,
);
}
/**
......@@ -193,6 +175,25 @@ function xmlsitemap_taxonomy_term_delete(stdClass $term) {
xmlsitemap_link_delete('taxonomy_term', $term->tid);
}
/**
* Implements hook_field_extra_fields().
*/
function xmlsitemap_taxonomy_field_extra_fields() {
$extras = array();
$bundles = xmlsitemap_get_link_type_enabled_bundles('taxonomy_term');
foreach (taxonomy_vocabulary_get_names() as $machine_name => $vocabulary) {
if (!in_array($vocabulary->vid, $bundles)) {
continue;
}
$extras['taxonomy_term'][$machine_name]['xmlsitemap'] = array(
'label' => t('XML sitemap'),
'description' => t('XML sitemap module element'),
'weight' => 30,
);
}
return $extras;
}
/**
* Create a sitemap link from a taxonomy term.
*
......@@ -233,12 +234,12 @@ function xmlsitemap_taxonomy_create_link(stdClass $term) {
/**
* Calculate the priority of a taxonomy term based on depth and weight.
*/
/*function xmlsitemap_taxonomy_calculate_term_priority(stdClass $term) {
// Calculate priority.
// Min weight = -128
// Max weight = 127
// Max depth = ?
}*/
//function xmlsitemap_taxonomy_calculate_term_priority(stdClass $term) {
// // Calculate priority.
// // Min weight = -128
// // Max weight = 127
// // Max depth = ?
//}
/**
* Find the tree depth of a taxonomy term.
......@@ -252,7 +253,7 @@ function xmlsitemap_taxonomy_get_term_depth(stdClass $term) {
static $depths = array();
if (!isset($depths[$term->tid])) {
if ($parent = db_query("SELECT parent FROM {term_hierarchy} WHERE tid = %d", $term->tid)->fetchField()) {
if ($parent = db_query("SELECT parent FROM {taxonomy_term_hierarchy} WHERE tid = %d", $term->tid)->fetchField()) {
// If the term has a parent, the term's depth is the parent's depth + 1.
if (!isset($depths[$parent])) {
$depths[$parent] = xmlsitemap_taxonomy_get_term_depth($parent);
......@@ -270,20 +271,7 @@ function xmlsitemap_taxonomy_get_term_depth(stdClass $term) {
function xmlsitemap_taxonomy_get_node_count(stdClass $term) {
// @todo Use db_rewrite_sql() w/ switch user.
return db_query_range("SELECT COUNT(tn.nid) FROM {term_node} tn LEFT JOIN {node n} USING (nid) WHERE tn.tid = :tid AND n.status = 1", 0, 1, array(':tid' => $term->tid))->fetchField();
}
/**
* Fetch an array of vocabulary IDs to be included in the sitemap.
*/
function xmlsitemap_taxonomy_get_vids() {
$vids = array_keys(taxonomy_get_vocabularies());
foreach ($vids as $index => $vid) {
if (!variable_get('xmlsitemap_taxonomy_status_' . $vid, 0)) {
unset($vids[$index]);
}
}
return $vids;
return db_query_range("SELECT COUNT(ti.nid) FROM {taxonomy_index} ti LEFT JOIN {node n} USING (nid) WHERE ti.tid = :tid AND n.status = 1", 0, 1, array(':tid' => $term->tid))->fetchField();
}
/**
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment