You are here

pollim.module in Poll Improved 7

Module for the Pollim Entity - a starting point to create your own Entity and associated administration interface

File

pollim.module
View source
<?php

/**
 * @file
 * Module for the Pollim Entity - a starting point to create your own Entity
 * and associated administration interface
 */

/**
 * Implement hook_entity_info().
 *
 * We define two entities here - the actual entity that will hold our domain
 * specific information and an entity that holds information about the different
 * types of entities. See here: http://drupal.org/node/977380 for a discussion on this
 * choice.
 */
function pollim_entity_info() {
  $return['pollim'] = array(
    'label' => t('Pollim'),
    // The entity class and controller class extend the classes provided by the
    // Entity API
    'entity class' => 'Pollim',
    'controller class' => 'PollimController',
    'base table' => 'pollim',
    'fieldable' => TRUE,
    'entity keys' => array(
      'id' => 'pollim_id',
      'bundle' => 'type',
    ),
    // Bundles are defined by the pollim types below
    'bundles' => array(),
    // Bundle keys tell the FieldAPI how to extract information from the bundle objects
    'bundle keys' => array(
      'bundle' => 'type',
    ),
    'label callback' => 'entity_class_label',
    'uri callback' => 'entity_class_uri',
    'creation callback' => 'pollim_create',
    'access callback' => 'pollim_access',
    'module' => 'pollim',
    // The information below is used by the PollimUIController (which extends the EntityDefaultUIController)
    'admin ui' => array(
      'path' => 'admin/content/pollims',
      'file' => 'pollim.admin.inc',
      'controller class' => 'PollimUIController',
      'menu wildcard' => '%pollim',
    ),
  );

  // The entity that holds information about the entity types
  $return['pollim_type'] = array(
    'label' => t('Pollim Type'),
    'entity class' => 'PollimType',
    'controller class' => 'PollimTypeController',
    'base table' => 'pollim_type',
    'fieldable' => FALSE,
    'bundle of' => 'pollim',
    'exportable' => TRUE,
    'entity keys' => array(
      'id' => 'id',
      'name' => 'type',
      'label' => 'label',
    ),
    'access callback' => 'pollim_type_access',
    'module' => 'pollim',
    // Enable the entity API's admin UI.
    'admin ui' => array(
      'path' => 'admin/structure/pollim_types',
      'file' => 'pollim_type.admin.inc',
      'controller class' => 'PollimTypeUIController',
    ),
  );
  $return['pollim_vote'] = array(
    'label' => t('Pollim Vote'),
    'entity class' => 'PollimVote',
    'controller class' => 'EntityAPIController',
    'base table' => 'pollim_vote',
    'fieldable' => FALSE,
    'entity keys' => array(
      'id' => 'vote_id',
    ),
  );
  return $return;
}

/**
 * Implements hook_entity_info_alter().
 *
 * We are adding the info about the pollim types via a hook to avoid a recursion
 * issue as loading the pollim types requires the entity info as well.
 *
 * @todo This needs to be improved
 */
function pollim_entity_info_alter(&$entity_info) {
  foreach (pollim_get_types() as $type => $info) {
    $entity_info['pollim']['bundles'][$type] = array(
      'label' => $info->label,
      'admin' => array(
        'path' => 'admin/structure/pollim_types/manage/%pollim_type',
        'real path' => 'admin/structure/pollim_types/manage/' . $type,
        'bundle argument' => 4,
        'access arguments' => array(
          'administer pollim types',
        ),
      ),
    );
  }
}

/**
 * Implements hook_permission().
 */
function pollim_permission() {

  // We set up permisssions to manage entity types, manage all entities and the
  // permissions for each individual entity
  $permissions = array(
    'administer pollim types' => array(
      'title' => t('Administer pollim types'),
      'description' => t('Create and delete fields for pollim types, and set their permissions.'),
    ),
    'administer pollims' => array(
      'title' => t('Administer pollims'),
      'description' => t('Edit and delete all polls.'),
    ),
    'view pollim polls' => array(
      'title' => t('View polls'),
      'description' => t('View all published polls'),
    ),
    'vote pollim polls' => array(
      'title' => t('Vote on polls'),
      'description' => t('Vote on all published polls.'),
    ),
  );

  //Generate permissions per pollim
  foreach (pollim_get_types() as $type) {
    $type_name = check_plain($type->type);
    $permissions += array(
      "edit any {$type_name} pollim" => array(
        'title' => t('%type_name: Edit any pollim', array(
          '%type_name' => $type->label,
        )),
      ),
      "view any {$type_name} pollim" => array(
        'title' => t('%type_name: View any pollim', array(
          '%type_name' => $type->label,
        )),
      ),
    );
  }
  return $permissions;
}

