View source  
  <?php
define('MESSAGE_FIELD_MESSAGE_TEXT', 'message_text');
define('MESSAGE_PURGE_LIMIT', 100);
function message_ctools_plugin_type() {
  $plugins['computed_arguments'] = array(
    'classes' => array(
      'class',
    ),
    'child plugins' => TRUE,
  );
  return $plugins;
}
function message_get_computed_arguments_handler(Message $message) {
  $plugin = message_get_computed_arguments_plugin($message
    ->bundle());
  if (!($class = ctools_plugin_load_class('message', 'computed_arguments', $message
    ->bundle(), 'class'))) {
    return NULL;
  }
  $handler = new $class($plugin);
  return $handler
    ->setMessage($message);
}
function message_get_computed_arguments_plugin($plugin_name = '') {
  ctools_include('plugins');
  return ctools_get_plugins('message', 'computed_arguments', $plugin_name);
}
function message_views_api() {
  return array(
    'api' => 3,
    'path' => drupal_get_path('module', 'message') . '/includes/views',
  );
}
function message_ctools_plugin_directory($module, $plugin) {
  if ($module == 'ctools') {
    return 'ctools/' . $plugin;
  }
}
function message_theme() {
  $info['message'] = array(
    'render element' => 'elements',
    'template' => 'message',
  );
  return $info;
}
function message_message_view_alter(&$build) {
  $build['#theme'] = 'message';
}
function template_preprocess_message(&$variables) {
  $message = $variables['elements']['#entity'];
  $variables['view_mode'] = $variables['elements']['#view_mode'];
  $variables['message'] = $message;
  
  $variables['content'] = array();
  foreach (element_children($variables['elements']) as $key) {
    $variables['content'][$key] = $variables['elements'][$key];
  }
  
  field_attach_preprocess('message', $message, $variables['content'], $variables);
  list(, , $bundle) = entity_extract_ids('message', $message);
  
  $variables['classes_array'][] = drupal_html_class('entity-message');
  $variables['classes_array'][] = drupal_html_class('message-' . $bundle);
  
  $variables['theme_hook_suggestions'][] = 'message';
  $variables['theme_hook_suggestions'][] = 'message__' . $bundle;
  $variables['theme_hook_suggestions'][] = 'message__' . $bundle . '__' . $variables['view_mode'];
  if ($id = entity_id('message', $message)) {
    $variables['theme_hook_suggestions'][] = 'message__' . $id;
  }
}
function message_permission() {
  $permissions = array();
  $permissions['administer message types'] = array(
    'title' => t('Administer message types'),
    'description' => t('Administer message types that can be used to log an event.'),
  );
  $permissions['create messages'] = array(
    'title' => t('Create messages'),
    'description' => t('Log new messages.'),
  );
  return $permissions;
}
function message_entity_info() {
  $items['message_type_category'] = array(
    'label' => t('Message type category'),
    'controller class' => 'EntityAPIControllerExportable',
    'entity class' => 'MessageTypeCategory',
    'base table' => 'message_type_category',
    'fieldable' => TRUE,
    'entity keys' => array(
      'id' => 'id',
      'label' => 'description',
      'name' => 'category',
      'language' => 'language',
    ),
    'exportable' => TRUE,
    'export' => array(
      'default hook' => 'default_message_type_category',
    ),
    'bundle of' => 'message_type',
    'module' => 'message',
    'access callback' => 'message_type_category_access',
  );
  $items['message_type'] = array(
    'label' => t('Message type'),
    'controller class' => 'EntityAPIControllerExportable',
    'entity class' => 'MessageType',
    'base table' => 'message_type',
    'fieldable' => TRUE,
    'entity keys' => array(
      'id' => 'id',
      'label' => 'description',
      'name' => 'name',
      'bundle' => 'category',
      'language' => 'language',
    ),
    'bundles' => array(
      'message_type' => array(
        'label' => t('Message type'),
      ),
    ),
    'bundle keys' => array(
      'bundle' => 'category',
    ),
    'exportable' => TRUE,
    'export' => array(
      'default hook' => 'default_message_type',
    ),
    'bundle of' => 'message',
    'module' => 'message',
    'access callback' => 'message_type_access',
    'entity cache' => module_exists('entitycache'),
    
    'admin ui' => array(
      'path' => 'admin/structure/messages',
      'file' => 'includes/message.admin.inc',
      'controller class' => 'MessageTypeUIController',
    ),
  );
  if (module_exists('locale')) {
    $items['message_type']['translation']['locale'] = TRUE;
  }
  
  if (db_table_exists('message_type_category')) {
    $message_categories = db_select('message_type_category', 'mtc')
      ->fields('mtc')
      ->execute()
      ->fetchAllAssoc('category');
    foreach ($message_categories as $category_name => $category) {
      $items['message_type']['bundles'][$category_name] = array(
        'label' => $category->category,
      );
    }
  }
  $items['message'] = array(
    'label' => t('Message'),
    'controller class' => 'EntityAPIController',
    'entity class' => 'Message',
    'base table' => 'message',
    'fieldable' => TRUE,
    'access callback' => 'message_access',
    'entity keys' => array(
      'id' => 'mid',
      
      'label' => FALSE,
      'bundle' => 'type',
      'language' => 'language',
    ),
    'bundles' => array(),
    'bundle keys' => array(
      'bundle' => 'name',
    ),
    'view modes' => array(
      'full' => array(
        'label' => t('Full'),
        'custom settings' => FALSE,
      ),
    ),
    'module' => 'message',
    'metadata controller class' => 'MessageMetadataController',
    'views controller class' => 'MessageViewsController',
    'entity cache' => module_exists('entitycache'),
  );
  
  if (db_table_exists('message_type')) {
    $message_types = db_select('message_type', 'mt')
      ->fields('mt')
      ->execute()
      ->fetchAllAssoc('name');
  }
  foreach ($message_types as $type_name => $type) {
    $items['message']['bundles'][$type_name] = array(
      'label' => $type->description,
      'admin' => array(
        'path' => 'admin/structure/messages/manage/%message_type',
        'real path' => 'admin/structure/messages/manage/' . $type->name,
        'bundle argument' => 4,
        'access arguments' => array(
          'administer message types',
        ),
      ),
    );
  }
  return $items;
}
function message_menu() {
  $items = array();
  $items['admin/config/system/message'] = array(
    'title' => 'Message settings',
    'description' => 'Manage message purging upon cron.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'message_user_admin_settings',
    ),
    'access arguments' => array(
      'administer message types',
    ),
    'file' => 'includes/message.admin.inc',
  );
  $items['admin/config/system/message/text-copy'] = array(
    'title' => 'Copy messages text fields',
    'description' => 'Copy messages text fields from one language to others',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'message_admin_text_copy',
    ),
    'access arguments' => array(
      'administer message types',
    ),
    'file' => 'includes/message.admin.inc',
  );
  return $items;
}
function message_cron() {
  
  $purge_limit = variable_get('message_delete_cron_limit', MESSAGE_PURGE_LIMIT);
  
  $purge_messages = array();
  
  $no_override_type_names = array();
  
  $override_types = array();
  
  foreach (message_type_load() as $message_type) {
    if (empty($message_type->data['purge']['override'])) {
      $no_override_type_names[] = $message_type->name;
    }
    else {
      
      $override_types[] = $message_type;
    }
  }
  
  foreach ($override_types as $message_type) {
    
    if (empty($message_type->data['purge']) || empty($message_type->data['purge']['enabled'])) {
      continue;
    }
    $purge_messages += message_get_purgeable_by_type($purge_limit, $message_type->name, $message_type->data['purge']);
  }
  
  if (!empty($no_override_type_names)) {
    
    if (variable_get('message_purge_enable', FALSE)) {
      $purge_settings = array(
        'quota' => variable_get('message_purge_quota', NULL),
        'days' => variable_get('message_purge_days', NULL),
      );
      $purge_messages += message_get_purgeable_by_type($purge_limit, $no_override_type_names, $purge_settings);
    }
  }
  
  if (!empty($purge_messages)) {
    message_delete_multiple(array_keys($purge_messages));
  }
}
function message_entity_delete($entity, $entity_type) {
  if ($entity_type == 'message') {
    return;
  }
  if (!($field_names = _message_get_referenced_fields($entity_type, $entity))) {
    return;
  }
  list($entity_id) = entity_extract_ids($entity_type, $entity);
  
  $delete_referenced_entities = FALSE;
  foreach ($field_names as $field_name) {
    $field = field_info_field($field_name);
    $columns = array_keys($field['columns']);
    
    $query = new EntityFieldQuery();
    $result = $query
      ->entityCondition('entity_type', 'message')
      ->fieldCondition($field['field_name'], $columns[0], $entity_id)
      ->execute();
    if (!empty($result['message'])) {
      $delete_referenced_entities = TRUE;
      break;
    }
  }
  if (!$delete_referenced_entities) {
    return;
  }
  if (variable_get('message_use_queue')) {
    $data = array(
      'range' => 200,
      'last_mid' => 0,
      'field_names' => $field_names,
      'entity_id' => $entity_id,
    );
    $queue = DrupalQueue::get('message_entity_delete');
    return $queue
      ->createItem($data);
  }
  _message_delete_messages($field_names, $entity_id);
}
function _message_get_referenced_fields($entity_type, $entity) {
  $entity_types = variable_get('message_delete_on_entity_delete', array(
    'node',
    'user',
    'taxonomy_term',
    'comment',
  ));
  if (!$entity_types || !in_array($entity_type, $entity_types)) {
    return;
  }
  list(, , $bundle) = entity_extract_ids($entity_type, $entity);
  $field_names = array();
  
  foreach (field_info_fields() as $field) {
    if (empty($field['bundles']['message'])) {
      
      continue;
    }
    
    if ($field['type'] == 'entityreference') {
      
      if ($entity_type != $field['settings']['target_type']) {
        continue;
      }
      
      if ($field['settings']['handler_settings']['target_bundles'] && !in_array($bundle, $field['settings']['handler_settings']['target_bundles'])) {
        continue;
      }
    }
    elseif ($field['type'] == 'taxonomy_term_reference') {
      if ($entity_type != 'taxonomy_term') {
        continue;
      }
    }
    else {
      continue;
    }
    $field_names[] = $field['field_name'];
  }
  return $field_names;
}
function _message_delete_messages($field_names, $entity_id, $last_mid = 0, $range = NULL) {
  
  $deletable_mids = array();
  
  $check_mids = array();
  foreach ($field_names as $field_name) {
    $field = field_info_field($field_name);
    $columns = array_keys($field['columns']);
    
    $query = new EntityFieldQuery();
    $query
      ->entityCondition('entity_type', 'message')
      ->propertyCondition('mid', $last_mid, '>')
      ->fieldCondition($field['field_name'], $columns[0], $entity_id);
    if ($range) {
      $query
        ->range(0, $range);
    }
    $result = $query
      ->execute();
    
    if (empty($result['message'])) {
      continue;
    }
    
    if ($field['cardinality'] == 1) {
      $deletable_mids += array_keys($result['message']);
    }
    else {
      foreach ($result['message'] as $mid => $message) {
        
        if (empty($check_mids[$mid])) {
          $check_mids[$mid] = array();
        }
        $check_mids[$mid][] = $field['field_name'];
      }
    }
  }
  
  if ($check_mids) {
    $messages = message_load_multiple(array_keys($check_mids));
    foreach ($messages as $message) {
      foreach ($check_mids[$message->mid] as $field_name) {
        $field = field_info_field($field_name);
        $wrapper = entity_metadata_wrapper('message', $message);
        $count = $field['cardinality'] == 1 ? 1 : $wrapper->{$field_name}
          ->count();
        
        $refrences_count = 0;
        for ($i = 0; $i < $count; $i++) {
          if ($wrapper->{$field_name}
            ->get($i)
            ->value()) {
            $refrences_count++;
          }
        }
        
        if ($refrences_count == 1) {
          $deletable_mids[] = $message->mid;
        }
      }
    }
  }
  if ($deletable_mids) {
    message_delete_multiple($deletable_mids);
    return reset($deletable_mids);
  }
}
function message_get_purgeable_by_type(&$purge_limit, $message_type_name, $purge_settings) {
  if ($purge_limit <= 0) {
    return;
  }
  
  $purge_messages = array();
  
  $base_query = new EntityFieldQuery();
  $base_query
    ->entityCondition('entity_type', 'message', '=')
    ->propertyCondition('type', $message_type_name, is_array($message_type_name) ? 'IN' : '=')
    ->propertyOrderBy('timestamp', 'DESC')
    ->propertyOrderBy('mid', 'DESC');
  
  if (!empty($purge_settings['quota'])) {
    $quota_query = clone $base_query;
    $result = $quota_query
      ->range($purge_settings['quota'], $purge_limit)
      ->execute();
    if (!empty($result['message'])) {
      $purge_limit -= count($result['message']);
      $purge_messages += $result['message'];
    }
  }
  
  if (!empty($purge_settings['days'])) {
    $age_query = clone $base_query;
    
    $earlier_than = time() - $purge_settings['days'] * 86400;
    $result = $age_query
      ->propertyCondition('timestamp', $earlier_than, '<')
      ->range(0, $purge_limit)
      ->execute();
    if (!empty($result['message'])) {
      $purge_limit -= count($result['message']);
      $purge_messages += $result['message'];
    }
  }
  return $purge_messages;
}
function message_field_extra_fields() {
  $return = array();
  foreach (message_type_load() as $message_type) {
    
    foreach (field_info_instances('message_type', $message_type->category) as $field_name => $value) {
      $field = field_info_field($field_name);
      if (empty($field['settings']['message_text'])) {
        continue;
      }
      $field_items = field_get_items('message_type', $message_type, $field_name);
      $count = is_array($field_items) ? count($field_items) : 1;
      for ($delta = 0; $delta < $count; $delta++) {
        $params = array(
          '@label' => $value['label'],
          '@delta' => $delta,
        );
        $return['message'][$message_type->name]['display']['message__' . $field['field_name'] . '__' . $delta] = array(
          'label' => $count == 1 ? $value['label'] : t('@label @delta partial', $params),
          'description' => $count == 1 ? t('Complete rendered message text.') : t('Rendered message text of the @delta partial', $params),
          'weight' => $delta,
        );
      }
    }
  }
  return $return;
}
function message_field_attach_form($entity_type, $entity, &$form, &$form_state, $langcode) {
  if ($entity_type != 'message_type' || empty($entity->name)) {
    return;
  }
  $bundle_settings = field_bundle_settings('message', $entity->name);
  $entity_info = entity_get_info('message');
  $current_view_modes = array();
  
  foreach (message_get_text_fields() as $field_name) {
    foreach ($bundle_settings['extra_fields']['display'] as $delta => $view_modes) {
      $identeifer = "message__{$field_name}__";
      if (strpos($delta, $identeifer) !== 0) {
        
        continue;
      }
      $delta = str_replace($identeifer, '', $delta);
      foreach ($view_modes as $view_mode => $value) {
        if ($value['visible']) {
          $url = "admin/structure/messages/manage/{$entity->name}/display/{$view_mode}";
          $label = $view_mode == 'default' ? t('Default') : $entity_info['view modes'][$view_mode]['label'];
          $current_view_modes[$field_name][$delta][] = l($label, $url);
        }
      }
    }
  }
  foreach (message_get_text_fields() as $field_name) {
    if (empty($form[$field_name])) {
      continue;
    }
    $langcodes = $form[$field_name];
    foreach (element_children($langcodes) as $langcode) {
      $deltas = $form[$field_name][$langcode];
      foreach (element_children($deltas) as $delta) {
        if (empty($current_view_modes[$field_name][$delta])) {
          continue;
        }
        $form[$field_name][$langcode][$delta]['view_mode'] = array(
          '#markup' => t('View modes: !view-modes', array(
            '!view-modes' => implode(', ', $current_view_modes[$field_name][$delta]),
          )),
        );
      }
    }
  }
}
function message_type_category_create($category, $values = array()) {
  global $language;
  
  if (message_type_category_load($category)) {
    throw new MessageException('Message type category' . check_plain($category) . ' already exists.');
  }
  $values['category'] = $category;
  $values += array(
    'language' => $language->language,
  );
  $return = entity_create('message_type_category', $values);
  return $return;
}
function message_type_category_load($name = NULL) {
  
  $types = entity_load_multiple_by_name('message_type_category', isset($name) ? array(
    strtr($name, array(
      '-' => '_',
    )),
  ) : FALSE);
  if (isset($name)) {
    return isset($types[$name]) ? $types[$name] : FALSE;
  }
  return $types;
}
function message_type_category_save($message) {
  return entity_save('message_type_category', $message);
}
function message_type_category_delete($message) {
  return entity_delete('message_type_category', $message);
}
function message_type_create($name, $values = array()) {
  global $language;
  
  if (message_type_load($name)) {
    throw new MessageException('Message type ' . check_plain($name) . ' already exists.');
  }
  $values['name'] = $name;
  $values += array(
    'language' => $language->language,
  );
  $return = entity_create('message_type', $values);
  return $return;
}
function message_type_load($name = NULL) {
  
  $types = entity_load_multiple_by_name('message_type', isset($name) ? array(
    strtr($name, array(
      '-' => '_',
    )),
  ) : FALSE);
  if (isset($name)) {
    return isset($types[$name]) ? $types[$name] : FALSE;
  }
  return $types;
}
function message_type_save($message) {
  return entity_save('message_type', $message);
}
function message_type_delete($message) {
  return entity_delete('message_type', $message);
}
function message_create($type, $values = array(), $account = NULL) {
  global $language;
  if (empty($account)) {
    global $user;
    $account = clone $user;
  }
  $values['type'] = $type;
  $values['user'] = $account;
  $values += array(
    'language' => $language->language,
  );
  return entity_create('message', $values);
}
function message_load($mid) {
  $result = entity_load('message', array(
    $mid,
  ));
  return $result ? reset($result) : FALSE;
}
function message_load_multiple($mids, $conditions = array()) {
  return entity_load('message', $mids, $conditions);
}
function message_save($message) {
  return entity_save('message', $message);
}
function message_delete_multiple($mids = array()) {
  entity_delete_multiple('message', $mids);
}
function message_access($op, $entity, $account = NULL, $entity_type = 'message') {
  return user_access('create messages', $account);
}
function message_type_access($op, $entity, $account, $entity_type) {
  return user_access('administer message types', $account);
}
function message_type_category_access($op, $entity, $account, $entity_type) {
  return user_access('administer message types', $account);
}
function message_property_get_argument($arguments, array $options, $name, $type, $context) {
  return isset($arguments[$context['message_replace_char'] . $name]) ? $arguments[$context['message_replace_char'] . $name] : NULL;
}
function message_property_set_argument(&$arguments, $name, $value, $langcode, $type, $context) {
  $arguments[$context['message_replace_char'] . $name] = $value;
}
function message_property_get_text($message, array $options) {
  $langcode = isset($options['language']) ? $options['language']->language : LANGUAGE_NONE;
  return $message
    ->getText($langcode);
}
function message_get_property_values(Message $message, $name, $key = NULL, $default_value = array()) {
  $message_type = $message
    ->getType();
  if (isset($key)) {
    $type_value = isset($message_type->{$name}[$key]) ? $message_type->{$name}[$key] : array();
    $value = isset($message->{$name}[$key]) ? $message->{$name}[$key] : array();
  }
  else {
    $type_value = isset($message_type->{$name}) ? $message_type->{$name} : array();
    $value = isset($message->{$name}) ? $message->{$name} : array();
  }
  if (isset($value) && !is_array($value)) {
    
    return $value;
  }
  elseif (isset($type_value) && !is_array($type_value)) {
    
    return $type_value;
  }
  elseif (!empty($value) || !empty($type_value)) {
    
    return array_merge($type_value, $value);
  }
  
  return $default_value;
}
function message_get_text_fields() {
  $message_fields = array();
  foreach (field_info_fields() as $field_name => $field) {
    if (!empty($field['settings']['message_text'])) {
      $message_fields[] = $field_name;
    }
  }
  return $message_fields;
}
function message_admin_text_copy_batch($origin_lang, $dest_langs, $override, &$context) {
  if (empty($context['sandbox'])) {
    $context['sandbox']['progress'] = 0;
    $context['sandbox']['current_id'] = 0;
    $context['sandbox']['max'] = db_select('message_type')
      ->countQuery()
      ->execute()
      ->fetchField();
  }
  $result = db_select('message_type', 'mt')
    ->fields('mt', array(
    'id',
  ))
    ->condition('id', $context['sandbox']['current_id'], '>')
    ->orderBy('id')
    ->range(0, 50)
    ->execute();
  foreach ($result as $row) {
    $context['sandbox']['progress']++;
    $context['sandbox']['current_id'] = $row->id;
    $entity = entity_load_single('message_type', $row->id);
    
    if (empty($entity->message_text[$origin_lang])) {
      continue;
    }
    foreach ($entity->message_text[$origin_lang] as $delta => $message_text) {
      
      foreach ($dest_langs as $dest_lang) {
        foreach (message_get_text_fields() as $field_name) {
          
          if (!$override && !empty($entity->{$field_name}[$dest_lang][$delta])) {
            continue;
          }
          
          $entity->{$field_name}[$dest_lang][$delta] = $message_text;
        }
      }
    }
    
    message_type_save($entity);
  }
  if ($context['sandbox']['progress'] != $context['sandbox']['max']) {
    $context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max'];
  }
}
function message_features_pipe_message_type_alter(&$pipe, $data, $export) {
  if (empty($data) || !module_exists('strongarm')) {
    return;
  }
  foreach ($data as $message_type) {
    $pipe['variable'][] = "field_bundle_settings_message__{$message_type}";
  }
}
function message_cron_queue_info() {
  $items['message_entity_delete'] = array(
    'title' => t('Message'),
    'worker callback' => 'message_entity_delete_queue_worker',
    'time' => 60,
  );
  return $items;
}
function message_entity_delete_queue_worker($data) {
  extract($data);
  if (!($mid = _message_delete_messages($field_names, $entity_id, $last_mid, $range))) {
    return;
  }
  $data = array(
    'range' => 200,
    'last_mid' => $mid,
    'field_names' => $field_names,
    'entity_id' => $entity_id,
  );
  $queue = DrupalQueue::get('message_entity_delete');
  return $queue
    ->createItem($data);
}