diff --git a/content_distribution.info b/content_distribution.info index d84d6c6fe4797c85a0eb9cf8780d1dad0ab84299..1587340f5ed88f0ac1b5426804158dfc5e5c7621 100644 --- a/content_distribution.info +++ b/content_distribution.info @@ -1,15 +1,15 @@ -; $Id$ -name = Content Distributor -description = Allows nodes to be distributed via the Services module. -package = Content Distribution -version = 6.x-1.x-dev -core = 6.x -dependencies[] = node -dependencies[] = date_api -dependencies[] = distributor_service -dependencies[] = system_service -dependencies[] = user_service -dependencies[] = nodequeue_service -dependencies[] = views_service -dependencies[] = views -dependencies[] = nodequeue +; $Id$ +name = Content Distributor +description = Allows nodes to be distributed via the Services module. +package = Content Distribution +version = 6.x-1.x-dev +core = 6.x +dependencies[] = node +dependencies[] = date_api +dependencies[] = distributor_service +dependencies[] = system_service +dependencies[] = user_service +dependencies[] = nodequeue_service +dependencies[] = views_service +dependencies[] = views +dependencies[] = nodequeue diff --git a/content_distribution.install b/content_distribution.install index 2c752a08cc495689023deeb0c4d3304553c5b79d..3e29b3459a98691e8020d497e426371eb81e2887 100644 --- a/content_distribution.install +++ b/content_distribution.install @@ -1,65 +1,65 @@ -type); - } - -} - -/** - * Implementation of hook_schema(). - */ -function content_distribution_schema() { - $schema['content_distribution'] = array( - 'description' => t('Stores node information on nodes set up for content distribution'), - 'fields' => array( - 'nid' => array( - 'type' => 'int', - 'unsigned' => TRUE, - 'not null' => TRUE, - 'description' => t("The distributed node's {node}.nid."), - ), - 'published_date' => array( - 'type' => 'int', - 'not null' => TRUE, - 'default' => 0, - 'description' => t("The Unix timestamp the distributed node was published."), - ), - ), - 'primary key' => array('nid'), - ); - - return $schema; -} - - +type); + } + +} + +/** + * Implementation of hook_schema(). + */ +function content_distribution_schema() { + $schema['content_distribution'] = array( + 'description' => t('Stores node information on nodes set up for content distribution'), + 'fields' => array( + 'nid' => array( + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'description' => t("The distributed node's {node}.nid."), + ), + 'published_date' => array( + 'type' => 'int', + 'not null' => TRUE, + 'default' => 0, + 'description' => t("The Unix timestamp the distributed node was published."), + ), + ), + 'primary key' => array('nid'), + ); + + return $schema; +} + + diff --git a/content_distribution.module b/content_distribution.module index 582247d9efafe6008a68eeffb1d28b89d8de4ac3..0fa3abab3ee141f36f3fd17715d92d863d6905be 100644 --- a/content_distribution.module +++ b/content_distribution.module @@ -1,428 +1,428 @@ -published_date; - if(empty($published_date)){ - // get local date and timezone settings for form values. - $date = date_make_date(time(),$local_timezone, DATE_UNIX); - $published_date = date_format_date($date, 'custom', $format); - } - - $form['date'] = array( - '#type' => 'fieldset', - '#title' => t('Published Date'), - '#collapsible' => 1, - '#collapsed' => 0, - ); - - $form['date']['published_date'] = array( - '#type' => 'date_select', - '#default_value' => $published_date, - '#date_format' => $format, - '#date_timezone' => $local_timezone, - '#date_year_range' => '0:+2', - '#date_increment' => 5, - ); - - $form['#submit'][] = 'content_distribution_node_add_form_submit'; - } - } - - // content type add form - add checkbox to enable / disable distribution of nodes of this type - if (($form_id == 'node_type_form')) { - $form['content_distribution'] = array( - '#type' => 'fieldset', - '#title' => t('Content Distribution Settings'), - '#collapsible' => TRUE, - '#collapsed' => TRUE, - ); - $form['content_distribution']['distribute'] = array( - '#type' => 'checkbox', - '#title' => t('Distribute content of this type'), - '#default_value' => variable_get('distribute_content_type_'.$form['#node_type']->type, 0), - '#description' => t('Allows nodes of this content type to be distributed via the services module. '), - ); - $form['#submit'][] = 'content_distribution_node_type_form_submit'; - } - - //hide workflow options that have no effect on CMS - if ($form['#id'] == 'node-form' && $user->uid != 1) { - unset($form['options']['sticky']); - unset($form['options']['promote']); - } -} - -/** - * Additional submit handler for the node type form. - */ -function content_distribution_node_type_form_submit($form, &$form_state) { - // set variable to distinguish if content type is distributable or not - - if($form['content_distribution']['distribute']['#default_value'] !== $form_state['values']['distribute']){ - if (($form_state['values']['distribute']) === 1) { - variable_set('distribute_content_type_'.$form['#node_type']->type, 1); - - //add node ids to distribution db table. - $result = db_query("SELECT nid from {node} WHERE type = '%s'", $form['#node_type']->type); - while($nid = db_fetch_object($result)){ - //write record in content_distribution table - drupal_write_record('content_distribution', $nid); - } - }else{ - variable_set('distribute_content_type_'.$form['#node_type']->type, 0); - - //delete node ids from distribution db table - $result = db_query("SELECT nid from {node} WHERE type = '%s'", $form['#node_type']->type); - while($nid = db_fetch_object($result)){ - db_query('DELETE FROM {content_distribution} WHERE nid = %d', $nid->nid); - } - } - } -} - - -/** - * Implementation of hook_nodeapi(). - * - * We add the vocab_name to the taxonomy object so we can use it later - * on the destination server to look up a matching vocabulary - vid is not - * necessarily the same on both servers, hence using the name instead - */ -function content_distribution_nodeapi(&$node, $op, $teaser, $page) { - $is_distributable = variable_get('distribute_content_type_'.$node->type, 0); - //print_r($node); - switch ($op) { - case 'load': - // check if nodes of this content type are distributable - if($is_distributable !== 0){ - // get the published date info from the {content_distribution} table - $result = db_query("SELECT published_date FROM {content_distribution} WHERE nid = %d", $node->nid); - $pub_date = db_result($result); - //format the date field - $format = 'Y-m-d H:i'; - $local_timezone = date_default_timezone_get(); - $pub_date = date_make_date($pub_date,$local_timezone, DATE_UNIX); - $pub_date = date_format_date($pub_date, 'custom', $format); - - //taxonomy objects are not available during the load op, so we need to load them ourselves - $taxonomy = taxonomy_node_get_terms($node); - if ($taxonomy) { - $vocab_names = array(); - foreach ($taxonomy as $tid => $term) { - $vocab_names[$tid] = taxonomy_vocabulary_load($term->vid)->name; - } - } - //load op must return a structured array to be appended to the $node object - return array( - 'vocab_names' => $vocab_names, - 'published_date' => $pub_date, - ); - } - break; - case 'insert': - if($is_distributable !== 0){ - // convert date to timestamp before insert - $published_date = $node->published_date; - $published_date = date_convert($published_date, DATE_DATETIME, DATE_UNIX); - - db_query("INSERT INTO {content_distribution} (nid, published_date) VALUES (%d, %d)", $node->nid,$published_date); - } - break; - case 'update': - if($is_distributable !== 0){ - // see if node is already in DB - $result = db_query("SELECT nid FROM {content_distribution} WHERE nid = %d", $node->nid); - - // convert date to timestamp before insert - $published_date = $node->published_date; - $published_date = date_convert($published_date, DATE_DATETIME, DATE_UNIX); - - // if result fetched we already have a row so just update the table with new published date - if (($nid = db_result($result)) != FALSE) { - db_query("UPDATE {content_distribution} SET published_date = %d WHERE nid = %d", $published_date, $nid); - } - } - break; - case 'delete': - // remove row from node delete - if($is_distributable !== 0){ - db_query('DELETE FROM {content_distribution} WHERE nid = %d', $node->nid); - - $sites = variable_get('distributed_sites', ''); - if($sites){ - //foreach site go and check if the node is there - //and delete it off that site. - foreach($sites as $k => $site){ - $endpoint = $site['sitetext'] . '/services/xmlrpc'; - $api_key = ''; - - //grab a session id from the system.connect method - $connect = xmlrpc($endpoint, 'system.connect'); - $session_id = $connect['sessid']; - - //call the service to delete the node on the remote site - $result = xmlrpc($endpoint, 'node.deleteDistributedNode', $session_id, (int)$node->nid); - - if($result){ - drupal_set_message(t('Deleted node on ' . $site['sitetext']. ' with node id ' . $result)); - }else{ - drupal_set_message(t('No node to delete on ' . $site['sitetext'])); - } - } - } - } - break; - } -} - -/** - * Implementation of hook_views_api(). - */ -function content_distribution_views_api() { - return array( - 'api' => 2, - 'path' => drupal_get_path('module', 'content_distribution') . '/includes', - ); -} - - -/** - * Implementation of hook_menu(). - */ -function content_distribution_menu(){ - $items = array(); - - $items['admin/settings/distribution'] = array( - 'title' => t('Content Distribution Settings'), - 'page callback' => 'drupal_get_form', - 'page arguments' => array('content_distribution_admin_form'), - 'access arguments' => array('administer content distribution'), - 'description' => t('Settings for content distribution.'), - 'weight' => -10, - 'type' => MENU_NORMAL_ITEM - ); - - $items ['distribution/js'] = array( - 'title' => 'Javascript Site Form', - 'page callback' => 'distribution_site_js', - 'access arguments' => array('access content'), - 'type' => MENU_CALLBACK, - ); - return $items; -} - -/** - * Implementation of hook_perm(). - * Here we add the permissions for access to our admin page. - */ -function content_distribution_perm() { - return array('administer content distribution'); -} - -/** - * build the admin form. - */ -function content_distribution_admin_form(&$form_state){ - - $form['site_count'] = array( - '#type' => 'value', - '#default_value' => 1, - '#value' => $form_state['values']['site_count'], - ); - // Add a wrapper for the choices and more button. - $form['site_wrapper'] = array( - '#tree' => FALSE, - '#weight' => -4, - '#prefix' => '
' . t('Please enter the URL(s) of the remote sites you will be distributing content to in the text fields below.'), - '#suffix' => '
', - ); - - // Container for just the poll choices. - $form['site_wrapper']['site'] = array( - '#tree' => TRUE, - '#prefix' => '
', - '#suffix' => '
', - '#theme' => 'site_choices', - ); - - $sites = variable_get('distributed_sites', ''); - - // set up choice count - if(isset($form_state['values']['site_count'])){ - $choice_count = $form_state['values']['site_count']; - }else if($sites){ - $choice_count = count($sites); - foreach($sites as $k => $site){ - $form_state['values']['site'][$k]['sitetext']['#value'] = $site['sitetext']; - } - }else{ - $choice_count = 1; - } - - // Add the current choices to the form. - for ($delta = 0; $delta < $choice_count; $delta++) { - $text = isset($form_state['values']['site'][$delta]) ? $form_state['values']['site'][$delta]['sitetext']['#value'] : ''; - $form['site_wrapper']['site'][$delta] = _site_choice_form($delta, $text); - } - - // ahah element to handle adding more sites - $form['site_wrapper']['site_more'] = array( - '#type' => 'submit', - '#value' => t('Add More Sites'), - '#description' => t("If the amount of boxes above isn't enough, click here to add more sites."), - '#weight' => 1, - '#submit' => array('more_sites_submit'), // If no javascript action. - '#ahah' => array( - 'path' => 'distribution/js', - 'wrapper' => 'site-choices', - 'method' => 'replace', - 'effect' => 'fade', - ), - ); - - $form['site_wrapper']['submit'] = array( - '#type' => 'submit', - '#weight' => 2, - '#value' => t('Save Settings'), - ); - - return $form; -} - -/** - * validate function for the distribution settings form. - */ -function content_distribution_admin_form_validate($form, &$form_state){ - // validate that the user entered a valid url - // in the format http://www.site.com - if($form_state['values']['site']){ - foreach($form_state['values']['site'] as $k => $site){ - if(empty($site['sitetext'])){continue;} - else if(!(valid_url($site['sitetext'], true))){ - form_set_error('sitetext', 'Site ' . ($k+1) . ' is not a valid URL, please re-enter.'); - } - } - } -} - -/** - * submit function for the distribution settings form. - */ -function content_distribution_admin_form_submit($form, &$form_state){ - //check there is actually a value in each text field - //then save the array of fields into a variable - if($form_state['values']['site']){ - foreach($form_state['values']['site'] as $k => $site){ - if(empty($site['sitetext'])){ - unset($form_state['values']['site'][$k]); - } - } - variable_set('distributed_sites', array_values($form_state['values']['site'])); - drupal_set_message(t('Content Distribution Settings Saved.')); - } - -} - -function more_sites_submit($form, &$form_state){ - // increment the site count variable - $form_state['values']['site_count']++; -} - -function _site_choice_form($delta, $value = '') { - - $form = array( - '#tree' => TRUE, - ); - - // We'll manually set the #parents property of these fields so that - // their values appear in the $form_state['values']['site'] array. - $form['sitetext'] = array( - '#type' => 'textfield', - '#title' => t('Site @n', array('@n' => ($delta + 1))), - '#default_value' => $value, - '#description' => t('Enter URL in the format http://www.mysite.com'), - '#parents' => array('site', $delta, 'sitetext'), - ); - - return $form; -} - -/** - * Menu callback for AHAH additions. - */ -function distribution_site_js() { - $delta = count($_POST['site']); - - // Build our new form element. - $form_element = _site_choice_form($delta); - - //drupal_alter('form', $form_element, array(), 'poll_choice_js'); - - // Build the new form. - $form_state = array('submitted' => FALSE); - $form_build_id = $_POST['form_build_id']; - // Add the new element to the stored form. Without adding the element to the - // form, Drupal is not aware of this new elements existence and will not - // process it. We retreive the cached form, add the element, and resave. - if (!$form = form_get_cache($form_build_id, $form_state)) { - exit(); - } - $form['site_wrapper']['site'][$delta] = $form_element; - form_set_cache($form_build_id, $form, $form_state); - $form += array( - '#post' => $_POST, - '#programmed' => FALSE, - ); - - // Rebuild the form. - $form = form_builder($_POST['form_id'], $form, $form_state); - - // Render the new output. - $choice_form = $form['site_wrapper']['site']; - unset($choice_form['#prefix'], $choice_form['#suffix']); // Prevent duplicate wrappers. - - $output = theme('status_messages') . drupal_render($choice_form); - - drupal_json(array('status' => TRUE, 'data' => $output)); -} - - -/** - * Theme the form for site choices. - * - * @ingroup themeable - */ -function theme_site_choices($form) { - foreach (element_children($form) as $key) { - drupal_render($form[$key]['sitetext']); - } - $output .= drupal_render($form); - return $output; -} - -/** - * Implementation of hook_theme() - */ -function content_distribution_theme() { - return array( - 'site_choices' => array( - 'arguments' => array('form' => NULL), - ), - ); +published_date; + if(empty($published_date)){ + // get local date and timezone settings for form values. + $date = date_make_date(time(),$local_timezone, DATE_UNIX); + $published_date = date_format_date($date, 'custom', $format); + } + + $form['date'] = array( + '#type' => 'fieldset', + '#title' => t('Published Date'), + '#collapsible' => 1, + '#collapsed' => 0, + ); + + $form['date']['published_date'] = array( + '#type' => 'date_select', + '#default_value' => $published_date, + '#date_format' => $format, + '#date_timezone' => $local_timezone, + '#date_year_range' => '0:+2', + '#date_increment' => 5, + ); + + $form['#submit'][] = 'content_distribution_node_add_form_submit'; + } + } + + // content type add form - add checkbox to enable / disable distribution of nodes of this type + if (($form_id == 'node_type_form')) { + $form['content_distribution'] = array( + '#type' => 'fieldset', + '#title' => t('Content Distribution Settings'), + '#collapsible' => TRUE, + '#collapsed' => TRUE, + ); + $form['content_distribution']['distribute'] = array( + '#type' => 'checkbox', + '#title' => t('Distribute content of this type'), + '#default_value' => variable_get('distribute_content_type_'.$form['#node_type']->type, 0), + '#description' => t('Allows nodes of this content type to be distributed via the services module. '), + ); + $form['#submit'][] = 'content_distribution_node_type_form_submit'; + } + + //hide workflow options that have no effect on CMS + if ($form['#id'] == 'node-form' && $user->uid != 1) { + unset($form['options']['sticky']); + unset($form['options']['promote']); + } +} + +/** + * Additional submit handler for the node type form. + */ +function content_distribution_node_type_form_submit($form, &$form_state) { + // set variable to distinguish if content type is distributable or not + + if($form['content_distribution']['distribute']['#default_value'] !== $form_state['values']['distribute']){ + if (($form_state['values']['distribute']) === 1) { + variable_set('distribute_content_type_'.$form['#node_type']->type, 1); + + //add node ids to distribution db table. + $result = db_query("SELECT nid from {node} WHERE type = '%s'", $form['#node_type']->type); + while($nid = db_fetch_object($result)){ + //write record in content_distribution table + drupal_write_record('content_distribution', $nid); + } + }else{ + variable_set('distribute_content_type_'.$form['#node_type']->type, 0); + + //delete node ids from distribution db table + $result = db_query("SELECT nid from {node} WHERE type = '%s'", $form['#node_type']->type); + while($nid = db_fetch_object($result)){ + db_query('DELETE FROM {content_distribution} WHERE nid = %d', $nid->nid); + } + } + } +} + + +/** + * Implementation of hook_nodeapi(). + * + * We add the vocab_name to the taxonomy object so we can use it later + * on the destination server to look up a matching vocabulary - vid is not + * necessarily the same on both servers, hence using the name instead + */ +function content_distribution_nodeapi(&$node, $op, $teaser, $page) { + $is_distributable = variable_get('distribute_content_type_'.$node->type, 0); + //print_r($node); + switch ($op) { + case 'load': + // check if nodes of this content type are distributable + if($is_distributable !== 0){ + // get the published date info from the {content_distribution} table + $result = db_query("SELECT published_date FROM {content_distribution} WHERE nid = %d", $node->nid); + $pub_date = db_result($result); + //format the date field + $format = 'Y-m-d H:i'; + $local_timezone = date_default_timezone_get(); + $pub_date = date_make_date($pub_date,$local_timezone, DATE_UNIX); + $pub_date = date_format_date($pub_date, 'custom', $format); + + //taxonomy objects are not available during the load op, so we need to load them ourselves + $taxonomy = taxonomy_node_get_terms($node); + if ($taxonomy) { + $vocab_names = array(); + foreach ($taxonomy as $tid => $term) { + $vocab_names[$tid] = taxonomy_vocabulary_load($term->vid)->name; + } + } + //load op must return a structured array to be appended to the $node object + return array( + 'vocab_names' => $vocab_names, + 'published_date' => $pub_date, + ); + } + break; + case 'insert': + if($is_distributable !== 0){ + // convert date to timestamp before insert + $published_date = $node->published_date; + $published_date = date_convert($published_date, DATE_DATETIME, DATE_UNIX); + + db_query("INSERT INTO {content_distribution} (nid, published_date) VALUES (%d, %d)", $node->nid,$published_date); + } + break; + case 'update': + if($is_distributable !== 0){ + // see if node is already in DB + $result = db_query("SELECT nid FROM {content_distribution} WHERE nid = %d", $node->nid); + + // convert date to timestamp before insert + $published_date = $node->published_date; + $published_date = date_convert($published_date, DATE_DATETIME, DATE_UNIX); + + // if result fetched we already have a row so just update the table with new published date + if (($nid = db_result($result)) != FALSE) { + db_query("UPDATE {content_distribution} SET published_date = %d WHERE nid = %d", $published_date, $nid); + } + } + break; + case 'delete': + // remove row from node delete + if($is_distributable !== 0){ + db_query('DELETE FROM {content_distribution} WHERE nid = %d', $node->nid); + + $sites = variable_get('distributed_sites', ''); + if($sites){ + //foreach site go and check if the node is there + //and delete it off that site. + foreach($sites as $k => $site){ + $endpoint = $site['sitetext'] . '/services/xmlrpc'; + $api_key = ''; + + //grab a session id from the system.connect method + $connect = xmlrpc($endpoint, 'system.connect'); + $session_id = $connect['sessid']; + + //call the service to delete the node on the remote site + $result = xmlrpc($endpoint, 'node.deleteDistributedNode', $session_id, (int)$node->nid); + + if($result){ + drupal_set_message(t('Deleted node on ' . $site['sitetext']. ' with node id ' . $result)); + }else{ + drupal_set_message(t('No node to delete on ' . $site['sitetext'])); + } + } + } + } + break; + } +} + +/** + * Implementation of hook_views_api(). + */ +function content_distribution_views_api() { + return array( + 'api' => 2, + 'path' => drupal_get_path('module', 'content_distribution') . '/includes', + ); +} + + +/** + * Implementation of hook_menu(). + */ +function content_distribution_menu(){ + $items = array(); + + $items['admin/settings/distribution'] = array( + 'title' => t('Content Distribution Settings'), + 'page callback' => 'drupal_get_form', + 'page arguments' => array('content_distribution_admin_form'), + 'access arguments' => array('administer content distribution'), + 'description' => t('Settings for content distribution.'), + 'weight' => -10, + 'type' => MENU_NORMAL_ITEM + ); + + $items ['distribution/js'] = array( + 'title' => 'Javascript Site Form', + 'page callback' => 'distribution_site_js', + 'access arguments' => array('access content'), + 'type' => MENU_CALLBACK, + ); + return $items; +} + +/** + * Implementation of hook_perm(). + * Here we add the permissions for access to our admin page. + */ +function content_distribution_perm() { + return array('administer content distribution'); +} + +/** + * build the admin form. + */ +function content_distribution_admin_form(&$form_state){ + + $form['site_count'] = array( + '#type' => 'value', + '#default_value' => 1, + '#value' => $form_state['values']['site_count'], + ); + // Add a wrapper for the choices and more button. + $form['site_wrapper'] = array( + '#tree' => FALSE, + '#weight' => -4, + '#prefix' => '
' . t('Please enter the URL(s) of the remote sites you will be distributing content to in the text fields below.'), + '#suffix' => '
', + ); + + // Container for just the poll choices. + $form['site_wrapper']['site'] = array( + '#tree' => TRUE, + '#prefix' => '
', + '#suffix' => '
', + '#theme' => 'site_choices', + ); + + $sites = variable_get('distributed_sites', ''); + + // set up choice count + if(isset($form_state['values']['site_count'])){ + $choice_count = $form_state['values']['site_count']; + }else if($sites){ + $choice_count = count($sites); + foreach($sites as $k => $site){ + $form_state['values']['site'][$k]['sitetext']['#value'] = $site['sitetext']; + } + }else{ + $choice_count = 1; + } + + // Add the current choices to the form. + for ($delta = 0; $delta < $choice_count; $delta++) { + $text = isset($form_state['values']['site'][$delta]) ? $form_state['values']['site'][$delta]['sitetext']['#value'] : ''; + $form['site_wrapper']['site'][$delta] = _site_choice_form($delta, $text); + } + + // ahah element to handle adding more sites + $form['site_wrapper']['site_more'] = array( + '#type' => 'submit', + '#value' => t('Add More Sites'), + '#description' => t("If the amount of boxes above isn't enough, click here to add more sites."), + '#weight' => 1, + '#submit' => array('more_sites_submit'), // If no javascript action. + '#ahah' => array( + 'path' => 'distribution/js', + 'wrapper' => 'site-choices', + 'method' => 'replace', + 'effect' => 'fade', + ), + ); + + $form['site_wrapper']['submit'] = array( + '#type' => 'submit', + '#weight' => 2, + '#value' => t('Save Settings'), + ); + + return $form; +} + +/** + * validate function for the distribution settings form. + */ +function content_distribution_admin_form_validate($form, &$form_state){ + // validate that the user entered a valid url + // in the format http://www.site.com + if($form_state['values']['site']){ + foreach($form_state['values']['site'] as $k => $site){ + if(empty($site['sitetext'])){continue;} + else if(!(valid_url($site['sitetext'], true))){ + form_set_error('sitetext', 'Site ' . ($k+1) . ' is not a valid URL, please re-enter.'); + } + } + } +} + +/** + * submit function for the distribution settings form. + */ +function content_distribution_admin_form_submit($form, &$form_state){ + //check there is actually a value in each text field + //then save the array of fields into a variable + if($form_state['values']['site']){ + foreach($form_state['values']['site'] as $k => $site){ + if(empty($site['sitetext'])){ + unset($form_state['values']['site'][$k]); + } + } + variable_set('distributed_sites', array_values($form_state['values']['site'])); + drupal_set_message(t('Content Distribution Settings Saved.')); + } + +} + +function more_sites_submit($form, &$form_state){ + // increment the site count variable + $form_state['values']['site_count']++; +} + +function _site_choice_form($delta, $value = '') { + + $form = array( + '#tree' => TRUE, + ); + + // We'll manually set the #parents property of these fields so that + // their values appear in the $form_state['values']['site'] array. + $form['sitetext'] = array( + '#type' => 'textfield', + '#title' => t('Site @n', array('@n' => ($delta + 1))), + '#default_value' => $value, + '#description' => t('Enter URL in the format http://www.mysite.com'), + '#parents' => array('site', $delta, 'sitetext'), + ); + + return $form; +} + +/** + * Menu callback for AHAH additions. + */ +function distribution_site_js() { + $delta = count($_POST['site']); + + // Build our new form element. + $form_element = _site_choice_form($delta); + + //drupal_alter('form', $form_element, array(), 'poll_choice_js'); + + // Build the new form. + $form_state = array('submitted' => FALSE); + $form_build_id = $_POST['form_build_id']; + // Add the new element to the stored form. Without adding the element to the + // form, Drupal is not aware of this new elements existence and will not + // process it. We retreive the cached form, add the element, and resave. + if (!$form = form_get_cache($form_build_id, $form_state)) { + exit(); + } + $form['site_wrapper']['site'][$delta] = $form_element; + form_set_cache($form_build_id, $form, $form_state); + $form += array( + '#post' => $_POST, + '#programmed' => FALSE, + ); + + // Rebuild the form. + $form = form_builder($_POST['form_id'], $form, $form_state); + + // Render the new output. + $choice_form = $form['site_wrapper']['site']; + unset($choice_form['#prefix'], $choice_form['#suffix']); // Prevent duplicate wrappers. + + $output = theme('status_messages') . drupal_render($choice_form); + + drupal_json(array('status' => TRUE, 'data' => $output)); +} + + +/** + * Theme the form for site choices. + * + * @ingroup themeable + */ +function theme_site_choices($form) { + foreach (element_children($form) as $key) { + drupal_render($form[$key]['sitetext']); + } + $output .= drupal_render($form); + return $output; +} + +/** + * Implementation of hook_theme() + */ +function content_distribution_theme() { + return array( + 'site_choices' => array( + 'arguments' => array('form' => NULL), + ), + ); } \ No newline at end of file diff --git a/includes/content_distribution.views.inc b/includes/content_distribution.views.inc index 8b00775436e1b482b3c4393dea8d1fb4d8b513d2..2da63132980e18e9e6ab4937f1b17bce13a66e0a 100644 --- a/includes/content_distribution.views.inc +++ b/includes/content_distribution.views.inc @@ -1,310 +1,310 @@ -name = 'content_distribution_queue'; -$view->description = 'Display a list of all nodes in queue \'Content Distribution Queue\''; -$view->tag = 'nodequeue'; -$view->view_php = ''; -$view->base_table = 'node'; -$view->is_cacheable = FALSE; -$view->api_version = 2; -$view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */ -$handler = $view->new_display('default', 'Defaults', 'default'); -$handler->override_option('relationships', array( - 'nodequeue_rel' => array( - 'label' => 'queue', - 'required' => 1, - 'limit' => 1, - 'qids' => $qids, - 'id' => 'nodequeue_rel', - 'table' => 'node', - 'field' => 'nodequeue_rel', - 'relationship' => 'none', - ), -)); -$handler->override_option('fields', array( - 'title' => array( - 'id' => 'title', - 'table' => 'node', - 'field' => 'title', - 'label' => '', - 'relationship' => 'none', - 'link_to_node' => 1, - ), -)); -$handler->override_option('sorts', array( - 'position' => array( - 'id' => 'position', - 'table' => 'nodequeue_nodes', - 'field' => 'position', - 'order' => 'ASC', - 'relationship' => 'nodequeue_rel', - ), -)); -$handler->override_option('arguments', array( - 'qid' => array( - 'default_action' => 'not found', - 'style_plugin' => 'default_summary', - 'style_options' => array(), - 'wildcard' => 'all', - 'wildcard_substitution' => 'All', - 'title' => '', - 'default_argument_type' => 'fixed', - 'default_argument' => '', - 'validate_type' => 'none', - 'validate_fail' => 'not found', - 'break_phrase' => 0, - 'not' => 0, - 'id' => 'qid', - 'table' => 'nodequeue_nodes', - 'field' => 'qid', - 'relationship' => 'nodequeue_rel', - 'default_options_div_prefix' => '', - 'default_argument_user' => 0, - 'default_argument_fixed' => '', - 'default_argument_php' => '', - 'validate_argument_node_type' => array(), - 'validate_argument_node_access' => 0, - 'validate_argument_nid_type' => 'nid', - 'validate_argument_vocabulary' => array(), - 'validate_argument_type' => 'tid', - 'validate_argument_php' => '', - ), - 'type' => array( - 'default_action' => 'not found', - 'style_plugin' => 'default_summary', - 'style_options' => array(), - 'wildcard' => 'all', - 'wildcard_substitution' => 'All', - 'title' => '', - 'default_argument_type' => 'fixed', - 'default_argument' => '', - 'validate_type' => 'none', - 'validate_fail' => 'not found', - 'id' => 'type', - 'table' => 'node', - 'field' => 'type', - 'relationship' => 'none', - 'default_options_div_prefix' => '', - 'default_argument_user' => 0, - 'default_argument_fixed' => '', - 'default_argument_php' => '', - 'validate_argument_node_type' => array(), - 'validate_argument_node_access' => 0, - 'validate_argument_nid_type' => 'nid', - 'validate_argument_vocabulary' => array(), - 'validate_argument_type' => 'tid', - 'validate_argument_php' => '', - ), - 'changed' => array( - 'id' => 'changed', - 'table' => 'node', - 'field' => 'changed', - 'validate_type' => 'none', - 'validate_fail' => 'not found', - 'default_argument_type' => 'php', - 'relationship' => 'none', - 'title' => '', - 'default_action' => 'not found', - 'wildcard' => '', - 'wildcard_substitution' => '', - 'default_options_div_prefix' => '', - 'default_argument_user' => 0, - 'default_argument_fixed' => '', - 'default_argument_php' => '', - 'validate_argument_node_type' => array(), - 'validate_argument_node_access' => 0, - 'validate_argument_nid_type' => 'nid', - 'validate_argument_vocabulary' => array(), - 'validate_argument_type' => 'tid', - 'validate_argument_php' => '', - ), -)); -$handler->override_option('filters', array( - 'published_date' => array( - 'operator' => '<=', - 'value' => array( - 'type' => 'offset', - 'value' => 'now', - 'min' => '', - 'max' => '', - ), - 'group' => '0', - 'exposed' => FALSE, - 'expose' => array( - 'operator' => 'published_date_op', - 'label' => 'Content Distribution: Published Date', - 'use_operator' => 0, - 'identifier' => 'published_date', - 'optional' => 1, - 'remember' => 0, - ), - 'id' => 'published_date', - 'table' => 'content_distribution', - 'field' => 'published_date', - 'relationship' => 'none', - ), -)); -$handler->override_option('access', array( - 'type' => 'none', - 'role' => array(), - 'perm' => '', -)); -$handler->override_option('title', 'Queue \'Content Distribution Queue\''); -$handler->override_option('use_pager', '1'); -$handler->override_option('use_more', 1); -$handler->override_option('row_plugin', 'node'); -$handler->override_option('row_options', array( - 'teaser' => 1, - 'links' => 1, -)); -$handler = $view->new_display('page', 'Page', 'page'); -$handler->override_option('path', 'nodequeue/distribution'); -$handler->override_option('menu', array( - 'type' => 'none', - 'title' => '', - 'weight' => 0, - 'name' => 'navigation', -)); -$handler->override_option('tab_options', array( - 'type' => 'none', - 'title' => '', - 'weight' => 0, -)); -$handler = $view->new_display('block', 'Block', 'block'); -$handler->override_option('items_per_page', 5); -$handler->override_option('style_plugin', 'list'); -$handler->override_option('style_options', array( - 'type' => 'ul', -)); -$handler->override_option('row_options', array( - 'inline' => array(), - 'separator' => '', -)); -$handler->override_option('block_description', 'Queue \'Content Distribution Queue\''); -$handler->override_option('block_caching', -1); - - - - - $views[$view->name] = $view; - return $views; -} - -/** - * Implementation of hook_views_data_alter() - * - * Replaces the node.changed data for the views module and adds an - * 'Updated date' argument. - */ -function content_distribution_views_data_alter(&$data) { - // changed field - $data['node']['changed'] = array( - 'title' => t('Updated date'), // The item it appears as on the UI, - 'help' => t('The date the node was last updated.'), // The help that appears on the UI, - 'field' => array( - 'handler' => 'views_handler_field_date', - 'click sortable' => TRUE, - ), - 'sort' => array( - 'handler' => 'views_handler_sort_date', - ), - 'filter' => array( - 'handler' => 'views_handler_filter_date', - ), - 'argument' => array( - 'field' => 'changed', - 'handler' => 'views_handler_argument_node_created_fulldate', - ), - ); -} - -/** - * Define extra filters for the views module. - */ -function content_distribution_views_data(){ - $data = array(); - - // Define the base group of this table. Fields that don't - // have a group defined will go into this field by default. - $data['content_distribution']['table']['group'] = t('Content Distribution'); - - $data['content_distribution']['table']['base'] = array( - 'field' => 'nid', - 'title' => t('Content Distribution'), - 'help' => t("Content distribution relates to nodes which are set up to be distributed remotely."), - ); - - $data['content_distribution']['table']['join'] = array( - 'node' => array( - 'left_field' => 'nid', - 'field' => 'nid', - ), - ); - // ---------------------------------------------------------------- - // Fields - - //published date - $data['content_distribution']['published_date'] = array( - 'title' => t('Published Date'), - 'help' => t('Date and time of when node is set to be published.'), - 'field' => array( - 'handler' => 'views_handler_field_date', - 'click sortable' => TRUE, - ), - 'sort' => array( - 'handler' => 'views_handler_sort_date', - ), - 'filter' => array( - 'handler' => 'views_handler_filter_date', - ), - ); - - //week argument - $data['content_distribution']['published_week'] = array( - 'title' => t('Published week'), - 'help' => t('In the form of WW (01 - 53).'), - 'argument' => array( - 'field' => 'published_date', - 'handler' => 'views_handler_argument_node_created_week', - ), - ); - return $data; -} - - -/** - * Implementation of hook_views_query_alter() - * - * Rewrites the where clause for the third argument (updated date) - * so it is 'greater than or equals' rather than the default 'equals' - * for the nodequeue view to function correctly - */ -function content_distribution_views_query_alter(&$view, &$query) { - if ($view->name == 'content_distribution_queue') { - $query->where[0]['clauses'][3] = "DATE_FORMAT((FROM_UNIXTIME(node.changed)), '%Y%m%%d%H%i') >= '%s'"; - } -} - -/** - * Implementation of hook_views_api(). - */ -function content_distribution_views_views_api() { - return array( - 'api' => 2, - 'path' => drupal_get_path('module', 'content_distribution') . '/includes', - ); +name = 'content_distribution_queue'; +$view->description = 'Display a list of all nodes in queue \'Content Distribution Queue\''; +$view->tag = 'nodequeue'; +$view->view_php = ''; +$view->base_table = 'node'; +$view->is_cacheable = FALSE; +$view->api_version = 2; +$view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */ +$handler = $view->new_display('default', 'Defaults', 'default'); +$handler->override_option('relationships', array( + 'nodequeue_rel' => array( + 'label' => 'queue', + 'required' => 1, + 'limit' => 1, + 'qids' => $qids, + 'id' => 'nodequeue_rel', + 'table' => 'node', + 'field' => 'nodequeue_rel', + 'relationship' => 'none', + ), +)); +$handler->override_option('fields', array( + 'title' => array( + 'id' => 'title', + 'table' => 'node', + 'field' => 'title', + 'label' => '', + 'relationship' => 'none', + 'link_to_node' => 1, + ), +)); +$handler->override_option('sorts', array( + 'position' => array( + 'id' => 'position', + 'table' => 'nodequeue_nodes', + 'field' => 'position', + 'order' => 'ASC', + 'relationship' => 'nodequeue_rel', + ), +)); +$handler->override_option('arguments', array( + 'qid' => array( + 'default_action' => 'not found', + 'style_plugin' => 'default_summary', + 'style_options' => array(), + 'wildcard' => 'all', + 'wildcard_substitution' => 'All', + 'title' => '', + 'default_argument_type' => 'fixed', + 'default_argument' => '', + 'validate_type' => 'none', + 'validate_fail' => 'not found', + 'break_phrase' => 0, + 'not' => 0, + 'id' => 'qid', + 'table' => 'nodequeue_nodes', + 'field' => 'qid', + 'relationship' => 'nodequeue_rel', + 'default_options_div_prefix' => '', + 'default_argument_user' => 0, + 'default_argument_fixed' => '', + 'default_argument_php' => '', + 'validate_argument_node_type' => array(), + 'validate_argument_node_access' => 0, + 'validate_argument_nid_type' => 'nid', + 'validate_argument_vocabulary' => array(), + 'validate_argument_type' => 'tid', + 'validate_argument_php' => '', + ), + 'type' => array( + 'default_action' => 'not found', + 'style_plugin' => 'default_summary', + 'style_options' => array(), + 'wildcard' => 'all', + 'wildcard_substitution' => 'All', + 'title' => '', + 'default_argument_type' => 'fixed', + 'default_argument' => '', + 'validate_type' => 'none', + 'validate_fail' => 'not found', + 'id' => 'type', + 'table' => 'node', + 'field' => 'type', + 'relationship' => 'none', + 'default_options_div_prefix' => '', + 'default_argument_user' => 0, + 'default_argument_fixed' => '', + 'default_argument_php' => '', + 'validate_argument_node_type' => array(), + 'validate_argument_node_access' => 0, + 'validate_argument_nid_type' => 'nid', + 'validate_argument_vocabulary' => array(), + 'validate_argument_type' => 'tid', + 'validate_argument_php' => '', + ), + 'changed' => array( + 'id' => 'changed', + 'table' => 'node', + 'field' => 'changed', + 'validate_type' => 'none', + 'validate_fail' => 'not found', + 'default_argument_type' => 'php', + 'relationship' => 'none', + 'title' => '', + 'default_action' => 'not found', + 'wildcard' => '', + 'wildcard_substitution' => '', + 'default_options_div_prefix' => '', + 'default_argument_user' => 0, + 'default_argument_fixed' => '', + 'default_argument_php' => '', + 'validate_argument_node_type' => array(), + 'validate_argument_node_access' => 0, + 'validate_argument_nid_type' => 'nid', + 'validate_argument_vocabulary' => array(), + 'validate_argument_type' => 'tid', + 'validate_argument_php' => '', + ), +)); +$handler->override_option('filters', array( + 'published_date' => array( + 'operator' => '<=', + 'value' => array( + 'type' => 'offset', + 'value' => 'now', + 'min' => '', + 'max' => '', + ), + 'group' => '0', + 'exposed' => FALSE, + 'expose' => array( + 'operator' => 'published_date_op', + 'label' => 'Content Distribution: Published Date', + 'use_operator' => 0, + 'identifier' => 'published_date', + 'optional' => 1, + 'remember' => 0, + ), + 'id' => 'published_date', + 'table' => 'content_distribution', + 'field' => 'published_date', + 'relationship' => 'none', + ), +)); +$handler->override_option('access', array( + 'type' => 'none', + 'role' => array(), + 'perm' => '', +)); +$handler->override_option('title', 'Queue \'Content Distribution Queue\''); +$handler->override_option('use_pager', '1'); +$handler->override_option('use_more', 1); +$handler->override_option('row_plugin', 'node'); +$handler->override_option('row_options', array( + 'teaser' => 1, + 'links' => 1, +)); +$handler = $view->new_display('page', 'Page', 'page'); +$handler->override_option('path', 'nodequeue/distribution'); +$handler->override_option('menu', array( + 'type' => 'none', + 'title' => '', + 'weight' => 0, + 'name' => 'navigation', +)); +$handler->override_option('tab_options', array( + 'type' => 'none', + 'title' => '', + 'weight' => 0, +)); +$handler = $view->new_display('block', 'Block', 'block'); +$handler->override_option('items_per_page', 5); +$handler->override_option('style_plugin', 'list'); +$handler->override_option('style_options', array( + 'type' => 'ul', +)); +$handler->override_option('row_options', array( + 'inline' => array(), + 'separator' => '', +)); +$handler->override_option('block_description', 'Queue \'Content Distribution Queue\''); +$handler->override_option('block_caching', -1); + + + + + $views[$view->name] = $view; + return $views; +} + +/** + * Implementation of hook_views_data_alter() + * + * Replaces the node.changed data for the views module and adds an + * 'Updated date' argument. + */ +function content_distribution_views_data_alter(&$data) { + // changed field + $data['node']['changed'] = array( + 'title' => t('Updated date'), // The item it appears as on the UI, + 'help' => t('The date the node was last updated.'), // The help that appears on the UI, + 'field' => array( + 'handler' => 'views_handler_field_date', + 'click sortable' => TRUE, + ), + 'sort' => array( + 'handler' => 'views_handler_sort_date', + ), + 'filter' => array( + 'handler' => 'views_handler_filter_date', + ), + 'argument' => array( + 'field' => 'changed', + 'handler' => 'views_handler_argument_node_created_fulldate', + ), + ); +} + +/** + * Define extra filters for the views module. + */ +function content_distribution_views_data(){ + $data = array(); + + // Define the base group of this table. Fields that don't + // have a group defined will go into this field by default. + $data['content_distribution']['table']['group'] = t('Content Distribution'); + + $data['content_distribution']['table']['base'] = array( + 'field' => 'nid', + 'title' => t('Content Distribution'), + 'help' => t("Content distribution relates to nodes which are set up to be distributed remotely."), + ); + + $data['content_distribution']['table']['join'] = array( + 'node' => array( + 'left_field' => 'nid', + 'field' => 'nid', + ), + ); + // ---------------------------------------------------------------- + // Fields + + //published date + $data['content_distribution']['published_date'] = array( + 'title' => t('Published Date'), + 'help' => t('Date and time of when node is set to be published.'), + 'field' => array( + 'handler' => 'views_handler_field_date', + 'click sortable' => TRUE, + ), + 'sort' => array( + 'handler' => 'views_handler_sort_date', + ), + 'filter' => array( + 'handler' => 'views_handler_filter_date', + ), + ); + + //week argument + $data['content_distribution']['published_week'] = array( + 'title' => t('Published week'), + 'help' => t('In the form of WW (01 - 53).'), + 'argument' => array( + 'field' => 'published_date', + 'handler' => 'views_handler_argument_node_created_week', + ), + ); + return $data; +} + + +/** + * Implementation of hook_views_query_alter() + * + * Rewrites the where clause for the third argument (updated date) + * so it is 'greater than or equals' rather than the default 'equals' + * for the nodequeue view to function correctly + */ +function content_distribution_views_query_alter(&$view, &$query) { + if ($view->name == 'content_distribution_queue') { + $query->where[0]['clauses'][3] = "DATE_FORMAT((FROM_UNIXTIME(node.changed)), '%Y%m%%d%H%i') >= '%s'"; + } +} + +/** + * Implementation of hook_views_api(). + */ +function content_distribution_views_views_api() { + return array( + 'api' => 2, + 'path' => drupal_get_path('module', 'content_distribution') . '/includes', + ); } \ No newline at end of file diff --git a/modules/content_retriever/content_retriever.admin.inc b/modules/content_retriever/content_retriever.admin.inc index 27c7612ea852771ac22949aced401e8d2350f2ec..72a206d980501f9d332b2fe1a93b52d069dbe309 100644 --- a/modules/content_retriever/content_retriever.admin.inc +++ b/modules/content_retriever/content_retriever.admin.inc @@ -1,436 +1,436 @@ - t('Web service endpoint'), - '#type' => 'textfield', - '#required' => 'true', - '#default_value' => variable_get('content_retriever_endpoint', 'http://cms.defaqto.com/services/xmlrpc'), - ); - $form['api_key'] = array( - '#title' => t('Web service API key'), - '#type' => 'textfield', - '#default_value' => variable_get('content_retriever_api_key', ''), - ); - $form['username'] = array( - '#title' => t('Web service User name'), - '#type' => 'textfield', - '#default_value' => variable_get('content_retriever_webservice_username', ''), - ); - $form['password'] = array( - '#title' => t('Web service Password'), - '#type' => 'textfield', - '#default_value' => variable_get('content_retriever_webservice_pass', ''), - ); - $form['view'] = array( - '#title' => t('Name of the view to query on the distribution server'), - '#type' => 'textfield', - '#required' => 'true', - '#default_value' => variable_get('content_retriever_viewname', 'content_distribution_queue'), - ); - $form['reset_timestamp'] = array( - '#type' => 'textfield', - '#title' => t('Reset the time the retriever was last run'), - '#size' => 40, - '#default_value' => $last_run, - '#description' => t('Use the Date Format: YYYY-MM-DD HH:MM. This will only be reset if you click \'Reset last run time\''), - ); - $form['reporting'] = array( - '#type' => 'checkbox', - '#title' => 'On screen reporting messages', - '#default_value' => variable_get('content_retriever_screen_messages', 0), - ); - $form['submit'] = array( - '#value' => 'Save settings', - '#type' => 'submit', - ); - $form['retrieve'] = array( - '#value' => 'Retrieve content now', - '#type' => 'submit', - '#name' => 'retrieve', - '#submit' => array('content_retriever_admin_retrieve_now_form_submit'), - ); - $form['reset_status'] = array( - '#value' => 'Reset HTTP request status', - '#type' => 'submit', - '#name' => 'reset_status', - '#submit' => array('content_retriever_admin_clear_http_status_form_submit'), - ); - - return $form; -} - -/** - * content types form. - */ -function content_retriever_admin_types_form($form_values = null) { - - // retrieve array of content types for distribution from web service - $endpoint = variable_get('content_retriever_endpoint', 'http://cms.defaqto.com/services/xmlrpc'); - $api_key = variable_get('content_retriever_api_key', ''); - - // connect to the system service to get a session id - $connect = content_retriever_xmlrpc($endpoint, 'system.connect', $api_key); - $session_id = $connect['sessid']; - - //retrieve content types - $fields = content_retriever_xmlrpc($endpoint, 'node.getAllTypes', $api_key, $session_id); - - // get local content types installed. - $local_types = array(); - $local_types = array_keys(node_get_types()); - - if(!empty($fields)){ - $not_installed = array_diff($fields, $local_types); - - // get list of installed types - foreach($not_installed as $item){ - unset($fields[$item]); - } - - //variable_set('content_retriever_content_types', $fields); - }else{ - drupal_set_message(t('Could not retrieve a list of content types from the remote server'), 'error'); - } - - // check which state of the form you are in - // and render form depending on if you are selecting content - // types or installing content types - if((!empty($not_installed)) && (empty($form_values['skip_install']))){ - //define our admin form - - if(empty($fields)){ - drupal_set_message(t('There are no content types currently installed which can be retrieved from the remote instance.'), 'error'); - } - $form = array(); - $default_value = array_values($not_installed); - $form['content_type_information'] = array( - '#value' => variable_get('content_type_information', t('Below is a list of content types set up for distribution by the remote instance but which are not ' . - 'installed on this instance. If you do not wish to install the selected content type click skip until you are presented with the content types to retrieve form.')), - ); - $form['not_installed'] = array( - '#title' => 'These content types are not installed do you want to install any now', - '#type' => 'radios', - '#options' => $not_installed, - '#default_value' => $default_value[0], - ); - $form['skip'] = array( - '#value' => 'Skip', - '#type' => 'submit', - '#name' => 'skip', - '#submit' => array('content_retriever_admin_skip_form_submit'), - ); - $form['install'] = array( - '#value' => 'Install', - '#type' => 'submit', - '#name' => 'install', - '#submit' => array('content_retriever_admin_install_types_form_submit'), - ); - $form['reset_status'] = array( - '#value' => 'Reset HTTP request status', - '#type' => 'submit', - '#name' => 'reset_status', - '#submit' => array('content_retriever_admin_clear_http_status_form_submit'), - ); - }else{ - $form = array(); - if(!empty($fields)){ - $form['content_type_information'] = array( - '#value' => variable_get('content_type_retrieve_information', t('Select which content types you would like to retrieve from the remote instance.')), - ); - $form['content_types'] = array( - '#title' => 'Content types to retrieve', - '#type' => 'checkboxes', - '#options' => $fields, - '#default_value' => variable_get('content_retriever_content_types', array('page', 'story')), - ); - $form['submit'] = array( - '#value' => 'Save settings', - '#type' => 'submit', - ); - $form['retrieve'] = array( - '#value' => 'Retrieve content now', - '#type' => 'submit', - '#name' => 'retrieve', - '#submit' => array('content_retriever_admin_retrieve_now_form_submit'), - ); - $form['reset_status'] = array( - '#value' => 'Reset HTTP request status', - '#type' => 'submit', - '#name' => 'reset_status', - '#submit' => array('content_retriever_admin_clear_http_status_form_submit'), - ); - }else{ - $form['content_type_information'] = array( - '#value' => variable_get('no_types_installed_information', t('

You may need to configure the content distribution module on the remote instance to allow content to be distributed.

Or you can try resetting the HTTP request status.

')), - ); - $form['reset_status'] = array( - '#value' => 'Reset HTTP request status', - '#type' => 'submit', - '#name' => 'reset_status', - '#submit' => array('content_retriever_admin_clear_http_status_form_submit'), - ); - } - - } - - return $form; -} - -/** - * submit function fires the node retrieval function - */ -function content_retriever_admin_retrieve_now_form_submit($form_id, $form_values) { - $last_run = variable_get('content_retriever_last_run', (time() - (24 * 60 * 60)) ); - if(_content_retriever_save_nodes($last_run)){ - drupal_set_message(t('Process complete.')); - variable_set('content_retriever_last_run', time()); - } -} -/** - * Submit function to skip the content type install process. - */ -function content_retriever_admin_skip_form_submit($form, &$form_state) { - // rebuild the form but go to selection of types to retrieve - // instead of installing - $form_state['rebuild'] = TRUE; - $form_state['skip_install'] = true; -} - - -/** - * Submit function to install selected content type. - */ -function content_retriever_admin_install_types_form_submit($form, &$form_state) { - $install_type = $form_state['values']['not_installed']; - $query = 'destination=admin/settings/retriever/types' . '&type='.$install_type; - // if content type installer is available use it to install content types - if (module_exists('defaqto_content_type_installer')) { - $types_available = _defaqto_content_type_installer_get_files('content'); - - // see if content type .inc file is available to install - foreach($types_available as $type){ - if(array_search($install_type, $type) !== false){ - $form_state['values']['content_types'] = array($install_type); - $form_state['values']['taxonomy'] = array(); - defaqto_content_type_installer_admin_form_submit(&$form, &$form_state); - $installed = true; - } - } - if(!$installed){ - // include does not exist so go to content type add form. - drupal_goto('admin/content/types/add', $query); - } - } - else{ - // go to content type add form. - drupal_goto('admin/content/types/add', $query); - } -} - -/** - * submit function sets the HTTP request variable back to FALSE if it has - * inadvertently been made TRUE by a faulty web service/bad address - */ -function content_retriever_admin_clear_http_status_form_submit($form_id, $form_state) { - variable_set('drupal_http_request_fails', FALSE); - drupal_set_message(t('HTTP request status reset.')); -} - -/** - * validate function to check user-entered data from the admin form - */ -function content_retriever_admin_form_validate($form, &$form_state) { - if (strpos($form_state['values']['endpoint'], 'http') != 0) { - form_set_error('endpoint', t('The service endpoint must be a valid HTTP or HTTPS web address.')); - } - $reset = $form_state['values']['reset_timestamp']; - // get the current timestamp and convert user entered date to - // timestamp to compare - $now = time(); - $reset_timestamp = date_convert($reset,DATE_DATETIME, DATE_UNIX); - - // set form error if invalid date format - if(!date_is_valid($reset, $type = DATE_DATETIME)){ - form_set_error('reset_timestamp', t('Please enter a valid date format.')); - }else if($reset_timestamp > $now){ - form_set_error('reset_timestamp', t('Please enter a time in the past to reset the last run time to.')); - } - -} -/** - * submit function for 'Settings' form. - */ -function content_retriever_admin_form_submit($form, &$form_state){ - // save api key and endpoint variables - variable_set('content_retriever_endpoint', $form_state['values']['endpoint']); - variable_set('content_retriever_api_key', $form_state['values']['api_key']); - variable_set('content_retriever_viewname', $form_state['values']['view']); - variable_set('content_retriever_webservice_username', $form_state['values']['username']); - variable_set('content_retriever_webservice_pass', $form_state['values']['password']); - variable_set('content_retriever_screen_messages', $form_state['values']['reporting']); - - $time = $form_state['values']['reset_timestamp']; - // convert date to unix timestamp - $reset = date_convert($time,DATE_DATETIME, DATE_UNIX); - variable_set('content_retriever_last_run', $reset); - - drupal_set_message(t('Content Retriever Settings Saved.')); -} - -/** - * submit function for the 'Content Types' form sets variables for this module: - * - * content_retriever_content_types - * an array of content types to be retrieved - * - */ -function content_retriever_admin_types_form_submit($form, &$form_state) { - //organise the content types in to the correct format - $selected_types = array(); - $selected_types = $form_state['values']['content_types']; - $save_types = array(); - $count = 0; - foreach ($selected_types as $selected_type) { - if ($selected_type != '0') { - $count++; - $save_types[] = $selected_type; - } - } - //inform user if the module is disabled by their content choices - if ($count == 0) { - drupal_set_message(t('No content types were selected. Module disabled.'), 'error'); - } - - //save the variables - variable_set('content_retriever_content_types', $save_types); - - drupal_set_message(t('Settings saved.')); - //since this is a critical module, tell watchdog settings have changed so we have an audit trail - watchdog(t('integration'), t('Content Retriever Type settings were changed.'), array(), WATCHDOG_NOTICE); - - // rebuild the form and keep on the retrieval selection state - $form_state['rebuild'] = TRUE; - $form_state['skip_install'] = true; -} - -/** - * Form containing the settings for the nodequeues - * - * @return $form - * form array - */ -function content_retriever_admin_queues_form(){ - $form = array(); - - //make sure we can actually make HTTP requests - if (variable_get('drupal_http_request_fails', FALSE) == TRUE) { - drupal_set_message(t('Drupal is unable to make HTTP requests. Please reset the HTTP request status.'), 'error', FALSE); - watchdog('integration', t('Drupal is unable to make HTTP requests. Please reset the HTTP request status.'), array(), WATCHDOG_CRITICAL); - } else { - //get list of nodequeues from remote web service - $api_key = variable_get('content_retriever_api_key', ''); - $endpoint = variable_get('content_retriever_endpoint', 'http://cms.defaqto.com/services/xmlrpc'); - - // connect to the web service to get a session id - $connect = content_retriever_xmlrpc($endpoint, 'system.connect', $api_key); - $session_id = $connect['sessid']; - - $queues = content_retriever_xmlrpc($endpoint, 'nodequeue.getQueues', $api_key, $session_id); - - if ($queues) { - foreach ($queues as $queue) { - $queue_fields[$queue['qid']] = $queue['title']; - } - } else { - drupal_set_message(t('No queues available.')); - } - } - - $form['queues'] = array( - '#title' => 'Nodequeues to interrogate', - '#type' => 'checkboxes', - '#options' => $queue_fields, - '#default_value' => variable_get('content_retriever_nodequeues', array()), - ); - $form['submit'] = array( - '#value' => 'Save settings', - '#type' => 'submit', - ); - $form['retrieve'] = array( - '#value' => 'Retrieve content now', - '#type' => 'submit', - '#name' => 'retrieve', - '#submit' => array('content_retriever_admin_retrieve_now_form_submit'), - ); - $form['reset_status'] = array( - '#value' => 'Reset HTTP request status', - '#type' => 'submit', - '#name' => 'reset_status', - '#submit' => array('content_retriever_admin_clear_http_status_form_submit'), - ); - - return $form; -} -/** - * Submit function for 'queues' form. - */ -function content_retriever_admin_queues_form_submit($form, &$form_state){ - //collate the nodequeues ready for saving - $queues = array(); - $queues = $form_state['values']['queues']; - $count = 0; - foreach ($queues as $queue) { - if ($queue != '0') { - $count++; - } - } - //inform user if the module is disabled by their nodequeue choices - if ($count == 0) { - drupal_set_message(t('No nodequeues were selected. Module disabled.'), 'error'); - } - - //save the variables - variable_set('content_retriever_nodequeues', $queues); - drupal_set_message(t('Nodequeue Settings Saved.')); -} - -/** - * theme function rendering the 'settings' admin page. - */ -function theme_content_retriever_admin_page() { - $output .= '

Important! '.t('After a failed HTTP request (e.g. web service goes down, endpoint URL is wrong, etc.) Drupal assumes it has no access to the Internet and prevents itself from trying to make HTTP requests again. You may use the "Reset HTTP request status" button below to reset Drupal and allow it to make HTTP requests again. Always try this if you are not receiving data and you don\'t know why.').'

