You are here

commerce_node_checkout.module in Commerce Node Checkout 7

Provides core hooks and the like for the module

File

commerce_node_checkout.module
View source
<?php

/**
 * @file
 *   Provides core hooks and the like for the module
 */

/**
 * Implements hook_help().
 */
function commerce_node_checkout_help($path, $arg) {
  switch ($path) {
    case 'admin/help#commerce_node_checkout':
      return t('Enables users to pay to publish content');
  }
}

/**
 * Implements hook_permission().
 */
function commerce_node_checkout_permission() {
  return array(
    'administer commerce node checkout' => array(
      'title' => t('Administer Commerce Node'),
      'description' => t('Perform administration tasks for Commerce Node Checkout.'),
    ),
  );
}

/**
 * Implements hook_field_extra_fields().
 */
function commerce_node_checkout_field_extra_fields() {
  $info = array();

  // Iterate all node types
  foreach (node_type_get_types() as $node_type) {

    // See if this node type has products
    if (commerce_node_checkout_get_node_type_enabled_products($node_type->type)) {

      // Add the form field to select the product
      $info['node'][$node_type->type]['form']['commerce_node_checkout'] = array(
        'label' => t('Commerce node checkout'),
        'description' => t('Product selection'),
        'weight' => 5,
      );
    }
  }
  return $info;
}

/**
 * Implements hook_field_attach_form().
 */
function commerce_node_checkout_field_attach_form($entity_type, $entity, &$form, &$form_state, $langcode) {
  list($id, , $bundle) = entity_extract_ids($entity_type, $entity);

  // Only proceed for new nodes
  if (!$id && $entity_type == 'node') {

    // Make sure there are products available for this node type
    if ($enabled_products = commerce_node_checkout_get_node_type_enabled_products($bundle)) {

      // Add the product selection
      $form['commerce_node_checkout'] = array(
        '#type' => 'commerce_node_checkout',
        '#node_type' => $bundle,
        // Give admins the option to skip checkout
        'commerce_node_checkout_skip' => array(
          '#type' => 'checkbox',
          '#title' => t('Don\'t add to the shopping cart'),
          '#description' => t('If checked, this node will be created without adding it to the shopping cart. This option is only available for administrators.'),
          '#default_value' => 0,
          '#access' => user_access('administer commerce node checkout'),
          '#weight' => 10,
        ),
      );

      // Include a submit handler
      $form['actions']['submit']['#submit'][] = 'commerce_node_checkout_node_form_submit';
    }
  }
}

/**
 * Implements hook_element_info().
 */
function commerce_node_checkout_element_info() {
  $types = array();
  $types['commerce_node_checkout'] = array(
    '#process' => array(
      'commerce_node_checkout_process_element',
    ),
  );
  return $types;
}

/**
 * Implements hook_form_FORM_ID_alter().
 */
function commerce_node_checkout_form_node_type_form_alter(&$form, $form_state) {
  $product_list = commerce_node_checkout_get_product_list();
  $form['commerce_node_checkout'] = array(
    '#type' => 'fieldset',
    '#title' => t('Commerce Node Checkout'),
    '#collapsible' => TRUE,
    '#collapsed' => TRUE,
    '#access' => !empty($product_list),
    '#group' => 'additional_settings',
  );
  $form['commerce_node_checkout']['commerce_node_checkout_products'] = array(
    '#type' => 'checkboxes',
    '#title' => t('Applicable products'),
    '#default_value' => commerce_node_checkout_get_node_type_enabled_products($form['#node_type']->type),
    '#options' => $product_list,
    '#description' => t('Purchasing this product will enable the user to publish their node.'),
  );
}

/**
 * Implements hook_commerce_line_item_type_info().
 */
function commerce_node_checkout_commerce_line_item_type_info() {
  $line_item_types = array();
  $line_item_types['commerce_node_checkout'] = array(
    'name' => t('Commerce Node Checkout'),
    'description' => t('Example Line Item type of line item'),
    'product' => TRUE,
    'add_form_submit_value' => t('Place listing'),
    'base' => 'commerce_product_line_item',
    'callbacks' => array(
      'title' => 'commerce_node_checkout_line_item_title_callback',
    ),
  );
  return $line_item_types;
}

/**
 * Element process callback to build the product selection form widget
 * for a node.
 */
function commerce_node_checkout_process_element($element) {

  // Get the available products for this node
  $products = commerce_node_checkout_get_node_type_product_list($element['#node_type']);

  // Add a selection for the product
  $element['commerce_node_checkout_product'] = array(
    '#type' => count($products) > 1 ? 'select' : 'radios',
    '#title' => t('Listing option'),
    '#options' => $products,
    '#description' => t('Select your desired listing option.'),
    '#default_value' => key($products),
    '#required' => TRUE,
    '#access' => !empty($products),
  );
  return $element;
}

/**
 * Fetch the enabled products for a given node.
 *
 * @param $type
 *   Node type machine name.
 * @return
 *   An array of product IDs that are enabled for the given node type.
 */
function commerce_node_checkout_get_node_type_enabled_products($type) {
  return variable_get('commerce_node_checkout_products_' . $type, array());
}

/**
 * Fetch the a list of available products for all node types.
 *
 * @param $available_products
 *   An optional array of product IDs to filter the list by.
 * @return array
 *   Array of product names keyed by product ID.
 */
function commerce_node_checkout_get_product_list($available_products = array()) {
  $options = array();

  // Set the options for the search
  $field = array(
    'field_name' => 'commerce_node_checkout_products',
  );
  $instance = array(
    'settings' => array(
      'referenceable_types' => array(
        'commerce_node_checkout',
      ),
    ),
  );

  // Execute the search
  $products = commerce_product_match_products($field, $instance, '', 'contains', $available_products);

  // Loop through all product matches.
  foreach ($products as $pid => $data) {

    // Add them to the options list.
    $options[$pid] = check_plain($data['title']);
  }
  return $options;
}

