View source
<?php
function flag_flag_definitions() {
$definitions = array(
'node' => array(
'title' => t('Nodes'),
'description' => t("Nodes are a Drupal site's primary content."),
'handler' => 'flag_node',
),
'comment' => array(
'title' => t('Comments'),
'description' => t('Comments are responses to node content.'),
'handler' => 'flag_comment',
),
'user' => array(
'title' => t('Users'),
'description' => t('Users who have created accounts on your site.'),
'handler' => 'flag_user',
),
);
return $definitions;
}
function flag_flag_definitions_alter(&$definitions) {
foreach (entity_get_info() as $entity_type => $entity) {
if (!isset($definitions[$entity_type]) && empty($entity['configuration'])) {
$definitions[$entity_type] = array(
'title' => $entity['label'],
'description' => t('@entity-type entity', array(
'@entity-type' => $entity['label'],
)),
'handler' => 'flag_entity',
);
}
}
}
function flag_fetch_definition($content_type = NULL) {
$defintions =& drupal_static(__FUNCTION__);
if (!isset($defintions)) {
$defintions = module_invoke_all('flag_definitions');
drupal_alter('flag_definitions', $defintions);
if (!isset($defintions['node'])) {
$defintions += flag_flag_definitions();
}
}
if (isset($content_type)) {
if (isset($defintions[$content_type])) {
return $defintions[$content_type];
}
}
else {
return $defintions;
}
}
function flag_get_types() {
$types =& drupal_static(__FUNCTION__);
if (!isset($types)) {
$types = array_keys(flag_fetch_definition());
}
return $types;
}
function flag_create_handler($content_type) {
$definition = flag_fetch_definition($content_type);
if (isset($definition) && class_exists($definition['handler'])) {
$handler = new $definition['handler']();
}
else {
$handler = new flag_broken();
}
$handler->content_type = $content_type;
$handler
->construct();
return $handler;
}
class flag_flag {
var $fid = NULL;
var $content_type = NULL;
var $name = '';
var $title = '';
var $global = FALSE;
var $types = array();
static function factory_by_row($row) {
$flag = flag_create_handler($row->content_type);
foreach ($row as $field => $value) {
$flag->{$field} = $value;
}
unset($flag->options, $flag->type);
$options = (array) unserialize($row->options);
$options += $flag
->options();
foreach ($options as $option => $value) {
$flag->{$option} = $value;
}
if (!empty($row->type)) {
$flag->types[] = $row->type;
}
return $flag;
}
static function factory_by_array($config) {
$flag = flag_create_handler($config['content_type']);
foreach ($config as $option => $value) {
$flag->{$option} = $value;
}
if (isset($config['locked']) && is_array($config['locked'])) {
$flag->locked = drupal_map_assoc($config['locked']);
}
return $flag;
}
static function factory_by_content_type($content_type) {
return flag_create_handler($content_type);
}
function options() {
$options = array(
'flag_short' => '',
'flag_long' => '',
'flag_message' => '',
'unflag_short' => '',
'unflag_long' => '',
'unflag_message' => '',
'unflag_denied_text' => '',
'link_type' => 'toggle',
'roles' => array(
'flag' => array(
DRUPAL_AUTHENTICATED_RID,
),
'unflag' => array(
DRUPAL_AUTHENTICATED_RID,
),
),
'weight' => 0,
);
$link_type = $this
->get_link_type();
$options = array_merge($options, $link_type['options']);
drupal_alter('flag_options', $options, $this);
return $options;
}
function options_form(&$form) {
}
function construct() {
$options = $this
->options();
foreach ($options as $option => $value) {
$this->{$option} = $value;
}
}
function form_input($form_values) {
foreach ($form_values as $field => $value) {
$this->{$field} = $value;
}
$this->roles['flag'] = array_values(array_filter($this->roles['flag']));
$this->roles['unflag'] = array_values(array_filter($this->roles['unflag']));
$this->types = array_values(array_filter($this->types));
$this
->get_title(NULL, TRUE);
}
function validate() {
return array_merge_recursive($this
->validate_name(), $this
->validate_access());
}
function validate_name() {
$errors = array();
if (!preg_match('/^[a-z_][a-z0-9_]*$/', $this->name)) {
$errors['name'][] = array(
'error' => 'flag_name_characters',
'message' => t('The flag name may only contain lowercase letters, underscores, and numbers.'),
);
}
$flag = flag_get_flag($this->name);
if (!empty($flag) && (!isset($this->fid) || $flag->fid != $this->fid)) {
$errors['name'][] = array(
'error' => 'flag_name_unique',
'message' => t('Flag names must be unique. This flag name is already in use.'),
);
}
return $errors;
}
function validate_access() {
$errors = array();
if (empty($this->unflag_denied_text)) {
foreach ($this->roles['flag'] as $key => $rid) {
if ($rid && empty($this->roles['unflag'][$key])) {
$errors['unflag_denied_text'][] = array(
'error' => 'flag_denied_text_required',
'message' => t('The "Unflag not allowed text" is required if any user roles are not allowed to unflag.'),
);
break;
}
}
}
foreach ($this->roles['unflag'] as $key => $rid) {
if ($rid && empty($this->roles['flag'][$key])) {
$errors['roles'][] = array(
'error' => 'flag_roles_unflag',
'message' => t('Any user role that has the ability to unflag must also have the ability to flag.'),
);
break;
}
}
return $errors;
}
function fetch_content($content_id, $object_to_remember = NULL) {
static $cache = array();
if (isset($object_to_remember)) {
$cache[$content_id] = $object_to_remember;
}
if (!array_key_exists($content_id, $cache)) {
$content = $this
->_load_content($content_id);
$cache[$content_id] = $content ? $content : NULL;
}
return $cache[$content_id];
}
function _load_content($content_id) {
return NULL;
}
function remember_content($content_id, $object) {
$this
->fetch_content($content_id, $object);
}
function applies_to_content_object($content) {
return FALSE;
}
function applies_to_content_id($content_id) {
return $this
->applies_to_content_object($this
->fetch_content($content_id));
}
function user_access($action = 'flag', $account = NULL) {
if (!isset($account)) {
$account = $GLOBALS['user'];
}
if ($account->uid == 0 && !module_exists('session_api')) {
return FALSE;
}
$matched_roles = array_intersect($this->roles[$action], array_keys($account->roles));
return !empty($matched_roles) || $account->uid == 1;
}
function access($content_id, $action = NULL, $account = NULL) {
if (!isset($account)) {
$account = $GLOBALS['user'];
}
if (isset($content_id) && !$this
->applies_to_content_id($content_id)) {
return FALSE;
}
if (!isset($action)) {
$uid = $account->uid;
$sid = flag_get_sid($uid);
$action = $this
->is_flagged($content_id, $uid, $sid) ? 'unflag' : 'flag';
}
$access = $this
->user_access($action, $account);
$child_access = $this
->type_access($content_id, $action, $account);
if (isset($child_access)) {
$access = $child_access;
}
$access_array = module_invoke_all('flag_access', $this, $content_id, $action, $account);
foreach ($access_array as $set_access) {
if (isset($set_access)) {
$access = $set_access;
}
}
return $access;
}
function access_multiple($content_ids, $account = NULL) {
$account = isset($account) ? $account : $GLOBALS['user'];
$access = array();
foreach ($content_ids as $content_id => $action) {
$access[$content_id] = $this
->user_access($content_ids[$content_id], $account);
}
$child_access = $this
->type_access_multiple($content_ids, $account);
if (isset($child_access)) {
foreach ($child_access as $content_id => $content_access) {
if (isset($content_access)) {
$access[$content_id] = $content_access;
}
}
}
foreach (module_implements('flag_access_multiple') as $module) {
$module_access = module_invoke($module, 'flag_access_multiple', $this, $content_ids, $account);
foreach ($module_access as $content_id => $content_access) {
if (isset($content_access)) {
$access[$content_id] = $content_access;
}
}
}
return $access;
}
function type_access($content_id, $action, $account) {
return NULL;
}
function type_access_multiple($content_ids, $account) {
return array();
}
function get_content_id($content) {
return NULL;
}
function uses_hook_link($teaser) {
return FALSE;
}
function uses_anonymous_cookies() {
global $user;
return $user->uid == 0 && variable_get('cache', 0);
}
function flag($action, $content_id, $account = NULL, $skip_permission_check = FALSE) {
if (!isset($account)) {
$account = $GLOBALS['user'];
}
if (!$account) {
return FALSE;
}
if (!$skip_permission_check) {
if (!$this
->access($content_id, $action, $account)) {
return FALSE;
}
}
else {
if (!$this
->applies_to_content_id($content_id)) {
return FALSE;
}
}
flag_get_counts(NULL, NULL, TRUE);
flag_get_user_flags(NULL, NULL, NULL, NULL, TRUE);
drupal_static_reset('flag_get_content_flags');
$uid = $this->global ? 0 : $account->uid;
if ($this->global) {
$sid = 0;
}
else {
$sid = flag_get_sid($uid, TRUE);
if ($sid == 0 && $account->uid == 0) {
return FALSE;
}
}
$flagged = $this
->_is_flagged($content_id, $uid, $sid);
if ($action == 'unflag') {
if ($this
->uses_anonymous_cookies()) {
$this
->_unflag_anonymous($content_id);
}
if ($flagged) {
$fcid = $this
->_unflag($content_id, $uid, $sid);
module_invoke_all('flag', 'unflag', $this, $content_id, $account, $fcid);
}
}
elseif ($action == 'flag') {
if ($this
->uses_anonymous_cookies()) {
$this
->_flag_anonymous($content_id);
}
if (!$flagged) {
$fcid = $this
->_flag($content_id, $uid, $sid);
module_invoke_all('flag', 'flag', $this, $content_id, $account, $fcid);
}
}
return TRUE;
}
function is_flagged($content_id, $uid = NULL, $sid = NULL) {
return (bool) $this
->get_flagging_record($content_id, $uid, $sid);
}
function get_flagging_record($content_id, $uid = NULL, $sid = NULL) {
$uid = $this->global ? 0 : (!isset($uid) ? $GLOBALS['user']->uid : $uid);
$sid = $this->global ? 0 : (!isset($sid) ? flag_get_sid($uid) : $sid);
$user_flags = flag_get_user_flags($this->content_type, $content_id, $uid, $sid);
return isset($user_flags[$this->name]) ? $user_flags[$this->name] : NULL;
}
function _is_flagged($content_id, $uid, $sid) {
return db_select('flag_content', 'fc')
->fields('fc', array(
'fcid',
))
->condition('fid', $this->fid)
->condition('uid', $uid)
->condition('sid', $sid)
->condition('content_id', $content_id)
->execute()
->fetchField();
}
function _flag($content_id, $uid, $sid) {
$fcid = db_insert('flag_content')
->fields(array(
'fid' => $this->fid,
'content_type' => $this->content_type,
'content_id' => $content_id,
'uid' => $uid,
'sid' => $sid,
'timestamp' => REQUEST_TIME,
))
->execute();
$this
->_increase_count($content_id);
return $fcid;
}
function _unflag($content_id, $uid, $sid) {
$fcid = db_select('flag_content', 'fc')
->fields('fc', array(
'fcid',
))
->condition('fid', $this->fid)
->condition('uid', $uid)
->condition('sid', $sid)
->condition('content_id', $content_id)
->execute()
->fetchField();
if ($fcid) {
db_delete('flag_content')
->condition('fcid', $fcid)
->execute();
$this
->_decrease_count($content_id);
}
return $fcid;
}
function _increase_count($content_id, $number = 1) {
db_merge('flag_counts')
->key(array(
'fid' => $this->fid,
'content_id' => $content_id,
))
->fields(array(
'content_type' => $this->content_type,
'count' => $number,
'last_updated' => REQUEST_TIME,
))
->updateFields(array(
'last_updated' => REQUEST_TIME,
))
->expression('count', 'count + :inc', array(
':inc' => $number,
))
->execute();
}
function _decrease_count($content_id, $number = 1) {
db_delete('flag_counts')
->condition('fid', $this->fid)
->condition('content_id', $content_id)
->condition('count', $number, '<=')
->execute();
db_update('flag_counts')
->expression('count', 'count - :inc', array(
':inc' => $number,
))
->fields(array(
'last_updated' => REQUEST_TIME,
))
->condition('fid', $this->fid)
->condition('content_id', $content_id)
->execute();
}
function _flag_anonymous($content_id) {
$storage = FlagCookieStorage::factory($this);
$storage
->flag($content_id);
}
function _unflag_anonymous($content_id) {
$storage = FlagCookieStorage::factory($this);
$storage
->unflag($content_id);
}
function get_count($content_id) {
$counts = flag_get_counts($this->content_type, $content_id);
return isset($counts[$this->name]) ? $counts[$this->name] : 0;
}
function get_user_count($uid, $sid = NULL) {
if (!isset($sid)) {
$sid = flag_get_sid($uid);
}
return db_select('flag_content', 'fc')
->fields('fc', array(
'fcid',
))
->condition('fid', $this->fid)
->condition('uid', $uid)
->condition('sid', $sid)
->countQuery()
->execute()
->fetchField();
}
function get_label($label, $content_id = NULL) {
if (!isset($this->{$label})) {
return;
}
$label = t($this->{$label});
if (strpos($label, '[') !== FALSE) {
$label = $this
->replace_tokens($label, array(), array(
'sanitize' => FALSE,
), $content_id);
}
return filter_xss_admin($label);
}
function get_link_type() {
$link_types = flag_get_link_types();
return isset($this->link_type) && isset($link_types[$this->link_type]) ? $link_types[$this->link_type] : $link_types['normal'];
}
function replace_tokens($label, $contexts, $options, $content_id) {
return token_replace($label, $contexts, $options);
}
function get_labels_token_types() {
return array();
}
function get_title($content_id = NULL, $reset = FALSE) {
static $titles = array();
if ($reset) {
$titles = array();
}
$slot = intval($content_id);
if (!isset($titles[$this->fid][$slot])) {
$titles[$this->fid][$slot] = $this
->get_label('title', $content_id);
}
return $titles[$this->fid][$slot];
}
function get_flag_action($content_id) {
$flag_action = new stdClass();
$flag_action->flag = $this->name;
$flag_action->content_type = $this->content_type;
$flag_action->content_id = $content_id;
return $flag_action;
}
function get_valid_actions() {
$actions = module_invoke_all('action_info');
foreach ($actions as $callback => $action) {
if ($action['type'] != $this->content_type && !in_array('any', $action['triggers'])) {
unset($actions[$callback]);
}
}
return $actions;
}
function get_relevant_action_objects($content_id) {
return array();
}
function get_views_info() {
return array();
}
function save() {
if (isset($this->fid)) {
$this
->update();
$this->is_new = FALSE;
}
else {
$this
->insert();
$this->is_new = TRUE;
}
cache_clear_all('*', 'cache_page', TRUE);
}
function update() {
db_update('flags')
->fields(array(
'name' => $this->name,
'title' => $this->title,
'global' => $this->global,
'options' => $this
->get_serialized_options(),
))
->condition('fid', $this->fid)
->execute();
db_delete('flag_types')
->condition('fid', $this->fid)
->execute();
foreach ($this->types as $type) {
db_insert('flag_types')
->fields(array(
'fid' => $this->fid,
'type' => $type,
))
->execute();
}
}
function insert() {
$this->fid = db_insert('flags')
->fields(array(
'content_type' => $this->content_type,
'name' => $this->name,
'title' => $this->title,
'global' => $this->global,
'options' => $this
->get_serialized_options(),
))
->execute();
foreach ($this->types as $type) {
db_insert('flag_types')
->fields(array(
'fid' => $this->fid,
'type' => $type,
))
->execute();
}
}
function get_serialized_options() {
$option_names = array_keys($this
->options());
$options = array();
foreach ($option_names as $option) {
$options[$option] = $this->{$option};
}
return serialize($options);
}
function delete() {
db_delete('flags')
->condition('fid', $this->fid)
->execute();
db_delete('flag_content')
->condition('fid', $this->fid)
->execute();
db_delete('flag_types')
->condition('fid', $this->fid)
->execute();
db_delete('flag_counts')
->condition('fid', $this->fid)
->execute();
module_invoke_all('flag_delete', $this);
}
function is_compatible() {
if (isset($this->fid)) {
return TRUE;
}
else {
if (!isset($this->api_version)) {
$this->api_version = 1;
}
return $this->api_version == FLAG_API_VERSION;
}
}
function find_default_flag() {
if ($this->fid) {
$default_flags = flag_get_default_flags(TRUE);
if (isset($default_flags[$this->name])) {
return $default_flags[$this->name];
}
}
}
function revert() {
if ($default_flag = $this
->find_default_flag()) {
if ($default_flag
->is_compatible()) {
$default_flag = clone $default_flag;
$default_flag->fid = $this->fid;
$default_flag
->save();
flag_get_flags(NULL, NULL, NULL, TRUE);
return TRUE;
}
else {
return FALSE;
}
}
}
function disable() {
if (isset($this->module)) {
$flag_status = variable_get('flag_default_flag_status', array());
$flag_status[$this->name] = FALSE;
variable_set('flag_default_flag_status', $flag_status);
}
}
function enable() {
if (isset($this->module)) {
$flag_status = variable_get('flag_default_flag_status', array());
$flag_status[$this->name] = TRUE;
variable_set('flag_default_flag_status', $flag_status);
}
}
function admin_path($action) {
if ($action == 'edit') {
return FLAG_ADMIN_PATH . '/manage/' . $this->name;
}
else {
return FLAG_ADMIN_PATH . '/manage/' . $this->name . '/' . $action;
}
}
function theme($action, $content_id, $after_flagging = FALSE) {
static $js_added = array();
global $user;
if ($user->uid == 0 && !isset($js_added['anonymous'])) {
$js_added['anonymous'] = TRUE;
drupal_add_js(array(
'flag' => array(
'anonymous' => TRUE,
),
), 'setting');
}
if ($this
->uses_anonymous_cookies() && !$after_flagging) {
if ($this->global) {
$js_action = $action == 'flag' ? 'unflag' : 'flag';
}
else {
$js_action = 'unflag';
$action = 'flag';
}
if (!isset($js_added[$this->name . '_' . $content_id])) {
$js_added[$this->name . '_' . $content_id] = TRUE;
$js_template = theme($this
->theme_suggestions(), array(
'flag' => $this,
'action' => $js_action,
'content_id' => $content_id,
'after_flagging' => $after_flagging,
));
drupal_add_js(array(
'flag' => array(
'templates' => array(
$this->name . '_' . $content_id => $js_template,
),
),
), 'setting');
}
}
return theme($this
->theme_suggestions(), array(
'flag' => $this,
'action' => $action,
'content_id' => $content_id,
'after_flagging' => $after_flagging,
));
}
function theme_suggestions() {
$suggestions = array();
$suggestions[] = 'flag__' . $this->name;
$suggestions[] = 'flag__' . $this->link_type;
$suggestions[] = 'flag';
return $suggestions;
}
}
class flag_entity extends flag_flag {
function options() {
$options = parent::options();
$options += array(
'show_on_entity' => TRUE,
'show_on_form' => FALSE,
'access_author' => '',
);
return $options;
}
function options_form(&$form) {
$bundles = array();
$entity_info = entity_get_info($this->content_type);
foreach ($entity_info['bundles'] as $bundle_key => $bundle) {
$bundles[$bundle_key] = check_plain($bundle['label']);
}
$form['access']['types'] = array(
'#type' => 'checkboxes',
'#title' => t('Bundles'),
'#options' => $bundles,
'#description' => t('Select the bundles that this flag may be used on. Leave blank to allow on all bundles for the entity type.'),
'#default_value' => $this->types,
);
$form['display']['show_on_entity'] = array(
'#type' => 'checkbox',
'#title' => t('Display link on entity'),
'#default_value' => isset($this->show_on_entity) ? $this->show_on_entity : TRUE,
'#access' => empty($this->locked['show_on_entity']),
'#weight' => 0,
);
$form['display']['show_on_form'] = array(
'#type' => 'checkbox',
'#title' => t('Display checkbox on entity edit form'),
'#default_value' => $this->show_on_form,
'#access' => empty($this->locked['show_on_form']),
'#weight' => 5,
);
}
function _load_content($content_id) {
if (is_numeric($content_id)) {
$entity = entity_load($this->content_type, array(
$content_id,
));
return reset($entity);
}
return NULL;
}
function applies_to_content_object($entity) {
$entity_info = entity_get_info($this->content_type);
if (empty($this->types) || empty($entity_info['entity keys']['bundle']) || in_array($entity->{$entity_info['entity keys']['bundle']}, $this->types)) {
return TRUE;
}
return FALSE;
}
function get_content_id($entity) {
$entity_info = entity_get_info($this->content_type);
if ($entity && isset($entity->{$entity_info['entity keys']['id']})) {
return $entity->{$entity_info['entity keys']['id']};
}
}
function uses_hook_link($teaser) {
if ($this->show_on_entity) {
return TRUE;
}
return FALSE;
}
function get_labels_token_types() {
return array_merge(array(
$this->content_type,
), parent::get_labels_token_types());
}
function replace_tokens($label, $contexts, $options, $content_id) {
if ($content_id && ($entity = $this
->fetch_content($content_id))) {
$contexts[$this->content_type] = $entity;
}
return parent::replace_tokens($label, $contexts, $options, $content_id);
}
function get_flag_action($content_id) {
$flag_action = parent::get_flag_action($content_id);
$entity = $this
->fetch_content($content_id);
$flag_action->content_title = entity_label($this->content_type, $entity);
$flag_action->content_url = _flag_url($this->content_type . '/' . $this
->get_content_id($entity));
return $flag_action;
}
function get_relevant_action_objects($content_id) {
return array(
$this->content_type => $this
->fetch_content($content_id),
);
}
function get_views_info() {
$entity_info = entity_get_info($this->content_type);
return array(
'views table' => $entity_info['base table'],
'join field' => $entity_info['entity keys']['id'],
'title field' => isset($entity_info['entity keys']['label']) ? $entity_info['entity keys']['label'] : '',
'title' => t('@entity_label flag', array(
'@entity_label' => $entity_info['label'],
)),
'help' => t('Limit results to only those entity flagged by a certain flag; Or display information about the flag set on a entity.'),
'counter title' => t('@entity_label flag counter', array(
'@entity_label' => $entity_info['label'],
)),
'counter help' => t('Include this to gain access to the flag counter field.'),
);
}
}
class flag_node extends flag_entity {
function options() {
$options = parent::options();
unset($options['show_on_entity']);
$options += array(
'show_on_page' => TRUE,
'show_on_teaser' => TRUE,
'show_on_form' => FALSE,
'show_contextual_link' => FALSE,
'i18n' => 0,
);
return $options;
}
function options_form(&$form) {
parent::options_form($form);
$form['access']['access_author'] = array(
'#type' => 'radios',
'#title' => t('Flag access by content authorship'),
'#options' => array(
'' => t('No additional restrictions'),
'own' => t('Users may only flag content they own'),
'others' => t('Users may only flag content of others'),
),
'#default_value' => $this->access_author,
'#description' => t("Restrict access to this flag based on the user's ownership of the content. Users must also have access to the flag through the role settings."),
);
$form['i18n'] = array(
'#type' => 'radios',
'#title' => t('Internationalization'),
'#options' => array(
'1' => t('Flag translations of content as a group'),
'0' => t('Flag each translation of content separately'),
),
'#default_value' => $this->i18n,
'#description' => t('Flagging translations as a group effectively allows users to flag the original piece of content regardless of the translation they are viewing. Changing this setting will <strong>not</strong> update content that has been flagged already.'),
'#access' => module_exists('translation_helpers'),
'#weight' => 5,
);
$form['display']['show_on_teaser'] = array(
'#type' => 'checkbox',
'#title' => t('Display link on node teaser'),
'#default_value' => $this->show_on_teaser,
'#access' => empty($this->locked['show_on_teaser']),
);
$form['display']['show_on_page'] = array(
'#type' => 'checkbox',
'#title' => t('Display link on node page'),
'#default_value' => $this->show_on_page,
'#access' => empty($this->locked['show_on_page']),
);
$form['display']['show_on_form'] = array(
'#title' => t('Display checkbox on node edit form'),
'#description' => t('If you elect to have a checkbox on the node edit form, you may specify its initial state in the settings form <a href="@content-types-url">for each content type</a>.', array(
'@content-types-url' => url('admin/structure/types'),
)),
) + $form['display']['show_on_form'];
$form['display']['show_contextual_link'] = array(
'#type' => 'checkbox',
'#title' => t('Display in contextual links'),
'#default_value' => $this->show_contextual_link,
'#access' => empty($this->locked['show_contextual_link']) && module_exists('contextual'),
'#weight' => 10,
);
unset($form['display']['show_on_entity']);
}
function type_access_multiple($content_ids, $account) {
$access = array();
if (empty($this->types)) {
return $access;
}
$result = db_select('node', 'n')
->fields('n', array(
'nid',
))
->condition('nid', array_keys($content_ids), 'IN')
->condition('type', $this->types, 'NOT IN')
->execute();
foreach ($result as $row) {
$access[$row->nid] = FALSE;
}
return $access;
}
function get_translation_id($content_id) {
if ($this->i18n) {
$node = $this
->fetch_content($content_id);
if (!empty($node->tnid)) {
$content_id = $node->tnid;
}
}
return $content_id;
}
function uses_hook_link($teaser) {
if ($teaser && $this->show_on_teaser || !$teaser && $this->show_on_page) {
return TRUE;
}
return FALSE;
}
function flag($action, $content_id, $account = NULL, $skip_permission_check = FALSE) {
$content_id = $this
->get_translation_id($content_id);
return parent::flag($action, $content_id, $account, $skip_permission_check);
}
function get_flagging_record($content_id, $uid = NULL, $sid = NULL) {
$content_id = $this
->get_translation_id($content_id);
return parent::get_flagging_record($content_id, $uid, $sid);
}
function replace_tokens($label, $contexts, $options, $content_id) {
if (is_numeric($content_id) && ($node = $this
->fetch_content($content_id))) {
$contexts['node'] = $node;
}
elseif (!empty($content_id) && ($type = node_type_get_type($content_id))) {
$content_id = NULL;
$contexts['node'] = (object) array(
'nid' => NULL,
'type' => $type->type,
'title' => '',
);
}
return parent::replace_tokens($label, $contexts, $options, $content_id);
}
}
class flag_comment extends flag_entity {
function options() {
$options = parent::options();
unset($options['show_on_entity']);
$options += array(
'access_author' => '',
'show_on_comment' => TRUE,
);
return $options;
}
function options_form(&$form) {
parent::options_form($form);
$form['access']['access_author'] = array(
'#type' => 'radios',
'#title' => t('Flag access by content authorship'),
'#options' => array(
'' => t('No additional restrictions'),
'comment_own' => t('Users may only flag own comments'),
'comment_others' => t('Users may only flag comments by others'),
'node_own' => t('Users may only flag comments of nodes they own'),
'node_others' => t('Users may only flag comments of nodes by others'),
),
'#default_value' => $this->access_author,
'#description' => t("Restrict access to this flag based on the user's ownership of the content. Users must also have access to the flag through the role settings."),
);
$form['display']['show_on_comment'] = array(
'#type' => 'checkbox',
'#title' => t('Display link under comment'),
'#default_value' => $this->show_on_comment,
'#access' => empty($this->locked['show_on_comment']),
);
unset($form['display']['show_on_entity']);
}
function type_access_multiple($content_ids, $account) {
$access = array();
$query = db_select('comment', 'c');
$query
->innerJoin('node', 'n', 'c.nid = n.nid');
$result = $query
->fields('c', array(
'cid',
))
->condition('c.cid', $content_ids, 'IN')
->condition('n.type', $this->types, 'NOT IN')
->execute();
foreach ($result as $row) {
$access[$row->nid] = FALSE;
}
return $access;
}
function get_content_id($comment) {
$this
->remember_content($comment->cid, $comment);
return $comment->cid;
}
function uses_hook_link($teaser) {
return $this->show_on_comment;
}
function get_labels_token_types() {
return array_merge(array(
'comment',
'node',
), parent::get_labels_token_types());
}
function replace_tokens($label, $contexts, $options, $content_id) {
if ($content_id) {
if (($comment = $this
->fetch_content($content_id)) && ($node = node_load($comment->nid))) {
$contexts['node'] = $node;
$contexts['comment'] = $comment;
}
}
return parent::replace_tokens($label, $contexts, $options, $content_id);
}
function get_flag_action($content_id) {
$flag_action = parent::get_flag_action($content_id);
$comment = $this
->fetch_content($content_id);
$flag_action->content_title = $comment->subject;
$flag_action->content_url = _flag_url("comment/{$comment->cid}", "comment-{$comment->cid}");
return $flag_action;
}
function get_relevant_action_objects($content_id) {
$comment = $this
->fetch_content($content_id);
return array(
'comment' => $comment,
'node' => node_load($comment->nid),
);
}
}
class flag_user extends flag_entity {
function options() {
$options = parent::options();
$options['show_on_entity'] = FALSE;
$options += array(
'show_on_profile' => TRUE,
'access_uid' => '',
);
return $options;
}
function options_form(&$form) {
parent::options_form($form);
$form['access']['types'] = array(
'#type' => 'value',
'#value' => array(
0 => 0,
),
);
$form['access']['access_uid'] = array(
'#type' => 'checkbox',
'#title' => t('Users may flag themselves'),
'#description' => t('Disabling this option may be useful when setting up a "friend" flag, when a user flagging themself does not make sense.'),
'#default_value' => $this->access_uid ? 0 : 1,
);
$form['display']['show_on_profile'] = array(
'#type' => 'checkbox',
'#title' => t('Display link on user profile page'),
'#description' => t('Show the link formatted as a user profile element.'),
'#default_value' => $this->show_on_profile,
'#access' => empty($this->locked['show_on_profile']),
'#weight' => -1,
);
$form['display']['show_on_entity']['#description'] = t('Show the link in the same format as on other entities.');
}
function form_input($form_values) {
parent::form_input($form_values);
$this->access_uid = empty($form_values['access_uid']) ? 'others' : '';
}
function type_access($content_id, $action, $account) {
if ($this->access_uid == 'others' && $content_id == $account->uid) {
return FALSE;
}
}
function type_access_multiple($content_ids, $account) {
$access = array();
if (array_key_exists(0, $content_ids)) {
$access[0] = FALSE;
}
if ($this->access_uid == 'others' && array_key_exists($account->uid, $content_ids)) {
$access[$account->uid] = FALSE;
}
return $access;
}
function get_flag_action($content_id) {
$flag_action = parent::get_flag_action($content_id);
$user = $this
->fetch_content($content_id);
$flag_action->content_title = $user->name;
$flag_action->content_url = _flag_url('user/' . $user->uid);
return $flag_action;
}
function get_relevant_action_objects($content_id) {
return array(
'user' => $this
->fetch_content($content_id),
);
}
function get_views_info() {
$views_info = parent::get_views_info();
$views_info['title field'] = 'name';
return $views_info;
}
}
class flag_broken extends flag_flag {
function options_form(&$form) {
drupal_set_message(t("The module providing this flag wasn't found, or this flag type, %type, isn't valid.", array(
'%type' => $this->content_type,
)), 'error');
$form = array();
}
}
function _flag_url($path, $fragment = NULL, $absolute = TRUE) {
return url($path, array(
'fragment' => $fragment,
'absolute' => $absolute,
));
}
abstract class FlagCookieStorage {
static function factory($flag) {
if ($flag->global) {
return new FlagGlobalCookieStorage($flag);
}
else {
return new FlagNonGlobalCookieStorage($flag);
}
}
function __construct($flag) {
$this->flag = $flag;
}
abstract function flag($content_id);
abstract function unflag($content_id);
static function drop() {
FlagGlobalCookieStorage::drop();
FlagNonGlobalCookieStorage::drop();
}
}
class FlagGlobalCookieStorage extends FlagCookieStorage {
function flag($content_id) {
$cookie_key = $this
->cookie_key($content_id);
setcookie($cookie_key, 1, REQUEST_TIME + $this
->get_lifetime(), base_path());
$_COOKIE[$cookie_key] = 1;
}
function unflag($content_id) {
$cookie_key = $this
->cookie_key($content_id);
setcookie($cookie_key, 0, REQUEST_TIME + $this
->get_lifetime(), base_path());
$_COOKIE[$cookie_key] = 0;
}
protected function get_lifetime() {
$cookie_lifetime = variable_get('cache', 0) ? variable_get('cache_lifetime', 0) : -1;
if ($cookie_lifetime == 0) {
$cookie_lifetime = 3600;
}
return $cookie_lifetime;
}
protected function cookie_key($content_id) {
return 'flag_global_' . $this->flag->name . '_' . $content_id;
}
static function drop() {
foreach ($_COOKIE as $key => $value) {
if (strpos($key, 'flag_global_') === 0) {
setcookie($key, FALSE, 0, base_path());
unset($_COOKIE[$key]);
}
}
}
}
class FlagNonGlobalCookieStorage extends FlagCookieStorage {
function __construct($flag) {
parent::__construct($flag);
$this->flaggings = isset($_COOKIE['flags']) ? explode(' ', $_COOKIE['flags']) : array();
}
function flag($content_id) {
if (!$this
->is_flagged($content_id)) {
$this->flaggings[] = $this
->cookie_key($content_id);
$this
->write();
}
}
function unflag($content_id) {
if (($index = $this
->index_of($content_id)) !== FALSE) {
unset($this->flaggings[$index]);
$this
->write();
}
}
protected function get_lifetime() {
return min((int) ini_get('session.cookie_lifetime'), (int) ini_get('session.gc_maxlifetime'));
}
protected function cookie_key($content_id) {
return $this->flag->name . '_' . $content_id;
}
protected function write() {
$serialized = implode(' ', array_filter($this->flaggings));
setcookie('flags', $serialized, REQUEST_TIME + $this
->get_lifetime(), base_path());
$_COOKIE['flags'] = $serialized;
}
protected function is_flagged($content_id) {
return $this
->index_of($content_id) !== FALSE;
}
protected function index_of($content_id) {
return array_search($this
->cookie_key($content_id), $this->flaggings);
}
static function drop() {
if (isset($_COOKIE['flags'])) {
setcookie('flags', FALSE, 0, base_path());
unset($_COOKIE['flags']);
}
}
}