You are here

custom_pub.module in Custom Publishing Options 6

Same filename and directory in other branches
  1. 8 custom_pub.module
  2. 7 custom_pub.module

Adds the ability to add Custom publishing options to the node Add/Edit form.

File

custom_pub.module
View source
<?php

/**
 * @file
 * Adds the ability to add Custom publishing options to the node Add/Edit form.
 */

/**
 * Implements hook_help().
 */
function custom_pub_help($path, $arg) {
  switch ($path) {
    case 'admin/help#custom_pub':
      return '<p>' . t("Custom Publishing Options allows you to create custom publishing options for nodes. It allows you to add to the default options of Publish, Promote to Front Page, and Sticky. It also ingrates with views to allow you add as a field, sort and filter by, your custom options.") . '</p>';
    case 'admin/content/custom_pub':
      return '<p>' . t("Custom Publishing Options allows you to create custom publishing options for nodes. It allows you to add to the default options of Publish, Promote to Front Page, and Sticky. It also ingrates with views to allow you add as a field, sort and filter by, your custom options.") . '</p>';
  }
}

/**
 * Implements hook_perm().
 *
 * We use these permissions on the individual elements in the
 * node_form via the #access parameter. So in order to use the elements
 * you must add the permissions to a role.
 */
function custom_pub_perm() {
  $types = variable_get('custom_pub_types', array());
  foreach ($types as $type) {
    $perms[] = 'toggle ' . $type['type'] . ' custom options';
  }
  return $perms;
}

/**
 * Implements hook_theme().
 */
function custom_pub_theme() {
  return array(
    'custom_pub_edit_form' => array(
      'file' => 'theme.inc',
      'path' => drupal_get_path('module', 'custom_pub'),
      'arguments' => array(
        'form' => array(),
      ),
    ),
  );
}

/**
 * Implements hook_menu().
 */
function custom_pub_menu() {
  $items['admin/content/custom_pub'] = array(
    'title' => 'Publishing Options',
    'page callback' => 'custom_pub_admin',
    'access arguments' => array(
      'administer nodes',
    ),
    'description' => 'Add and remove custom publishing options from the Node form.',
  );
  return $items;
}

/**
 * Callback function for our menu item.
 */
function custom_pub_admin() {
  $table = '';

  //add the js for the admin page
  drupal_add_js(drupal_get_path('module', 'custom_pub') . '/custom_pub.admin.js');
  $types = variable_get('custom_pub_types', array());

  //get the current custom publishing types
  foreach ($types as $type) {

    // Build table rows for the
    $form_row = array();
    $types_of_nodes = '';
    if (isset($type['node_types']) && is_array($type['node_types'])) {
      $types_of_nodes = implode(', ', $type['node_types']);
    }
    $row = array(
      check_plain($type['name']),
      $type['type'],
      $types_of_nodes,
      array(
        'data' => '',
        'class' => 'custom_pub-option-edit-cell',
      ),
    );
    $form_row[] = array(
      'data' => drupal_get_form('custom_pub_edit_' . $type['type'], $type),
      'colspan' => 4,
    );
    $rows[] = array(
      'data' => $row,
      'class' => 'custom_pub-option-row',
    );
    $rows[] = array(
      'data' => $form_row,
      'class' => 'custom_pub-form-edit',
    );
  }
  if (!empty($rows)) {
    $table = theme('table', array(
      t('Label'),
      t('Machine Name'),
      t('Node Types'),
      array(
        'data' => '',
        'class' => 'custom_pub-head-edit',
      ),
    ), $rows);

    //generate the table for the current options
  }
  return $table . drupal_get_form('custom_pub_add');
}

/**
 * Implements hook_forms().
 */
function custom_pub_forms($form_id, $args) {

  //We need to use this hook because on the admin page there is the possibility of multiple forms for the edit form. See http://drupal.org/node/354519
  $types = variable_get('custom_pub_types', array());
  foreach ($types as $type) {
    if ($form_id == 'custom_pub_edit_' . $type['type']) {
      if ($form_id == 'custom_pub_edit_' . $type['type']) {
        $forms[$form_id] = array(
          'callback' => 'custom_pub_edit',
        );
        return $forms;
      }
    }
  }
}

/**
 * Form callback function for add form.
 */
