You are here

custom_pub.module in Custom Publishing Options 7

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

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

File

custom_pub.module
View source
<?php

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

/**
 * 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_permission().
 *
 * 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_permission() {
  $permissions = array();
  $types = variable_get('custom_pub_types', array());
  foreach ($types as $type) {
    $key = 'edit_custom_pub_' . $type['type'];
    $permissions[$key] = array(
      'title' => 'Can access/use ' . t('%type', array(
        '%type' => $type['type'],
      )) . ' custom publishing option on node forms',
    );
  }
  return $permissions;
}

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

/**
 * Implements hook_menu().
 */
function custom_pub_menu() {
  $items['admin/structure/custom_pub'] = array(
    'title' => 'Custom Publishing Options',
    'page callback' => 'custom_pub_admin',
    'access arguments' => array(
      'administer content types',
    ),
    'description' => 'Add and remove custom publishing options from the Node form(s).',
    'file' => 'custom_pub.admin.inc',
  );
  $items['admin/structure/custom_pub/list'] = array(
    'title' => 'Overview',
    'type' => MENU_DEFAULT_LOCAL_TASK,
    'weight' => -10,
  );
  $items['admin/structure/custom_pub/add'] = array(
    'title' => 'Add a publishing option',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'custom_pub_add',
    ),
    'access arguments' => array(
      'administer content types',
    ),
    'description' => 'Add and remove custom publishing options from the Node form(s).',
    'file' => 'custom_pub.admin.inc',
    'type' => MENU_LOCAL_TASK,
    'context' => MENU_CONTEXT_PAGE | MENU_CONTEXT_INLINE,
  );
  return $items;
}

/**
 * Implements hook_menu_alter().
 */
function custom_pub_menu_alter(&$items) {
  $items['admin/content']['module'] = 'custom_pub';
  $items['admin/content']['file'] = 'custom_pub.admin.inc';
}

/**
 * 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']) {
      $forms[$form_id] = array(
        'callback' => 'custom_pub_edit',
      );
      return $forms;
    }
  }
  if ($form_id == 'node_admin_content') {
    module_load_include('inc', 'node', 'node.admin');
    $forms['node_admin_content'] = array(
      'callback' => 'custom_pub_node_admin_content',
    );
    return $forms;
  }
}

/**
 * Implements hook_form_alter().
 * @param $form
 * @param $form_state
 * @param $form_id
 */
function custom_pub_form_alter(&$form, $form_state, $form_id) {
  if (isset($form['#node_edit_form']) && $form['#node_edit_form'] === TRUE) {
    $node = $form['#node'];
    $types = custom_pub_by_node_type($node);
    foreach ($types as $type) {
      $default_value = isset($node->{$type['type']}) ? $node->{$type['type']} : NULL;
      $form['options'][$type['type']] = array(
        '#type' => 'checkbox',
        '#title' => check_plain(t($type['name'])),
        '#default_value' => $default_value,
        '#access' => user_access('administer content types') ? TRUE : user_access('edit_custom_pub_' . $type['type']),
      );
    }

    // set access states on core publishing options so we don't create a security issue
    $core = array(
      'status',
      'promote',
      'sticky',
    );
    foreach ($core as $core_option) {
      if (!isset($form['options'][$core_option]['#access'])) {
        $form['options'][$core_option]['#access'] = user_access('administer nodes') ? TRUE : FALSE;
      }
    }
    foreach ($form['options'] as $option) {
      if (isset($option['#access']) && $option['#access'] === TRUE) {
        $form['options']['#access'] = TRUE;
        break;
      }
    }
  }

  // Add options to the node_type_form for editing default node options
  if ($form_id == 'node_type_form') {
    $node_type = $form['#node_type'];
    $types = custom_pub_by_node_type($node_type);
    foreach ($types as $type) {
      $form['workflow']['node_options']['#options'][$type['type']] = check_plain(t($type['name']));
    }
  }
  if ($form_id == 'node_admin_content') {
    if (isset($form_state['values']['operation']) && $form_state['values']['operation'] == 'delete') {
      array_unshift($form['#submit'], 'custom_pub_node_admin_inc_add');
    }
  }
}

/**
 * Implements hook_views_data_alter().
 */