/**
 * Provide a formatted list of products enabled for a specific node type
 * that can be used to present to a user.
 *
 * @param $type
 *   The node type.
 * @return
 *   An array of products keyed by product ID with a value of the product
 *   name with the price appended.
 */
function commerce_node_checkout_get_node_type_product_list($type) {
  $products = array();

  // See if this node type has enabled products
  if ($enabled = commerce_node_checkout_get_node_type_enabled_products($type)) {

    // Load and iterate the enabled products
    foreach (commerce_product_load_multiple($enabled) as $pid => $product) {

      // Create a wrapper
      $wrapper = entity_metadata_wrapper('commerce_product', $product);

      // Extract the price
      $price_data = $wrapper->commerce_price
        ->value();
      $price = commerce_currency_format($price_data['amount'], $price_data['currency_code'], $product);

      // Format the title along with the price
      $products[$pid] = $wrapper->title
        ->value() . ($price ? ' - ' . $price : '');
    }
  }
  return $products;
}

/**
 * Form submission handler that executes only when a new node that contains
 * the product selection widget is saved.
 *
 * This is used to potentially add the node to the user's cart.
 */
function commerce_node_checkout_node_form_submit($form, &$form_state) {

  // Only add to the cart if the admin didn't choose to skip this step
  if (!$form_state['values']['commerce_node_checkout_skip']) {

    // Make sure we can load the product that was selected
    if ($product = commerce_product_load($form_state['values']['commerce_node_checkout_product'])) {

      // Add the node product to the user's cart
      commerce_node_checkout_add_node($form_state['node'], $product);
    }

    // Redirect to the user's cart
    $form_state['redirect'] = 'cart';
  }
}

/**
 * Adds a node to a line item in the user's cart
 *
 * @param $node
 *   The node object to be associated with the line item.
 * @param $product
 *   The product chosen by the user.
 * @return
 *   The line item object that was created when the node was added to
 *   the cart, or FALSE, if an error occurred.
 */
function commerce_node_checkout_add_node($node, $product) {
  global $user;

  // Create our new line item.
  if ($line_item = commerce_product_line_item_new($product, 1, 0, array(), 'commerce_node_checkout')) {

    // Set the reference field value.
    $line_item->commerce_node_checkout_node[LANGUAGE_NONE][0]['target_id'] = $node->nid;

    // Let other modules alter the line item before it's added to the cart.
    drupal_alter('commerce_node_checkout_line_item', $line_item, $product, $node);

    // Add to cart.
    if ($line_item = commerce_cart_product_add($user->uid, $line_item, FALSE)) {
      return $line_item;
    }
  }
  return FALSE;
}

/**
 * Title callback for the Commerce Node Checkout line item type.
 *
 * @param $line_item
 *   A Commerce line item object.
 * @return
 *   The title to render for the line item.
 *
 * @see
 *   commerce_node_checkout_commerce_line_item_type_info()
 */
function commerce_node_checkout_line_item_title_callback($line_item) {

  // Default to the normal title
  $title = commerce_product_line_item_title($line_item);

  // Create a wrapper for the line item
  $wrapper = entity_metadata_wrapper('commerce_line_item', $line_item);

  // Load the referenced node
  if ($node = $wrapper->commerce_node_checkout_node
    ->value()) {

    // Get the node's URI
    $uri = entity_uri('node', $node);

    // Generate a link and append to the title
    $title .= ' (' . l($node->title, $uri['path']) . ')';
  }
  return $title;
}

/**
 * Extract the products from a given order.
 *
 * Does Commerce already offer this somewhere?
 *
 * @param $order
 *   An order entity.
 * @return
 *   An array of products from the order keyed by delta.
 */
function commerce_node_checkout_get_order_products($order) {
  $products =& drupal_static(__FUNCTION__, array());

  // Check the static cache
  if (!isset($products[$order->order_id])) {

    // Create a wrapper for the order
    $wrapper = entity_metadata_wrapper('commerce_order', $order);

    // Iterate the line items
    foreach ($wrapper->commerce_line_items as $delta => $line_item) {

      // Extract the product
      if ($product = $line_item->commerce_product
        ->value()) {

        // Add it to be returned
        $products[$order->order_id][$delta] = $product;
      }
    }
  }
  return $products[$order->order_id];
}

Functions

Namesort descending Description
commerce_node_checkout_add_node Adds a node to a line item in the user's cart
commerce_node_checkout_commerce_line_item_type_info Implements hook_commerce_line_item_type_info().
commerce_node_checkout_element_info Implements hook_element_info().
commerce_node_checkout_field_attach_form Implements hook_field_attach_form().
commerce_node_checkout_field_extra_fields Implements hook_field_extra_fields().
commerce_node_checkout_form_node_type_form_alter Implements hook_form_FORM_ID_alter().
commerce_node_checkout_get_node_type_enabled_products Fetch the enabled products for a given node.
commerce_node_checkout_get_node_type_product_list Provide a formatted list of products enabled for a specific node type that can be used to present to a user.
commerce_node_checkout_get_order_products Extract the products from a given order.
commerce_node_checkout_get_product_list Fetch the a list of available products for all node types.
commerce_node_checkout_help Implements hook_help().
commerce_node_checkout_line_item_title_callback Title callback for the Commerce Node Checkout line item type.
commerce_node_checkout_node_form_submit Form submission handler that executes only when a new node that contains the product selection widget is saved.
commerce_node_checkout_permission Implements hook_permission().
commerce_node_checkout_process_element Element process callback to build the product selection form widget for a node.