function custom_pub_add(&$form_state) {
  $form['state_fs'] = array(
    '#type' => 'fieldset',
    '#title' => t('Add A Publishing Option'),
  );
  $form['state_fs']['state'] = array(
    '#title' => t('Publishing label'),
    '#type' => 'textfield',
    '#description' => t('The label for your custom publishing option. This is the text that will be displayed on the node add/edit form.'),
    '#maxlength' => 255,
    '#required' => TRUE,
  );
  $form['state_fs']['state_machine'] = array(
    '#type' => 'textfield',
    '#title' => t('Option name'),
    '#description' => t('The machine-readable name of this publishing option. This text will be used for constructing the database table column name. This name must contain only lowercase letters, numbers, and underscores. This name must be unique.'),
    '#required' => TRUE,
  );
  $form['state_fs']['node_types'] = array(
    '#type' => 'checkboxes',
    '#title' => t('Available on'),
    '#description' => t('The Node Types this option is available on.'),
    '#options' => node_get_types('names'),
  );
  $form['state_fs']['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Add'),
  );
  return $form;
}

/**
 * Form validation function for add form.
 */
function custom_pub_add_validate($form, $form_state) {
  $types = variable_get('custom_pub_types', array());
  $type = array();
  $type['type'] = trim($form_state['values']['state_machine']);
  $type['name'] = check_plain(trim($form_state['values']['state']));
  $node = drupal_get_schema('node');
  if (isset($types[$type['type']])) {
    form_set_error('state_machine', t('The machine-readable name %type is already taken.', array(
      '%type' => $type->type,
    )));
  }
  if (!preg_match('!^[a-z0-9_]+$!', $type['type'])) {
    form_set_error('state_machine', t('The machine-readable name must contain only lowercase letters, numbers, and underscores.'));
  }

  // 'theme' conflicts with theme_node_form().
  // '0' is invalid, since elsewhere we check it using empty().
  if (in_array($type['type'], array_keys($node['fields'])) && !isset($types[$type['type']])) {
    form_set_error('state_machine', t("Invalid machine-readable name. That name is already taken by a database column. Please enter a name other than %invalid.", array(
      '%invalid' => $type['type'],
    )));
  }
  foreach ($types as $check) {
    if ($type['name'] == $check['name']) {
      form_set_error('state', t("Invalid Label. That Publishing Label is already taken. Please enter a label other than %invalid.", array(
        '%invalid' => $type['name'],
      )));
    }
  }
}

/**
 * Form submit function for add form.
 */
function custom_pub_add_submit($form, $form_state) {
  $types = variable_get('custom_pub_types', array());
  $node_types = node_get_types();
  $type = array();
  $type[trim($form_state['values']['state_machine'])]['type'] = trim($form_state['values']['state_machine']);
  $type[trim($form_state['values']['state_machine'])]['name'] = check_plain(trim($form_state['values']['state']));
  foreach ($form_state['values']['node_types'] as $node_type => $value) {
    if (!empty($value)) {
      $type[trim($form_state['values']['state_machine'])]['node_types'][$node_type] = $node_types[$node_type]->name;
    }
  }
  $ret = array();
  $spec = array(
    'description' => 'Custom publishing option ' . t(check_plain(trim($form_state['values']['state']))),
    'type' => 'int',
    'not null' => TRUE,
    'default' => 0,
  );
  db_add_field($ret, 'node', trim($form_state['values']['state_machine']), $spec);
  if ($ret[0]['success']) {
    variable_set('custom_pub_types', array_merge($types, $type));
    cache_clear_all('schema', 'cache');
    drupal_set_message(t('Publishing option created.'));
  }
  else {
    drupal_set_message(t('There was an error creating your Publishing option.'), 'error');
  }
}

/**
 * Form callback function for edit form.
 */
function custom_pub_edit(&$form_state, $type) {
  $form['type'] = array(
    '#type' => 'value',
    '#value' => $type,
  );
  $form['state'] = array(
    '#title' => t('Publishing label'),
    '#type' => 'textfield',
    '#maxlength' => 255,
    '#size' => 100,
    '#default_value' => check_plain($type['name']),
  );
  $form['node_types'] = array(
    '#type' => 'checkboxes',
    '#title' => t('Available on'),
    '#description' => t('The Node Types this option is available on.'),
    '#options' => node_get_types('names'),
    '#default_value' => isset($type['node_types']) ? array_keys($type['node_types']) : array(),
  );
  $form['stateh'] = array(
    '#type' => 'hidden',
    '#value' => $type['type'],
  );
  $form['save'] = array(
    '#type' => 'submit',
    '#value' => t('Save'),
  );
  $form['delete'] = array(
    '#type' => 'submit',
    '#value' => t('Delete'),
    '#attributes' => array(
      'id' => 'edit-delete',
    ),
  );
  $form['#theme'][] = 'custom_pub_edit_form';
  $form['#validate'][] = 'custom_pub_edit_validate';
  $form['#submit'][] = 'custom_pub_edit_submit';
  return $form;
}