'; - $output .= drupal_get_form('content_retriever_admin_form'); - return $output; -} - -/** - * theme function for rendering the 'content types' admin page - */ -function theme_content_retriever_admin_types_page() { - // $output .= '

' .t('Choose which content types are to be retrieved.').'

'; - $output .= drupal_get_form('content_retriever_admin_types_form'); - return $output; -} - -/** - * Theme function for rendering the 'queues' admin page - */ -function theme_content_retriever_admin_queues_page(){ - $output .= drupal_get_form('content_retriever_admin_queues_form'); - return $output; -} - + t('Web service endpoint'), + '#type' => 'textfield', + '#required' => 'true', + '#default_value' => variable_get('content_retriever_endpoint', 'http://cms.defaqto.com/services/xmlrpc'), + ); + $form['api_key'] = array( + '#title' => t('Web service API key'), + '#type' => 'textfield', + '#default_value' => variable_get('content_retriever_api_key', ''), + ); + $form['username'] = array( + '#title' => t('Web service User name'), + '#type' => 'textfield', + '#default_value' => variable_get('content_retriever_webservice_username', ''), + ); + $form['password'] = array( + '#title' => t('Web service Password'), + '#type' => 'textfield', + '#default_value' => variable_get('content_retriever_webservice_pass', ''), + ); + $form['view'] = array( + '#title' => t('Name of the view to query on the distribution server'), + '#type' => 'textfield', + '#required' => 'true', + '#default_value' => variable_get('content_retriever_viewname', 'content_distribution_queue'), + ); + $form['reset_timestamp'] = array( + '#type' => 'textfield', + '#title' => t('Reset the time the retriever was last run'), + '#size' => 40, + '#default_value' => $last_run, + '#description' => t('Use the Date Format: YYYY-MM-DD HH:MM. This will only be reset if you click \'Reset last run time\''), + ); + $form['reporting'] = array( + '#type' => 'checkbox', + '#title' => 'On screen reporting messages', + '#default_value' => variable_get('content_retriever_screen_messages', 0), + ); + $form['submit'] = array( + '#value' => 'Save settings', + '#type' => 'submit', + ); + $form['retrieve'] = array( + '#value' => 'Retrieve content now', + '#type' => 'submit', + '#name' => 'retrieve', + '#submit' => array('content_retriever_admin_retrieve_now_form_submit'), + ); + $form['reset_status'] = array( + '#value' => 'Reset HTTP request status', + '#type' => 'submit', + '#name' => 'reset_status', + '#submit' => array('content_retriever_admin_clear_http_status_form_submit'), + ); + + return $form; +} + +/** + * content types form. + */ +function content_retriever_admin_types_form($form_values = null) { + + // retrieve array of content types for distribution from web service + $endpoint = variable_get('content_retriever_endpoint', 'http://cms.defaqto.com/services/xmlrpc'); + $api_key = variable_get('content_retriever_api_key', ''); + + // connect to the system service to get a session id + $connect = content_retriever_xmlrpc($endpoint, 'system.connect', $api_key); + $session_id = $connect['sessid']; + + //retrieve content types + $fields = content_retriever_xmlrpc($endpoint, 'node.getAllTypes', $api_key, $session_id); + + // get local content types installed. + $local_types = array(); + $local_types = array_keys(node_get_types()); + + if(!empty($fields)){ + $not_installed = array_diff($fields, $local_types); + + // get list of installed types + foreach($not_installed as $item){ + unset($fields[$item]); + } + + //variable_set('content_retriever_content_types', $fields); + }else{ + drupal_set_message(t('Could not retrieve a list of content types from the remote server'), 'error'); + } + + // check which state of the form you are in + // and render form depending on if you are selecting content + // types or installing content types + if((!empty($not_installed)) && (empty($form_values['skip_install']))){ + //define our admin form + + if(empty($fields)){ + drupal_set_message(t('There are no content types currently installed which can be retrieved from the remote instance.'), 'error'); + } + $form = array(); + $default_value = array_values($not_installed); + $form['content_type_information'] = array( + '#value' => variable_get('content_type_information', t('Below is a list of content types set up for distribution by the remote instance but which are not ' . + 'installed on this instance. If you do not wish to install the selected content type click skip until you are presented with the content types to retrieve form.')), + ); + $form['not_installed'] = array( + '#title' => 'These content types are not installed do you want to install any now', + '#type' => 'radios', + '#options' => $not_installed, + '#default_value' => $default_value[0], + ); + $form['skip'] = array( + '#value' => 'Skip', + '#type' => 'submit', + '#name' => 'skip', + '#submit' => array('content_retriever_admin_skip_form_submit'), + ); + $form['install'] = array( + '#value' => 'Install', + '#type' => 'submit', + '#name' => 'install', + '#submit' => array('content_retriever_admin_install_types_form_submit'), + ); + $form['reset_status'] = array( + '#value' => 'Reset HTTP request status', + '#type' => 'submit', + '#name' => 'reset_status', + '#submit' => array('content_retriever_admin_clear_http_status_form_submit'), + ); + }else{ + $form = array(); + if(!empty($fields)){ + $form['content_type_information'] = array( + '#value' => variable_get('content_type_retrieve_information', t('Select which content types you would like to retrieve from the remote instance.')), + ); + $form['content_types'] = array( + '#title' => 'Content types to retrieve', + '#type' => 'checkboxes', + '#options' => $fields, + '#default_value' => variable_get('content_retriever_content_types', array('page', 'story')), + ); + $form['submit'] = array( + '#value' => 'Save settings', + '#type' => 'submit', + ); + $form['retrieve'] = array( + '#value' => 'Retrieve content now', + '#type' => 'submit', + '#name' => 'retrieve', + '#submit' => array('content_retriever_admin_retrieve_now_form_submit'), + ); + $form['reset_status'] = array( + '#value' => 'Reset HTTP request status', + '#type' => 'submit', + '#name' => 'reset_status', + '#submit' => array('content_retriever_admin_clear_http_status_form_submit'), + ); + }else{ + $form['content_type_information'] = array( + '#value' => variable_get('no_types_installed_information', t('

