You are here

nopremium.module in Node Option Premium 7

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

Written by Henri MEDOT <henri.medot[AT]absyx[DOT]fr> http://www.absyx.fr

File

nopremium.module
View source
<?php

/**
 * @file
 * Written by Henri MEDOT <henri.medot[AT]absyx[DOT]fr>
 * http://www.absyx.fr
 */

/**
 * Node is not premium.
 */
define('NODE_NOT_PREMIUM', 0);

/**
 * Node is premium.
 */
define('NODE_PREMIUM', 1);

/******************************************************************************
 * Hook functions
 ******************************************************************************/

/**
 * Implementation of hook_form_FORM_ID_alter().
 */
function nopremium_form_node_type_form_alter(&$form, &$form_state) {
  if (isset($form['workflow']['node_options']['#options'])) {
    $form['workflow']['node_options']['#options']['premium'] = t('Premium content');
  }
}

/**
 * Implementation of hook_node_operations().
 */
function nopremium_node_operations() {
  return array(
    'premium' => array(
      'label' => t('Make premium'),
      'callback' => 'node_mass_update',
      'callback arguments' => array(
        'updates' => array(
          'status' => NODE_PUBLISHED,
          'premium' => NODE_PREMIUM,
        ),
      ),
    ),
    'non_premium' => array(
      'label' => t('Make non-premium'),
      'callback' => 'node_mass_update',
      'callback arguments' => array(
        'updates' => array(
          'premium' => NODE_NOT_PREMIUM,
        ),
      ),
    ),
  );
}

/**
 * Implementation of hook_action_info().
 */
function nopremium_action_info() {
  return array(
    'node_make_premium_action' => array(
      'type' => 'node',
      'label' => t('Make content premium'),
      'configurable' => FALSE,
      'behavior' => array(
        'changes_property',
      ),
      'triggers' => array(
        'node_presave',
        'comment_insert',
        'comment_update',
        'comment_delete',
      ),
    ),
    'node_make_non_premium_action' => array(
      'type' => 'node',
      'label' => t('Make content non-premium'),
      'configurable' => FALSE,
      'behavior' => array(
        'changes_property',
      ),
      'triggers' => array(
        'node_presave',
        'comment_insert',
        'comment_update',
        'comment_delete',
      ),
    ),
  );
}

/**
 * Implementation of a Drupal action.
 * Sets the premium property of a node to 1.
 */
function node_make_premium_action($node, $context = array()) {
  $node->premium = NODE_PREMIUM;
  watchdog('action', 'Set @type %title to premium.', array(
    '@type' => node_type_get_name($node),
    '%title' => $node->title,
  ));
}

/**
 * Implementation of a Drupal action.
 * Sets the premium property of a node to 0.
 */
function node_make_non_premium_action($node, $context = array()) {
  $node->premium = NODE_NOT_PREMIUM;
  watchdog('action', 'Set @type %title to non-premium.', array(
    '@type' => node_type_get_name($node),
    '%title' => $node->title,
  ));
}

/**
 * Implementation of hook_theme().
 */
function nopremium_theme() {
  return array(
    'nopremium_message' => array(
      'variables' => array(
        'node' => NULL,
      ),
    ),
  );
}

/**
 * Implementation of hook_node_view().
 */
function nopremium_node_view($node, $view_mode, $langcode) {
  if ($node->premium && !nopremium_access_full_content($node)) {
    $node->content['nopremium_message'] = array(
      '#markup' => theme('nopremium_message', array(
        'node' => $node,
      )),
    );
  }
}

/**
 * Implementation of hook_node_view_alter().
 */
function nopremium_node_view_alter(&$build) {
  $node = $build['#node'];
  if ($build['#view_mode'] != 'teaser' && $build['#view_mode'] != 'search_index' && $node->premium && !nopremium_access_full_content($node)) {
    nopremium_alter_node($build);
  }
}

/**
 * Implementation of hook_node_prepare().
 * Set up premium default value, if required.
 */
function nopremium_node_prepare($node) {
  if (!isset($node->nid) || isset($node->is_new)) {
    $node_options = variable_get('node_options_' . $node->type, array());
    if (!isset($node->premium)) {
      $node->premium = (int) in_array('premium', $node_options);
    }
  }
}

/**
 * Implementation of hook_form_BASE_FORM_ID_alter().
 */