/**
 * Form validate function for edit form.
 */
function custom_pub_edit_validate($form, $form_state) {
  $types = variable_get('custom_pub_types', array());
  $type = $form_state['values']['type'];
  $name = trim($form_state['values']['state']);
  foreach ($types as $check) {
    if (check_plain($type['name']) == $check['name'] && $type['type'] != $check['type']) {
      form_set_error('state', t("Invalid Label. That Publishing Label is already taken. Please enter a label other than %invalid.", array(
        '%invalid' => $type['name'],
      )));
    }
  }
}

/**
 * Form submit function for edit form.
 */
function custom_pub_edit_submit($form, $form_state) {
  $node_types = node_get_types();
  $type = $form_state['values']['type'];
  $types = variable_get('custom_pub_types', array());
  if ($form_state['values']['op'] == 'Delete') {
    unset($types[$type['type']]);
    $ret = array();
    db_drop_field($ret, 'node', $type['type']);
    $success = $ret[0]['success'];
  }
  else {
    unset($types[$type['type']]['node_types']);
    foreach ($form_state['values']['node_types'] as $node_type => $value) {
      if (!empty($value)) {
        $types[$type['type']]['node_types'][$node_type] = $node_types[$node_type]->name;
      }
    }
    $type['name'] = trim($form_state['values']['state']);
    $types[$type['type']]['name'] = check_plain($type['name']);
    $success = TRUE;
  }
  if ($success) {
    variable_set('custom_pub_types', $types);
    drupal_set_message(t('!op publishing option successful.', array(
      '!op' => $form_state['values']['op'],
    )));
  }
  else {
    drupal_set_message(t('There was an error trying to !op the publishing option. Please Try Again', array(
      '!op' => $form_state['values']['op'],
    )), 'error');
  }
}

/**
 * Implements hook_form_alter().
 */
function custom_pub_form_alter(&$form, $form_state, $form_id) {
  $types = variable_get('custom_pub_types', array());

  //add the options to the node form
  if ($form['#id'] === 'node-form') {
    $node = $form['#node'];
    foreach ($types as $type) {
      if (!empty($type['node_types'][$node->type])) {
        $form['options'][$type['type']] = array(
          '#type' => 'checkbox',
          '#title' => check_plain(t($type['name'])),
          '#default_value' => $node->{$type}['type'],
          '#access' => user_access('administer nodes') ? TRUE : user_access('toggle ' . $type['type'] . ' custom options'),
        );
      }
    }
  }

  //Add options to the node_type_form for editing default node options
  if ($form_id == 'node_type_form') {
    $node_type = $form['#node_type'];
    foreach ($types as $type) {
      if (!empty($type['node_types'][$node_type->type])) {
        $form['workflow']['node_options']['#options'][$type['type']] = t($type['name']);
      }
    }
  }

  //We are altering the content list form so that we can add out custom options to the filters
  if ($form_id == 'node_admin_content') {
    $session =& $_SESSION['node_overview_filter'];
    $session = is_array($session) ? $session : array();
    $filters = node_filters();
    foreach ($types as $type) {
      $form['filters']['status']['status']['#options'][$type['type'] . '-1'] = t($type['name']);
      $form['filters']['status']['status']['#options'][$type['type'] . '-0'] = t('not ' . $type['name']);
      $form['#submit'][] = 'custom_pub_node_filter_submit';
      $filters['status']['options'][$type['type'] . '-1'] = t($type['name']);
      $filters['status']['options'][$type['type'] . '-0'] = t('not ' . $type['name']);
    }
    $form['filters']['current'] = array();
    foreach ($session as $filter) {
      list($type, $value) = $filter;
      if ($type == 'category') {

        // Load term name from DB rather than search and parse options array.
        $value = module_invoke('taxonomy', 'get_term', $value);
        $value = $value->name;
      }
      elseif ($type == 'language') {
        $value = empty($value) ? t('Language neutral') : module_invoke('locale', 'language_name', $value);
      }
      else {
        $value = $filters[$type]['options'][$value];
      }
      if ($i++) {
        $form['filters']['current'][] = array(
          '#value' => t('<em>and</em> where <strong>%a</strong> is <strong>%b</strong>', array(
            '%a' => $filters[$type]['title'],
            '%b' => $value,
          )),
        );
      }
      else {
        $form['filters']['current'][] = array(
          '#value' => t('<strong>%a</strong> is <strong>%b</strong>', array(
            '%a' => $filters[$type]['title'],
            '%b' => $value,
          )),
        );
      }
      if (in_array($type, array(
        'type',
        'language',
      ))) {

        // Remove the option if it is already being filtered on.
        unset($filters[$type]);
      }
    }
  }
}