/**
 * Determines whether the given user has access to a pollim.
 *
 * @param $op
 *   The operation being performed. One of 'view', 'update', 'create', 'delete'
 *   or just 'edit' (being the same as 'create' or 'update').
 * @param $pollim
 *   Optionally a pollim or a pollim type to check access for. If nothing is
 *   given, access for all pollims is determined.
 * @param $account
 *   The user to check for. Leave it to NULL to check for the global user.
 * @return boolean
 *   Whether access is allowed or not.
 */
function pollim_access($op, $pollim = NULL, $account = NULL) {
  if (user_access('administer pollims', $account)) {
    return TRUE;
  }
  if (isset($pollim) && is_object($pollim) && ($type_name = $pollim->type)) {
    $op = $op == 'view' ? 'view' : 'edit';
    if (user_access("{$op} any {$type_name} pollim", $account)) {
      return TRUE;
    }
  }
  return FALSE;
}

/**
 * Access callback for the entity API.
 */
function pollim_type_access($op, $type = NULL, $account = NULL) {
  return user_access('administer pollim types', $account);
}

/**
 * Gets an array of all pollim types, keyed by the type name.
 *
 * @param $type_name
 *   If set, the type with the given name is returned.
 * @return PollimType[]
 *   Depending whether $type isset, an array of pollim types or a single one.
 */
function pollim_get_types($type_name = NULL) {

  // entity_load will get the Entity controller for our pollim entity and call the load
  // function of that object - we are loading entities by name here.
  $types = entity_load_multiple_by_name('pollim_type', isset($type_name) ? array(
    $type_name,
  ) : FALSE);
  return isset($type_name) ? reset($types) : $types;
}

/**
 * Menu argument loader; Load a pollim type by string.
 *
 * @param $type
 *   The machine-readable name of a pollim type to load.
 * @return
 *   A pollim type array or FALSE if $type does not exist.
 */
function pollim_type_load($type) {
  return pollim_get_types($type);
}

/**
 * Fetch a pollim object. Make sure that the wildcard you choose 
 * in the pollim entity definition fits the function name here.
 *
 * @param $pollim_id
 *   Integer specifying the pollim id.
 * @param $reset
 *   A boolean indicating that the internal cache should be reset.
 * @return
 *   A fully-loaded $pollim object or FALSE if it cannot be loaded.
 *
 * @see pollim_load_multiple()
 */
function pollim_load($pollim_id, $reset = FALSE) {
  $pollims = pollim_load_multiple(array(
    $pollim_id,
  ), array(), $reset);
  return reset($pollims);
}

/**
 * Load multiple pollims based on certain conditions.
 *
 * @param $pollim_ids
 *   An array of pollim IDs.
 * @param $conditions
 *   An array of conditions to match against the {pollim} table.
 * @param $reset
 *   A boolean indicating that the internal cache should be reset.
 * @return
 *   An array of pollim objects, indexed by pollim_id.
 *
 * @see entity_load()
 * @see pollim_load()
 */
function pollim_load_multiple($pollim_ids = array(), $conditions = array(), $reset = FALSE) {
  return entity_load('pollim', $pollim_ids, $conditions, $reset);
}

/**
 * Deletes a pollim.
 */
function pollim_delete(Pollim $pollim) {
  $pollim
    ->delete();
}

/**
 * Delete multiple pollims.
 *
 * @param $pollim_ids
 *   An array of pollim IDs.
 */
function pollim_delete_multiple(array $pollim_ids) {
  entity_get_controller('pollim')
    ->delete($pollim_ids);
}

/**
 * Create a pollim object.
 */
function pollim_create($values = array()) {
  return entity_get_controller('pollim')
    ->create($values);
}

/**
 * Saves a pollim to the database.
 *
 * @param $pollim
 *   The pollim object.
 */
function pollim_save(Pollim $pollim) {
  return $pollim
    ->save();
}

/**
 * Saves a pollim type to the db.
 */
function pollim_type_save(PollimType $type) {
  $type
    ->save();
}

