timestamp, $comment->nid);
if (variable_get('xmlsitemap_node_count_comments', TRUE)) {
xmlsitemap_flag_sitemap();
}
break;
}
}
/**
* Implementation of hook_form_alter().
*/
function xmlsitemap_node_form_alter($form_id, &$form) {
switch ($form_id) {
case 'node_type_form':
if (isset($form['identity']['type'])) {
$form['xmlsitemap_node'] = array(
'#type' => 'fieldset',
'#title' => t('XML sitemap'),
'#collapsible' => TRUE,
);
$form['xmlsitemap_node']['xmlsitemap_node_type_priority'] = array(
'#type' => 'select',
'#title' => t('Priority adjustment'),
'#description' => t('This number will be added to the priority of this content type.'),
'#default_value' => variable_get('xmlsitemap_node_type_priority_'. $form['#node_type']->type, 0.5),
'#options' => xmlsitemap_priority_options('exclude'),
);
$form['xmlsitemap_node']['xmlsitemap_old_priority'] = array(
'#type' => 'value',
'#value' => variable_get('xmlsitemap_node_type_priority_'. $form['#node_type']->type, 0.5)
);
$form['#submit']['_xmlsitemap_node_submit'] = array();
}
break;
case 'xmlsitemap_settings_sitemap':
$options = xmlsitemap_priority_options();
$form['general']['priority']['xmlsitemap_node_promote_priority'] = array(
'#type' => 'select',
'#title' => t('Promotion adjustment'),
'#description' => t('This number will be added to the priority of each post that is promoted to the front page.'),
'#default_value' => variable_get('xmlsitemap_node_promote_priority', 0.3),
'#options' => $options,
);
$form['general']['priority']['xmlsitemap_node_comment_priority'] = array(
'#type' => 'select',
'#title' => t('Comment ratio weight'),
'#description' => t("This number will be added to the priority of the post with the highest number of comments. This doesn't apply if the maximum number of comments is one."),
'#default_value' => variable_get('xmlsitemap_node_comment_priority', 0.2),
'#options' => $options,
);
$form['xmlsitemap_node'] = array(
'#type' => 'fieldset',
'#title' => t('Content settings'),
'#description' => t('The settings for the content to include in the sitemap.'),
'#collapsible' => TRUE,
);
$form['xmlsitemap_node']['xmlsitemap_node_count_comments'] = array(
'#type' => 'checkbox',
'#title' => t('Count comments in change date and frequency'),
'#description' => t('If enabled, the frequency of comments on a post will affect its change frequency and last modification date.'),
'#default_value' => variable_get('xmlsitemap_node_count_comments', TRUE),
);
$form['buttons']['#weight'] = 1;
break;
default:
if (isset($form['type']) && $form_id == $form['type']['#value'] .'_node_form') {
$node = $form['#node'];
if (user_access('override node settings')) {
$form['xmlsitemap_node'] = array(
'#type' => 'fieldset',
'#title' => t('XML sitemap'),
'#collapsible' => TRUE,
'#weight' => 30,
);
$options = xmlsitemap_priority_options('both');
$default = variable_get('xmlsitemap_node_type_priority_'. $node->type, '0.5');
$form['xmlsitemap_node']['priority_override'] = array(
'#type' => 'select',
'#title' => t('Priority'),
'#description' => t('The default priority is %priority.', array('%priority' => $options[$default])),
'#default_value' => isset($node->priority_override) ? $node->priority_override : -2,
'#options' => $options,
);
}
else {
$form['priority_override'] = array(
'#type' => 'value',
'#value' => $node->priority_override
);
}
$form['xmlsitemap_node_status'] = array(
'#type' => 'value',
'#value' => $node->status
);
}
break;
}
}
/**
* Implementation of hook_node_type().
*/
function xmlsitemap_node_node_type($op, $info) {
if ($op == 'delete') {
variable_del("xmlsitemap_node_type_priority_$info->type");
}
elseif ($op == 'update' && !empty($info->old_type) && $info->type != $info->old_type) {
variable_set('xmlsitemap_node_type_priority_'. $info->type, variable_get('xmlsitemap_node_type_priority_'. $info->old_type, 0.5));
variable_del('xmlsitemap_node_type_priority_'. $info->old_type);
}
xmlsitemap_flag_sitemap();
}
/**
* Implementation of hook_nodeapi().
*/
function xmlsitemap_node_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) {
switch ($op) {
case 'prepare':
$priority_override = db_result(db_query("SELECT priority_override
FROM {xmlsitemap_node}
WHERE nid = %d", $node->nid)
);
$node->priority_override = $priority_override === FALSE ? 'NULL' : $priority_override;
break;
case 'insert':
$node->priority_override = isset($node->priority_override) ? $node->priority_override : 'NULL';
db_query("INSERT INTO {xmlsitemap_node} (nid, last_changed, priority_override) VALUES (%d, %d, %s)", $node->nid, $node->changed, $node->priority_override);
if ($node->status) {
xmlsitemap_flag_sitemap();
}
break;
case 'update':
if (!isset($node->priority_override)) {
$priority_override = db_result(db_query("SELECT priority_override FROM {xmlsitemap_node} WHERE nid = %d", $node->nid));
$node->priority_override = $priority_override !== FALSE ? $priority_override : 'NULL';
}
db_query("UPDATE {xmlsitemap_node}
SET previously_changed = last_changed, last_changed = %d, priority_override = %s
WHERE nid = %d",
$node->changed, $node->priority_override, $node->nid
);
xmlsitemap_flag_sitemap();
break;
case 'delete':
db_query("DELETE FROM {xmlsitemap_node} WHERE nid = %d", $node->nid);
if ($node->status) {
xmlsitemap_flag_sitemap();
}
break;
}
}
/**
* Implementation of hook_views_query_alter().
*/
function xmlsitemap_node_views_query_alter(&$query, &$view, $summary = NULL, $level = NULL) {
switch ($view->page_type) {
case 'xmlsitemap_news':
$query->add_field('created', 'node');
case 'xmlsitemap_sitemap':
$xn_join = array(
'left' => array(
'table' => 'node',
'field' => 'nid',
),
'right' => array(
'field' => 'nid',
),
);
$ua_join = array(
'left' => array(
'table' => 'url_alias',
'field' => 'pid',
),
'right' => array(
'field' => 'pid',
),
'extra' => array(
"src = CONCAT('node/', node.nid)" => NULL,
),
);
$query->add_table('xmlsitemap_node', FALSE, 1, $xn_join);
$query->add_table('url_alias', FALSE, 1, $ua_join);
if (module_exists('comment')) {
$query->add_table('node_comment_statistics');
$query->add_field('comment_count', 'node_comment_statistics');
$query->add_field('last_comment_timestamp', 'node_comment_statistics');
$query->add_field('previous_comment', 'xmlsitemap_node');
}
$query->add_field('type', 'node');
$query->add_field('promote', 'node');
$query->add_field('changed', 'node');
$query->add_field('previously_changed', 'xmlsitemap_node');
$query->add_field('priority_override', 'xmlsitemap_node');
$query->add_field('dst', 'url_alias', 'alias');
break;
}
}
/**
* Implementation of hook_views_style_plugins().
*/
function xmlsitemap_node_views_style_plugins() {
return array(
'xmlsitemap_sitemap' => array(
'name' => t('XML sitemap: Sitemap'),
'theme' => 'xmlsitemap_node_view_sitemap',
),
'xmlsitemap_news' => array(
'name' => t('XML sitemap: News'),
'theme' => 'xmlsitemap_node_view_news',
),
);
}
/**
* Implementation of hook_xmlsitemap_description().
*/
function xmlsitemap_node_xmlsitemap_description() {
return '
'. t('XML sitemap node') .''.
''. t('It adds nodes to the sitemap. The default priority of a node is determined by a combination of its content type priority, whether it appears on the front page of your site, and the number of comments it has received. You can override the default priority for individual nodes when you add or edit a node.', array('@content' => url('admin/content/types'))) .'';
}
/**
* Implementation of hook_xmlsitemap_links().
*/
function xmlsitemap_node_xmlsitemap_links() {
$excludes = xmlsitemap_node_excludes();
switch ($GLOBALS['db_type']) {
case 'mysql':
case 'mysqli':
$coalesce = 'COALESCE';
break;
case 'pgsql':
$coalesce = 'FIRST';
break;
}
if (module_exists('comment')) {
$columns = 'n.nid, n.type, n.promote, n.changed, xn.previously_changed, xn.priority_override, s.comment_count, s.last_comment_timestamp, xn.previous_comment';
$left_join = "LEFT JOIN {node_comment_statistics} s ON n.nid = s.nid";
}
else {
$columns = 'n.nid, n.type, n.promote, n.changed, xn.previously_changed, xn.priority_override';
$left_join = '';
}
$query = "SELECT $columns, $coalesce(ua.dst) AS alias FROM {node} n
LEFT JOIN {xmlsitemap_node} xn ON n.nid = xn.nid
$left_join
LEFT JOIN {url_alias} ua ON ua.src = CONCAT('node/', n.nid)
WHERE n.status > 0
AND n.type NOT IN (". xmlsitemap_placeholders($excludes, 'varchar') .")
AND (xn.priority_override IS NULL OR xn.priority_override = -2 OR xn.priority_override >= 0)
AND n.nid <> %d
GROUP BY $columns";
$nid = 0;
$frontpage = explode('/', drupal_get_normal_path(variable_get('site_frontpage', 'node')));
if (count($frontpage) == 2 && $frontpage[0] == 'node' && is_numeric($frontpage[1])) {
$nid = $frontpage[1];
}
$query_args = array_merge($excludes, array($nid));
$result = db_query(db_rewrite_sql($query), $query_args);
$count_comments = (variable_get('xmlsitemap_node_count_comments', TRUE) && module_exists('comment'));
while ($node = db_fetch_object($result)) {
db_query("INSERT INTO {xmlsitemap} (loc, lastmod, changefreq, priority) VALUES ('%s', %d, %d, %f)",
xmlsitemap_url('node/'. $node->nid, $node->alias, NULL, NULL, TRUE),
$count_comments ? max($node->changed, $node->last_comment_timestamp) : $node->changed,
xmlsitemap_node_frequency($node),
xmlsitemap_node_priority($node)
);
}
}
/*****************************************************************************
* Menu callbacks / form builders, submit/validate functions.
****************************************************************************/
/**
* Add submit actions to forms.
* @return None
*/
function _xmlsitemap_node_submit($form_id, $form_values) {
$op = isset($form_values['op']) ? $form_values['op'] : '';
$priority = $form_values['xmlsitemap_node_type_priority'];
$old_priority = $form_values['xmlsitemap_old_priority'];
if ($op == t('Save content type') && $priority != $old_priority || $op == t('Reset to defaults') && $old_priority != 0.1) {
xmlsitemap_flag_sitemap();
}
}
/*****************************************************************************
* Theme functions.
****************************************************************************/
/**
* Display the nodes of a view as a Google News sitemap.
*/
function theme_xmlsitemap_node_view_news($view, $nodes, $type) {
drupal_set_header('Content-Type: text/xml; charset=utf-8');
print ''."\n";
print ''."\n";
foreach ($nodes as $node) {
$lastmod = variable_get('xmlsitemap_node_count_comments', TRUE) ? max($node->changed, $node->last_comment_timestamp) : $node->changed;
print ' '."\n";
print ' '. xmlsitemap_url('node/'. $node->nid, $node->alias, NULL, NULL, TRUE) .''."\n";
print ' '. gmdate('Y-m-d\TH:i:s+00:00', $lastmod) .''."\n";
print ' '. xmlsitemap_sitemap_frequency(xmlsitemap_node_frequency($node)) .''."\n";
print ' '."\n";
print ' '. gmdate('Y-m-d\TH:i:s+00:00', $node->created) .''."\n";
print ' '."\n";
print ' '."\n";
}
print '';
drupal_page_footer();
exit;
}
/**
* Display the nodes of a view as an XML sitemap.
*/
function theme_xmlsitemap_node_view_sitemap($view, $nodes, $type) {
drupal_set_header('Content-Type: text/xml; charset=utf-8');
print ''."\n";
print ''."\n";
$count_comments = (variable_get('xmlsitemap_node_count_comments', TRUE) && module_exists('comment'));
foreach ($nodes as $node) {
if ($count_comments) {
$lastmod = max($node->changed, $node->last_comment_timestamp);
}
else {
$lastmod = $node->changed;
}
print ' '."\n";
print ' '. xmlsitemap_url('node/'. $node->nid, $node->alias, NULL, NULL, TRUE) .''."\n";
print ' '. gmdate('Y-m-d\TH:i:s+00:00', $lastmod) .''."\n";
print ' '. xmlsitemap_sitemap_frequency(xmlsitemap_node_frequency($node)) .''."\n";
print ' '. number_format(xmlsitemap_node_priority($node), 1) .''."\n";
print ' '."\n";
}
print '';
drupal_page_footer();
exit;
}
/*****************************************************************************
* Public functions.
****************************************************************************/
/**
* Get array of excluded types.
* @return An array of node types to exclude.
*/
function xmlsitemap_node_excludes() {
static $excludes;
if (!isset($excludes)) {
$excludes = array();
foreach (node_get_types() as $type => $name) {
if (variable_get("xmlsitemap_node_type_priority_$type", 0.5) < 0) {
$excludes[] = $type;
}
}
if (empty($excludes)) {
$excludes = array(0);
}
}
return $excludes;
}
/**
* Calculate the change frequency of a node.
* @param $node: Data for a node retrieved by _xmlsitemap_node_links().
* @return Number of seconds between updates
*/
function xmlsitemap_node_frequency($node) {
$age = REQUEST_TIME - $node->changed;
if (variable_get('xmlsitemap_node_count_comments', TRUE) && module_exists('comment')) {
$age = REQUEST_TIME - max($node->changed, $node->last_comment_timestamp);
$interval = 0;
if (!empty($node->previously_changed) && isset($node->previous_comment)) {
$interval = min($node->changed, $node->last_comment_timestamp) - max($node->previously_changed, $node->previous_comment);
}
elseif (!empty($node->previously_changed)) {
$interval = min($node->changed, $node->last_comment_timestamp) - $node->previously_changed;
}
elseif (isset($node->previous_comment)) {
$interval = min($node->changed, $node->last_comment_timestamp) - $node->previous_comment;
}
}
else {
$interval = empty($node->previously_changed) ? 0 : $node->changed - $node->previously_changed;
}
return max($age, $interval);
}
/**
* Get the nid of the front page node.
* @return Integer of front page node ID, or 0 if front page is not a node.
*/
function _xmlsitemap_node_frontpage() {
$nid = 0;
$frontpage = explode('/', drupal_get_normal_path(variable_get('site_frontpage', 'node')));
if (count($frontpage) == 2 && $frontpage[0] == 'node' && is_numeric($frontpage[1])) {
$nid = $frontpage[1];
}
return $nid;
}
/**
* Calculate the priority of a node.
* @param $node: A node object
* @return A number between 0 and 1, or -1
*/
function xmlsitemap_node_priority($node) {
static $maxcomments;
if (!isset($maxcomments)) {
$maxcomments = 0;
if (module_exists('comment')) {
$maxcomments = db_result(db_query("SELECT MAX(comment_count) FROM {node_comment_statistics}"));
}
}
if (!isset($node->priority_override) || $node->priority_override == -2.0) {
$priority = 0;
$priority += variable_get("xmlsitemap_node_type_priority_$node->type", 0.5);
if ($node->promote) {
$priority += variable_get('xmlsitemap_node_promote_priority', 0.3);
}
if (!empty($maxcomments)) {
$priority += $node->comment_count / $maxcomments * variable_get('xmlsitemap_node_comment_priority', 0.5);
}
$priority = round($priority, 1);
$priority = min($priority, 1);
}
else {
$priority = $node->priority_override;
}
return $priority;
}
/**
* @} End of "addtogroup xmlsitemap".
*/