/**
 * Form submit function for the node_admin_content form.
 */
function custom_pub_node_filter_submit($form, $form_state) {
  $types = variable_get('custom_pub_types', array());
  switch ($form_state['values']['op']) {
    case t('Filter'):
    case t('Refine'):
      if (isset($form_state['values']['filter'])) {
        $filter = $form_state['values']['filter'];
        list($type, $val) = explode('-', $form_state['values'][$filter]);
        if (isset($types[$type])) {
          $_SESSION['node_overview_filter'][] = array(
            $filter,
            $form_state['values'][$filter],
          );
        }
      }
      break;
  }
}

/**
 * Implements hook_nodeapi().
 */
function custom_pub_nodeapi(&$node, $op) {
  $types = variable_get('custom_pub_types', array());
  if ($op == 'prepare') {

    // If this is a new node, fill in the default values.
    if (!isset($node->nid)) {
      $node_options = variable_get('node_options_' . $node->type, array(
        'status',
        'promote',
      ));
      foreach ($types as $key => $value) {
        $node->{$key} = in_array($key, $node_options);
      }
    }
  }
}

/**
 * Implements hook_views_data_alter().
 */
function custom_pub_views_data_alter(&$data) {
  $types = variable_get('custom_pub_types', array());
  $node_types = node_get_types();
  foreach ($types as $type) {
    $used_in = array();
    foreach ($node_types as $node_type) {
      if (!empty($type['node_types'][$node_type->type])) {
        $used_in[] = $node_type->name;
      }
    }

    // published status
    $data['node'][$type['type']] = array(
      'title' => t($type['name']),
      'help' => t('Custom Publishing Option. Appears in: !types', array(
        '!types' => implode(', ', $used_in),
      )),
      'field' => array(
        'handler' => 'views_handler_field_boolean',
        'click sortable' => TRUE,
      ),
      'filter' => array(
        'handler' => 'views_handler_filter_boolean_operator',
        'label' => t($type['name']),
        'type' => 'yes-no',
      ),
      'sort' => array(
        'handler' => 'views_handler_sort',
      ),
    );
  }
}

/**
 * Implements hook_schema_alter().
 */
function custom_pub_schema_alter(&$schema) {
  $types = variable_get('custom_pub_types', array());
  foreach ($types as $type) {
    $schema['node']['fields'][$type['type']] = array(
      'description' => t('Custom publishing option @name', array(
        '@name' => $type['name'],
      )),
      'type' => 'int',
      'not null' => TRUE,
      'default' => 0,
    );
  }
}

/**
 * Implements hook_action_info().
 */
function custom_pub_action_info() {
  $actions["custom_pub_on_action"] = array(
    'type' => 'node',
    'description' => t('Toggle a Custom Publishing Option on'),
    'configurable' => TRUE,
    'behavior' => array(
      'changes_node_property',
    ),
    'hooks' => array(
      'nodeapi' => array(
        'presave',
      ),
      'comment' => array(
        'insert',
        'update',
      ),
    ),
  );
  $actions["custom_pub_off_action"] = array(
    'type' => 'node',
    'description' => t('Toggle a Custom Publishing Option off'),
    'configurable' => TRUE,
    'behavior' => array(
      'changes_node_property',
    ),
    'hooks' => array(
      'nodeapi' => array(
        'presave',
      ),
      'comment' => array(
        'delete',
        'insert',
        'update',
      ),
    ),
  );
  return $actions;
}

/**
 * Implements a configurable action.
 *
 * Toggles a custom publishing option on as an action.
 *
 * @param $node
 *   The node object of the current node.
 *
 * @param $context
 *   The available context of the current action.
 */