/**
 * Deletes a pollim type from the db.
 */
function pollim_type_delete(PollimType $type) {
  $type
    ->delete();
}

/**
 * URI callback for pollims
 */
function pollim_uri(Pollim $pollim) {
  return array(
    'path' => 'pollim/' . $pollim->pollim_id,
  );
}

/**
 * Menu title callback for showing individual entities
 */
function pollim_page_title(Pollim $pollim) {
  return $pollim->name;
}

/**
 * Sets up content to show an individual pollim
 * @todo - get rid of drupal_set_title();
 */
function pollim_page_view($pollim, $view_mode = 'full') {
  $controller = entity_get_controller('pollim');
  $content = $controller
    ->view(array(
    $pollim->pollim_id => $pollim,
  ));
  drupal_set_title($pollim->name);
  return $content;
}

/**
 * Implements hook_views_api().
 */
function pollim_views_api() {
  return array(
    'api' => 3,
    'path' => drupal_get_path('module', 'pollim') . '/views',
  );
}

/**
 * Implement hook_theme().
 */
function pollim_theme() {
  return array(
    'pollim_add_list' => array(
      'variables' => array(
        'content' => array(),
      ),
      'file' => 'pollim.admin.inc',
    ),
    'pollim' => array(
      'render element' => 'elements',
      'template' => 'pollim',
    ),
    'pollim_sample_data' => array(
      'variables' => array(
        'pollim_sample_data',
        'pollim' => NULL,
      ),
      'template' => 'pollim-sample-data',
    ),
  );
}

/**
 * Implements hook_menu_local_tasks_alter().
 */
function pollim_menu_local_tasks_alter(&$data, $router_item, $root_path) {

  // Add action link 'admin/structure/pollims/add' on 'admin/structure/pollims'.
  if ($root_path == 'admin/content/pollims') {
    $item = menu_get_item('admin/content/pollims/add');
    if ($item['access']) {
      $data['actions']['output'][] = array(
        '#theme' => 'menu_local_action',
        '#link' => $item,
      );
    }
  }
}

/**
 * Implements hook_menu().
 */
function pollim_menu() {
  $items = array();
  $items['pollim/ajax/vote/%pollim'] = array(
    'title' => '',
    'type' => MENU_CALLBACK,
    'page callback' => 'pollim_ajax_vote',
    'page arguments' => array(
      3,
    ),
    'access arguments' => array(
      'vote pollim polls',
    ),
  );
  $items['admin/config/content/pollim'] = array(
    'title' => t('Poll Improved'),
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'pollim_settings_form',
    ),
    'access arguments' => array(
      'administer site configuration',
    ),
    'file' => 'pollim.settings.admin.inc',
  );
  return $items;
}
function pollim_ajax_vote($pollim) {
  if (!pollim_ip_check($pollim
    ->internalIdentifier(), ip_address())) {
    print "<p class='messages error'>" . t('IP address blocked') . "</p>";
    exit;
  }
  $choice = $_REQUEST['data'];
  $entity = entity_create('pollim_vote', array(
    'pollim_id' => $pollim->pollim_id,
    'timestamp' => time(),
    'hostname' => ip_address(),
    'data' => $choice,
  ));
  $entity
    ->save();
  $controller = entity_get_controller('pollim');
  $content = $controller
    ->view(array(
    $pollim->pollim_id => $pollim,
  ));
  $output = render($content);
  $output .= '<p class="message">' . t('Thanks for your vote!') . '</p>';
  print $output;
  exit;
}
function pollim_ip_check($pollim_id, $ip_address) {
  $ok = TRUE;
  if (variable_get('pollim_threshold_count', 10) == 0) {
    return TRUE;

    //No IP restrictions
  }
  $votes_for_this_ip = db_query("SELECT COUNT(*) FROM {pollim_vote} " . "WHERE pollim_id = :pollim_id AND hostname = :hostname AND timestamp > :timestamp", array(
    ':pollim_id' => $pollim_id,
    ':hostname' => $ip_address,
    ':timestamp' => time() - variable_get('pollanon_threshold_time', 600),
  ))
    ->fetchField(0);

  //Do we need to block voting for the given IP address ?
  if ($votes_for_this_ip >= variable_get('pollim_threshold_count', 10)) {
    $ok = FALSE;
    drupal_set_message(t('Voting temporarily closed for your remote address.'));
  }
  return $ok;
}
function pollim_block_info() {
  $blocks['pollim'] = array(
    'info' => t('Latest Poll'),
    'cache' => DRUPAL_NO_CACHE,
  );
  return $blocks;
}