You may need to configure the content distribution module on the remote instance to allow content to be distributed.

Or you can try resetting the HTTP request status.

')), + ); + $form['reset_status'] = array( + '#value' => 'Reset HTTP request status', + '#type' => 'submit', + '#name' => 'reset_status', + '#submit' => array('content_retriever_admin_clear_http_status_form_submit'), + ); + } + + } + + return $form; +} + +/** + * submit function fires the node retrieval function + */ +function content_retriever_admin_retrieve_now_form_submit($form_id, $form_values) { + $last_run = variable_get('content_retriever_last_run', (time() - (24 * 60 * 60)) ); + if(_content_retriever_save_nodes($last_run)){ + drupal_set_message(t('Process complete.')); + variable_set('content_retriever_last_run', time()); + } +} +/** + * Submit function to skip the content type install process. + */ +function content_retriever_admin_skip_form_submit($form, &$form_state) { + // rebuild the form but go to selection of types to retrieve + // instead of installing + $form_state['rebuild'] = TRUE; + $form_state['skip_install'] = true; +} + + +/** + * Submit function to install selected content type. + */ +function content_retriever_admin_install_types_form_submit($form, &$form_state) { + $install_type = $form_state['values']['not_installed']; + $query = 'destination=admin/settings/retriever/types' . '&type='.$install_type; + // if content type installer is available use it to install content types + if (module_exists('defaqto_content_type_installer')) { + $types_available = _defaqto_content_type_installer_get_files('content'); + + // see if content type .inc file is available to install + foreach($types_available as $type){ + if(array_search($install_type, $type) !== false){ + $form_state['values']['content_types'] = array($install_type); + $form_state['values']['taxonomy'] = array(); + defaqto_content_type_installer_admin_form_submit(&$form, &$form_state); + $installed = true; + } + } + if(!$installed){ + // include does not exist so go to content type add form. + drupal_goto('admin/content/types/add', $query); + } + } + else{ + // go to content type add form. + drupal_goto('admin/content/types/add', $query); + } +} + +/** + * submit function sets the HTTP request variable back to FALSE if it has + * inadvertently been made TRUE by a faulty web service/bad address + */ +function content_retriever_admin_clear_http_status_form_submit($form_id, $form_state) { + variable_set('drupal_http_request_fails', FALSE); + drupal_set_message(t('HTTP request status reset.')); +} + +/** + * validate function to check user-entered data from the admin form + */ +function content_retriever_admin_form_validate($form, &$form_state) { + if (strpos($form_state['values']['endpoint'], 'http') != 0) { + form_set_error('endpoint', t('The service endpoint must be a valid HTTP or HTTPS web address.')); + } + $reset = $form_state['values']['reset_timestamp']; + // get the current timestamp and convert user entered date to + // timestamp to compare + $now = time(); + $reset_timestamp = date_convert($reset,DATE_DATETIME, DATE_UNIX); + + // set form error if invalid date format + if(!date_is_valid($reset, $type = DATE_DATETIME)){ + form_set_error('reset_timestamp', t('Please enter a valid date format.')); + }else if($reset_timestamp > $now){ + form_set_error('reset_timestamp', t('Please enter a time in the past to reset the last run time to.')); + } + +} +/** + * submit function for 'Settings' form. + */ +function content_retriever_admin_form_submit($form, &$form_state){ + // save api key and endpoint variables + variable_set('content_retriever_endpoint', $form_state['values']['endpoint']); + variable_set('content_retriever_api_key', $form_state['values']['api_key']); + variable_set('content_retriever_viewname', $form_state['values']['view']); + variable_set('content_retriever_webservice_username', $form_state['values']['username']); + variable_set('content_retriever_webservice_pass', $form_state['values']['password']); + variable_set('content_retriever_screen_messages', $form_state['values']['reporting']); + + $time = $form_state['values']['reset_timestamp']; + // convert date to unix timestamp + $reset = date_convert($time,DATE_DATETIME, DATE_UNIX); + variable_set('content_retriever_last_run', $reset); + + drupal_set_message(t('Content Retriever Settings Saved.')); +} + +/** + * submit function for the 'Content Types' form sets variables for this module: + * + * content_retriever_content_types + * an array of content types to be retrieved + * + */ +function content_retriever_admin_types_form_submit($form, &$form_state) { + //organise the content types in to the correct format + $selected_types = array(); + $selected_types = $form_state['values']['content_types']; + $save_types = array(); + $count = 0; + foreach ($selected_types as $selected_type) { + if ($selected_type != '0') { + $count++; + $save_types[] = $selected_type; + } + } + //inform user if the module is disabled by their content choices + if ($count == 0) { + drupal_set_message(t('No content types were selected. Module disabled.'), 'error'); + } + + //save the variables + variable_set('content_retriever_content_types', $save_types); + + drupal_set_message(t('Settings saved.')); + //since this is a critical module, tell watchdog settings have changed so we have an audit trail + watchdog(t('integration'), t('Content Retriever Type settings were changed.'), array(), WATCHDOG_NOTICE); + + // rebuild the form and keep on the retrieval selection state + $form_state['rebuild'] = TRUE; + $form_state['skip_install'] = true; +} + +/** + * Form containing the settings for the nodequeues + * + * @return $form + * form array + */ +function content_retriever_admin_queues_form(){ + $form = array(); + + //make sure we can actually make HTTP requests + if (variable_get('drupal_http_request_fails', FALSE) == TRUE) { + drupal_set_message(t('Drupal is unable to make HTTP requests. Please reset the HTTP request status.'), 'error', FALSE); + watchdog('integration', t('Drupal is unable to make HTTP requests. Please reset the HTTP request status.'), array(), WATCHDOG_CRITICAL); + } else { + //get list of nodequeues from remote web service + $api_key = variable_get('content_retriever_api_key', ''); + $endpoint = variable_get('content_retriever_endpoint', 'http://cms.defaqto.com/services/xmlrpc'); + + // connect to the web service to get a session id + $connect = content_retriever_xmlrpc($endpoint, 'system.connect', $api_key); + $session_id = $connect['sessid']; + + $queues = content_retriever_xmlrpc($endpoint, 'nodequeue.getQueues', $api_key, $session_id); + + if ($queues) { + foreach ($queues as $queue) { + $queue_fields[$queue['qid']] = $queue['title']; + } + } else { + drupal_set_message(t('No queues available.')); + } + } + + $form['queues'] = array( + '#title' => 'Nodequeues to interrogate', + '#type' => 'checkboxes', + '#options' => $queue_fields, + '#default_value' => variable_get('content_retriever_nodequeues', array()), + ); + $form['submit'] = array( + '#value' => 'Save settings', + '#type' => 'submit', + ); + $form['retrieve'] = array( + '#value' => 'Retrieve content now', + '#type' => 'submit', + '#name' => 'retrieve', + '#submit' => array('content_retriever_admin_retrieve_now_form_submit'), + ); + $form['reset_status'] = array( + '#value' => 'Reset HTTP request status', + '#type' => 'submit', + '#name' => 'reset_status', + '#submit' => array('content_retriever_admin_clear_http_status_form_submit'), + ); + + return $form; +} +/** + * Submit function for 'queues' form. + */ +function content_retriever_admin_queues_form_submit($form, &$form_state){ + //collate the nodequeues ready for saving + $queues = array(); + $queues = $form_state['values']['queues']; + $count = 0; + foreach ($queues as $queue) { + if ($queue != '0') { + $count++; + } + } + //inform user if the module is disabled by their nodequeue choices + if ($count == 0) { + drupal_set_message(t('No nodequeues were selected. Module disabled.'), 'error'); + } + + //save the variables + variable_set('content_retriever_nodequeues', $queues); + drupal_set_message(t('Nodequeue Settings Saved.')); +} + +/** + * theme function rendering the 'settings' admin page. + */ +function theme_content_retriever_admin_page() { + $output .= '

