diff -urN publish_47/publish.info publish_5/publish.info
--- publish_47/publish.info 1969-12-31 19:00:00.000000000 -0500
+++ publish_5/publish.info 2007-06-11 18:24:19.526581928 -0400
@@ -0,0 +1,5 @@
+name = Publish
+description = Allow site to send content to other Drupal sites.
+version = 5.x-1.x-dev
+dependencies = taxonomy
+package = Publish
\ No newline at end of file
diff -urN publish_47/publish.install publish_5/publish.install
--- publish_47/publish.install 2006-12-08 14:49:14.000000000 -0500
+++ publish_5/publish.install 2007-06-11 18:24:19.519582992 -0400
@@ -12,7 +12,7 @@
pub_vocab varchar(255) NOT NULL default '',
UNIQUE KEY channel_id (channel_id,type)
) TYPE=MyISAM /*!40100 DEFAULT CHARACTER SET utf8 */;");
-
+
db_query("CREATE TABLE {publish_channel} (
channel_id int(10) unsigned NOT NULL auto_increment,
name varchar(255) NOT NULL default '',
@@ -26,6 +26,11 @@
PRIMARY KEY (channel_id)
) TYPE=MyISAM /*!40100 DEFAULT CHARACTER SET utf8 */;");
+ db_query("CREATE TABLE {publish_views} (
+ channel_id int(10) unsigned NOT NULL default '0',
+ view_name varchar(32) NOT NULL default '0'
+ ) TYPE=MyISAM /*!40100 DEFAULT CHARACTER SET utf8 */;");
+
db_query("CREATE TABLE {publish_subscribers} (
channel_id int(10) unsigned NOT NULL default '0',
sid int(10) unsigned NOT NULL default '0',
@@ -52,18 +57,6 @@
PRIMARY KEY (qid)
) TYPE=MyISAM /*!40100 DEFAULT CHARACTER SET utf8 */;");
- db_query("CREATE TABLE {publish_cond} (
- fid int(10) NOT NULL default '0',
- channel_id int(10) NOT NULL default '0',
- sid int(10) NOT NULL default '0',
- field varchar(128) NOT NULL default '',
- cond varchar(16) NOT NULL default '',
- value varchar(255) NOT NULL default '',
- PRIMARY KEY (fid),
- KEY channel_id (channel_id),
- KEY sid (sid)
- ) TYPE=MyISAM /*!40100 DEFAULT CHARACTER SET utf8 */;");
-
db_query("CREATE TABLE {publish_vocab_map} (
channel_id int(10) NOT NULL default '0',
sid int(10) unsigned NOT NULL default '0',
@@ -105,4 +98,25 @@
}
return $ret;
+}
+
+function publish_update_3() {
+ switch($GLOBALS['db_type']) {
+ case 'mysql':
+ case 'mysqli':
+ $r = db_query("CREATE TABLE {publish_views} (
+ channel_id int(10) unsigned NOT NULL default '0',
+ view_name varchar(32) NOT NULL default '0'
+ ) TYPE=MyISAM /*!40100 DEFAULT CHARACTER SET utf8 */;");
+ break;
+ case 'pgsql':
+ $r = FALSE;
+ break;
+ }
+
+ if($r) {
+ drupal_set_message(t("Publish updated to integrate with views."));
+ } else {
+ drupal_set_message(t("Publish could not be updated to integrate with views. Perhaps you are running an unsupported database type."), 'error');
+ }
}
\ No newline at end of file
diff -urN publish_47/publish.module publish_5/publish.module
--- publish_47/publish.module 2006-10-31 16:50:29.000000000 -0500
+++ publish_5/publish.module 2007-06-11 18:24:19.519582992 -0400
@@ -25,13 +25,11 @@
*/
function publish_help($section) {
switch ($section) {
- case 'admin/modules#description':
- return t('Allow site to send content to other Drupal sites.');
- case 'admin/publish' :
+ case 'admin/build/publish' :
return t('
Channels can be subscribed to by other Drupal sites using the subscribe module.
');
- case strstr($section, 'admin/publish/pub/nodes'):
+ case strstr($section, 'admin/build/publish/pub/nodes'):
return t('
Choose which which node types you would like to publish to other Drupal sites.
');
- case strstr($section, 'admin/publish/pub/vocabularies'):
+ case strstr($section, 'admin/build/publish/pub/vocabularies'):
return t('Choose which vocabularies will accompany the nodes you publish to other Drupal sites. If a checkbox does not appear next to a node type it is because the node type is not associated with the vocabulary (you can change associations using administer > categories > edit vocabulary.)
');
}
}
@@ -40,73 +38,107 @@
* Implementation of hook_menu().
*/
function publish_menu($may_cache) {
+ $path = drupal_get_path('module', 'publish');
+ require_once("$path/publish_views.inc");
+
$items = array();
$admin = user_access('administer channels');
if (!$may_cache) {
- if (arg(2) == 'pub' && is_numeric(arg(4))) {
- $items[] = array(
- 'path' => 'admin/publish/pub/edit/' . arg(4),
- 'title' => t('edit'),
- 'callback' => 'publish_channel_edit',
- 'type' => MENU_CALLBACK,
- 'access' => $admin);
- }
+ /**
+ * Subscribers.
+ */
$items[] = array(
- 'path' =>'admin/publish/subscribers/' . arg(3),
- 'title' => t('subscribers'),
+ 'path' =>'admin/build/publish/subscribers/' . arg(4),
+ 'title' => t('Subscribers'),
'callback' => 'publish_subscribers',
+ 'callback arguments' => array(
+ arg(4), // Channel ID
+ ),
'type' => MENU_CALLBACK,
- 'access' => $admin);
- $items[] = array('path' => 'admin/publish/filters/' . arg(3),
- 'title' => t('filters'),
- 'callback' => 'publish_channel_filter_form',
+ 'access' => $admin,
+ );
+
+ /**
+ * Channel wizard.
+ */
+ $items[] = array(
+ 'path' => 'admin/build/publish/pub/edit',
+ 'title' => t('Edit'),
+ 'callback arguments' => array(
+ arg(5), // Channel ID
+ ),
+ 'callback' => 'publish_channel_edit',
+ 'type' => MENU_CALLBACK,
+ 'access' => $admin,
+ );
+ $items[] = array(
+ 'path' => 'admin/build/publish/pub/vocabularies',
+ 'title' => t('Vocabularies'),
+ 'callback' => 'drupal_get_form',
+ 'callback arguments' => array(
+ 'publish_vocabulary_form', // Form ID
+ arg(5), // Channel ID
+ ),
'type' => MENU_CALLBACK,
- 'access' => $admin);
- $items[] = array('path' => 'admin/publish/edit/' . arg(4),
- 'title' => t('configure'),
- 'callback' => 'publish_channel_edit',
+ 'access' => $admin,
+ );
+ $items[] = array(
+ 'path' => 'admin/build/publish/pub/views',
+ 'title' => t('Views'),
+ 'callback' => 'publish_channel_views',
+ 'callback arguments' => array(
+ arg(5), // Channel ID
+ ),
'type' => MENU_CALLBACK,
- 'access' => $admin);
+ 'access' => $admin,
+ );
+ $items[] = array(
+ 'path' => 'admin/build/publish/pub/delete',
+ 'title' => t('Delete'),
+ 'callback' => 'drupal_get_form',
+ 'callback arguments' => array(
+ 'publish_channel_delete_form', // Form ID
+ arg(5), // Channel ID
+ ),
+ 'type' => MENU_CALLBACK,
+ 'access' => $admin,
+ );
}
else {
+ /**
+ * Main UI.
+ */
$items[] = array(
- 'path' => 'admin/publish',
- 'title' => t('publish'),
+ 'path' => 'admin/build/publish',
+ 'title' => t('Publish'),
'callback' => 'publish_overview',
- 'access' => $admin);
- $items[] = array(
- 'path' => 'admin/publish/pub/vocabularies',
- 'title' => t('vocabularies'),
- 'callback' => 'publish_vocabulary_form',
- 'type' => MENU_CALLBACK,
- 'access' => $admin);
+ 'access' => $admin,
+ );
+
+ /**
+ * Tabs
+ */
$items[] = array(
- 'path' => 'admin/publish/list',
- 'title' => t('channels'),
+ 'path' => 'admin/build/publish/list',
+ 'title' => t('Channels'),
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => -10,
'callback' => 'publish_overview',
- 'access' => $admin);
+ 'access' => $admin,
+ );
$items[] = array(
- 'path' => 'admin/publish/add',
- 'title' => t('add channel'),
+ 'path' => 'admin/build/publish/add',
+ 'title' => t('Add channel'),
'type' => MENU_LOCAL_TASK,
- 'callback' => 'publish_channel_form',
- 'access' => $admin);
- $items[] = array(
- 'path' => 'admin/publish/pub/delete',
- 'title' => t('delete'),
- 'callback' => 'publish_channel_delete_form',
- 'type' => MENU_CALLBACK,
- 'access' => $admin);
- $items[] = array(
- 'path' => 'admin/publish/pub/filters/delete',
- 'title' => t('filters'),
- 'callback' => 'publish_channel_filter_delete_form',
- 'type' => MENU_CALLBACK,
- 'access' => $admin);
+ 'callback' => 'drupal_get_form',
+ 'callback arguments' => array(
+ 'publish_channel_form', // Form ID
+ ),
+ 'access' => $admin,
+ );
}
+
return $items;
}
@@ -114,7 +146,10 @@
* Implementation of hook_perm().
*/
function publish_perm() {
- return array('subscribe to channels', 'administer channels');
+ return array(
+ 'subscribe to channels',
+ 'administer channels',
+ );
}
/********************************************************************
@@ -128,6 +163,9 @@
*
*/
function publish_cron() {
+ $path = drupal_get_path('module', 'publish');
+ require_once("$path/publish_views.inc");
+
publish_push();
}
@@ -141,33 +179,47 @@
switch ($op) {
case 'insert':
case 'update':
- // exit quickly if node is not in published state
- if ($node->status != 1) {
- return;
- }
if (PUBLISH_DEBUG_MODE) watchdog('publish', t('nodeapi firing'));
- // Find all subscribers to this node.
- $result = db_query("SELECT * FROM {publish_channel} p INNER JOIN {publish_nodetypes} n ON n.channel_id = p.channel_id INNER JOIN {publish_subscribers} s ON s.channel_id = p.channel_id WHERE n.type = '%s'", $node->type);
- $exists = db_result(db_query("SELECT nid FROM {publish_queue} WHERE nid = %d", $node->nid));
- if ($exists) { // delete older version from queue
- db_query("DELETE FROM {publish_queue} WHERE nid = %d", $node->nid);
+ //Get all channels
+ $qs = db_query("SELECT pc.channel_id, pc.name FROM {publish_channel} pc WHERE pc.whenpub = 1");
+ while($obj = db_fetch_object($qs)) {
+ $channels[$obj->channel_id] = $obj->name;
}
- $publish_now = FALSE;
- while ($data = db_fetch_object($result)) {
- if ($data->whenpub == PUBLISH_WHENPUB_NODESUB) {
- $publish_now = TRUE;
- }
- // add them to the queue to have the node pushed out to them
- // TODO: we should run the node through the channel's condition filters here?
- db_query("INSERT INTO {publish_queue} (qid, nid, sid, channel_id, changed) VALUES (%d, %d, %d, %d, %d)", db_next_id('publish_queue'), $node->nid, $data->sid, $data->channel_id, $node->changed);
- if (PUBLISH_DEBUG_MODE) watchdog('publish', t('channel %cid added node %nid to q for subscriber id %sid', array('%cid' => $data->channel_id, '%nid' => $node->nid, '%sid' => $data->sid)));
+
+ //Get all subscribers, keyed by channel_id and then by subscriber id.
+ $qs = db_query("SELECT ps.sid, ps.channel_id from {publish_subscribers} ps");
+ while($obj = db_fetch_object($qs)) {
+ $subscribers[$obj->channel_id][$obj->sid] = $obj->sid;
}
- // set publish on exit if channel is set to publish at node submission time
- if ($publish_now) {
- if (PUBLISH_DEBUG_MODE) watchdog('publish', t('setting publish_exit'));
- publish_exit(TRUE);
+
+ //Check to see if this node already exists in the publish queue. If it does, delete it.
+ $exists = db_result(db_query("SELECT COUNT(pq.nid) FROM {publish_queue} pq WHERE pq.nid = %d", $node->nid));
+ if($exists > 0) {
+ db_query("DELETE FROM {publish_queue} WHERE nid = %d", $node->nid);
+ }
+
+ $publish_now = FALSE;
+ foreach($channels as $channel_id => $channel) {
+ $channel_subscribers = $subscribers[$channel_id];
+
+ //Get all nodes of the channel.
+ $nodes = publish_get_nodes_by_channel($channel_id, 'nid');
+
+ //If the node is in the channel, add it to the queue for each subscriber.
+ if(array_key_exists($node->nid, (array)$nodes)) {
+ $publish_now = TRUE;
+ foreach(array_keys((array)$channel_subscribers) as $sid) {
+ db_query("INSERT INTO {publish_queue} (qid, nid, sid, channel_id, changed) VALUES (%d, %d, %d, %d, %d)", db_next_id('publish_queue'), $node->nid, $sid, $channel_id, $node->changed);
+ if (PUBLISH_DEBUG_MODE) watchdog('publish', t('channel !cid added node !nid to q for subscriber id !sid', array('!cid' => $channel_id, '!nid' => $node->nid, '!sid' => $sid)));
+ }
+ }
}
- break;
+
+ // Set publish on exit if channel is set to publish at node submission time
+ if ($publish_now) {
+ if (PUBLISH_DEBUG_MODE) watchdog('publish', t('setting publish_exit'));
+ publish_exit(TRUE);
+ }
}
}
@@ -197,14 +249,26 @@
* Registering xml-rpc methods to callback functions.
*/
function publish_xmlrpc() {
+ return array(
+ 'drupal.publish.maySubscribe' => 'publish_xmls_may_subscribe',
+ 'drupal.publish.subscribe' => 'publish_xmls_receive_subscription',
+ 'drupal.publish.pull' => 'publish_xmls_publish',
+ 'drupal.publish.getNode' => 'publish_xmls_get_node',
+ 'drupal.publish.getChannels' => 'publish_xmls_get_channels',
+ 'drupal.publish.cancelSubscription' => 'publish_xmls_cancel_subscription',
+ );
+
+ /**
+ * TODO: Update function signatures to match what we currently have.
return array(
array('drupal.publish.maySubscribe', 'publish_xmls_may_subscribe', array('array', 'int','string','string'), t('Return channel info if caller supplies appropriate credentials.')),
array('drupal.publish.subscribe', 'publish_xmls_receive_subscription', array('int', 'int', 'string', 'string', 'string', 'string', 'array', 'array', 'array'), t('Establish relationship with subscriber.')),
- array('drupal.publish.pull', 'publish_xmls_publish', array('array', 'int', 'int', 'string', 'string', 'array'), t('Send nodes matching certain conditions to subscriber.')),
+ array('drupal.publish.pull', 'publish_xmls_publish', array('array', 'int', 'int', 'string', 'string'), t('Send nodes matching certain conditions to subscriber.')),
array('drupal.publish.getNode', 'publish_xmls_get_node', array('array', 'int', 'string', 'string', 'int'), t('Send single node to subscriber.')),
array('drupal.publish.getChannels', 'publish_xmls_get_channels', array('array'), t('Return list of public channels on this site.')),
array('drupal.publish.cancelSubscription', 'publish_xmls_cancel_subscription', array('boolean', 'int', 'string'), t('Cancel subscription.'))
);
+ */
}
/********************************************************************
@@ -223,20 +287,20 @@
$row = array();
while ($data = db_fetch_object($result)) {
$edit_items = array();
- $edit_items[] = l(t('edit'), "admin/publish/pub/edit/$data->channel_id");
- $edit_items[] = l(t('vocabularies'), "admin/publish/pub/vocabularies/$data->channel_id");
- $edit_items[] = l(t('filters'), "admin/publish/filters/$data->channel_id");
+ $edit_items[] = l(t('edit'), "admin/build/publish/pub/edit/$data->channel_id");
+ $edit_items[] = l(t('vocabularies'), "admin/build/publish/pub/vocabularies/$data->channel_id");
+ $edit_items[] = l(t('views'), "admin/build/publish/pub/views/$data->channel_id");
$count = db_result(db_query("SELECT COUNT(*) FROM {publish_subscribers} WHERE channel_id = %d", $data->channel_id));
- $edit_items[] = l(t('delete'), "admin/publish/pub/delete/$data->channel_id");
+ $edit_items[] = l(t('delete'), "admin/build/publish/pub/delete/$data->channel_id");
$row[] = array(
array('data' => $data->channel_id, 'valign' => 'top'),
array('data' => "$data->name", 'valign' => 'top'),
array('data' => $data->advertise ? t('yes') : t('no'), 'valign' => 'top'),
- array('data' => $count ? l($count, "admin/publish/subscribers/$data->channel_id") : t('none'), 'valign' => 'top'),
+ array('data' => $count ? l($count, "admin/build/publish/subscribers/$data->channel_id") : t('none'), 'valign' => 'top'),
array('data' => implode("
\n", $edit_items)));
}
- $output = $row ? theme('table', $header, $row) : t('No channels created. Would you like to create one?', array('%add-channel' => url('admin/publish/add')));
+ $output = $row ? theme('table', $header, $row) : t('No channels created. Would you like to create one?', array('!add-channel' => url('admin/build/publish/add')));
return $output;
}
@@ -251,26 +315,147 @@
* An object representing a channel
*/
function publish_channel_load($channel_id) {
+
$channel = db_fetch_object(db_query('SELECT * FROM {publish_channel} WHERE channel_id = %d', $channel_id));
if ($channel) {
- $result = db_query('SELECT * FROM {publish_cond} WHERE channel_id = %d AND sid = 0', $channel_id);
- $channel->filters = array();
- while ($data = db_fetch_object($result)) {
- $channel->filters[] = array('fid' => $data->fid, 'field' => $data->field, 'operator' => $data->cond, 'value' => $data->value);
- }
+ $views = db_result(db_query("SELECT pv.view_name FROM {publish_views} pv WHERE pv.channel_id = %d", $channel_id));
+ $channel->views['view'] = $views;
+ $arguments = views_argument_api_get('publish_channel_' . $channel_id, array());
+ $channel->views['arguments'] = $arguments;
}
return $channel;
}
-function publish_channel_edit() {
- $channel_id = arg(4);
+function publish_channel_views($channel_id) {
+ $op = check_plain($_POST['op']);
+ $view_name = check_plain($_POST['channel_view']);
+
+ if($op == t('Update')) {
+ publish_channel_view_save($channel_id, $view_name);
+ }
+
+ $channel = publish_channel_load($channel_id);
+
+ if(empty($channel)) {
+ drupal_set_message(t('No such channel.', 'error'));
+ drupal_goto('admin/build/publish');
+ } else {
+ return drupal_get_form('publish_channel_views_form', $channel);
+ }
+}
+
+function publish_channel_views_form($channel) {
+ //Todo: Good candidate for jQuery
+
+ //Put together a views selector and an update button.
+ $form['channel_id'] = array(
+ '#type' => 'value',
+ '#value' => $channel->channel_id,
+ );
+
+ $form['view'] = array(
+ '#type' => 'fieldset',
+ '#title' => t('View'),
+ '#collapsible' => FALSE,
+ '#collasped' => FALSE,
+ );
+
+ $form['view']['channel_view'] = array(
+ '#title' => t('View'),
+ '#description' => t('Select a view to use with this channel.'),
+ '#type' => 'select',
+ '#default_value' => $channel->views['view'],
+ '#value' => $channel->views['view'],
+ '#options' => publish_get_views(),
+ );
+ $form['view']['channel_update'] = array(
+ '#type' => 'button',
+ '#value' => t('Update'),
+ );
+
+ //Node types
+ $view = views_get_view($channel->views['view']);
+ $filters = $view->filter;
+ foreach((array)$filters as $filter) {
+ if($filter['field'] == 'node.type') {
+ $types = $filter['value'];
+ }
+ }
+
+ if(empty($types)) {
+ foreach(node_get_types() as $type) {
+ $types[] = $type->type;
+ }
+ }
+
+ $form['node_types'] = array(
+ '#type' => 'value',
+ '#value' => $types,
+ );
+
+ $typemsg = theme('item_list', $types);
+
+ $form['node_types_message'] = array(
+ '#title' => t('Node types'),
+ '#description' => t('This channel currently uses a view that publishes nodes of the following types:'),
+ '#type' => 'fieldset',
+ '#collapsible' => TRUE,
+ '#collapsed' => FALSE,
+ );
+
+ $form['node_types_message']['list'] = array(
+ '#type' => 'item',
+ '#value' => $typemsg,
+ );
+
+ //Put together a place for arguments
+ $form['channel_arguments'] = array(
+ '#title' => t('View arguments'),
+ '#type' => 'fieldset',
+ '#collapsible' => TRUE,
+ '#collapsed' => FALSE,
+ '#theme' => 'views_argument_api_form_tabular',
+ );
+
+ $views_argument_api_form = views_argument_api_build_argument_form($channel->views['view']);
+ $views_argument_api_default_values = views_argument_api_get('publish_channel_' . $channel->channel_id, NULL);
+
+ foreach($views_argument_api_form as $key => $element) {
+ $form['channel_arguments'][$key] = $element;
+ $form['channel_arguments'][$key]['#default_value'] = $views_argument_api_default_values[$key];
+ }
+
+ $form['submit'] = array(
+ '#type' => 'submit',
+ '#value' => t('Submit'),
+ );
+
+ return $form;
+}
+
+
+function publish_channel_views_form_submit($form_id, $form_values) {
+ //Save a channel's view.
+ publish_channel_view_save($form_values['channel_id'], $form_values['channel_view']);
+
+ //Save a channel's view arguments.
+ views_argument_api_save_arguments('publish_channel_' . $form_values['channel_id'], $form_values, $form_values['channel_view']);
+
+ //Save the node type information
+ publish_node_save($form_values);
+
+ drupal_set_message(t('The channel was updated.'));
+ return 'admin/build/publish';
+}
+
+function publish_channel_edit($channel_id) {
$channel = publish_channel_load($channel_id);
if (!$channel) {
drupal_set_message(t('No such channel.', 'error'));
- drupal_goto('admin/publish');
+ drupal_goto('admin/build/publish');
}
- return publish_channel_form($channel);
+ return drupal_get_form('publish_channel_form', $channel);
}
/**
@@ -282,16 +467,9 @@
* Array with form values
*
* @return
- * HTML output
+ * An array of form elements.
*/
function publish_channel_form($channel = NULL, $edit = array()) {
- if (!isset($channel->name)) {
- $output = '' . t('Adding channel') . '
';
- }
- else {
- $output = '' . t('Configuring channel') . ' "' . $channel->name . '"' . '
';
- }
-
$form['name'] = array(
'#type' => 'textfield',
'#title' => t('Name'),
@@ -314,22 +492,6 @@
'#description' => t('Show name and description of this channel when another site asks which channels are available.')
);
- $published = array();
- $result = db_query("SELECT * FROM {publish_nodetypes} WHERE channel_id = '%s'", $channel->channel_id);
- while ($data = db_fetch_object($result)) {
- $published[] = $data->type;
- }
-
- $form['node_types'] = array(
- '#type' => 'fieldset',
- '#title' => t('Node types')
- );
- $form['node_types']['types'] = array(
- '#type' => 'checkboxes',
- '#title' => t('Publish the following node types'),
- '#default_value' => $published,
- '#options' => node_get_types(),
- );
$form['authentication'] = array(
'#type' => 'fieldset',
'#title' => t('Who may subscribe to this channel?')
@@ -338,7 +500,7 @@
'#type' => 'radios',
'#title' => t('Choose an authorization model'),
'#default_value' => isset($channel->authtype) ? $channel->authtype : 'none',
- '#options' => array(t('None'), t('Users with %perm permission', array('%perm' => theme('placeholder', 'subscribe to channel'))), t('Username and password (enter below)'))
+ '#options' => array(t('None'), t('Users with %perm permission', array('%perm' => 'subscribe to channel')), t('Username and password (enter below)'))
);
$form['authentication']['username'] = array(
'#type' => 'textfield',
@@ -362,7 +524,8 @@
'#type' => 'textarea',
'#title' => t('Domains'),
'#rows' => '2',
- '#description' => t('Subscribers will be restricted to domains listed here, e.g. %example. If no domains are listed, all may subscribe.', array('%example' => theme('placeholder', 'example.org, example2.org')))
+ '#description' => t('Subscribers will be restricted to domains listed here, e.g. %example. If no domains are listed, all may subscribe.', array('%example' => 'example.org, example2.org')),
+ '#default_value' => $channel->domains,
);
$form['channel_id'] = array(
'#type' => 'value',
@@ -382,7 +545,7 @@
'#type' => 'submit',
'#value' => t('Update Channel Settings')
);
- return drupal_get_form('publish_channel_form', $form);
+ return $form;
}
/**
@@ -416,9 +579,7 @@
form_set_value($form['domains']['allowed'], ltrim($clean_domains, ','));
}
}
- if (!array_filter($form_values['types'])) {
- $errors['types'] = t('You must choose at least one node type to publish.');
- }
+
foreach ($errors as $name => $message) {
form_set_error($name, $message);
}
@@ -426,210 +587,19 @@
function publish_channel_form_submit($form_id, $form_values) {
// get an array of checked node types
- $form_values['types'] = array_filter($form_values['types']);
if ($form_values['channel_id']) {
publish_channel_save($form_values);
}
else { // new channel
$form_values['channel_id'] = publish_channel_save($form_values);
}
- publish_node_save($form_values);
- return 'admin/publish';
-}
-
-/**
- * Menu callback. Build form for editing channel filters
- *
- * @param $edit
- * Array with form values
- *
- * @return
- * HTML output
- */
-function publish_channel_filter_form($edit = array()) {
- $channel_id = arg(3);
- $channel = publish_channel_load($channel_id);
- if (!$channel) {
- drupal_set_message(t('No such channel.'), 'error');
- drupal_goto('admin/publish');
- }
- $form['field'] = array(
- '#type' => 'select',
- '#title' => t('Field'),
- '#options' => publish_channel_filter_options()
- );
- foreach (publish_supported_operators() as $operator) {
- $operators[$operator] = $operator;
- }
- $form['operation'] = array(
- '#type' => 'select',
- '#title' => t('Condition'),
- '#options' => $operators
- );
- $form['value'] = array(
- '#type' => 'textfield',
- '#title' => t('Value'),
- '#size' => '25',
- '#maxlength' => '254'
- );
- $form['submit'] = array(
- '#type' => 'submit',
- '#value' => t('Add filter')
- );
- $form['channel_id'] = array(
- '#type' => 'value',
- '#value' => $channel_id);
- return drupal_get_form('publish_channel_filter_form', $form);
-}
-
-function theme_publish_channel_filter_form($form) {
- $channel = publish_channel_load($form['channel_id']['#value']);
- if (count($channel->filters)) {
- $output = t('The following filters are in effect for this channel:');
- $header = array(t('Field'), t('Condition'), t('Value'), t('Operation'));
- foreach ($channel->filters as $filter) {
- $operation = l(t('delete'), 'admin/publish/pub/filters/delete/' . $channel->channel_id . '/' .$filter['fid']);
- $rows[] = array(
- array('data' => $filter['field']),
- array('data' => $filter['condition']),
- array('data' => $filter['value']),
- array('data' => $operation)
- );
- }
- $output = theme('table', $header, $rows);
- }
- else {
- $output = t('No filters are currently defined.');
- }
-
- // we don't want theming so we do a table the old-fashioned way
- $output .= '';
- $output .= '| ' . form_render($form['field']) . ' | ';
- $output .= ' | ' . form_render($form['operation']) . ' | ';
- $output .= ' | ' . form_render($form['value']) . ' | ';
- $output .= ' | ' . form_render($form['submit']) . ' | ';
- $output .= '
';
- $output .= form_render($form);
-
- return $output;
-}
-
-function publish_channel_filter_options() {
- $v_names = array();
- if (module_exist('taxonomy')) {
- $vocabularies = taxonomy_get_vocabularies();
- foreach ($vocabularies as $v) {
- $v_names[$v->vid] = $v->name;
- }
- }
- $merged = array_merge($v_names, publish_supported_fields());
- foreach ($merged as $name) {
- $options[$name] = $name;
- }
- return $options;
-}
-
-function publish_channel_filter_form_validate($form_id, $edit) {
- $errors = array();
-
- if ($edit['field'] == '') {
- $errors['field'] = t('Please choose a field.');
- }
- elseif (!array_key_exists($edit['field'], publish_channel_filter_options())) {
- $errors['field'] = t('Invalid field.');
- }
-
- if (!in_array($edit['operation'], publish_supported_operators())) {
- $errors['operation'] = t('Invalid condition.');
- }
-
- foreach ($errors as $name => $message) {
- form_set_error($name, $message);
- }
-}
-
-function publish_channel_filter_form_submit($form_id, $form_values) {
- $channel = publish_channel_load($form_values['channel_id']);
- publish_channel_filter_save($channel, $form_values);
- drupal_set_message(t('Filter added.'));
- return 'admin/publish/filters/' . $form_values['channel_id'];
-}
-
-function publish_channel_filter_save(&$channel, $edit = array()) {
- $options = publish_channel_filter_options();
- $field = $options[$edit['field']];
- $condition = $edit['operation'];
- $value = $edit['value'];
- // get the new field, condition and value from the form
- // validate them (make sure they're not already in
- if (!isset($channel->filters)) {
- $channel->filters = array();
- }
- $duplicate = FALSE;
- foreach ($channel->filters as $filter) {
- if (($filter['field'] == $field) && ($filter['condition'] == $condition) && ($filter['value'] == $value)) {
- $duplicate = TRUE;
- }
- }
- if (!$duplicate) {
- $fid = db_next_id('publish_filter');
- $channel->filters[] = array('fid' => $fid, 'field' => $field, 'condition' => $condition, 'value' => $value);
- // the insertion of 0 into the sid (subscription id) field denotes
- // that this condition is a local channel condition
- db_query("INSERT INTO {publish_cond} (fid, channel_id, sid, field, cond, value) VALUES (%d, %d, 0, '%s', '%s', '%s')", $fid, $channel->channel_id, $field, $condition, $value);
- }
- else {
- drupal_set_message(t('This filter already exists.'), 'error');
- }
+ return 'admin/build/publish';
}
-function publish_channel_filter_delete_form() {
- $channel_id = arg(5);
- $filter_id = arg(6);
- $channel = publish_channel_load($channel_id);
- if (!$channel) {
- drupal_set_message(t('No such channel.', 'error'));
- drupal_goto('admin/publish');
- }
- $form['channel_id'] = array('#type' => 'value', '#value' => $channel_id);
- $form['filter_id'] = array('#type' => 'value', '#value' => $filter_id);
- $output = confirm_form('publish_channel_filter_delete_form', $form,
- t('Are you sure you want to delete this filter?'),
- 'admin/publish', t('This action cannot be undone.'),
- t('Delete'), t('Cancel') );
- return $output;
-}
-
-function publish_channel_filter_delete_form_submit($form_id, $form_values) {
- publish_channel_filter_delete($form_values['channel_id'], $form_values['filter_id']);
- return 'admin/publish/filters/' . $form_values['channel_id'];
-}
-function publish_channel_filter_delete($channel_id, $fid) {
- $data = db_fetch_object(db_query('SELECT pc.field, pc.cond, pc.value, pp.name FROM {publish_cond} as pc, {publish_channel} as pp WHERE pc.fid = %d AND pp.channel_id = %d', $fid, $channel_id));
- $filtertext = $data->field . ' ' . $data->cond . ' ' . $data->value;
- db_query('DELETE FROM {publish_cond} WHERE fid = %d', $fid);
- watchdog('special', t('Deleted filter %filter from channel %name.', array('%filter' => theme('placeholder', $filtertext), '%name' => $data->name)));
- drupal_set_message(t('Deleted filter %filter.', array('%filter' => theme('placeholder', $filtertext))));
-}
-
-/**
- * Load list of publishable node types from the database.
- *
- * @param $channel_id
- * The ID of the channel in question.
- *
- * @return
- * An array with node types as keys
- */
-function publish_nodetypes_load($channel_id) {
- $types = array();
-
- $result = db_query('SELECT type FROM {publish_nodetypes} WHERE channel_id = %d', $channel_id);
- while ($data = db_fetch_object($result)) {
- $types[$data->type] = $data->type;
- }
-
- return $types;
+function publish_channel_view_save($channel_id, $view_name) {
+ db_query("DELETE FROM {publish_views} WHERE channel_id = %d", $channel_id);
+ $r = db_query("INSERT INTO {publish_views} (channel_id, view_name) VALUES (%d, '%s')", $channel_id, $view_name);
+ return $r;
}
/**
@@ -638,7 +608,8 @@
* @param $edit
*/
function publish_channel_save($edit) {
- if (!$edit['clean_domains']) $edit['clean_domains'] = '';
+// if (!$edit['clean_domains']) $edit['clean_domains'] = '';
+ $edit['domains'] = $edit['allowed'];
$channel_id = $edit['channel_id'];
$fields = publish_db_fields('publish_channel');
@@ -652,8 +623,8 @@
}
}
db_query("UPDATE {publish_channel} SET ". implode(', ', $q) ." WHERE channel_id = ". db_escape_string($edit['channel_id']), $v);
- watchdog('special', t('%type: updated channel %name', array('%type' => ''. t('publish') .'', '%name' => "" . $edit['name'] . "")));
- drupal_set_message(t('Updated channel %name', array('%name' => theme('placeholder', $edit['name']))));
+ watchdog('special', t('%type: updated channel %name', array('%type' => t('publish'), '%name' => $edit['name'])));
+ drupal_set_message(t('Updated channel %name', array('%name' => $edit['name'])));
}
else {
// create new channel
@@ -672,35 +643,32 @@
// Insert the node into the database:
$query = "INSERT INTO {publish_channel} (". implode(", ", $k) .") VALUES(". implode(", ", $s) .")";
db_query($query, $v);
- watchdog('special', t('%type: created channel %name.', array('%type' => ''. t('publish') .'', '%name' => "" . $edit['name'] . "")));
- drupal_set_message(t('Created channel %name', array('%name' => theme('placeholder', $edit['name']))));
+ watchdog('special', t('!type: created channel !name.', array('!type' => t('publish'), '!name' => $edit['name'])));
+ drupal_set_message(t('Created channel !name', array('!name' => $edit['name'])));
}
return $edit['channel_id'];
}
/**
- * Menu callback.
- * The HTML form to confirm deletion of a channel.
+ * The form to confirm deletion of a channel.
*/
-function publish_channel_delete_form() {
- $channel_id = arg(4);
- $channel = publish_channel_load($channel_id);
+function publish_channel_delete_form($channel_id) {
+ $channel = publish_channel_load($channel_id);
if (!$channel) {
drupal_set_message(t('No such channel.', 'error'));
- drupal_goto('admin/publish');
+ drupal_goto('admin/build/publish');
}
+
$form['channel_id'] = array('#type' => 'value', '#value' => $channel_id);
- $output = confirm_form('publish_delete_form', $form,
- t('Are you sure you want to delete %title?', array('%title' => theme('placeholder', $channel->name))),
- 'admin/publish', t('This action cannot be undone.'),
- t('Delete'), t('Cancel') );
- return $output;
+
+ return confirm_form($form, t('Are you sure you want to delete %title?', array('%title' => $channel->name)), 'admin/build/publish', t('This action cannot be undone.'), t('Delete'), t('Cancel'), 'publish_channel_delete_form');
+
}
-function publish_delete_form_submit($form_id, $form_values) {
+function publish_channel_delete_form_submit($form_id, $form_values) {
$channel = publish_channel_load($form_values['channel_id']);
publish_channel_delete($channel);
- return 'admin/publish';
+ return 'admin/build/publish';
}
/**
@@ -711,71 +679,18 @@
*/
function publish_channel_delete($channel) {
db_query('DELETE FROM {publish_channel} WHERE channel_id = %d', $channel->channel_id);
- db_query("DELETE FROM {publish_nodetypes} WHERE channel_id = '%s'", $channel->channel_id);
- db_query('DELETE FROM {publish_cond} WHERE channel_id = %d', $channel->channel_id);
watchdog('publish', t('deleted channel %name.', array('%name' => $channel->name)));
}
-
-/**
- * Form to set the publish settings for node types.
- */
-function publish_node_form($channel_id, $edit = array()) {
-
- $nodetypes = array();
- foreach (node_list() as $type) {
- $nodetypes[$type] = node_invoke($type, 'node_name');
- }
-
- $published = array();
- $result = db_query("SELECT * FROM {publish_nodetypes} WHERE channel_id = '%s'", $channel_id);
- while ($data = db_fetch_object($result)) {
- $published[] = $data->type;
- }
-
-
- $node_checkboxes = '';
- foreach ($nodetypes as $internal_type => $type) {
- $node_checkboxes .= form_checkbox($type, 'pub_' . $internal_type, $internal_type, in_array($internal_type, $published));
- }
-
- $output = form_group(t('Publish the following node types'), $node_checkboxes);
- $output .= form_hidden('channel_id', $channel_id);
-
- return $output;
-}
-
/**
* Save a nodetype config data to the database.
*/
function publish_node_save($edit) {
-
+
$channel_id = $edit['channel_id'];
- $submitted_nodetypes = $edit['types'];
-
- /*
+ $submitted_nodetypes = $edit['node_types'];
- $nodetypes = array();
- foreach (node_list() as $type) {
- $nodetypes[$type] = node_invoke($type, 'node_name');
- if ($edit['pub_' . $type]) {
- $submitted_nodetypes[$type] = $type;
- }
- }
-
- $result = db_query("SELECT * FROM {publish_nodetypes} WHERE channel_id = '%s'", $channel_id);
- while ($data = db_fetch_object($result)) {
- if (key_exists($data->type, $submitted_nodetypes)) {
- // node type exists in database and has been checked; no change so delete from array
- unset($submitted_nodetypes[$data->type]);
- }
- else {
- // node type exists in database but not checked; delete from database
- db_query("DELETE FROM {publish_nodetypes} WHERE type = '%s'", $data->type);
- }
- }
- */
db_query("DELETE FROM {publish_nodetypes} WHERE channel_id = %d", $channel_id);
// now we are left with the node types to add
@@ -792,12 +707,7 @@
$channel = publish_channel_load($channel_id);
if (!$channel) {
drupal_set_message(t('No such channel.', 'error'));
- drupal_goto('admin/publish');
- }
-
- if (!module_exist('taxonomy')) {
- drupal_set_message(t('The taxonomy module is disabled. Please enable the taxonomy module.'), 'warning');
- drupal_goto('/admin/publish');
+ drupal_goto('admin/build/publish');
}
$vocabularies = taxonomy_get_vocabularies();
@@ -842,7 +752,7 @@
'#name' => 'edit[' . $type . '|' . $v->name . ']',
'#return_value' => 1
);
- $s = form_render($form[$type . '|' . $v->name]);
+ $s = drupal_render($form[$type . '|' . $v->name]);
}
$table .= '' . $s . ' | ';
}
@@ -864,10 +774,15 @@
else {
// no node types have been chosen for publication
drupal_set_message(t('No node types have been chosen for publication. Edit channel and choose at least one node type.'));
- drupal_goto('/admin/publish');
+ drupal_goto('/admin/build/publish');
}
- return drupal_get_form('publish_vocabulary_form', $form);
+ $form['return'] = array(
+ '#type' => 'item',
+ '#value' => l(t('Return to Publish'), 'admin/build/publish/'),
+ );
+
+ return $form;
}
/**
@@ -900,9 +815,9 @@
db_query("INSERT INTO {publish_nodetypes} (channel_id, type, pub_vocab) VALUES ('%s', '%s', '%s')", $channel_id, $type, serialize($vocs_this_node));
}
$channel = publish_channel_load($channel_id);
- drupal_set_message(t("Saved vocabulary publication configuration for channel %name.", array('%name' => theme('placeholder', $channel->name))));
+ drupal_set_message(t("Saved vocabulary publication configuration for channel %name.", array('%name' => $channel->name)));
- return 'admin/publish';
+ return 'admin/build/publish';
}
/**
@@ -940,7 +855,9 @@
static $nodetypes = array();
static $published_vocabularies = array();
- $lookup = node_get_types();
+ foreach(node_get_types() as $type) {
+ $lookup[$type->type] = $type->name;
+ }
$result = db_query("SELECT * FROM {publish_nodetypes} WHERE channel_id = '%s'", $channel_id);
while ($data = db_fetch_object($result)) {
$nodetypes[$data->type] = $lookup[$data->type];
@@ -964,8 +881,7 @@
* @return
* an HTML table of subscribers and related information
*/
- function publish_subscribers () {
- $channel_id = arg(3);
+ function publish_subscribers($channel_id) {
$channel = publish_channel_load($channel_id);
$output = '' . t('Subscribers to channel') . " '$channel->name':
";
$header = array(array('data' => t('Subscriber')), array('data' => t('Status')), array('data' => 'Operations', 'colspan' => '1'));
@@ -982,73 +898,16 @@
}
/**
- * Compile array of publishable nodes according to given conditions.
+ * Compile array of publishable nodes.
*
* @param $channel_id
* The ID of the channel in question.
*
- * @param $cond
- * Array of triplet arrays containing field, condition, value.
- * Example: array(array('created', '>', '0'))
- * Example: array(array('created', '>', '0'), array('nid', '<', '5'))
- *
* @return
* An array of node objects.
*/
-function publish_publish($channel_id, $cond) {
- static $channels = array();
-
- if (isset($channels[$channel_id])) {
- $channel = $channels[$channel_id];
- }
- else {
- $channel = publish_channel_load($channel_id);
- $channels[$channel_id] = $channel;
- }
- $node_ids = array();
- $published_types = publish_nodetypes_load($channel_id);
- if (!$published_types) return array();
-
- $where = '';
- foreach ($published_types as $type) {
- $where .= "OR type = '" . (function_exists('db_escape_string') ? db_escape_string($type) : check_query($type)) . "' ";
- }
- // strip off leading 'OR '
- $where = $where ? '(' . strstr($where, " ") . ')' : '';
-
- list($clean_cond, $taxonomy_cond) = publish_cond_validate(array_merge($channel->filters, $cond));
- $filter = array();
-
- foreach ($clean_cond as $triplet) {
- $field = $triplet['field'];
- $operator = $triplet['operator'];
- $value = $triplet['value'];
-
- // check if value is numeric. If not, put single quotes around it and clean it
- $quot_start = ' ';
- $quot_end = ' ';
- $clean_value = null;;
-
- if (!is_numeric($value)) {
- $quot_start = " '";
- $quot_end = "' ";
- $clean_value = function_exists('db_escape_string') ? db_escape_string($value) : check_query($value);
- }
-
- $filter[] = $field . ' ' . $operator . $quot_start . ($clean_value ? $clean_value : $value) . $quot_end;
- }
-
- if ($filter) {
- $where .= $filter[1] ? implode($filter, ' AND') : ' AND ' . $filter[0];
- }
-
- $query = "SELECT nid FROM {node} WHERE $where";
- $result = db_query($query);
- while ($data = db_fetch_object($result)) {
- $node_ids[] = $data->nid;
- }
-
- return _publish_publish($node_ids, $taxonomy_cond);
+function publish_publish($channel_id) {
+ return publish_get_nodes_by_channel($channel_id);
}
/**
@@ -1071,76 +930,57 @@
// qtime should be long enough that an attempt to send each item
// in the queue can be made within the time window
// we use db_fetch_object() to get one node at a time
- while ($data = db_fetch_object(db_query("SELECT * FROM {publish_queue} WHERE last_attempt < %d ORDER BY changed", time() - $qtime))) {
- if (PUBLISH_DEBUG_MODE) watchdog('publish', t('beginning push for channel %channel, subscriber %subscriber', array('%channel' => $data->channel_id, '%subscriber' => $data->sid)));
-
- // see if there are any other nodes we can include for this subscriber
- // while we have the overhead of sending xmlrpc anyway
- $node_ids = array();
- $qids = array();
- $result = db_query("SELECT qid, nid, attempts FROM {publish_queue} WHERE sid = %d AND channel_id = %d", $data->sid, $data->channel_id);
- while ($row = db_fetch_object($result)) {
- if (PUBLISH_DEBUG_MODE) watchdog('publish', t('preparing to push qid %qid; nid %nid', array('%qid' => $row->qid, '%nid' => $row->nid)));
- $node_ids[] = $row->nid;
- $qids[$row->nid] = array('qid' => $row->qid, 'attempts' => $row->attempts);
- }
- $nodes = array();
- foreach ($node_ids as $nid) {
- // run the nodes through the channel's condition filters
- // note that if push is happening from nodeapi insert/update (not cron),
- // _publish_publish is doing a node_load before modules after us
- // have had a chance to respond to the nodeapi insert/update
- // TODO: need to include the subscription's optional condition filters here;
- // currently we ignore them (channel-specific filters are handled in publish_publish())
- $survived_filter = publish_publish($data->channel_id, array(array('field' => 'nid', 'operator' => '=', 'value' => $nid)));
- if ($survived_filter) {
- if (PUBLISH_DEBUG_MODE) watchdog('publish', t('keeping node %nid', array('%nid' => $nid)));
- $nodes = array_merge($nodes, $survived_filter);
- }
- else { // this node did not pass conditions for this channel
- // and thus will never be sent; delete it from the queue
- if (PUBLISH_DEBUG_MODE) watchdog('publish', t('removing filtered node %nid from queue', array('%nid' => nid)));
- db_query("DELETE FROM {publish_queue} WHERE qid = %d", $qids[$nid]['qid']);
- }
- }
-
- // we've got the nodes, now push them out
- $subscription = publish_subscriptions_load($data->sid);
- $message = array(
- 'token' => $subscription->token,
- 'rsid' => (int)$subscription->sid,
- 'count' => count($nodes),
- 'site_url' => $base_url,
- 'site_name' => variable_get('site_name', 'drupal'),
- 'nodes' => $nodes
- );
-
- $response = xmlrpc($subscription->url, 'drupal.subscribe.receive', $message);
- if ($response) {
- // we have successfully published the pending nodes for this channel to this subscriber
- // thus, delete them from the queue
- foreach ($nodes as $node) {
- if (PUBLISH_DEBUG_MODE) watchdog('publish', t('removing node %nid from queue (qid %qid)', array('%nid' => $node->nid, '%qid' => $qids[$node->nid]['qid'])));
- db_query("DELETE FROM {publish_queue} WHERE qid = %d", $qids[$node->nid]['qid']);
- }
- watchdog('publish', t('XMLRPC pushed %count nodes to %url (channel id %channel_id)', array('%count' => $message['count'], '%url' => check_plain($subscription->url), '%channel_id' => check_plain($data->channel_id))));
- }
- else { // push failed
- $error = xmlrpc_error_msg();
- foreach ($node_ids as $nid) {
- $attempts = $qids[$nid]['attempts'];
- $max_attempts = variable_get('publish_push_max_attempts', 5);
- if ($attempts > $max_attempts) {
- if (PUBLISH_DEBUG_MODE) watchdog('publish', t('max of %attempts attempts exceeded; removing node %nid from queue', array('%attempts' => $max_attempts, '%nid' => $node->nid)));
- db_query("DELETE FROM {publish_queue} WHERE qid = %d", $qids[$nid]['qid']);
- }
- else {
- db_query("UPDATE {publish_queue} SET attempts = %d, last_attempt = %d WHERE qid = %d", $attempts + 1, time(), $qids[$nid]['qid']);
- }
- }
- watchdog('publish', t('XMLRPC push failed for %url (channel id %channel_id): %faultString', array('%url' => theme('placeholder', $subscription->url), '%channel_id' => theme('placeholder', $data->channel_id), '%faultString' => $error ? $error : t('unavailable'))), WATCHDOG_ERROR);
- }
- }
+ $qs = db_query("SELECT * FROM {publish_queue} WHERE last_attempt < %d ORDER BY changed", time() - $qtime);
+ while ($data = db_fetch_object($qs)) {
+ $queue[$data->channel_id][$data->sid][$data->nid] = $data;
+ }
+
+ foreach($queue as $channel_id => $channel) {
+ $channel_nodes = publish_get_nodes_by_channel($channel_id, 'nid');
+
+ foreach($channel as $sid => $queue_items) {
+ if (PUBLISH_DEBUG_MODE) watchdog('publish', t('beginning push for channel %channel, subscriber %subscriber', array('%channel' => $channel_id, '%subscriber' => $sid)));
+
+ foreach($queue_items as $queue_item) {
+ $nodes[$queue_item->nid] = $channel_nodes[$queue_item->nid];
+ }
+
+ // we've got the nodes, now push them out
+ $subscription = publish_subscriptions_load($sid);
+ $message = array(
+ 'token' => $subscription->token,
+ 'rsid' => (int)$subscription->sid,
+ 'count' => count($nodes),
+ 'site_url' => $base_url,
+ 'site_name' => variable_get('site_name', 'drupal'),
+ 'nodes' => $nodes
+ );
+
+ $response = xmlrpc($subscription->url, 'drupal.subscribe.receive', $message);
+ if ($response) {
+ // we have successfully published the pending nodes for this channel to this subscriber
+ // thus, delete them from the queue
+ if (PUBLISH_DEBUG_MODE) watchdog('publish', t('removing node %nid from queue (qid %qid)', array('%nid' => $node->nid, '%qid' => $queue_items[$node->nid]->qid)));
+ db_query("DELETE FROM {publish_queue} WHERE channel_id = %d AND sid = %d", $channel_id, $sid);
+ watchdog('publish', t('XMLRPC pushed !count nodes to !url (channel id !channel_id)', array('!count' => $message['count'], '!url' => check_plain($subscription->url), '!channel_id' => check_plain($channel_id))));
+ }
+ else { // push failed
+ $error = xmlrpc_error_msg();
+ foreach ($nodes as $nid => $node) {
+ $attempts = $queue_items[$nid]->attempts;
+ $max_attempts = variable_get('publish_push_max_attempts', 5);
+ if ($attempts > $max_attempts) {
+ if (PUBLISH_DEBUG_MODE) watchdog('publish', t('max of !attempts attempts exceeded; removing node !nid from queue', array('!attempts' => $max_attempts, '!nid' => $node->nid)));
+ db_query("DELETE FROM {publish_queue} WHERE qid = %d", $queue_items[$nid]->qid);
+ }
+ else {
+ db_query("UPDATE {publish_queue} SET attempts = %d, last_attempt = %d WHERE qid = %d", $attempts + 1, time(), $queue_items[$nid]->qid);
+ }
+ }
+ watchdog('publish', t('XMLRPC push failed for %url (channel id %channel_id): %faultString', array('%url' => $subscription->url, '%channel_id' => $channel_id, '%faultString' => $error ? $error : t('unavailable'))), WATCHDOG_ERROR);
+ }
+ }
+ }
}
/********************************************************************
@@ -1247,7 +1087,7 @@
}
$who = $username? check_plain($username) : t('anonymous');
- watchdog('publish', t('XML-RPC: may subscribe to channel %channel_id? %name (%link).', array('%channel_id' => $channel_id, '%name' => "$who", '%link' => "$host")));
+ watchdog('publish', t('XML-RPC: may subscribe to channel !channel_id? %name (%link).', array('!channel_id' => $channel_id, '%name' => $who, '%link' => $host)));
return $response;
}
@@ -1264,14 +1104,12 @@
* @param
* $dest the XMLRPC endpoint on the client to which publishing site
* may publish nodes
- * @param
- * $cond array of condition triplets; see publish_publish()
*
* @return
* An array containing a status message and the subscription id on the publishing site.
*/
- function publish_xmls_receive_subscription($channel_id, $username, $pass, $dest, $method, $remote_vids, $local_vids, $cond) {
-
+ function publish_xmls_receive_subscription($channel_id, $username, $pass, $dest, $method, $remote_vids, $local_vids) {
+
$host = gethostbyaddr($_SERVER['REMOTE_ADDR']);
// should check if $dest is in domain of $host here
@@ -1314,14 +1152,12 @@
* $username (string)
* @param
* $password (string)
- * @param
- * $cond (array of condition triplets; see publish_publish() )
*
* @return
* An array of node objects keyed by node id.
*/
- function publish_xmls_publish($channel_id, $sid, $username, $pass, $cond) {
-
+ function publish_xmls_publish($channel_id, $sid, $username, $pass) {
+//MS: watchdog('publish-ms', 'channel_id: ' . $channel_id . ' | sid: ' . $sid . ' | username: ' . $username . ' | pass: ' . $pass);
$ip = $_SERVER['REMOTE_ADDR'];
$host = gethostbyaddr($ip);
@@ -1331,9 +1167,8 @@
}
if ($channel) {
$may_subscribe = publish_may_subscribe($channel, $username, $pass, $host);
-
if ($may_subscribe && (publish_subscription_validate($sid))) {
- $nodes = publish_publish($channel_id, $cond);
+ $nodes = publish_publish($channel_id);
global $base_url;
$response = array(
@@ -1382,6 +1217,87 @@
* Module Functions :: Private
********************************************************************/
+/**
+ * Returns a list of views, including default views.
+ * @return
+ * An array of view names, keyed by view name.
+ */
+function publish_get_views() {
+ $views = array();
+ $qs = db_query("SELECT v.vid, v.name FROM {view_view} v");
+ while($obj = db_fetch_object($qs)) {
+ $views[$obj->name] = $obj->name;
+ }
+ $default_views = module_invoke_all('views_default_views');
+ foreach($default_views as $default_view) {
+ $views[$default_view->name] = $default_view->name;
+ }
+
+ return $views;
+}
+
+/**
+ * Returns a list of nodes for a given channel.
+ *
+ * @param $channel_id
+ * A numeric channel_id.
+ * @param $key
+ * 'nid' to key by node IDs. Otherwise, NULL.
+ * @return
+ * An array of nodes, in the proper format to be published.
+ */
+function publish_get_nodes_by_channel($channel_id, $key = NULL) {
+ //Include this here so that we can work with the queries.
+ $path = drupal_get_path('module', 'views');
+ require_once("./$path/views_query.inc");
+
+ $channel = publish_channel_load($channel_id);
+ if(!empty($channel)) {
+ $api_id = 'publish_channel_' . $channel_id;
+ $default = array();
+ $view_name = $channel->views['view'];
+ $for_view = TRUE;
+
+ $args = views_argument_api_get_processed($api_id, $default, $view_name, $for_view);
+ $view = views_get_view($view_name);
+ $filters = array();
+ $queries = _views_build_query($view, $args);
+
+ $query = $queries['query'];
+ $qs = call_user_func_array('db_query', array_merge(array($queries['query']), $queries['args']));
+ while($obj = db_fetch_object($qs)) {
+ $node = node_load($obj->nid);
+ unset($node->data);
+ unset($node->revisions);
+ unset($node->picture);
+ unset($node->workspaces);
+ $node->url = url('node/' . $node->nid, NULL, NULL, TRUE);
+
+ // we need to add vocabulary information ourselves, per the settings in the channel
+ $taxonomy_terms = taxonomy_node_get_terms($node->nid);
+ $published_vocabularies = publish_node_vocabularies($channel_id);
+ $published_vocabularies = array_pop($published_vocabularies);
+ $published_vocabularies = array_keys((array)$published_vocabularies[$node->type]);
+
+ foreach($taxonomy_terms as $term) {
+ if(in_array($term->vid, $published_vocabularies)) {
+ $terms[$term->tid] = $term;
+ }
+ }
+ $node->taxonomy_terms = $terms;
+
+ if($key == 'nid') {
+ $nodes[$node->nid] = $node;
+ } else {
+ $nodes[] = $node;
+ }
+ }
+ } else {
+ $nodes = array();
+ }
+
+ return $nodes;
+}
/**
* Return an array of all vocabulary objects.
@@ -1470,57 +1386,8 @@
function publish_db_fields($table_name) {
switch ($table_name) {
case 'publish_channel':
- return array('channel_id', 'name', 'description', 'advertise', 'authtype', 'whenpub', 'username', 'pass', 'domain');
- }
-}
-
-/**
- * Instantiate some nodes and remove some unwanted properties.
- *
- * @param $node_ids
- * Array of node IDs to instantiate
- * @param $cond
- * Array of triplets representing a filter (only vocabulary filters apply here)
- *
- * @return
- * An array of node objects.
- */
- function _publish_publish($node_ids = array(), $cond) {
- $nodes = array();
- foreach ($node_ids as $nid) {
- $node = node_load(array('nid' => $nid));
- unset($node->data);
- unset($node->revisions);
- unset($node->picture);
- unset($node->workspaces);
- $node->url = url('node/' . $nid, NULL, NULL, TRUE);
-
- // we need to add vocabulary information ourselves
- $node->taxonomy_terms = taxonomy_node_get_terms($node->nid);
-
- if ($cond) {
- // implement field = value
- $conditions_met = FALSE;
- foreach ($cond as $triplet) {
- switch ($triplet['operator']) {
- case '=':
- foreach ($node->taxonomy_terms as $term) {
- if($term->name == $triplet['value']) {
- $conditions_met = TRUE;
- continue;
- }
- }
- }
- }
- if ($conditions_met) {
- $nodes[$nid] = $node;
- }
- }
- else {
- $nodes[$nid] = $node;
- }
+ return array('channel_id', 'name', 'description', 'advertise', 'authtype', 'whenpub', 'username', 'pass', 'domains');
}
- return $nodes;
}
/**
@@ -1536,14 +1403,12 @@
* to this subscriber
* @param $dest
* the URL of the XML-RPC endpoint to which content can be pushed
- * @param $cond
- * an array of triplets describing how to filter content
* @param $sid
* subscription id if not a new subscription
*
* @return $sid
*/
-function publish_subscription_save($channel_id, $username, $pass, $dest, $method, $remote_vids, $local_vids, $cond, $sid = null) {
+function publish_subscription_save($channel_id, $username, $pass, $dest, $method, $remote_vids, $local_vids, $sid = null) {
$sub = NULL;
$op = 'insert';
@@ -1591,89 +1456,48 @@
}
}
- // save any additional conditions the subscriber requests
- if ($cond) {
- db_query("DELETE FROM {publish_cond} WHERE sid = %d", $sid);
-
- list($clean_cond, $taxonomy_cond) = publish_cond_validate($cond);
-
- foreach ($clean_cond as $triplet) {
- $field = $triplet['field'];
- $operator = $triplet['operator'];
- $value = $triplet['value'];
- db_query("INSERT INTO {publish_cond} (channel_id, sid, field, cond, value) VALUES %d, %d, '%s', '%s', '%s'", $channel_id, $sid, $field, $operator, $value);
- }
-
- foreach ($taxonomy_cond as $triplet) {
- $field = $triplet['field'];
- $operator = $triplet['operator'];
- $value = $triplet['value'];
- db_query("INSERT INTO {publish_cond} (channel_id, sid, field, cond, value) VALUES %d, %d, '%s', '%s', '%s'", $channel_id, $sid, $field, $operator, $value);
- }
- }
-
return $sid;
}
-function publish_supported_operators() {
- return array (
- '=',
- '>',
- '<'
- );
-}
-
-function publish_supported_fields() {
- return array (
- 'nid', 'type',
- 'title', 'score',
- 'votes', 'uid',
- 'status', 'created',
- 'changed', 'comment',
- 'promote', 'moderate',
- 'users', 'teaser',
- 'body', 'sticky',
- 'format'
- );
-}
+/********************************************************************
+ * Views Hooks
+ ********************************************************************/
/**
- * We only support a limited number of fields and conditions.
- * This function filters out unsupported fields and conditions.
- *
- * @param $cond
- * an array of triplets
- *
- * @return
- * an array of triplets
+ * Provides a default view for views_multiblock
*/
-function publish_cond_validate($cond) {
-
- $supported_operators = array_flip(publish_supported_operators());
-
- $supported_fields = array_flip(publish_supported_fields());
-
- $vocabularies = publish_get_vocabularies();
- $voc_names = array();
- foreach ($vocabularies as $v) {
- $voc_names[$v->name] = 0;
- }
-
- $clean_cond = array();
- foreach ($cond as $triplet) {
- $field = isset($triplet['field']) ? $triplet['field'] : $triplet[0];
- $operator = isset($triplet['operator']) ? $triplet['operator'] : $triplet[1];
- $value = isset($triplet['value']) ? $triplet['value'] : $triplet[2];
-
- // we need to treat node conditions and taxonomy conditions separately
- // since node conditions are used for SQL building and taxonomy conditions are not
- if (key_exists($operator, $supported_operators) && key_exists ($field, $supported_fields)) {
- $clean_cond[] = array('field' => $field, 'operator' => $operator, 'value' => $value);
- }
- elseif (key_exists($field, $voc_names)) {
- $taxonomy_cond[] = array('field' => $field, 'operator' => $operator, 'value' => $value);
- }
- }
-
- return array($clean_cond, $taxonomy_cond);
-}
\ No newline at end of file
+function publish_views_default_views() {
+ $view = new stdClass();
+ $view->name = 'publish';
+ $view->description = 'A default channel view for the Publish module.';
+ $view->access = array (
+);
+ $view->view_args_php = '';
+ $view->sort = array (
+ );
+ $view->argument = array (
+ array (
+ 'type' => 'taxid',
+ 'argdefault' => '1',
+ 'title' => '',
+ 'options' => '',
+ 'wildcard' => '',
+ 'wildcard_substitution' => '',
+ ),
+ );
+ $view->field = array (
+ array (
+ 'tablename' => 'node',
+ 'field' => 'nid',
+ 'label' => '',
+ ),
+ );
+ $view->filter = array (
+ );
+ $view->exposed_filter = array (
+ );
+ $view->requires = array(node);
+ $views[$view->name] = $view;
+
+ return $views;
+}
diff -urN publish_47/publish_views.inc publish_5/publish_views.inc
--- publish_47/publish_views.inc 1969-12-31 19:00:00.000000000 -0500
+++ publish_5/publish_views.inc 2007-06-11 18:24:19.526581928 -0400
@@ -0,0 +1,330 @@
+ 'publish_queue',
+ 'join' => array(
+ 'left' => array(
+ 'table' => 'node',
+ 'field' => 'nid',
+ ),
+ 'right' => array(
+ 'field' => 'nid',
+ ),
+ ),
+ 'fields' => array(
+ 'qid' => array(
+ 'name' => t('Publish: Queue ID'),
+ 'help' => t('Use this field to show the Publish queue ID number.'),
+ 'sortable' => TRUE,
+ ),
+ 'sid' => array(
+ 'name' => t('Publish: Subscriber ID'),
+ 'help' => t('Use this field to show the subscriber ID number.'),
+ 'sortable' => TRUE,
+ ),
+ 'channel_id' => array(
+ 'name' => t('Publish: Channel ID'),
+ 'help' => t('Use this field to show the channel ID number.'),
+ 'sortable' => TRUE,
+ ),
+ 'attempts' => array(
+ 'name' => t('Publish: Attempts'),
+ 'help' => t('Use this field to show the number of attempts made to push a node.'),
+ 'sortable' => TRUE,
+ ),
+ 'last_attempt' => array(
+ 'name' => t('Publish: Last Attempt'),
+ 'help' => t('Use this field to show the last time that Publish attempted to push a node.'),
+ 'sortable' => TRUE,
+ ),
+ ),
+ 'sorts' => array(
+ 'qid' => array(
+ 'name' => t('Publish: Queue ID'),
+ 'help' => t('Sort by the Publish queue ID number.'),
+ ),
+ 'sid' => array(
+ 'name' => t('Publish: Subscriber ID'),
+ 'help' => t('Sort by the subscriber ID number.'),
+ ),
+ 'channel_id' => array(
+ 'name' => t('Publish: Channel ID'),
+ 'help' => t('Sort by the channel ID number.'),
+ ),
+ 'attempts' => array(
+ 'name' => t('Publish: Attempts'),
+ 'help' => t('Sort by the number of attempts made to push a node.'),
+ ),
+ 'last_attempt' => array(
+ 'name' => t('Publish: Last Attempt'),
+ 'help' => t('Sort by the last time that Publish attempted to push a node.'),
+ ),
+ ),
+ 'filters' => array(
+ 'channel_id' => array(
+ 'field' => 'channel_id',
+ 'name' => t('Publish: Channel ID'),
+ 'operator' => 'views_handler_operator_or',
+ 'list' => 'publish_views_get_channel_id_values',
+ 'help' => t('Filter by the channel ID number.'),
+ ),
+ ),
+ );
+
+ $tables['publish_channel'] = array(
+ 'name' => 'publish_channel',
+ 'join' => array(
+ 'left' => array(
+ 'table' => 'publish_queue',
+ 'field' => 'channel_id',
+ ),
+ 'right' => array(
+ 'field' => 'channel_id',
+ ),
+ ),
+ 'fields' => array(
+ 'name' => array(
+ 'name' => t('Publish: Channel Name'),
+ 'help' => t('Use this field to show the Publish Channel name.'),
+ 'sortable' => TRUE,
+ ),
+ 'description' => array(
+ 'name' => t('Publish: Channel Description'),
+ 'help' => t('Use this field to show the Publish Channel description.'),
+ 'sortable' => TRUE,
+ ),
+ 'advertise' => array(
+ 'name' => t('Publish: Channel is Advertised'),
+ 'help' => t('Use this field to show whether or not the Publish Channel is advertised.'),
+ 'sortable' => TRUE,
+ ),
+ ),
+ 'sorts' => array(
+ 'name' => array(
+ 'name' => t('Publish: Channel Name'),
+ 'help' => t('Sort by the Publish channel name.'),
+ ),
+ 'description' => array(
+ 'name' => t('Publish: Channel Description'),
+ 'help' => t('Sort by the Publish channel description.'),
+ ),
+ 'advertise' => array(
+ 'name' => t('Publish: Channel is Advertised'),
+ 'help' => t('Sort by the Publish channel advertised status.'),
+ ),
+ ),
+ 'filters' => array(
+ 'advertise' => array(
+ 'field' => 'advertise',
+ 'name' => t('Publish: Advertised'),
+ 'operator' => 'views_handler_operator_or',
+ 'list' => array(
+ t('Advertised'),
+ t('Not advertised'),
+ ),
+ 'help' => t('Filter by the Publish channel advertised status.'),
+ ),
+ ),
+ );
+
+ return $tables;
+}
+
+/**
+ * Provides a default view for publish
+ *
+function publish_views_default_views() {
+ $view = new stdClass();
+ $view->name = 'publish';
+
+ $view->description = 'Publish';
+ $view->access = array ('anonymous user');
+ $view->view_args_php = '';
+ $view->page = TRUE;
+ $view->page_title = '';
+ $view->page_header = '';
+ $view->page_header_format = '1';
+ $view->page_footer = '';
+ $view->page_footer_format = '1';
+ $view->page_empty = '';
+ $view->page_empty_format = '1';
+ $view->page_type = 'teaser';
+ $view->url = 'publish_view';
+ $view->use_pager = TRUE;
+ $view->nodes_per_page = '10';
+ $view->block = TRUE;
+ $view->block_title = '';
+ $view->block_header = '';
+ $view->block_header_format = '1';
+ $view->block_footer = '';
+ $view->block_footer_format = '1';
+ $view->block_empty = '';
+ $view->block_empty_format = '1';
+ $view->block_type = 'publish';
+ $view->nodes_per_block = '1';
+ $view->block_more = TRUE;
+ $view->block_use_page_header = FALSE;
+ $view->block_use_page_footer = FALSE;
+ $view->block_use_page_empty = FALSE;
+ $view->sort = array (
+ array (
+ 'tablename' => 'node',
+ 'field' => 'sticky',
+ 'sortorder' => 'ASC',
+ 'options' => '',
+ ),
+ array (
+ 'tablename' => 'node',
+ 'field' => 'changed',
+ 'sortorder' => 'DESC',
+ 'options' => 'normal',
+ ),
+ array (
+ 'tablename' => 'node',
+ 'field' => 'title',
+ 'sortorder' => 'ASC',
+ 'options' => '',
+ ),
+ );
+ $view->argument = array (
+ array (
+ 'type' => 'taxid',
+ 'argdefault' => '7',
+ 'title' => '%1',
+ 'options' => '',
+ 'wildcard' => '',
+ 'wildcard_substitution' => '',
+ ),
+ array (
+ 'type' => 'node_feed',
+ 'argdefault' => '2',
+ 'title' => '',
+ 'options' => 'News Feed',
+ 'wildcard' => '',
+ 'wildcard_substitution' => '',
+ ),
+ );
+ $view->field = array (
+ array (
+ 'tablename' => 'node',
+ 'field' => 'title',
+ 'label' => '',
+ 'handler' => 'views_handler_field_nodelink',
+ 'options' => 'link',
+ ),
+ array (
+ 'tablename' => 'node',
+ 'field' => 'changed',
+ 'label' => '',
+ 'handler' => 'views_handler_field_date_small',
+ ),
+ array (
+ 'tablename' => 'node',
+ 'field' => 'body',
+ 'label' => '',
+ 'handler' => 'views_handler_field_teaser',
+ ),
+
+ );
+ $view->filter = array (
+ array (
+ 'tablename' => 'node',
+ 'field' => 'status',
+ 'operator' => '=',
+ 'options' => '',
+ 'value' => '1',
+ ),
+ );
+
+ $view->exposed_filter = array ();
+
+ $view->requires = array(node);
+ $views[$view->name] = $view;
+
+ return $views;
+}
+*/
+
+/**
+ * Define additional view type names.
+ */
+function publish_info() {
+ return array(
+ 'publish' => array('label' => 'Publish: Prepare for Channel'),
+ );
+}
+
+/**
+ * Implementation of hook_views_style_plugins()
+ */
+function publish_views_style_plugins() {
+
+ $plugins = array();
+ $types = publish_view_types();
+ foreach ($types as $name => $type) {
+ $plugins[$name] = array(
+ 'name' => $type,
+ 'theme' => 'publish_display',
+ 'validate' => 'views_ui_plugin_validate_table',
+ 'needs_fields' => TRUE,
+ 'needs_table_header' => FALSE,
+ );
+ }
+
+ return $plugins;
+}
+
+/**
+ * Possible views page display types
+ */
+function publish_view_types() {
+ return array('publish' => t('Publish: Prepare for Channel'));
+}
+
+/**
+ * A form element for a view selector
+ */
+function _publish_view_type_form($view = NULL) {
+ $form['publish_view'] = array(
+ '#type' => 'select',
+ '#options' => publish_view_types(),
+ '#default_value' => $view ? $view->page_type : 'publish',
+ '#title' => t('View'),
+ );
+ return $form;
+}
+
+/***********************************************************
+ * THEME FUNCTIONS
+ */
+
+/**
+ * Publish: XML plugin theme, overrides default views theme
+ */
+function theme_publish_display($view, $nodes) {
+ drupal_set_message(t('This view is for the Publish module, only.'), 'error');
+ return;
+}
+/*********************************************************************
+ * Helper Functions
+ */
+
+function publish_views_get_channel_id_values() {
+ $qs = db_query("SELECT pc.channel_id, pc.name FROM {publish_channel} pc");
+ while($obj = db_fetch_object($qs)) {
+ $filters[$obj->channel_id] = $obj->name;
+ }
+
+ return $filters;
+}
+
+?>
\ No newline at end of file