<?php

/**
 * Send a notification to all subscribers.
 */
function pusher_notify($nids, $channel = array(), $url = 'rss.xml') {
  node_load(NULL, NULL, TRUE);
  $changed = pusher_feed($nids, $channel, $url);
  push_hub_notify(url($url, array('absolute' => TRUE)), $changed, FALSE);
  pusher_execute_hub_queue();
}

function pusher_execute_hub_queue() {
  // Manually execute pushhub queue.
  $infos = push_hub_cron_queue_info();
  $info = $infos[PUSH_HUB_NOTIFICATIONS_QUEUE];
  $function = $info['worker callback'];
  $end = time() + (isset($info['time']) ? $info['time'] : 1);
  $queue = DrupalQueue::get(PUSH_HUB_NOTIFICATIONS_QUEUE);
  while (time() < $end && ($item = $queue->claimItem())) {
    $function($item->data);
    $queue->deleteItem($item);
  }
}

/**
 * Recognize node_feed()?
 *
 * Change: feed_url and hub_url embedding, don't print to screen.
 *
 * Atom specific adaptation of node_feed
 * http://api.drupal.org/api/drupal/modules--node--node.module/function/node_feed/7
 */
function pusher_feed($nids = FALSE, $channel = array(), $url = 'rss.xml') {
global $base_url, $language_content;

  if ($nids === FALSE) {
    $nids = db_select('node', 'n')
      ->fields('n', array('nid', 'created'))
      ->condition('n.promote', 1)
      ->condition('status', 1)
      ->orderBy('n.created', 'DESC')
      ->range(0, variable_get('feed_default_items', 10))
      ->addTag('node_access')
      ->execute()
      ->fetchCol();
  }

  $item_length = variable_get('feed_item_length', 'fulltext');
  $namespaces = array(
    'xmlns:dc' => 'http://purl.org/dc/elements/1.1/',
    'xmlns:atom' => 'http://www.w3.org/2005/Atom',
  );
  $teaser = ($item_length == 'teaser');

  // Load all nodes to be rendered.
  $nodes = node_load_multiple($nids);
  $items = '';
  foreach ($nodes as $node) {
    $item_text = '';

    $node->link = url("node/$node->nid", array('absolute' => TRUE));
    $node->rss_namespaces = array();
    $node->rss_elements = array(
      array(
        'key' => 'pubDate',
        'value' => gmdate('r', $node->created),
      ),
      array(
        'key' => 'dc:creator',
        'value' => $node->name,
      ),
      array(
        'key' => 'guid',
        'value' => $node->nid . ' at ' . $base_url,
        'attributes' => array('isPermaLink' => 'false'),
      ),
    );

    // The node gets built and modules add to or modify $node->rss_elements
    // and $node->rss_namespaces.
    $build = node_view($node, 'rss');
    unset($build['#theme']);

    if (!empty($node->rss_namespaces)) {
      $namespaces = array_merge($namespaces, $node->rss_namespaces);
    }

    if ($item_length != 'title') {
      // We render node contents and force links to be last.
      $build['links']['#weight'] = 1000;
      $item_text .= drupal_render($build);
    }

    $items .= format_rss_item($node->title, $node->link, $item_text, $node->rss_elements);
  }

  $channel_defaults = array(
    'version' => '2.0',
    'title' => variable_get('site_name', 'Drupal'),
    'link' => $base_url,
    'description' => variable_get('feed_description', ''),
    'language' => $language_content->language,
  );
  $channel_extras = array_diff_key($channel, $channel_defaults);
  $channel = array_merge($channel_defaults, $channel);

  // Custom atom feeds functionality begin.
  $feed_url = url($url, array('absolute' => TRUE));
  $hub_url = url('pubsubhubbub/endpoint', array('absolute' => TRUE));
  $output = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
  $output .= "<rss version=\"" . $channel["version"] . "\" xml:base=\"" . $base_url . "\" " . drupal_attributes($namespaces) . ">\n";

  // Add push atom links to channel before items
  // TODO: Use channel args instead?
  $pushinfo = "<atom:link rel=\"hub\" href=\"$hub_url\" />\n";
  $pushinfo .= "<atom:link rel=\"self\" href=\"$feed_url\" />\n";
  $items = $pushinfo . $items;

  $output .= format_rss_channel($channel['title'], $channel['link'], $channel['description'], $items, $channel['language']);
  $output .= "</rss>\n";
  return $output;
  // Custom atom feeds functionality end.
}