Important! '.t('After a failed HTTP request (e.g. web service goes down, endpoint URL is wrong, etc.) Drupal assumes it has no access to the Internet and prevents itself from trying to make HTTP requests again. You may use the "Reset HTTP request status" button below to reset Drupal and allow it to make HTTP requests again. Always try this if you are not receiving data and you don\'t know why.').'

'; + $output .= drupal_get_form('content_retriever_admin_form'); + return $output; +} + +/** + * theme function for rendering the 'content types' admin page + */ +function theme_content_retriever_admin_types_page() { + // $output .= '

' .t('Choose which content types are to be retrieved.').'

'; + $output .= drupal_get_form('content_retriever_admin_types_form'); + return $output; +} + +/** + * Theme function for rendering the 'queues' admin page + */ +function theme_content_retriever_admin_queues_page(){ + $output .= drupal_get_form('content_retriever_admin_queues_form'); + return $output; +} + diff --git a/modules/content_retriever/content_retriever.info b/modules/content_retriever/content_retriever.info index 6c2348a6596ef4f450cbf85cb92831a93dd1cc44..3089b09c0d6d6da96887cb81d6a519845d06b044 100644 --- a/modules/content_retriever/content_retriever.info +++ b/modules/content_retriever/content_retriever.info @@ -1,9 +1,9 @@ -; $Id$ -name = Content Retriever -description = Queries the views.getView method exposed by the Services module on an endpoint of your choice and parses and saves the resulting nodes in the local database. -package = Content Distribution -version = 6.x-1.x-dev -core = 6.x -dependencies[] = node -dependencies[] = distributor_service -dependencies[] = system_service +; $Id$ +name = Content Retriever +description = Queries the views.getView method exposed by the Services module on an endpoint of your choice and parses and saves the resulting nodes in the local database. +package = Content Distribution +version = 6.x-1.x-dev +core = 6.x +dependencies[] = node +dependencies[] = distributor_service +dependencies[] = system_service diff --git a/modules/content_retriever/content_retriever.install b/modules/content_retriever/content_retriever.install index e374fad195a84deaef0fa66f7f56b54cff67d2f0..59cb215944141d02195d12f43cc312a60a67f5ab 100644 --- a/modules/content_retriever/content_retriever.install +++ b/modules/content_retriever/content_retriever.install @@ -1,71 +1,71 @@ -nid, $nid->field_original_nid); - }*/ -} - -/** - * Implementation of hook_uninstall(). - */ -function content_retriever_uninstall() { - // Remove tables. - drupal_uninstall_schema('content_retriever'); - //remove variables - variable_del('content_retriever_last_run'); - variable_del('content_retriever_content_types'); - variable_del('content_retriever_endpoint'); - variable_del('content_retriever_api_key'); - variable_del('content_retriever_viewname'); - variable_del('content_retriever_webservice_username'); - variable_del('content_retriever_webservice_pass'); - variable_del('content_retriever_nodequeues'); -} - -/** - * Implementation of hook_schema(). - */ -function content_retriever_schema() { - $schema['content_retriever'] = array( - 'description' => t('Stores node information on nodes which have been retrieved over XMLRPC by the retriever module'), - 'fields' => array( - 'nid' => array( - 'type' => 'int', - 'unsigned' => TRUE, - 'not null' => TRUE, - 'description' => t("The node's {node}.nid."), - ), - 'original_nid' => array( - 'type' => 'int', - 'not null' => TRUE, - 'description' => t("The retrieved node over XMLRPC's {node}.nid. ") - ), - 'published_date' => array( - 'type' => 'int', - 'not null' => TRUE, - 'default' => 0, - 'description' => t("The Unix timestamp node was published."), - ), - ), - 'primary key' => array('nid'), - 'indexes' => array( - 'original_nid' => array('original_nid'), - ), - ); - - return $schema; -} - - +nid, $nid->field_original_nid); + }*/ +} + +/** + * Implementation of hook_uninstall(). + */ +function content_retriever_uninstall() { + // Remove tables. + drupal_uninstall_schema('content_retriever'); + //remove variables + variable_del('content_retriever_last_run'); + variable_del('content_retriever_content_types'); + variable_del('content_retriever_endpoint'); + variable_del('content_retriever_api_key'); + variable_del('content_retriever_viewname'); + variable_del('content_retriever_webservice_username'); + variable_del('content_retriever_webservice_pass'); + variable_del('content_retriever_nodequeues'); +} + +/** + * Implementation of hook_schema(). + */ +function content_retriever_schema() { + $schema['content_retriever'] = array( + 'description' => t('Stores node information on nodes which have been retrieved over XMLRPC by the retriever module'), + 'fields' => array( + 'nid' => array( + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + 'description' => t("The node's {node}.nid."), + ), + 'original_nid' => array( + 'type' => 'int', + 'not null' => TRUE, + 'description' => t("The retrieved node over XMLRPC's {node}.nid. ") + ), + 'published_date' => array( + 'type' => 'int', + 'not null' => TRUE, + 'default' => 0, + 'description' => t("The Unix timestamp node was published."), + ), + ), + 'primary key' => array('nid'), + 'indexes' => array( + 'original_nid' => array('original_nid'), + ), + ); + + return $schema; +} + + diff --git a/modules/content_retriever/content_retriever.module b/modules/content_retriever/content_retriever.module index 69f43e221ac1957b961e76ae3bfa6e3045bfbbbd..2979e2bf94fe489985b7fd2504401433b7c4edf8 100644 --- a/modules/content_retriever/content_retriever.module +++ b/modules/content_retriever/content_retriever.module @@ -1,701 +1,701 @@ - 'Content Retriever Settings', - 'description' => t('Settings for content retrieval over web services from a central distribution server.'), - 'page callback' => 'theme', - 'page arguments' => array('content_retriever_admin_page'), - 'access arguments' => array('administer content retrieval'), - 'weight' => -10, - 'type' => MENU_NORMAL_ITEM, - 'file' => 'content_retriever.admin.inc', - ); - - $items['admin/settings/retriever/settings'] = array( - 'title' => 'Settings', - 'description' => t('Settings for content retrieval over web services from a central distribution server.'), - 'page callback' => 'theme', - 'page arguments' => array('content_retriever_admin_page'), - 'access arguments' => array('administer content retrieval'), - 'weight' => -10, - 'type' => MENU_DEFAULT_LOCAL_TASK, - 'file' => 'content_retriever.admin.inc', - ); - - $items['admin/settings/retriever/types'] = array( - 'title' => 'Content Types', - 'description' => t('Settings for content retrieval over web services from a central distribution server.'), - 'page callback' => 'theme', - 'page arguments' => array('content_retriever_admin_types_page'), - 'access arguments' => array('administer content retrieval'), - 'type' => MENU_LOCAL_TASK, - 'file' => 'content_retriever.admin.inc', - ); - - $items['admin/settings/retriever/queues'] = array( - 'title' => 'Nodequeues', - 'description' => t('Nodequeues to interrogate on remote server to retrieve distributed content.'), - 'page callback' => 'theme', - 'page arguments' => array('content_retriever_admin_queues_page'), - 'access arguments' => array('administer content retrieval'), - 'type' => MENU_LOCAL_TASK, - 'file' => 'content_retriever.admin.inc', - ); - - //visual output for debug purposes - $last_run = variable_get('content_retriever_last_run', (time() - (24 * 60 * 60)) ); - $items['admin/settings/retriever/output'] = array( - 'title' => 'Content Retriever visual output', - 'description' => t('If you need to physically see the retrieved content for debug purposes, touching this page runs the processes and outputs the resulting nodes to screen.'), - 'page callback' => '_content_retriever_save_nodes', - 'page arguments' => array((string) $last_run), - 'access arguments' => array('administer content retrieval'), - 'weight' => 5, - 'type' => MENU_LOCAL_TASK, - ); - return $items; -} - -/** - * Implementation of hook_theme(). - */ -function content_retriever_theme() { - return array( - 'content_retriever_admin_page' => array( - 'arguments' => array(), - ), - 'content_retriever_admin_types_page' => array( - 'arguments' => array(), - ), - 'content_retriever_admin_queues_page' => array( - 'arguments' => array(), - ), - ); -} - - -/** - * parses and saves nodes sent back from the web service - * - * @param $last_run - * timestamp - Unix time of last time process executed - * - * @return - * string of HTML for debug purposes only - */ -function _content_retriever_save_nodes($last_run) { - global $user; - - //load variables required by web service - $endpoint = variable_get('content_retriever_endpoint', 'http://cms.defaqto.com/services/xmlrpc'); - $api_key = variable_get('content_retriever_api_key', ''); - //check if screen reporting messages for debug are on or off - $screen_reports = variable_get('content_retriever_screen_messages', 0); - - //fetch node data - $nodes = _content_retriever_fetch_nodes($last_run); - if ($nodes) { - if($screen_reports != 0){ - drupal_set_message('_content_retriever_fetch_nodes ran! No. of nodes: '.count($nodes)); - } - }else{ - if($screen_reports != 0){ - drupal_set_message(t('There are no new nodes to retrieve. Process complete.')); - } - return; - } - - if ($nodes) { - foreach ($nodes as $node) { - - // get a handle on the original_nid stored in the local database - // to check if we already have a version of the incoming node - $result = db_query("SELECT nid FROM {content_retriever} WHERE original_nid = %d",$node->nid); - $nid = (int)db_result($result); - - //we need to be a superuser to do this next stuff - $temp_user = $user; - $user = user_load(array('uid' => 1)); - - //store remote nid - $remote_nid = $node->nid; - - //unset the CMS node ID - unset($node->nid); - - //if we have nodes carrying this CMS nid already, use that local ID so we update them as the NID - if(!empty($nid)){ - $node->nid = $nid; - //need to get the latest revision id - $result = db_query("SELECT MAX(vid) FROM {node_revisions} WHERE nid = %d",$node->nid); - $vid = (int)db_result($result); - // set revision id to latest revision and tell drupal this - // is a new revision - $node->vid = $vid; - $node->revision = 1; - - if($screen_reports != 0){ - drupal_set_message(t('Updating node with nid: '. $nid)); - } - watchdog(t('integration'), t('Updating node with nid: %nid.'), array('%nid' => $nid), WATCHDOG_NOTICE); - }else{ - unset($node->vid); - } - - //unset anything unique to each instance of Drupal and save the node - unset($node->created); - unset($node->changed); - - unset($node->promote); - unset($node->sticky); - - unset($node->revision_uid); - unset($node->revision_timestamp); - unset($node->field_related_items); - - unset($node->path); - - unset($node->comment_count); - unset($node->last_comment_timestamp); - unset($node->last_comment_name); - - //reset the teaser so a new, safe, teaser is created - $node->teaser = node_teaser($node->body, $node->format); - - unset($node->queues); - - //taxonomy parsing - rewrites the taxonomy object - if (module_exists('taxonomy_parser')) { - if ($node->taxonomy) { - // construct array of term names from the $node->taxonomy - $term_categories = array(); - foreach($node->taxonomy as $term){ - $term_categories[$term['name']]['vocab'] = $node->vocab_names[$term['tid']]; - } - // parse the taxonomy and return taxonomy array to be attached to the node object - $node->taxonomy = taxonomy_parser_import_taxonomy($term_categories, $node->type); - } - }else{ - // module is not installed so capture the issue - watchdog('integration', 'Failed to call taxonomy_parser_import_taxonomy(). The taxonomy_parser module is not available.', WATCHDOG_WARNING); - unset($node->taxonomy); - } - - //fetch imagefield / filefield files - if((module_exists('imagefield')) || (module_exists('filefield'))){ - $fields = content_fields(); - $files_array = array(); - //check the cck field exists on the local content type - - if (!empty($fields)) { - foreach($fields as $content_type_field){ - if(($content_type_field['type_name'] == $node->type) && (($content_type_field['module'] == 'imagefield')) || ($content_type_field['module'] == 'filefield')){ - if(!empty($node->$content_type_field['field_name'])){ - $files_array[$content_type_field['field_name']] = $node->$content_type_field['field_name']; - } - } - } - } - - $file_count = count($files_array); - if ($file_count > 0) { - // get a session id from system.service module - $connect = content_retriever_xmlrpc($endpoint, 'system.connect', $api_key); - $session_id = $connect['sessid']; - - foreach($files_array as $field => $file_type){ - $field_array = $node->$field; - foreach($file_type as $key => $incoming_file){ - $file = content_retriever_xmlrpc($endpoint, 'file.get', $api_key, $session_id, (int)$incoming_file['fid']); - $file_details = _content_retriever_save_file($file, $node->nid, 'cck', null, $field, $node->type); - - $field_array[$key]['fid'] = $file_details->fid; - $field_array[$key]['filepath'] = $file_details->filepath; - } - $node->$field = $field_array; - } - } - } - - //grab files array and unset files on the node before save - $files_array = array(); - $files_array = $node->files; - unset($node->files); - - // save the node - node_save($node); - - //format node->published_date to unix timestamp for DB entry. - $published_date = $node->published_date; - $published_date = date_convert($published_date, DATE_DATETIME, DATE_UNIX); - - // check whether we are inserting a new node or updating an existing one - if(!empty($nid)){ - db_query("UPDATE {content_retriever} SET published_date = %d WHERE nid = %d", $published_date, $node->nid); - }else{ - db_query("INSERT INTO {content_retriever} (nid, original_nid, published_date) VALUES (%d, %d, %d)", $node->nid, $remote_nid, $published_date); - } - - //fetch ordinary upload module attached files - if (module_exists('upload')) { - $file_count = count($files_array); - if ($file_count > 0) { - // get a session id from system.service module - $connect = content_retriever_xmlrpc($endpoint, 'system.connect', $api_key); - $session_id = $connect['sessid']; - $files = content_retriever_xmlrpc($endpoint, 'file.getNodeFiles', $api_key, $session_id, $remote_nid); - if(!empty($files)){ - foreach ($files as $file) { - _content_retriever_save_file($file, $node->nid, 'file', $node->vid); - } - }else{ - watchdog(t('integration'), t('Content retriever ran but could not retrieve files on node with node ID %node'), array('%node' => $node->nid), WATCHDOG_NOTICE); - } - } - } - - //now stop being the superuser - $user = $temp_user; - - //tell watchdog the process has completed with content - $output .= '
'. htmlspecialchars(print_r($node, true)) .'
'; - } - watchdog(t('integration'), t('Content Retriever ran and processed '.(count($nodes) /*+ $images_count*/). ' nodes.'), array(), WATCHDOG_NOTICE); - } else { - $output .= ''; - watchdog(t('integration'), t('Content Retriever ran but there were no new nodes.'), array(), WATCHDOG_NOTICE); - if($screen_reports != 0){ - drupal_set_message(t('No new content.')); - } - } - return $output; -} - -/** - * retrieves and builds an array of nodes from the remote resource, - * ready to be saved to the database - * - * @param $last_run - * timestamp - Unix time of last time process executed - * - * @return - * array containing retrieved node objects - */ -function _content_retriever_fetch_nodes($last_run) { - //define arguments for xmlrpc method call - //variables are set in the admin form submit function - $viewname = variable_get('content_retriever_viewname', 'content_distribution_queue'); - $endpoint = variable_get('content_retriever_endpoint', 'http://cms.defaqto.com/services/xmlrpc'); - $content_types = variable_get('content_retriever_content_types', array()); - $queues = variable_get('content_retriever_nodequeues', array()); - $api_key = variable_get('content_retriever_api_key', ''); - $username = variable_get('content_retriever_webservice_username', ''); - $password = variable_get('content_retriever_webservice_pass', ''); - - //warn sysadm via watchdog if no safe content types are found - if (count($content_types) == 0) { - watchdog('integration', t('Content Retriever found no valid content types - doing nothing.'), array(), WATCHDOG_WARNING); - drupal_set_message(t('There are no available content types installed on this instance - cannot retrieve content'), 'error'); - return false; - } else { - $nodes = array(); - $processed_nids = array(); - - //we need to be logged in as webservice user with - //'administer nodes' permissions to be able to - //retrieve unpublished nodes via views.get service call - $connect = content_retriever_xmlrpc($endpoint, 'system.connect', $api_key); - $session_id = $connect['sessid']; - - //login as webservice user - $login = content_retriever_xmlrpc($endpoint, 'user.login', $api_key, $session_id, $username, $password); - $session_id = $login['sessid']; - - foreach ($content_types as $contenttype) { - - foreach ($queues as $qid => $queue) { - if ($queue != '0') { - //make the call - $result = content_retriever_xmlrpc($endpoint, 'views.get', $api_key, $session_id, $viewname, array((int)$qid, $contenttype, format_date($last_run, 'custom', 'YmdHi'))); - - if($result) { - foreach ($result as $node_info) { - //load the remote node - $node = _content_retriever_fetch_node($node_info['nid'], $session_id); - //check we haven't already got this node in the $nodes array from another queue - foreach($nodes as $processed_node) { - $processed_nids[$processed_node->nid] = $processed_node->nid; - } - if (array_search($node->nid, $processed_nids) === false) { - $nodes[] = $node; - } - $processed_nids = array(); - } - } - } - } - } - // logout as webservice user from remote site - content_retriever_xmlrpc($endpoint, 'user.logout', $api_key, $session_id); - return $nodes; - } - -} - - -/** - * retrieves a specific node from the remote resource, - * ready to be saved to the database - * - * @param $nid - * integer node id - * - * @param $fields - * optional array of CCK field names - * - * @return - * node object - */ -function _content_retriever_fetch_node($nid, $session_id, $fields = array()) { - //define arguments for xmlrpc method call - //variables are set in the admin form submit function - $endpoint = variable_get('content_retriever_endpoint', 'http://cms.defaqto.com/services/xmlrpc'); - $api_key = variable_get('content_retriever_api_key', ''); - - $result = content_retriever_xmlrpc($endpoint, 'node.get', $api_key, $session_id, (int)$nid, $fields); - - //convert returned array in to a proper object - if ($result) { - $node = new stdClass(); - foreach($result as $k => $v){ - $node->$k = $v; - } - return $node; - } else { - return false; - } - -} - - -/** - * @param $file - * array of file data - * - * @param $nid - * integer: the NEW node id on the local instance - * - * @param $type - * string denoting type of file, possible values: - * - image - * - file - */ -function _content_retriever_save_file($file, $nid, $type, $vid = null, $field = '', $node_type = '') { - $file_data = base64_decode($file['file']); - switch ($type) { - case 'file': - //set filepath to save to - $file['filepath'] = file_directory_path().'/'.$file['filename']; - - //check if the file is already on the system, if it is no need to save it again - $result = db_query("SELECT fid FROM {files} WHERE filename = '%s' AND timestamp = %d", $file['filename'], $file['timestamp']); - $fid_int = (int)db_result($result); - - if(!$fid_int){ - //save file - //note, safe to REPLACE because we can be certain we will not have duplicates - //we wish to keep - distirbution site will be handling duplicate file names - //so we will only ever receive unique ones here - file_save_data($file_data, $file['filepath'], FILE_EXISTS_REPLACE); - - //write record in files table - drupal_write_record('files', $file); - - //fetch the new fid for later use in upload table - $result = db_query("SELECT fid FROM {files} WHERE filename = '%s'", $file['filename']); - $fid_int = (int)db_result($result); - } - - //build array for upload table insertion - $upload = array( - 'fid' => $fid_int, - 'nid' => $nid, - 'vid' => $vid, - 'description' => $file['filename'], - 'list' => 1, - 'weight' => 0, - ); - - //write record in upload table - drupal_write_record('upload', $upload); - - return true; - break; - - case 'cck': - //set filepath to save to - $file['filepath'] = file_directory_path().'/'.$file['filename']; - - //set content type db table, and field to search on. - $content_table = 'content_type_'.$node_type; - $fid_field = $field.'_fid'; - - $file_details = array(); - //get timestamp and fid if there is a file on this node - $result = db_query("SELECT f.timestamp, f.fid, f.filepath FROM {files} as f - RIGHT JOIN {%s} as ctype - ON f.fid=ctype.%s - WHERE ctype.vid = (SELECT MAX({%s}.vid) - FROM {%s}) AND ctype.nid = %d", $content_table, $fid_field, $content_table, $content_table, $nid); - - - $file_details = db_fetch_object($result); - - //check if it's the same file coming over - if($file_details->timestamp == $file['timestamp']){ - //if it is it dont write another record in the files table. - return $file_details; - }else{ - //save file - //note, safe to REPLACE because we can be certain we will not have duplicates - //we wish to keep - distribution site will be handling duplicate file names - //so we will only ever receive unique ones here - file_save_data($file_data, $file['filepath'], FILE_EXISTS_REPLACE); - - //write record in files table - drupal_write_record('files', $file); - - $result = db_query("SELECT fid,filepath FROM {files} WHERE filename = '%s'", $file['filename']); - $file_details = db_fetch_object($result); - - return $file_details; - } - break; - } - -} - -/** - * abstraction of the service calling code needed to retrieve nodes - * - * makes and xml-rpc call to the Services module of another Drupal - * installation, calling the views.get method, and returns the - * resulting array - * - * @param $endpoint - * string representing the valid URI for the web service endpoint - * - * @param $method - * string telling us what method to call, examples: - * - views.get - * - file.getNodeFiles - * - nodequeue.getQueues - * - node.get - * - image.getNodeImages - * - * @param $api_key - * string containing a valid API key for this service - * - * @param $param1 thru $param3 - * various: placeholder vars for passing parameters to the web - * service methods - can be anything valid for the method call being - * invoked - empty strings by default - * - * @return - * array containing results of the call - */ -function content_retriever_xmlrpc($endpoint, $method, $api_key, $session_id = '',$param1 = '', $param2 = '', $param3 = '') { - //check if HTTP requests are enabled and report error if not - if (variable_get('drupal_http_request_fails', FALSE) == TRUE) { - drupal_set_message(t('Drupal is unable to make HTTP requests. Please reset the HTTP request status.'), 'error', FALSE); - watchdog('integration', t('Drupal is unable to make HTTP requests. Please reset the HTTP request status.'), array(), WATCHDOG_CRITICAL); - } else { - - if($api_key != ''){ - //use api key to get a hash code for the service. - $timestamp = (string) strtotime("now"); - $domain = $_SERVER['SERVER_NAME']; - $nonce = content_retriever_get_unique_code('10'); - $hash_parameters = array( - $timestamp, - $domain, - $nonce, - $method, - ); - $hash = hash_hmac("sha256", implode(';', $hash_parameters), $api_key); - } - - switch ($method) { - case 'system.connect': - $result = xmlrpc($endpoint, $method); - break; - case 'user.login': - //check for an API key - if not supplied, presume not required - if ($api_key == '') { - $result = xmlrpc($endpoint, $method, $session_id, (string) $param1, (string) $param2); - } else { - $result = xmlrpc($endpoint, $method, $hash, $domain, $timestamp, $nonce, $session_id, (string) $param1, (string) $param2); - } - break; - case 'user.logout': - //check for an API key - if not supplied, presume not required - if ($api_key == '') { - $result = xmlrpc($endpoint, $method, $session_id); - } else { - $result = xmlrpc($endpoint, $method, $hash, $domain, $timestamp, $nonce, $session_id); - } - break; - case 'views.get': - //check for an API key - if not supplied, presume not required - if ($api_key == '') { - //$param1 is view name, $param2 is array of view arguments - //'default' is display_id parameter hardcoded to default. - $result = xmlrpc($endpoint, $method, $session_id, (string) $param1, 'default', array(), (array) $param2, 0, 0); - } else { - //var_dump($endpoint, $method, $hash, $domain, $timestamp, $nonce, $session_id, $param1, $param2); - $result = xmlrpc($endpoint, $method, $hash, $domain, $timestamp, $nonce, $session_id, (string) $param1, 'default', array(), (array) $param2, 0, 0); - } - break; - - case 'file.getNodeFiles': - //check for an API key - if not supplied, presume not required - if ($api_key == '') { - //$param1 is nid - $result = xmlrpc($endpoint, $method, $session_id, (int) $param1); - } else { - $result = xmlrpc($endpoint, $method, $hash, $domain, $timestamp, $nonce, $session_id, (int) $param1); - } - break; - - case 'file.get': - //check for an API key - if not supplied, presume not required - if ($api_key == '') { - //$param1 is fid - $result = xmlrpc($endpoint, $method, $session_id, (int) $param1); - } else { - $result = xmlrpc($endpoint, $method, $hash, $domain, $timestamp, $nonce, $session_id, (int) $param1); - } - break; - - case 'nodequeue.getQueues': - //check for an API key - if not supplied, presume not required - if ($api_key == '') { - $result = xmlrpc($endpoint, $method, $session_id); - } else { - $result = xmlrpc($endpoint, $method, $hash, $domain, $timestamp, $nonce, $session_id); - } - break; - - case 'node.get': - //check for an API key - if not supplied, presume not required - if ($api_key == '') { - //$param1 is nid, $param2 is array of cck field names - $result = xmlrpc($endpoint, $method, $session_id, (int) $param1, (array) $param2); - } else { - $result = xmlrpc($endpoint, $method, $hash, $domain, $timestamp, $nonce, $session_id, (int) $param1, (array) $param2); - } - break; - - case 'image.getNodeImages': - //check for an API key - if not supplied, presume not required - if ($api_key == '') { - //$param1 is nid - $result = xmlrpc($endpoint, $method, $session_id, (int) $param1); - } else { - $result = xmlrpc($endpoint, $method, $hash, $domain, $timestamp, $nonce, $session_id, (int) $param1); - } - break; - - case 'node.getAllTypes': - //check for an API key - if not supplied, presume not required - if ($api_key == '') { - //$param1 is nid - $result = xmlrpc($endpoint, $method, $session_id); - } else { - $result = xmlrpc($endpoint, $method, $hash, $domain, $timestamp, $nonce, $session_id); - } - break; - - default: - $result = array(); - watchdog('integration', t('Unknown method call attempted.'), array(), WATCHDOG_NOTICE); - break; - } - return $result; - } -} - - -/** - * Implementation of hook_cron(). - */ -function content_retriever_cron() { - //retrieve the time content retriever last ran - $last_run = variable_get('content_retriever_last_run', (time() - (24 * 60 * 60)) ); - //set time to now for next run to use as the last run time - variable_set('content_retriever_last_run', time()); - //run - _content_retriever_save_nodes((string) $last_run); -} - - -/** - * Function extending the available page variables - * - * This has been implemented to expose the last time the content - * retriever has ran to page.tpl. This is purely for admin purposes, - * so they can simply visit the homepage of any site retrieving content - * to easily see when the last time the retriever ran was. - */ -function content_retriever_preprocess_page(&$variables) { - $last_run = variable_get('content_retriever_last_run', (time() - (24 * 60 * 60))); - $variables['last_run_timestamp'] = $last_run; - $variables['last_run'] = format_date($last_run, 'custom', 'd/m/Y H:i'); -} - -/** - * Implementation of hook_nodeapi(). - * - * delete the record from the content_retriever table when a node - * is deleted. - */ -function content_retriever_nodeapi(&$node, $op, $teaser, $page) { - switch ($op) { - case 'delete': - // remove db row from content_retriever - db_query('DELETE FROM {content_retriever} WHERE nid = %d', $node->nid); - break; - } -} - -function content_retriever_get_unique_code($length = ''){ - $code = md5(uniqid(rand(), true)); - if ($length != "") return substr($code, 0, $length); - else return $code; -} - + 'Content Retriever Settings', + 'description' => t('Settings for content retrieval over web services from a central distribution server.'), + 'page callback' => 'theme', + 'page arguments' => array('content_retriever_admin_page'), + 'access arguments' => array('administer content retrieval'), + 'weight' => -10, + 'type' => MENU_NORMAL_ITEM, + 'file' => 'content_retriever.admin.inc', + ); + + $items['admin/settings/retriever/settings'] = array( + 'title' => 'Settings', + 'description' => t('Settings for content retrieval over web services from a central distribution server.'), + 'page callback' => 'theme', + 'page arguments' => array('content_retriever_admin_page'), + 'access arguments' => array('administer content retrieval'), + 'weight' => -10, + 'type' => MENU_DEFAULT_LOCAL_TASK, + 'file' => 'content_retriever.admin.inc', + ); + + $items['admin/settings/retriever/types'] = array( + 'title' => 'Content Types', + 'description' => t('Settings for content retrieval over web services from a central distribution server.'), + 'page callback' => 'theme', + 'page arguments' => array('content_retriever_admin_types_page'), + 'access arguments' => array('administer content retrieval'), + 'type' => MENU_LOCAL_TASK, + 'file' => 'content_retriever.admin.inc', + ); + + $items['admin/settings/retriever/queues'] = array( + 'title' => 'Nodequeues', + 'description' => t('Nodequeues to interrogate on remote server to retrieve distributed content.'), + 'page callback' => 'theme', + 'page arguments' => array('content_retriever_admin_queues_page'), + 'access arguments' => array('administer content retrieval'), + 'type' => MENU_LOCAL_TASK, + 'file' => 'content_retriever.admin.inc', + ); + + //visual output for debug purposes + $last_run = variable_get('content_retriever_last_run', (time() - (24 * 60 * 60)) ); + $items['admin/settings/retriever/output'] = array( + 'title' => 'Content Retriever visual output', + 'description' => t('If you need to physically see the retrieved content for debug purposes, touching this page runs the processes and outputs the resulting nodes to screen.'), + 'page callback' => '_content_retriever_save_nodes', + 'page arguments' => array((string) $last_run), + 'access arguments' => array('administer content retrieval'), + 'weight' => 5, + 'type' => MENU_LOCAL_TASK, + ); + return $items; +} + +/** + * Implementation of hook_theme(). + */ +function content_retriever_theme() { + return array( + 'content_retriever_admin_page' => array( + 'arguments' => array(), + ), + 'content_retriever_admin_types_page' => array( + 'arguments' => array(), + ), + 'content_retriever_admin_queues_page' => array( + 'arguments' => array(), + ), + ); +} + + +/** + * parses and saves nodes sent back from the web service + * + * @param $last_run + * timestamp - Unix time of last time process executed + * + * @return + * string of HTML for debug purposes only + */ +function _content_retriever_save_nodes($last_run) { + global $user; + + //load variables required by web service + $endpoint = variable_get('content_retriever_endpoint', 'http://cms.defaqto.com/services/xmlrpc'); + $api_key = variable_get('content_retriever_api_key', ''); + //check if screen reporting messages for debug are on or off + $screen_reports = variable_get('content_retriever_screen_messages', 0); + + //fetch node data + $nodes = _content_retriever_fetch_nodes($last_run); + if ($nodes) { + if($screen_reports != 0){ + drupal_set_message('_content_retriever_fetch_nodes ran! No. of nodes: '.count($nodes)); + } + }else{ + if($screen_reports != 0){ + drupal_set_message(t('There are no new nodes to retrieve. Process complete.')); + } + return; + } + + if ($nodes) { + foreach ($nodes as $node) { + + // get a handle on the original_nid stored in the local database + // to check if we already have a version of the incoming node + $result = db_query("SELECT nid FROM {content_retriever} WHERE original_nid = %d",$node->nid); + $nid = (int)db_result($result); + + //we need to be a superuser to do this next stuff + $temp_user = $user; + $user = user_load(array('uid' => 1)); + + //store remote nid + $remote_nid = $node->nid; + + //unset the CMS node ID + unset($node->nid); + + //if we have nodes carrying this CMS nid already, use that local ID so we update them as the NID + if(!empty($nid)){ + $node->nid = $nid; + //need to get the latest revision id + $result = db_query("SELECT MAX(vid) FROM {node_revisions} WHERE nid = %d",$node->nid); + $vid = (int)db_result($result); + // set revision id to latest revision and tell drupal this + // is a new revision + $node->vid = $vid; + $node->revision = 1; + + if($screen_reports != 0){ + drupal_set_message(t('Updating node with nid: '. $nid)); + } + watchdog(t('integration'), t('Updating node with nid: %nid.'), array('%nid' => $nid), WATCHDOG_NOTICE); + }else{ + unset($node->vid); + } + + //unset anything unique to each instance of Drupal and save the node + unset($node->created); + unset($node->changed); + + unset($node->promote); + unset($node->sticky); + + unset($node->revision_uid); + unset($node->revision_timestamp); + unset($node->field_related_items); + + unset($node->path); + + unset($node->comment_count); + unset($node->last_comment_timestamp); + unset($node->last_comment_name); + + //reset the teaser so a new, safe, teaser is created + $node->teaser = node_teaser($node->body, $node->format); + + unset($node->queues); + + //taxonomy parsing - rewrites the taxonomy object + if (module_exists('taxonomy_parser')) { + if ($node->taxonomy) { + // construct array of term names from the $node->taxonomy + $term_categories = array(); + foreach($node->taxonomy as $term){ + $term_categories[$term['name']]['vocab'] = $node->vocab_names[$term['tid']]; + } + // parse the taxonomy and return taxonomy array to be attached to the node object + $node->taxonomy = taxonomy_parser_import_taxonomy($term_categories, $node->type); + } + }else{ + // module is not installed so capture the issue + watchdog('integration', 'Failed to call taxonomy_parser_import_taxonomy(). The taxonomy_parser module is not available.', WATCHDOG_WARNING); + unset($node->taxonomy); + } + + //fetch imagefield / filefield files + if((module_exists('imagefield')) || (module_exists('filefield'))){ + $fields = content_fields(); + $files_array = array(); + //check the cck field exists on the local content type + + if (!empty($fields)) { + foreach($fields as $content_type_field){ + if(($content_type_field['type_name'] == $node->type) && (($content_type_field['module'] == 'imagefield')) || ($content_type_field['module'] == 'filefield')){ + if(!empty($node->$content_type_field['field_name'])){ + $files_array[$content_type_field['field_name']] = $node->$content_type_field['field_name']; + } + } + } + } + + $file_count = count($files_array); + if ($file_count > 0) { + // get a session id from system.service module + $connect = content_retriever_xmlrpc($endpoint, 'system.connect', $api_key); + $session_id = $connect['sessid']; + + foreach($files_array as $field => $file_type){ + $field_array = $node->$field; + foreach($file_type as $key => $incoming_file){ + $file = content_retriever_xmlrpc($endpoint, 'file.get', $api_key, $session_id, (int)$incoming_file['fid']); + $file_details = _content_retriever_save_file($file, $node->nid, 'cck', null, $field, $node->type); + + $field_array[$key]['fid'] = $file_details->fid; + $field_array[$key]['filepath'] = $file_details->filepath; + } + $node->$field = $field_array; + } + } + } + + //grab files array and unset files on the node before save + $files_array = array(); + $files_array = $node->files; + unset($node->files); + + // save the node + node_save($node); + + //format node->published_date to unix timestamp for DB entry. + $published_date = $node->published_date; + $published_date = date_convert($published_date, DATE_DATETIME, DATE_UNIX); + + // check whether we are inserting a new node or updating an existing one + if(!empty($nid)){ + db_query("UPDATE {content_retriever} SET published_date = %d WHERE nid = %d", $published_date, $node->nid); + }else{ + db_query("INSERT INTO {content_retriever} (nid, original_nid, published_date) VALUES (%d, %d, %d)", $node->nid, $remote_nid, $published_date); + } + + //fetch ordinary upload module attached files + if (module_exists('upload')) { + $file_count = count($files_array); + if ($file_count > 0) { + // get a session id from system.service module + $connect = content_retriever_xmlrpc($endpoint, 'system.connect', $api_key); + $session_id = $connect['sessid']; + $files = content_retriever_xmlrpc($endpoint, 'file.getNodeFiles', $api_key, $session_id, $remote_nid); + if(!empty($files)){ + foreach ($files as $file) { + _content_retriever_save_file($file, $node->nid, 'file', $node->vid); + } + }else{ + watchdog(t('integration'), t('Content retriever ran but could not retrieve files on node with node ID %node'), array('%node' => $node->nid), WATCHDOG_NOTICE); + } + } + } + + //now stop being the superuser + $user = $temp_user; + + //tell watchdog the process has completed with content + $output .= '
'. htmlspecialchars(print_r($node, true)) .'
'; + } + watchdog(t('integration'), t('Content Retriever ran and processed '.(count($nodes) /*+ $images_count*/). ' nodes.'), array(), WATCHDOG_NOTICE); + } else { + $output .= ''; + watchdog(t('integration'), t('Content Retriever ran but there were no new nodes.'), array(), WATCHDOG_NOTICE); + if($screen_reports != 0){ + drupal_set_message(t('No new content.')); + } + } + return $output; +} + +/** + * retrieves and builds an array of nodes from the remote resource, + * ready to be saved to the database + * + * @param $last_run + * timestamp - Unix time of last time process executed + * + * @return + * array containing retrieved node objects + */ +function _content_retriever_fetch_nodes($last_run) { + //define arguments for xmlrpc method call + //variables are set in the admin form submit function + $viewname = variable_get('content_retriever_viewname', 'content_distribution_queue'); + $endpoint = variable_get('content_retriever_endpoint', 'http://cms.defaqto.com/services/xmlrpc'); + $content_types = variable_get('content_retriever_content_types', array()); + $queues = variable_get('content_retriever_nodequeues', array()); + $api_key = variable_get('content_retriever_api_key', ''); + $username = variable_get('content_retriever_webservice_username', ''); + $password = variable_get('content_retriever_webservice_pass', ''); + + //warn sysadm via watchdog if no safe content types are found + if (count($content_types) == 0) { + watchdog('integration', t('Content Retriever found no valid content types - doing nothing.'), array(), WATCHDOG_WARNING); + drupal_set_message(t('There are no available content types installed on this instance - cannot retrieve content'), 'error'); + return false; + } else { + $nodes = array(); + $processed_nids = array(); + + //we need to be logged in as webservice user with + //'administer nodes' permissions to be able to + //retrieve unpublished nodes via views.get service call + $connect = content_retriever_xmlrpc($endpoint, 'system.connect', $api_key); + $session_id = $connect['sessid']; + + //login as webservice user + $login = content_retriever_xmlrpc($endpoint, 'user.login', $api_key, $session_id, $username, $password); + $session_id = $login['sessid']; + + foreach ($content_types as $contenttype) { + + foreach ($queues as $qid => $queue) { + if ($queue != '0') { + //make the call + $result = content_retriever_xmlrpc($endpoint, 'views.get', $api_key, $session_id, $viewname, array((int)$qid, $contenttype, format_date($last_run, 'custom', 'YmdHi'))); + + if($result) { + foreach ($result as $node_info) { + //load the remote node + $node = _content_retriever_fetch_node($node_info['nid'], $session_id); + //check we haven't already got this node in the $nodes array from another queue + foreach($nodes as $processed_node) { + $processed_nids[$processed_node->nid] = $processed_node->nid; + } + if (array_search($node->nid, $processed_nids) === false) { + $nodes[] = $node; + } + $processed_nids = array(); + } + } + } + } + } + // logout as webservice user from remote site + content_retriever_xmlrpc($endpoint, 'user.logout', $api_key, $session_id); + return $nodes; + } + +} + + +/** + * retrieves a specific node from the remote resource, + * ready to be saved to the database + * + * @param $nid + * integer node id + * + * @param $fields + * optional array of CCK field names + * + * @return + * node object + */ +function _content_retriever_fetch_node($nid, $session_id, $fields = array()) { + //define arguments for xmlrpc method call + //variables are set in the admin form submit function + $endpoint = variable_get('content_retriever_endpoint', 'http://cms.defaqto.com/services/xmlrpc'); + $api_key = variable_get('content_retriever_api_key', ''); + + $result = content_retriever_xmlrpc($endpoint, 'node.get', $api_key, $session_id, (int)$nid, $fields); + + //convert returned array in to a proper object + if ($result) { + $node = new stdClass(); + foreach($result as $k => $v){ + $node->$k = $v; + } + return $node; + } else { + return false; + } + +} + + +/** + * @param $file + * array of file data + * + * @param $nid + * integer: the NEW node id on the local instance + * + * @param $type + * string denoting type of file, possible values: + * - image + * - file + */ +function _content_retriever_save_file($file, $nid, $type, $vid = null, $field = '', $node_type = '') { + $file_data = base64_decode($file['file']); + switch ($type) { + case 'file': + //set filepath to save to + $file['filepath'] = file_directory_path().'/'.$file['filename']; + + //check if the file is already on the system, if it is no need to save it again + $result = db_query("SELECT fid FROM {files} WHERE filename = '%s' AND timestamp = %d", $file['filename'], $file['timestamp']); + $fid_int = (int)db_result($result); + + if(!$fid_int){ + //save file + //note, safe to REPLACE because we can be certain we will not have duplicates + //we wish to keep - distirbution site will be handling duplicate file names + //so we will only ever receive unique ones here + file_save_data($file_data, $file['filepath'], FILE_EXISTS_REPLACE); + + //write record in files table + drupal_write_record('files', $file); + + //fetch the new fid for later use in upload table + $result = db_query("SELECT fid FROM {files} WHERE filename = '%s'", $file['filename']); + $fid_int = (int)db_result($result); + } + + //build array for upload table insertion + $upload = array( + 'fid' => $fid_int, + 'nid' => $nid, + 'vid' => $vid, + 'description' => $file['filename'], + 'list' => 1, + 'weight' => 0, + ); + + //write record in upload table + drupal_write_record('upload', $upload); + + return true; + break; + + case 'cck': + //set filepath to save to + $file['filepath'] = file_directory_path().'/'.$file['filename']; + + //set content type db table, and field to search on. + $content_table = 'content_type_'.$node_type; + $fid_field = $field.'_fid'; + + $file_details = array(); + //get timestamp and fid if there is a file on this node + $result = db_query("SELECT f.timestamp, f.fid, f.filepath FROM {files} as f + RIGHT JOIN {%s} as ctype + ON f.fid=ctype.%s + WHERE ctype.vid = (SELECT MAX({%s}.vid) + FROM {%s}) AND ctype.nid = %d", $content_table, $fid_field, $content_table, $content_table, $nid); + + + $file_details = db_fetch_object($result); + + //check if it's the same file coming over + if($file_details->timestamp == $file['timestamp']){ + //if it is it dont write another record in the files table. + return $file_details; + }else{ + //save file + //note, safe to REPLACE because we can be certain we will not have duplicates + //we wish to keep - distribution site will be handling duplicate file names + //so we will only ever receive unique ones here + file_save_data($file_data, $file['filepath'], FILE_EXISTS_REPLACE); + + //write record in files table + drupal_write_record('files', $file); + + $result = db_query("SELECT fid,filepath FROM {files} WHERE filename = '%s'", $file['filename']); + $file_details = db_fetch_object($result); + + return $file_details; + } + break; + } + +} + +/** + * abstraction of the service calling code needed to retrieve nodes + * + * makes and xml-rpc call to the Services module of another Drupal + * installation, calling the views.get method, and returns the + * resulting array + * + * @param $endpoint + * string representing the valid URI for the web service endpoint + * + * @param $method + * string telling us what method to call, examples: + * - views.get + * - file.getNodeFiles + * - nodequeue.getQueues + * - node.get + * - image.getNodeImages + * + * @param $api_key + * string containing a valid API key for this service + * + * @param $param1 thru $param3 + * various: placeholder vars for passing parameters to the web + * service methods - can be anything valid for the method call being + * invoked - empty strings by default + * + * @return + * array containing results of the call + */ +function content_retriever_xmlrpc($endpoint, $method, $api_key, $session_id = '',$param1 = '', $param2 = '', $param3 = '') { + //check if HTTP requests are enabled and report error if not + if (variable_get('drupal_http_request_fails', FALSE) == TRUE) { + drupal_set_message(t('Drupal is unable to make HTTP requests. Please reset the HTTP request status.'), 'error', FALSE); + watchdog('integration', t('Drupal is unable to make HTTP requests. Please reset the HTTP request status.'), array(), WATCHDOG_CRITICAL); + } else { + + if($api_key != ''){ + //use api key to get a hash code for the service. + $timestamp = (string) strtotime("now"); + $domain = $_SERVER['SERVER_NAME']; + $nonce = content_retriever_get_unique_code('10'); + $hash_parameters = array( + $timestamp, + $domain, + $nonce, + $method, + ); + $hash = hash_hmac("sha256", implode(';', $hash_parameters), $api_key); + } + + switch ($method) { + case 'system.connect': + $result = xmlrpc($endpoint, $method); + break; + case 'user.login': + //check for an API key - if not supplied, presume not required + if ($api_key == '') { + $result = xmlrpc($endpoint, $method, $session_id, (string) $param1, (string) $param2); + } else { + $result = xmlrpc($endpoint, $method, $hash, $domain, $timestamp, $nonce, $session_id, (string) $param1, (string) $param2); + } + break; + case 'user.logout': + //check for an API key - if not supplied, presume not required + if ($api_key == '') { + $result = xmlrpc($endpoint, $method, $session_id); + } else { + $result = xmlrpc($endpoint, $method, $hash, $domain, $timestamp, $nonce, $session_id); + } + break; + case 'views.get': + //check for an API key - if not supplied, presume not required + if ($api_key == '') { + //$param1 is view name, $param2 is array of view arguments + //'default' is display_id parameter hardcoded to default. + $result = xmlrpc($endpoint, $method, $session_id, (string) $param1, 'default', array(), (array) $param2, 0, 0); + } else { + //var_dump($endpoint, $method, $hash, $domain, $timestamp, $nonce, $session_id, $param1, $param2); + $result = xmlrpc($endpoint, $method, $hash, $domain, $timestamp, $nonce, $session_id, (string) $param1, 'default', array(), (array) $param2, 0, 0); + } + break; + + case 'file.getNodeFiles': + //check for an API key - if not supplied, presume not required + if ($api_key == '') { + //$param1 is nid + $result = xmlrpc($endpoint, $method, $session_id, (int) $param1); + } else { + $result = xmlrpc($endpoint, $method, $hash, $domain, $timestamp, $nonce, $session_id, (int) $param1); + } + break; + + case 'file.get': + //check for an API key - if not supplied, presume not required + if ($api_key == '') { + //$param1 is fid + $result = xmlrpc($endpoint, $method, $session_id, (int) $param1); + } else { + $result = xmlrpc($endpoint, $method, $hash, $domain, $timestamp, $nonce, $session_id, (int) $param1); + } + break; + + case 'nodequeue.getQueues': + //check for an API key - if not supplied, presume not required + if ($api_key == '') { + $result = xmlrpc($endpoint, $method, $session_id); + } else { + $result = xmlrpc($endpoint, $method, $hash, $domain, $timestamp, $nonce, $session_id); + } + break; + + case 'node.get': + //check for an API key - if not supplied, presume not required + if ($api_key == '') { + //$param1 is nid, $param2 is array of cck field names + $result = xmlrpc($endpoint, $method, $session_id, (int) $param1, (array) $param2); + } else { + $result = xmlrpc($endpoint, $method, $hash, $domain, $timestamp, $nonce, $session_id, (int) $param1, (array) $param2); + } + break; + + case 'image.getNodeImages': + //check for an API key - if not supplied, presume not required + if ($api_key == '') { + //$param1 is nid + $result = xmlrpc($endpoint, $method, $session_id, (int) $param1); + } else { + $result = xmlrpc($endpoint, $method, $hash, $domain, $timestamp, $nonce, $session_id, (int) $param1); + } + break; + + case 'node.getAllTypes': + //check for an API key - if not supplied, presume not required + if ($api_key == '') { + //$param1 is nid + $result = xmlrpc($endpoint, $method, $session_id); + } else { + $result = xmlrpc($endpoint, $method, $hash, $domain, $timestamp, $nonce, $session_id); + } + break; + + default: + $result = array(); + watchdog('integration', t('Unknown method call attempted.'), array(), WATCHDOG_NOTICE); + break; + } + return $result; + } +} + + +/** + * Implementation of hook_cron(). + */ +function content_retriever_cron() { + //retrieve the time content retriever last ran + $last_run = variable_get('content_retriever_last_run', (time() - (24 * 60 * 60)) ); + //set time to now for next run to use as the last run time + variable_set('content_retriever_last_run', time()); + //run + _content_retriever_save_nodes((string) $last_run); +} + + +/** + * Function extending the available page variables + * + * This has been implemented to expose the last time the content + * retriever has ran to page.tpl. This is purely for admin purposes, + * so they can simply visit the homepage of any site retrieving content + * to easily see when the last time the retriever ran was. + */ +function content_retriever_preprocess_page(&$variables) { + $last_run = variable_get('content_retriever_last_run', (time() - (24 * 60 * 60))); + $variables['last_run_timestamp'] = $last_run; + $variables['last_run'] = format_date($last_run, 'custom', 'd/m/Y H:i'); +} + +/** + * Implementation of hook_nodeapi(). + * + * delete the record from the content_retriever table when a node + * is deleted. + */ +function content_retriever_nodeapi(&$node, $op, $teaser, $page) { + switch ($op) { + case 'delete': + // remove db row from content_retriever + db_query('DELETE FROM {content_retriever} WHERE nid = %d', $node->nid); + break; + } +} + +function content_retriever_get_unique_code($length = ''){ + $code = md5(uniqid(rand(), true)); + if ($length != "") return substr($code, 0, $length); + else return $code; +} + diff --git a/modules/distributor_service/distributor_service.inc b/modules/distributor_service/distributor_service.inc index a0cc773ce899268b9b10378bbabc258a708a42fa..88380e5dd1740294f7502296ca9037561ca04152 100644 --- a/modules/distributor_service/distributor_service.inc +++ b/modules/distributor_service/distributor_service.inc @@ -1,101 +1,101 @@ -type,0); - if($is_distributable !== 0){ - $types[$type->type] = $type->type; - } - } - return $types; -} - - -/** - * look's up the node id on the local server based on the node id which - * is being deleted on the other site and delete's the corresponding node - * - * @param $nid - * the node id to look up - */ -function distributor_service_delete_node($nid){ - global $user; - - //we need to be a superuser to do this next stuff - //this should be refactored so the webservice logs in - //using the user service - $temp_user = $user; - $user = user_load(array('uid' => 1)); - - // find the local node id. - $result = db_query("SELECT nid FROM {content_retriever} WHERE original_nid = %d", $nid); - $node_id = (int)db_result($result); - - //delete the node - if($node_id) - node_delete($node_id); - - $user = $temp_user; - return $node_id; -} - - - +type,0); + if($is_distributable !== 0){ + $types[$type->type] = $type->type; + } + } + return $types; +} + + +/** + * look's up the node id on the local server based on the node id which + * is being deleted on the other site and delete's the corresponding node + * + * @param $nid + * the node id to look up + */ +function distributor_service_delete_node($nid){ + global $user; + + //we need to be a superuser to do this next stuff + //this should be refactored so the webservice logs in + //using the user service + $temp_user = $user; + $user = user_load(array('uid' => 1)); + + // find the local node id. + $result = db_query("SELECT nid FROM {content_retriever} WHERE original_nid = %d", $nid); + $node_id = (int)db_result($result); + + //delete the node + if($node_id) + node_delete($node_id); + + $user = $temp_user; + return $node_id; +} + + + diff --git a/modules/distributor_service/distributor_service.info b/modules/distributor_service/distributor_service.info index 46e3cbb2b6d8625c5351f2c5c19ed87ceea627da..460c24bb482be6cbb712f2a08a37ecc50dbe8977 100644 --- a/modules/distributor_service/distributor_service.info +++ b/modules/distributor_service/distributor_service.info @@ -1,7 +1,7 @@ -; $Id$ -name = Distributor Service -description = Allows other modules to poll the content distribution module and retreive data via the Services module. -package = Content Distribution -version = 6.x-1.x-dev -core = 6.x +; $Id$ +name = Distributor Service +description = Allows other modules to poll the content distribution module and retreive data via the Services module. +package = Content Distribution +version = 6.x-1.x-dev +core = 6.x dependencies[] = services \ No newline at end of file diff --git a/modules/distributor_service/distributor_service.module b/modules/distributor_service/distributor_service.module index 146e7f37974fb3537f2deaa47bfb7cd235b4e5f6..2fb34537327dc01c20d03e9206ba927d967b2cfc 100644 --- a/modules/distributor_service/distributor_service.module +++ b/modules/distributor_service/distributor_service.module @@ -1,80 +1,80 @@ -'. t('Provides node distribution methods to services applications. Requires services.module.') .'