function nopremium_form_node_form_alter(&$form, &$form_state, $form_id) {
  $node = $form_state['node'];
  $form['options']['premium'] = array(
    '#type' => 'checkbox',
    '#title' => t('Premium content'),
    '#default_value' => $node->premium,
  );

  // Allow or not to override the premium option.
  // See http://drupal.org/project/override_node_options
  if (!user_access('administer nodes')) {
    if (user_access('override premium option of any content type') || user_access('override ' . $node->type . ' premium option')) {
      foreach (element_children($form['options']) as $key) {
        if (!isset($form['options'][$key]['#access'])) {
          $form['options'][$key]['#access'] = FALSE;
        }
      }
      $form['options']['#access'] = $form['options']['premium']['#access'] = TRUE;
    }
    else {
      $form['options']['premium']['#access'] = FALSE;
    }
  }
}

/**
 * Implementation of hook_views_api().
 */
function nopremium_views_api() {
  return array(
    'api' => 2,
  );
}

/**
 * Implementation of hook_permission().
 */
function nopremium_permission() {
  $perms['view full premium content of any type'] = array(
    'title' => t('View full premium content of any type'),
  );
  $perms['override premium option of any content type'] = array(
    'title' => t('Override premium option of any content type'),
  );
  foreach (node_type_get_types() as $type => $info) {
    $perms['view full ' . $type . ' premium content'] = array(
      'title' => t('%type_name: View full premium content', array(
        '%type_name' => $info->name,
      )),
    );
    $perms['override ' . $type . ' premium option'] = array(
      'title' => t('%type_name: Override premium option', array(
        '%type_name' => $info->name,
      )),
    );
  }
  return $perms;
}

/**
 * Implementation of hook_menu().
 */
function nopremium_menu() {
  $items['admin/config/workflow/nopremium'] = array(
    'title' => 'Node Option Premium',
    'description' => 'Configure Node Option Premium.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'nopremium_settings_form',
    ),
    'access arguments' => array(
      'administer permissions',
    ),
    'file' => 'nopremium.admin.inc',
  );
  return $items;
}

/**
 * Implementation of hook_field_extra_fields().
 */
function nopremium_field_extra_fields() {
  $extra = array();
  foreach (node_type_get_types() as $type) {
    $extra['node'][$type->type] = array(
      'display' => array(
        'nopremium_message' => array(
          'label' => t('Premium message'),
          'description' => t('Node Option Premium module message.'),
          'weight' => 1,
        ),
      ),
    );
  }
  return $extra;
}

/**
 * Implementation of hook_file_download().
 *
 * @todo use hook_file_download_access_alter() instead
 *   once file_file_download() is fixed.
 *   See http://drupal.org/node/1245220.
 */
function nopremium_file_download($uri, $field_type = 'file') {
  global $user;

  // Get the file record based on the URI. If not in the database just return.
  $files = file_load_multiple(array(), array(
    'uri' => $uri,
  ));
  if (count($files)) {
    foreach ($files as $item) {

      // Since some database servers sometimes use a case-insensitive comparison
      // by default, double check that the filename is an exact match.
      if ($item->uri === $uri) {
        $file = $item;
        break;
      }
    }
  }
  if (!isset($file)) {
    return;
  }

  // Find out which (if any) fields of this type contain the file.
  $references = file_get_file_references($file, NULL, FIELD_LOAD_CURRENT, $field_type);

  // Stop processing if there are no references in order to avoid returning
  // headers for files controlled by other modules. Make an exception for
  // temporary files where the host entity has not yet been saved (for example,
  // an image preview on a node/add form) in which case, allow download by the
  // file's owner.
  if (empty($references) && ($file->status == FILE_STATUS_PERMANENT || $file->uid != $user->uid)) {
    return;
  }

  // Loop through all references of this file. If a reference explicitly denies
  // access to the field to which this file belongs, according to
  // nopremium_access_full_content, no further checks are done and download
  // access is denied.
  foreach ($references as $field_name => $field_references) {
    if (!empty($field_references['node'])) {
      foreach ($field_references['node'] as $id => $reference) {

        // Try to load $entity and $field.
        $entity = entity_load('node', array(
          $id,
        ));
        $entity = reset($entity);
        $field = field_info_field($field_name);

        // Load the field item that references the file if $entity is premium.
        if ($entity && $entity->premium) {

          // Load all field items for that entity.
          $field_items = field_get_items('node', $entity, $field_name);

          // Find the field item with the matching URI.
          foreach ($field_items as $item) {
            if ($item['uri'] == $uri) {
              if (!nopremium_access_full_content($entity)) {
                return -1;
              }
              break;
            }
          }
        }
      }
    }
  }
}