function custom_pub_on_action(&$node, &$context) {

  //This is mainly for the Rules Module. I couldn't get a node to save unless I set this manually
  $context['auto_save'] = TRUE;
  $types = variable_get('custom_pub_types', array());
  foreach ($context['types'] as $type) {
    if (!empty($type) && in_array($node->type, array_keys($types[$type]['node_types']))) {
      $node->{$type} = 1;
      watchdog('action', 'Toggled @type %title custom publishing option: @label to on.', array(
        '@type' => node_get_types('name', $node),
        '%title' => $node->title,
        '@label' => $types[$type]['name'],
      ));
    }
  }
}

/**
 * Implements a configurable action form.
 *
 * Allows the user to pick custom publishing options to turn on.
 */
function custom_pub_on_action_form($context) {
  $types = variable_get('custom_pub_types', array());

  //get the current custom publishing types
  foreach ($types as $type) {
    $pub_types[$type['type']] = $type['name'];
  }
  $form['types'] = array(
    '#title' => t('Custom Publishing Options'),
    '#description' => t('Select the Custom publishing options to toggle on when this action is triggered.'),
    '#type' => 'checkboxes',
    '#options' => $pub_types,
    '#default_value' => isset($context['types']) ? $context['types'] : array(),
  );
  return $form;
}

/**
 * Implements a configurable action form submit callback.
 */
function custom_pub_on_action_submit($form, $form_state) {
  return array(
    'types' => $form_state['values']['types'],
  );
}

/**
 * Implements a configurable action.
 *
 * Toggles a custom publishing option off as an action.
 *
 * @param $node
 *   The node object of the current node.
 *
 * @param $context
 *   The available context of the current action.
 */
function custom_pub_off_action(&$node, &$context) {

  //This is mainly for the Rules Module. I couldn't get a node to save unless I set this manually
  $context['auto_save'] = TRUE;
  $types = variable_get('custom_pub_types', array());
  foreach ($context['types'] as $type) {
    if (in_array($node->type, array_keys($types[$type]['node_types']))) {
      $node->{$type} = 0;
      watchdog('action', 'Toggled @type %title custom publishing option: @label to off.', array(
        '@type' => node_get_types('name', $node),
        '%title' => $node->title,
        '@label' => $types[$type]['name'],
      ));
    }
  }
  return array(
    'node' => $node,
  );
}

/**
 * Implements a configurable action form.
 *
 * Allows the user to pick custom publishing options to turn off.
 */
function custom_pub_off_action_form($context) {
  $types = variable_get('custom_pub_types', array());

  //get the current custom publishing types
  foreach ($types as $type) {
    $pub_types[$type['type']] = $type['name'];
  }
  $form['types'] = array(
    '#title' => t('Custom Publishing Options'),
    '#description' => t('Select the Custom publishing options to toggle off when this action is triggered.'),
    '#type' => 'checkboxes',
    '#options' => $pub_types,
    '#default_value' => isset($context['types']) ? $context['types'] : array(),
  );
  return $form;
}

/**
 * Implements a configurable action form submit callback.
 */
function custom_pub_off_action_submit($form, $form_state) {
  return array(
    'types' => $form_state['values']['types'],
  );
}

Functions

Namesort descending Description
custom_pub_action_info Implements hook_action_info().
custom_pub_add Form callback function for add form.
custom_pub_add_submit Form submit function for add form.
custom_pub_add_validate Form validation function for add form.
custom_pub_admin Callback function for our menu item.
custom_pub_edit Form callback function for edit form.
custom_pub_edit_submit Form submit function for edit form.
custom_pub_edit_validate Form validate function for edit form.
custom_pub_forms Implements hook_forms().
custom_pub_form_alter Implements hook_form_alter().
custom_pub_help Implements hook_help().
custom_pub_menu Implements hook_menu().
custom_pub_nodeapi Implements hook_nodeapi().
custom_pub_node_filter_submit Form submit function for the node_admin_content form.
custom_pub_off_action Implements a configurable action.
custom_pub_off_action_form Implements a configurable action form.
custom_pub_off_action_submit Implements a configurable action form submit callback.
custom_pub_on_action Implements a configurable action.
custom_pub_on_action_form Implements a configurable action form.
custom_pub_on_action_submit Implements a configurable action form submit callback.
custom_pub_perm Implements hook_perm().
custom_pub_schema_alter Implements hook_schema_alter().
custom_pub_theme Implements hook_theme().
custom_pub_views_data_alter Implements hook_views_data_alter().