'; - case 'admin/modules#description': - return t('Provides node distribution methods to services applications. Requires services.module.'); - } -} - -/** - * Implementation of hook_perm(). - */ -function distributor_service_perm() { - return array( - 'get any node distribution data', - ); -} - -/** - * Implementation of hook_service(). - */ -function distributor_service_service() { - return array( - - // node.getType - array( - '#method' => 'node.getType', - '#callback' => 'distributor_service_get_type', - '#access callback' => 'distributor_service_get_access', - '#file' => array('file' => 'inc', 'module' => 'distributor_service'), - '#args' => array( - array( - '#name' => 'type', - '#type' => 'string', - '#description' => t('A node type.') - ), - ), - '#return' => 'boolean', - '#help' => t('Returns a boolean.') - ), - - // node.getAllTypes - array( - '#method' => 'node.getAllTypes', - '#callback' => 'distributor_service_get_all_types', - '#access callback' => 'distributor_service_get_access', - '#file' => array('file' => 'inc', 'module' => 'distributor_service'), - '#args' => array(), - '#return' => 'array', - '#help' => t('Obtain whether or not nodes are flagged as distributable pieces of content.') - ), - - // node.deleteDistributedNode - array( - '#method' => 'node.deleteDistributedNode', - '#callback' => 'distributor_service_delete_node', - '#access callback' => 'distributor_service_get_access', - '#file' => array('file' => 'inc', 'module' => 'distributor_service'), - '#args' => array( - array( - '#name' => 'nid', - '#type' => 'int', - '#description' => t('A node id.') - ), - ), - '#return' => 'boolean', - '#help' => t('Returns a boolean.')), - ); -} +'. t('Provides node distribution methods to services applications. Requires services.module.') .'