/******************************************************************************
 * Theme functions
 ******************************************************************************/

/**
 * Theme nopremium message.
 *
 * @ingroup themeable
 */
function theme_nopremium_message($variables) {
  return '<div class="nopremium-message">' . check_markup(t(nopremium_get_message($variables['node']->type))) . '</div>';
}

/******************************************************************************
 * API and helper functions
 ******************************************************************************/

/**
 * Determine whether the current user may access the full content of the
 * specified nopremium node.
 */
function nopremium_access_full_content($node, $account = NULL) {
  if (empty($account)) {
    $account = $GLOBALS['user'];
  }
  return user_access('administer nodes', $account) || user_access('view full premium content of any type', $account) || user_access('view full ' . $node->type . ' premium content', $account) || node_access('update', $node, $account) || $account->uid && $account->uid == $node->uid;
}

/**
 * Alter a node replacing full content by nopremium content.
 */
function nopremium_alter_node(&$build) {
  $view_mode = $build['#view_mode'];
  if ($view_mode != 'teaser') {
    $node = $build['#node'];
    $langcode = $build['#language'];
    node_build_content($node, 'teaser', $langcode);
    unset($node->content['links']['node']['#links']['node-readmore']);
    $build = $node->content;
    unset($node->content);
    $build += array(
      '#theme' => 'node',
      '#node' => $node,
      '#view_mode' => 'teaser',
      '#language' => $langcode,
    );
    if (!empty($node->nid) && !($view_mode == 'full' && node_is_page($node))) {
      $build['#contextual_links']['node'] = array(
        'node',
        array(
          $node->nid,
        ),
      );
    }
    $type = 'node';
    drupal_alter(array(
      'node_view',
      'entity_view',
    ), $build, $type);

    // Override _field_extra_fields_pre_render().
    if (isset($build['#pre_render'])) {
      $key = array_search('_field_extra_fields_pre_render', $build['#pre_render']);
      if ($key !== FALSE) {
        $build['#pre_render'][$key] = '_nopremium_field_extra_fields_pre_render';
      }
    }
    $build['#view_mode'] = $view_mode;
  }
}
function _nopremium_field_extra_fields_pre_render($elements) {
  if (isset($elements['#view_mode'])) {
    $view_mode = $elements['#view_mode'];
    $elements['#view_mode'] = 'teaser';
    $elements = _field_extra_fields_pre_render($elements);
    $elements['#view_mode'] = $view_mode;
  }
  return $elements;
}

/**
 * Get the raw nopremium message for the given node type.
 */
function nopremium_get_message($type = '') {
  if ($type) {
    $message = variable_get('nopremium_message_' . $type, '');
    if ($message) {
      return $message;
    }
  }
  return variable_get('nopremium_message', 'The full content of this page is available to premium users only.');
}

Functions

Namesort descending Description
node_make_non_premium_action Implementation of a Drupal action. Sets the premium property of a node to 0.
node_make_premium_action Implementation of a Drupal action. Sets the premium property of a node to 1.
nopremium_access_full_content Determine whether the current user may access the full content of the specified nopremium node.
nopremium_action_info Implementation of hook_action_info().
nopremium_alter_node Alter a node replacing full content by nopremium content.
nopremium_field_extra_fields Implementation of hook_field_extra_fields().
nopremium_file_download Implementation of hook_file_download().
nopremium_form_node_form_alter Implementation of hook_form_BASE_FORM_ID_alter().
nopremium_form_node_type_form_alter Implementation of hook_form_FORM_ID_alter().
nopremium_get_message Get the raw nopremium message for the given node type.
nopremium_menu Implementation of hook_menu().
nopremium_node_operations Implementation of hook_node_operations().
nopremium_node_prepare Implementation of hook_node_prepare(). Set up premium default value, if required.
nopremium_node_view Implementation of hook_node_view().
nopremium_node_view_alter Implementation of hook_node_view_alter().
nopremium_permission Implementation of hook_permission().
nopremium_theme Implementation of hook_theme().
nopremium_views_api Implementation of hook_views_api().
theme_nopremium_message Theme nopremium message.
_nopremium_field_extra_fields_pre_render

Constants

Namesort descending Description
NODE_NOT_PREMIUM Node is not premium.
NODE_PREMIUM Node is premium.