You are here

gathercontent.module in GatherContent 7

Imports pages from GatherContent (http://gathercontent.com/) into Drupal as nodes.

@TODO code efficiency can probably be improved quite a bit (for example, batch operation for node creation, OOP vs procedural, ...).

@TODO form elements in tableselect form: is this possible/usable at all? Ie. is there a way to use the form data?

@TODO Move GatherContent API functions to its own file (for example, gathercontent_api.inc).

@TODO etc etc etc ... See issue queue. Patches welcome!

File

gathercontent.module
View source
<?php

/**
 * @file
 * Imports pages from GatherContent (http://gathercontent.com/) into Drupal as 
 * nodes.
 *
 * @TODO code efficiency can probably be improved quite a bit 
 * (for example, batch operation for node creation, OOP vs procedural, ...).
 * 
 * @TODO form elements in tableselect form: is this possible/usable at all? 
 * Ie. is there a way to use the form data?
 * 
 * @TODO Move GatherContent API functions to its own file (for example, 
 * gathercontent_api.inc).
 * 
 * @TODO etc etc etc ... See issue queue. Patches welcome!
 */

/**
 * Implements hook_help().
 */
function gathercontent_help($path, $arg) {

  // @TODO help.
}

/**
 * Implements hook_menu().
 */
function gathercontent_menu() {
  $items = array(
    'admin/config/content/gathercontent' => array(
      'title' => 'GatherContent',
      'description' => 'Import pages from GatherContent.',
      'page callback' => 'system_admin_menu_block_page',
      'access arguments' => array(
        'administer gathercontent',
      ),
      'file' => 'system.admin.inc',
      'file path' => drupal_get_path('module', 'system'),
    ),
    'admin/config/content/gathercontent/settings' => array(
      'title' => 'Settings',
      'description' => 'Administer GatherContent settings.',
      'page callback' => 'drupal_get_form',
      'page arguments' => array(
        'gathercontent_api_admin',
      ),
      'access arguments' => array(
        'administer gathercontent',
      ),
      'file' => 'gathercontent_admin.inc',
      'type' => MENU_NORMAL_ITEM,
    ),
    'admin/config/content/gathercontent/%gathercontent_ctools_js/import' => array(
      'title' => 'Import pages',
      'description' => 'Use the wizard to import pages from GatherContent.',
      'page callback' => 'gathercontent_import',
      'page arguments' => array(
        4,
      ),
      'access callback' => TRUE,
      'access arguments' => array(
        'administer gathercontent',
      ),
      'type' => MENU_NORMAL_ITEM,
    ),
  );
  return $items;
}

/**
 * Fixes weird menu_translate error.
 */
function gathercontent_ctools_js_to_arg() {
  return 'nojs';
}

/**
 * Implements hook_permission().
 */
function gathercontent_permission() {
  return array(
    'administer gathercontent' => array(
      'title' => t('Administer GatherContent'),
      'description' => t('Change settings and import pages from GatherContent'),
      'restrict access' => TRUE,
    ),
  );
}

/**
 * Import wizard, built with CTools multistep form wizard.
 */
function gathercontent_import($js = NULL, $step = NULL) {
  if ($js) {
    ctools_include('modal');
    ctools_include('ajax');
  }

  // Define array for ctools multistep wizard.
  $form_info = array(
    'id' => 'gathercontent-import-form',
    'path' => "admin/config/content/gathercontent/" . ($js ? 'ajax' : 'nojs') . "/import/%step",
    'show trail' => FALSE,
    'show back' => TRUE,
    'show cancel' => FALSE,
    'show return' => FALSE,
    'finish text' => 'Import pages',
    'next callback' => 'gathercontent_import_next',
    'finish callback' => 'gathercontent_import_finish',
    'cancel callback' => 'gathercontent_import_cancel',
    // Define forms order.
    'order' => array(
      'content_type' => t('Select content type'),
      'pages' => t('Import pages'),
    ),
    // Define forms.
    'forms' => array(
      'content_type' => array(
        'form id' => 'gathercontent_import_content_type',
      ),
      'pages' => array(
        'form id' => 'gathercontent_import_pages',
      ),
    ),
  );
  $object_id = 'gathercontent_import';
  if (empty($step)) {

    // Reset the form when $step is NULL.
    gathercontent_import_cache_clear($object_id);
    $step = 'content_type';
  }

  // This automatically gets defaults if nothing was saved.
  $object = gathercontent_import_cache_get($object_id);

  // Live $form_state changes.
  $form_state = array(
    'ajax' => $js,
    'object_id' => $object_id,
    'object' => &$object,
  );

  // Send this all off to our form. This is like drupal_get_form only wizardy.
  ctools_include('wizard');
  $form = ctools_wizard_multistep_form($form_info, $step, $form_state);
  $output = drupal_render($form);
  return $output;
}

/**
 * Clears CTools' multistep form cache.
 */
function gathercontent_import_cache_clear($name) {
  ctools_include('object-cache');
  ctools_object_cache_clear('gathercontent_import', $name);
}

/**
 * Stores CTools' multistep form cache so we can retain data from form to form.
 *
 * @param string $name
 *   cache id.
 *
 * @param object $object
 *   object with form values.
 */
function gathercontent_import_cache_set($name, $object) {
  ctools_include('object-cache');
  ctools_object_cache_set('gathercontent_import', $name, $object);
}

/**
 * Gets the current object from the cache, or default.
 *
 * @param string $name
 *   cache id.
 *
 * @return object
 *   cache with stored stuff.
 */
function gathercontent_import_cache_get($name) {
  ctools_include('object-cache');
  return ctools_object_cache_get('gathercontent_import', $name);
}

/**
 * Handles the 'next' click on the add/edit pane form wizard.
 *
 * All we need to do is store the updated pane in the cache.
 */
function gathercontent_import_next(&$form_state) {
  $form_state['object'] = $form_state['values'];
  gathercontent_import_cache_set($form_state['object_id'], $form_state['object']);
}

/**
 * Handles the 'finish' click on teh add/edit pane form wizard.
 *
 * All we need to do is set a flag so the return can handle adding
 * the pane.
 */
function gathercontent_import_finish(&$form_state) {
  $form_state['complete'] = TRUE;
}

/**
 * Handles the 'cancel' click on the add/edit pane form wizard.
 */
function gathercontent_import_cancel(&$form_state) {
  $form_state['cancel'] = TRUE;
}

/**
 * Import wizard step 1: Select content type.
 */
function gathercontent_import_content_type($form, &$form_state) {
  $account_name = variable_get('gathercontent_account_name');
  $api_key = variable_get('gathercontent_api_key');
  $project_id = variable_get('gathercontent_project_id');

  // Build an array of available GatherContent projects, if any.
  $projects = gathercontent_get_command('get_projects');
  $projects_list = gathercontent_projects_list($projects);
  if (empty($account_name) || empty($api_key)) {
    drupal_set_message(t('Please <a href="/admin/config/content/gathercontent/settings">enter your GatherContent account name and API key</a> before continuing.'), 'warning', FALSE);
  }
  if (!empty($account_name) && !empty($api_key)) {
    if (isset($projects->success) && $projects->success == TRUE) {
      if (empty($project_id) || !array_key_exists($project_id, $projects_list)) {
        drupal_set_message(t('Please <a href="/admin/config/content/gathercontent/settings">select one of your available GatherContent projects</a> before continuing.'), 'warning', FALSE);
      }
    }
    elseif (isset($projects->is_error) && $projects->is_error == TRUE) {
      drupal_set_message(t('It looks like you didn\'t configure any GatherContent projects yet. <a href="@gc_link">Please do so first</a>, then <a href="/admin/config/content/gathercontent/settings">select it here</a> before continuing with your import.', array(
        '@gc_link' => 'https://' . $account_name . '.gathercontent.com/',
      )), 'warning', FALSE);
    }
  }
  $content_types = array();
  $available_content_types = node_type_get_types();
  foreach ($available_content_types as $type => $info) {
    $content_types[$type] = $info->name;
  }
  asort($content_types);
  $content_type = variable_get('gathercontent_content_type');
  $form['gathercontent_content_type'] = array(
    '#title' => t("Select content type."),
    '#description' => t("Select the content type of which you want to create nodes. By default, your GatherContent page content will be imported into the new node's body field, so make sure your content type has a body field. You can override this default behaviour by implementing hook_gathercontent_presave()."),
    '#type' => 'select',
    '#default_value' => $content_type == '' ? 'all' : $content_type,
    '#options' => $content_types,
    '#required' => TRUE,
  );
  return $form;
}

/**
 * Form submit handler.
 */
function gathercontent_import_content_type_submit($form, &$form_state) {
  variable_set('gathercontent_content_type', $form_state['values']['gathercontent_content_type']);
}

/**
 * Import wizard step 3: Import pages.
 */
function gathercontent_import_pages($form, &$form_state) {
  $project_id = variable_get('gathercontent_project_id');
  $pages = GatherContentPages::getPages($project_id);

  // Build table header.
  $header = array(
    'title' => t('Page title'),
  );
  $options = array();
  $rows = GatherContentPages::pageImportForm($pages, $options);
  $form['#prefix'] = '<p>' . t("Select the page(s) you want to import. Then, click the 'Import pages' button at the bottom of this page.") . '</p>';
  $form['pages_list'] = array(
    '#type' => 'tableselect',
    '#header' => $header,
    '#options' => $rows,
    '#empty' => t('No pages found.'),
  );
  return $form;
}

/**
 * Form submit handler.
 */
function gathercontent_import_pages_submit($form, &$form_state) {
  $content_type = $form_state['object']['gathercontent_content_type'];

  // Get rid of unchecked rows.
  $page_ids = array_filter($form_state['values']['pages_list']);
  GatherContentPages::createNodes($page_ids, $content_type);
}

/**
 * Connecting to the GatherContent API. Data retrieved as JSON.
 */
function gathercontent_get_command($command = '', $postfields = array(), $account_name = '', $api_key = '') {
  if ($account_name == '') {
    $account_name = variable_get('gathercontent_account_name');
  }
  if ($api_key == '') {
    $api_key = variable_get('gathercontent_api_key');
  }
  $api_url = 'https://' . $account_name . '.gathercontent.com/api/0.2/' . $command;
  $postfields = http_build_query($postfields);

  // Using cURL, since GatherContent's API requires Digest authentication,
  // and drupal_http_request() doesn't support that
  // (see https://drupal.org/node/289820).
  $session = curl_init();
  curl_setopt($session, CURLOPT_URL, $api_url);
  curl_setopt($session, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
  curl_setopt($session, CURLOPT_HEADER, FALSE);
  curl_setopt($session, CURLOPT_HTTPHEADER, array(
    'Accept: application/json',
    'Content-Type: application/x-www-form-urlencoded',
  ));
  curl_setopt($session, CURLOPT_RETURNTRANSFER, TRUE);
  curl_setopt($session, CURLOPT_USERPWD, $api_key . ":x");
  curl_setopt($session, CURLOPT_POST, TRUE);
  curl_setopt($session, CURLOPT_POSTFIELDS, $postfields);
  curl_setopt($session, CURLOPT_SSL_VERIFYPEER, TRUE);
  $response = curl_exec($session);
  $httpcode = curl_getinfo($session, CURLINFO_HTTP_CODE);
  curl_close($session);
  try {
    $resp = json_decode($response);
    if (isset($resp->success) && $resp->success === TRUE) {
      return $resp;
    }
    elseif (isset($resp->error)) {
      if ($resp->error == 'You have to log in.') {
        $error = 'login_error';
      }
      return gathercontent_error_return($resp->error);
    }
    else {
      return gathercontent_error_return('login_error');
    }
  } catch (Exception $e) {
    return gathercontent_error_return('There was a problem contacting the API. Please check your server allows it.');
  }
  return FALSE;
}

/**
 * GatherContent API error handling.
 */
function gathercontent_error_return($msg) {
  $cls = new stdClass();
  $cls->is_error = TRUE;
  if ($msg == 'login_error') {
    $cls->error = t('There was a problem contacting the API. Please check your API credentials.');
  }
  else {
    $cls->error = $msg;
  }
  return $cls;
}

/**
 * Build an array of available GatherContent projects.
 */
function gathercontent_projects_list($projects) {
  $projects_list = array();
  if (is_object($projects) && isset($projects->projects) && is_array($projects->projects)) {
    foreach ($projects->projects as $project) {
      $projects_list[$project->id] = $project->name;
    }
    asort($projects_list);
  }
  return $projects_list;
}

Functions

Namesort descending Description
gathercontent_ctools_js_to_arg Fixes weird menu_translate error.
gathercontent_error_return GatherContent API error handling.
gathercontent_get_command Connecting to the GatherContent API. Data retrieved as JSON.
gathercontent_help Implements hook_help().
gathercontent_import Import wizard, built with CTools multistep form wizard.
gathercontent_import_cache_clear Clears CTools' multistep form cache.
gathercontent_import_cache_get Gets the current object from the cache, or default.
gathercontent_import_cache_set Stores CTools' multistep form cache so we can retain data from form to form.
gathercontent_import_cancel Handles the 'cancel' click on the add/edit pane form wizard.
gathercontent_import_content_type Import wizard step 1: Select content type.
gathercontent_import_content_type_submit Form submit handler.
gathercontent_import_finish Handles the 'finish' click on teh add/edit pane form wizard.
gathercontent_import_next Handles the 'next' click on the add/edit pane form wizard.
gathercontent_import_pages Import wizard step 3: Import pages.
gathercontent_import_pages_submit Form submit handler.
gathercontent_menu Implements hook_menu().
gathercontent_permission Implements hook_permission().
gathercontent_projects_list Build an array of available GatherContent projects.