/**
 * The class used for pollim entities
 */
class Pollim extends Entity {
  public function __construct($values = array()) {
    parent::__construct($values, 'pollim');
  }
  protected function defaultLabel() {
    return $this->name;
  }
  protected function defaultUri() {
    return array(
      'path' => 'pollim/' . $this->pollim_id,
    );
  }

}

/**
 * The class used for pollim type entities
 */
class PollimType extends Entity {
  public $type;
  public $label;
  public function __construct($values = array()) {
    parent::__construct($values, 'pollim_type');
  }

}

/**
 * The class used for vote entities
 */
class PollimVote extends Entity {

}

/**
 * The Controller for Pollim entities
 */
class PollimController extends EntityAPIController {
  public function __construct($entityType) {
    parent::__construct($entityType);
  }

  /**
   * Create a pollim - we first set up the values that are specific
   * to our pollim schema but then also go through the EntityAPIController
   * function.
   *
   * @param $type
   *   The machine-readable type of the pollim.
   *
   * @return
   *   A pollim object with all default fields initialized.
   */
  public function create(array $values = array()) {

    // Add values that are specific to our Pollim
    $values += array(
      'pollim_id' => '',
      'is_new' => TRUE,
      'title' => '',
      'created' => '',
      'changed' => '',
      'data' => '',
    );
    $pollim = parent::create($values);
    return $pollim;
  }

  /**
   * Overriding the buldContent function to add entity specific fields
   */
  public function buildContent($entity, $view_mode = 'full', $langcode = NULL, $content = array()) {
    $content = parent::buildContent($entity, $view_mode, $langcode, $content);

    //var_dump($content);exit();

    /*
    $content['pollim_sample_data'] =  array(
      '#markup' => theme('pollim_sample_data', array('pollim_sample_data' => check_plain($entity->data['sample_data']), 'pollim' => $entity)),
    );
    */
    return $content;
  }

}

/**
 * The Controller for Pollim entities
 */
class PollimTypeController extends EntityAPIControllerExportable {
  public function __construct($entityType) {
    parent::__construct($entityType);
  }

  /**
   * Create a pollim type - we first set up the values that are specific
   * to our pollim type schema but then also go through the EntityAPIController
   * function.
   *
   * @param $type
   *   The machine-readable type of the pollim.
   *
   * @return
   *   A pollim type object with all default fields initialized.
   */
  public function create(array $values = array()) {

    // Add values that are specific to our Pollim
    $values += array(
      'id' => '',
      'is_new' => TRUE,
      'data' => '',
    );
    $pollim_type = parent::create($values);
    return $pollim_type;
  }

}

Functions

Namesort descending Description
pollim_access Determines whether the given user has access to a pollim.
pollim_ajax_vote
pollim_block_info
pollim_create Create a pollim object.
pollim_delete Deletes a pollim.
pollim_delete_multiple Delete multiple pollims.
pollim_entity_info Implement hook_entity_info().
pollim_entity_info_alter Implements hook_entity_info_alter().
pollim_get_types Gets an array of all pollim types, keyed by the type name.
pollim_ip_check
pollim_load Fetch a pollim object. Make sure that the wildcard you choose in the pollim entity definition fits the function name here.
pollim_load_multiple Load multiple pollims based on certain conditions.
pollim_menu Implements hook_menu().
pollim_menu_local_tasks_alter Implements hook_menu_local_tasks_alter().
pollim_page_title Menu title callback for showing individual entities
pollim_page_view Sets up content to show an individual pollim @todo - get rid of drupal_set_title();
pollim_permission Implements hook_permission().
pollim_save Saves a pollim to the database.
pollim_theme Implement hook_theme().
pollim_type_access Access callback for the entity API.
pollim_type_delete Deletes a pollim type from the db.
pollim_type_load Menu argument loader; Load a pollim type by string.
pollim_type_save Saves a pollim type to the db.
pollim_uri URI callback for pollims
pollim_views_api Implements hook_views_api().

Classes

Namesort descending Description
Pollim The class used for pollim entities
PollimController The Controller for Pollim entities
PollimType The class used for pollim type entities
PollimTypeController The Controller for Pollim entities
PollimVote The class used for vote entities