function custom_pub_views_data_alter(&$data) {
  $types = variable_get('custom_pub_types', array());
  $node_types = node_type_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(
    'label' => 'Toggle a Custom Publishing Option on',
    '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(
    'label' => 'Toggle a Custom Publishing Option off',
    '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;
      node_save($node);
      watchdog('action', 'Toggled @type %title custom publishing option: @label to on.', array(
        '@type' => node_type_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.
 *
 * @param $context
 * @return array
 */
function custom_pub_on_action_form($context) {
  $pub_types = custom_pub_types_list();
  $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;
}

/**
 * Submit callback for custom_pub_on_action_form().
 *
 * @param $form
 * @param $form_state
 * @return array
 */
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.
 *
 * @return array
 */
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;
      node_save($node);
      watchdog('action', 'Toggled @type %title custom publishing option: @label to off.', array(
        '@type' => node_type_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.
 *
 * @param $context
 * @return array
 */
function custom_pub_off_action_form($context) {
  $pub_types = custom_pub_types_list();
  $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;
}

/**
 * Submit callback for custom_pub_off_action_form().
 *
 * @param $form
 * @param $form_state
 * @return array
 */
function custom_pub_off_action_submit($form, &$form_state) {
  return array(
    'types' => $form_state['values']['types'],
  );
}

/**
 * Implements hook_query_TAG_alter().
 */
function custom_pub_query_node_load_multiple_alter(QueryAlterableInterface $query) {
  $types = variable_get('custom_pub_types', array());
  if (count($types)) {
    foreach ($types as $field => $type) {
      if (db_field_exists('node', $field)) {
        $query
          ->addField('base', $field);
      }
    }
  }
}

/**
 * Implements hook_node_prepare().
 */
function custom_pub_node_prepare($node) {
  $types = custom_pub_by_node_type($node);

  // 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 (array_keys($types) as $key) {
      if (!isset($node->{$key})) {
        $node->{$key} = in_array($key, $node_options);
      }
    }
  }
}

/**
 * Implements hook_entity_property_info().
 */
function custom_pub_entity_property_info() {
  $info = array();
  $types = variable_get('custom_pub_types', array());
  if (!empty($types)) {
    $properties =& $info['node']['properties'];
    foreach ($types as $type) {
      if (isset($type['node_types']) && is_array($type['node_types'])) {
        $description = t('Custom Publishing Option. Appears in: !types', array(
          '!types' => implode(', ', $type['node_types']),
        ));
      }
      else {
        $description = t('Custom Publishing Option. Not currently used.');
      }
      $properties[$type['type']] = array(
        'label' => t($type['name']),
        'type' => 'boolean',
        'setter callback' => 'entity_property_verbatim_set',
        'description' => $description,
      );
    }
  }
  return $info;
}

/**
 * Implements hook_entity_presave().
 *
 * hook_node_prepare() is not called when a node is created by entity_create()
 * so use this hook to prepare nodes.
 *
 * @param $entity
 * @param $type
 */
function custom_pub_entity_presave($entity, $type) {
  if ($type == 'node') {
    custom_pub_node_prepare($entity);
  }
}

/**
 * Returns only the custom types available for the given node type.
 *
 * @param $node_type
 *   Can be either a string of the node type or an object/array with a key of 'type'.
 *
 * @return array
 */
function custom_pub_by_node_type($node_type) {
  $return_types = array();
  if (is_object($node_type) || is_array($node_type)) {
    (object) $node_type;
    $node_type = $node_type->type;
  }
  $types = variable_get('custom_pub_types', array());
  foreach ($types as $key => $type) {
    if (!empty($type['node_types'][$node_type])) {
      $return_types[$key] = $type;
    }
  }
  return $return_types;
}

/**
 * Return all custom publish options defined in the system.
 *
 * This is different than custom_pub_types(), as we return an array of machine
 * name keyed to the name of the option.
 *
 * @return array
 */
function custom_pub_types_list() {
  $pub_types = array();
  $types = variable_get('custom_pub_types', array());
  foreach ($types as $type) {
    $pub_types[$type['type']] = $type['name'];
  }
  return $pub_types;
}

/**
 * Implements hook_node_operations().
 *
 * @return array
 */
function custom_pub_node_operations() {
  $types = custom_pub_types_list();
  $operations = array();
  foreach ($types as $machine_name => $name) {
    $operations[$machine_name] = array(
      'label' => t('Add "!name" status', array(
        '!name' => $name,
      )),
      'callback' => 'node_mass_update',
      'callback arguments' => array(
        'updates' => array(
          $machine_name => 1,
        ),
      ),
    );
    $operations['remove_' . $machine_name] = array(
      'label' => t('Remove "!type" status', array(
        '!type' => $name,
      )),
      'callback' => 'node_mass_update',
      'callback arguments' => array(
        'updates' => array(
          $machine_name => 0,
        ),
      ),
    );
  }
  return $operations;
}

/**
 * Implements hook_features_api().
 *
 * @return array
 */
function custom_pub_features_api() {
  return array(
    'custom_pub' => array(
      'name' => t('Custom Publishing Options'),
      'feature_source' => TRUE,
      'default_hook' => 'custom_pub_defaults',
      'file' => drupal_get_path('module', 'custom_pub') . '/custom_pub.features.inc',
    ),
  );
}

/**
 * Returns custom publish types defined in the system.
 *
 * @param bool $rebuild
 * @return array
 */
function custom_pub_types($rebuild = FALSE) {
  $pub_types = variable_get('custom_pub_types', array());
  if ($rebuild) {
    foreach (module_implements('custom_pub_defaults') as $module) {
      $options_array = module_invoke($module, 'custom_pub_defaults');
      foreach ($options_array as $type => $option) {
        if (!isset($pub_types[$type])) {
          $pub_types[$type] = $option;
          if (!db_field_exists('node', $type)) {
            $spec = array(
              'description' => 'Custom publishing option ' . $option['name'],
              'type' => 'int',
              'not null' => TRUE,
              'default' => 0,
            );
            db_add_field('node', $type, $spec);
          }
        }
        $pub_types[$type]['default'] = TRUE;
      }
    }
    variable_set('custom_pub_types', $pub_types);
  }
  return $pub_types;
}

/**
 * Rebuilds list of custom publish options.
 *
 * Typically used during Features enabling/reverting/disabling.
 */
function custom_pub_types_rebuild() {
  custom_pub_types(TRUE);
}

/**
 * Implements hook_i18n_sync_options_alter().
 * @param $fields
 * @param $type
 */
function custom_pub_i18n_sync_options_alter(&$fields, $type) {

  // We are handling only nodes.
  if ($type != 'node') {
    return;
  }
  $pub_types = custom_pub_types();
  foreach ($pub_types as $machine_name => $pub_type) {
    $fields[$machine_name] = array(
      'title' => t($pub_type['name']),
    );
  }
}

/**
 * Implements hook_preprocess_node().
 * Add the custom publishing option state as a class if it is enabled, similar to core node publish states.
 * @param $variables
 */
function custom_pub_preprocess_node(&$variables) {
  $types = custom_pub_by_node_type($variables['type']);
  if (count($types)) {
    $ids = array_keys($types);
    $node = $variables['node'];
    foreach ($ids as $machine_name) {
      if (isset($node->{$machine_name}) && $node->{$machine_name}) {
        $variables['classes_array'][] = 'node-' . $machine_name;
      }
    }
  }
}

Functions

Namesort descending Description
custom_pub_action_info Implements hook_action_info().
custom_pub_by_node_type Returns only the custom types available for the given node type.
custom_pub_entity_presave Implements hook_entity_presave().
custom_pub_entity_property_info Implements hook_entity_property_info().
custom_pub_features_api Implements hook_features_api().
custom_pub_forms Implements hook_forms().
custom_pub_form_alter Implements hook_form_alter().
custom_pub_help Implements hook_help().
custom_pub_i18n_sync_options_alter Implements hook_i18n_sync_options_alter().
custom_pub_menu Implements hook_menu().
custom_pub_menu_alter Implements hook_menu_alter().
custom_pub_node_operations Implements hook_node_operations().
custom_pub_node_prepare Implements hook_node_prepare().
custom_pub_off_action Implements a configurable action.
custom_pub_off_action_form Implements a configurable action form.
custom_pub_off_action_submit Submit callback for custom_pub_off_action_form().
custom_pub_on_action Implements a configurable action.
custom_pub_on_action_form Implements a configurable action form.
custom_pub_on_action_submit Submit callback for custom_pub_on_action_form().
custom_pub_permission Implements hook_permission().
custom_pub_preprocess_node Implements hook_preprocess_node(). Add the custom publishing option state as a class if it is enabled, similar to core node publish states.
custom_pub_query_node_load_multiple_alter Implements hook_query_TAG_alter().
custom_pub_schema_alter Implements hook_schema_alter().
custom_pub_theme Implements hook_theme().
custom_pub_types Returns custom publish types defined in the system.
custom_pub_types_list Return all custom publish options defined in the system.
custom_pub_types_rebuild Rebuilds list of custom publish options.
custom_pub_views_data_alter Implements hook_views_data_alter().