'; + case 'admin/modules#description': + return t('Provides node distribution methods to services applications. Requires services.module.'); + } +} + +/** + * Implementation of hook_perm(). + */ +function distributor_service_perm() { + return array( + 'get any node distribution data', + ); +} + +/** + * Implementation of hook_service(). + */ +function distributor_service_service() { + return array( + + // node.getType + array( + '#method' => 'node.getType', + '#callback' => 'distributor_service_get_type', + '#access callback' => 'distributor_service_get_access', + '#file' => array('file' => 'inc', 'module' => 'distributor_service'), + '#args' => array( + array( + '#name' => 'type', + '#type' => 'string', + '#description' => t('A node type.') + ), + ), + '#return' => 'boolean', + '#help' => t('Returns a boolean.') + ), + + // node.getAllTypes + array( + '#method' => 'node.getAllTypes', + '#callback' => 'distributor_service_get_all_types', + '#access callback' => 'distributor_service_get_access', + '#file' => array('file' => 'inc', 'module' => 'distributor_service'), + '#args' => array(), + '#return' => 'array', + '#help' => t('Obtain whether or not nodes are flagged as distributable pieces of content.') + ), + + // node.deleteDistributedNode + array( + '#method' => 'node.deleteDistributedNode', + '#callback' => 'distributor_service_delete_node', + '#access callback' => 'distributor_service_get_access', + '#file' => array('file' => 'inc', 'module' => 'distributor_service'), + '#args' => array( + array( + '#name' => 'nid', + '#type' => 'int', + '#description' => t('A node id.') + ), + ), + '#return' => 'boolean', + '#help' => t('Returns a boolean.')), + ); +} diff --git a/readme.txt b/readme.txt index 22243c02b3b39be8e235254c7fd3ab62d00eb5ca..70940b17b94f331933b291ce9d6fa21f65f4ac4b 100644 --- a/readme.txt +++ b/readme.txt @@ -1,101 +1,101 @@ ------------------------------------------ -content_distribution configuration notes ------------------------------------------ - -Typical Setup - - 1 central content distribution site - - 1-many remote content retriever sites - -You should choose which drupal instance is going to be your 'content serving' instance. -This should be configured with the content_distribution module installed on it (see content distribution settings below) - -You may then have 1 or more remote 'content retrieving' sites which will receive content -via web services from your 'content serving' drupal instance. All sites may sit on the same server or may be disparate -since all the data is sent and received via XMLRPC and the various services modules it does not matter. - -To configure the content_distribution module you should do the following - - ---------------------------------------------------------- -Content distribution settings - distributor site (content serving) settings ---------------------------------------------------------- - - Install content_distribution module and relevant dependencies then: - - - admin/settings/distribution - set up website URLs of your 'content retrieving' sites in the form http://www.site.com - - - admin/build/services/settings - For best results Enable Session IDs for services, Enable Use Keys for services - - - admin/build/services/keys - Set up individual API keys for each remote website that you have - - - admin/user/user - set up a webservice user with a role with access to all permissions below - - - admin/user/permissions - configure the following permissions to be accessed by your webservice user - - - distributor service module permissions - - file service module permissions - - node service module permissions - - nodequeue_service module permissions - - services module permissions - - system_service module permissions - - - admin/content/node-type/type - For each content type you want to distribute you should - tick the box to 'enable node type to be distributed' under the content distribution settings fieldset. - - - Set up Nodequeues in admin/content/nodequeue - - nodequeues allow you to filter / target content to specific sites. Each remote site can be configured to receive (or not) content from the - available nodequeues set-up on the 'content serving' site. For example site1.com might be receiving content from nodequeue 1 and nodequeue 2 whereas - site2.com might only receive content from nodequeue 2. - - You will need to add at least 1 queue. A typical example is you might want to set-up a queue for each remote site you have. - This will allow content to be targetted to each of these sites individual. You might also want to have a queue which gets received by 'all' sites (for general content for example). - ------------------------ -Good test at this stage ------------------------ - - try create a piece of distributable content on a node/add page - there should be 2 additional fieldsets on the node/add form - - Published Date and Nodequeues for you to choose from to publish content to. - --------------------- -Test view is working --------------------- - - another good test at this stage is to test your content distribution view is working correctly. since this is what your remote - site will interrogate to bring content over. - - - in admin/build/views/edit/content_distribution_queue - check view is configured correctly to display data - try previewing the view - it will accept arguments in the format - - - - NodequeueID/ContentType/Date - - Date should be in the format - YYYYMMDD - - e.g. 1/news_item/20090101 - ----------------------------------------------- -Content Retriever - remote site configurations ----------------------------------------------- - - install content_retriever module and relevant dependencies then: - - - *NOTE* the same content type must be installed on the distributing / remote site otherwise you will not be able to retrieve and save the nodes. - - - admin/build/services/settings - Enable use of sessid. - - - admin/settings/retriever - - - - service endpoint (distribution site (content serving) xmlrpc url) - usually http://sitename.com/services/xmlrpc - - Service API key for this site (as set up in distribution settings) - - service username and password (as set up in distribution settings) - - view to query on distribution site (by default this will be the view provided with the module - which has the name 'content_distribution_queue' - - reset time retriever last run - Useful if you want to set the time back to re-import a bunch of nodes - - - - admin/settings/retriever/types - - - this page should show a list of 'available' content types to retrieve from the content serving site - - if the remote site does not have one of the 'available' content types installed the module will: - - ask if you want to install any content types which have not been installed on this site - - - skipping/installing then allows you to check which content types to retrieve from distribution server - - - - admin/settings/retriever/queues - - This page shows a list of available nodequeue on the distribution site to retrieve content from. - - check which queues you want your remote site to retrieve from. - - - admin/settings/retriever/output - this just runs the content retriever and shows a visual output of the nodes it retrieved. -useful for debugging purposes. +----------------------------------------- +content_distribution configuration notes +----------------------------------------- + +Typical Setup + - 1 central content distribution site + - 1-many remote content retriever sites + +You should choose which drupal instance is going to be your 'content serving' instance. +This should be configured with the content_distribution module installed on it (see content distribution settings below) + +You may then have 1 or more remote 'content retrieving' sites which will receive content +via web services from your 'content serving' drupal instance. All sites may sit on the same server or may be disparate +since all the data is sent and received via XMLRPC and the various services modules it does not matter. + +To configure the content_distribution module you should do the following - + +--------------------------------------------------------- +Content distribution settings - distributor site (content serving) settings +--------------------------------------------------------- + - Install content_distribution module and relevant dependencies then: + + - admin/settings/distribution - set up website URLs of your 'content retrieving' sites in the form http://www.site.com + + - admin/build/services/settings - For best results Enable Session IDs for services, Enable Use Keys for services + + - admin/build/services/keys - Set up individual API keys for each remote website that you have + + - admin/user/user - set up a webservice user with a role with access to all permissions below + + - admin/user/permissions - configure the following permissions to be accessed by your webservice user + + - distributor service module permissions + - file service module permissions + - node service module permissions + - nodequeue_service module permissions + - services module permissions + - system_service module permissions + + - admin/content/node-type/type - For each content type you want to distribute you should + tick the box to 'enable node type to be distributed' under the content distribution settings fieldset. + + - Set up Nodequeues in admin/content/nodequeue + - nodequeues allow you to filter / target content to specific sites. Each remote site can be configured to receive (or not) content from the + available nodequeues set-up on the 'content serving' site. For example site1.com might be receiving content from nodequeue 1 and nodequeue 2 whereas + site2.com might only receive content from nodequeue 2. + - You will need to add at least 1 queue. A typical example is you might want to set-up a queue for each remote site you have. + This will allow content to be targetted to each of these sites individual. You might also want to have a queue which gets received by 'all' sites (for general content for example). + +----------------------- +Good test at this stage +----------------------- + - try create a piece of distributable content on a node/add page - there should be 2 additional fieldsets on the node/add form + - Published Date and Nodequeues for you to choose from to publish content to. + +-------------------- +Test view is working +-------------------- + - another good test at this stage is to test your content distribution view is working correctly. since this is what your remote + site will interrogate to bring content over. + + - in admin/build/views/edit/content_distribution_queue - check view is configured correctly to display data - try previewing the view + it will accept arguments in the format - + + - NodequeueID/ContentType/Date + - Date should be in the format - YYYYMMDD + - e.g. 1/news_item/20090101 + +---------------------------------------------- +Content Retriever - remote site configurations +---------------------------------------------- + - install content_retriever module and relevant dependencies then: + + - *NOTE* the same content type must be installed on the distributing / remote site otherwise you will not be able to retrieve and save the nodes. + + - admin/build/services/settings - Enable use of sessid. + + - admin/settings/retriever - + + - service endpoint (distribution site (content serving) xmlrpc url) - usually http://sitename.com/services/xmlrpc + - Service API key for this site (as set up in distribution settings) + - service username and password (as set up in distribution settings) + - view to query on distribution site (by default this will be the view provided with the module + which has the name 'content_distribution_queue' + - reset time retriever last run - Useful if you want to set the time back to re-import a bunch of nodes + + + - admin/settings/retriever/types - + - this page should show a list of 'available' content types to retrieve from the content serving site + - if the remote site does not have one of the 'available' content types installed the module will: + - ask if you want to install any content types which have not been installed on this site + + - skipping/installing then allows you to check which content types to retrieve from distribution server + + + - admin/settings/retriever/queues + - This page shows a list of available nodequeue on the distribution site to retrieve content from. + - check which queues you want your remote site to retrieve from. + + - admin/settings/retriever/output - this just runs the content retriever and shows a visual output of the nodes it retrieved. +useful for debugging purposes.