FINAL suepr merge step : added all modules to this super repos
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
View Mandrill activity for any entity with a valid email address.
|
||||
Activity keys off of an email address.
|
||||
|
||||
## Installation
|
||||
|
||||
1. Enable the Mandrill Activity module.
|
||||
2. To use Mandrill Activity module, you will need to install and enable Mandrill
|
||||
and Entity API module [http://drupal.org/project/entity]([http://drupal.org/project/entity).
|
||||
|
||||
## Usage
|
||||
|
||||
1. Define which entity types you want to show Mandrill activity for at
|
||||
/admin/config/services/mandrill/activity.
|
||||
* Select a Drupal entity type.
|
||||
* Select a bundle.
|
||||
* Select the email entity property.
|
||||
2. Configure permissions for viewing Mandrill activity.
|
||||
3. Once setup, a new Mandrill activity local task will appear for any configured
|
||||
entity.
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
/**
|
||||
* @file
|
||||
* Class defining a MandrillActivityEntity.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class MandrillActivityEntity
|
||||
*
|
||||
* Extend Entity to define a MandrillActivityEntity.
|
||||
*/
|
||||
class MandrillActivityEntity extends Entity {
|
||||
public
|
||||
$mandrill_activity_entity_id,
|
||||
$name,
|
||||
$label,
|
||||
$entity_type,
|
||||
$bundle,
|
||||
$email_property,
|
||||
$entity_path,
|
||||
$enabled;
|
||||
|
||||
/**
|
||||
* Override constructor to set entity type.
|
||||
*/
|
||||
public function __construct(array $values = array()) {
|
||||
parent::__construct($values, 'mandrill_activity_entity');
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a label for this entity.
|
||||
*
|
||||
* @return string
|
||||
* Label.
|
||||
*/
|
||||
public function label() {
|
||||
return $this->label;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
/**
|
||||
* @file
|
||||
* Class defining MandrillActivityUIController.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Override EntityDefaultUIController to customize our menu items.
|
||||
*/
|
||||
class MandrillActivityUIController extends EntityDefaultUIController {
|
||||
|
||||
/**
|
||||
* Override hook_menu() to add a proper description.
|
||||
*/
|
||||
public function hook_menu() {
|
||||
$items = parent::hook_menu();
|
||||
$items[$this->path]['description'] = 'Manage Mandrill Activity entity settings.';
|
||||
$items[$this->path]['type'] = MENU_LOCAL_TASK;
|
||||
return $items;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,228 @@
|
||||
<?php
|
||||
/**
|
||||
* @file
|
||||
* Administration pages for mandrill_activity module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Returns a form for a mandrill_activity_entity.
|
||||
*/
|
||||
function mandrill_activity_entity_form($form, &$form_state, MandrillActivityEntity $mandrill_activity_entity = NULL, $op = 'edit') {
|
||||
if ($op == 'clone') {
|
||||
$mandrill_activity_entity->label .= ' (cloned)';
|
||||
$mandrill_activity_entity->name = '';
|
||||
}
|
||||
$entitynotnull = isset($mandrill_activity_entity->mandrill_activity_entity_id);
|
||||
$form_state['mandrill_activity'] = $mandrill_activity_entity;
|
||||
|
||||
$form['label'] = array(
|
||||
'#title' => t('Label'),
|
||||
'#type' => 'textfield',
|
||||
'#default_value' => $entitynotnull ? $mandrill_activity_entity->label : '',
|
||||
'#description' => t('The human-readable name of this activity entity.'),
|
||||
'#required' => TRUE,
|
||||
'#weight' => -10,
|
||||
);
|
||||
|
||||
$form['name'] = array(
|
||||
'#title' => t('Name'),
|
||||
'#type' => 'machine_name',
|
||||
'#default_value' => $entitynotnull ? $mandrill_activity_entity->name : '',
|
||||
'#description' => t('machine name should only contain lowercase letters & underscores'),
|
||||
'#disabled' => !empty($mandrill_activity_entity->name),
|
||||
'#required' => TRUE,
|
||||
'#machine_name' => array(
|
||||
'exists' => 'mandrill_activity_load',
|
||||
'source' => array('label'),
|
||||
),
|
||||
'#weight' => -9,
|
||||
);
|
||||
|
||||
$form['drupal_entity'] = array(
|
||||
'#title' => t('Drupal entity'),
|
||||
'#type' => 'fieldset',
|
||||
'#attributes' => array(
|
||||
'id' => array('Mandrill-activity-drupal-entity'),
|
||||
),
|
||||
'#weight' => -8,
|
||||
);
|
||||
|
||||
// Prep the entity type list before creating the form item:
|
||||
$entity_types = array('' => t('-- Select --'));
|
||||
foreach (entity_get_info() as $entity_type => $info) {
|
||||
// Ignore Mandrill entity types.
|
||||
if (strpos($entity_type, 'mandrill') === FALSE) {
|
||||
$entity_types[$entity_type] = $info['label'];
|
||||
}
|
||||
}
|
||||
asort($entity_types);
|
||||
$form['drupal_entity']['entity_type'] = array(
|
||||
'#title' => t('Entity type'),
|
||||
'#type' => 'select',
|
||||
'#options' => $entity_types,
|
||||
'#default_value' => $entitynotnull ? $mandrill_activity_entity->entity_type : 0,
|
||||
'#required' => TRUE,
|
||||
'#description' => t('Select an entity type to enable Mandrill history on.'),
|
||||
'#ajax' => array(
|
||||
'callback' => 'mandrill_activity_mapping_form_callback',
|
||||
'wrapper' => 'Mandrill-activity-drupal-entity',
|
||||
),
|
||||
'#weight' => -8,
|
||||
);
|
||||
|
||||
$form_entity_type = & $form_state['values']['entity_type'];
|
||||
if (!$form_entity_type && $entitynotnull) {
|
||||
$form_entity_type = $mandrill_activity_entity->entity_type;
|
||||
}
|
||||
if ($form_entity_type) {
|
||||
// Prep the bundle list before creating the form item:
|
||||
$bundles = array('' => t('-- Select --'));
|
||||
$info = entity_get_info($form_entity_type);
|
||||
foreach ($info['bundles'] as $key => $bundle) {
|
||||
$bundles[$key] = $bundle['label'];
|
||||
}
|
||||
asort($bundles);
|
||||
$form['drupal_entity']['bundle'] = array(
|
||||
'#title' => t('Entity bundle'),
|
||||
'#type' => 'select',
|
||||
'#required' => TRUE,
|
||||
'#description' => t('Select a Drupal entity bundle with an email address to report on.'),
|
||||
'#options' => $bundles,
|
||||
'#default_value' => $entitynotnull ? $mandrill_activity_entity->bundle : 0,
|
||||
'#weight' => -7,
|
||||
'#ajax' => array(
|
||||
'callback' => 'mandrill_activity_mapping_form_callback',
|
||||
'wrapper' => 'Mandrill-activity-drupal-entity',
|
||||
),
|
||||
);
|
||||
|
||||
$form_bundle = & $form_state['values']['bundle'];
|
||||
if (!$form_bundle && $entitynotnull) {
|
||||
$form_bundle = $mandrill_activity_entity->bundle;
|
||||
}
|
||||
if ($form_bundle) {
|
||||
// Prep the field & properties list before creating the form item:
|
||||
$fields = mandrill_activity_email_fieldmap_options($form_entity_type, $form_bundle);
|
||||
$form['drupal_entity']['email_property'] = array(
|
||||
'#title' => t('Email Property'),
|
||||
'#type' => 'select',
|
||||
'#required' => TRUE,
|
||||
'#description' => t('Select the field which contains the email address'),
|
||||
'#options' => $fields,
|
||||
'#default_value' => $entitynotnull ? $mandrill_activity_entity->email_property : 0,
|
||||
'#maxlength' => 127,
|
||||
'#weight' => -6,
|
||||
);
|
||||
}
|
||||
}
|
||||
$form['enabled'] = array(
|
||||
'#title' => t('Enabled'),
|
||||
'#type' => 'checkbox',
|
||||
'#default_value' => $entitynotnull ? $mandrill_activity_entity->enabled : TRUE,
|
||||
'#weight' => -5,
|
||||
);
|
||||
|
||||
$form['actions'] = array('#type' => 'actions');
|
||||
$form['actions']['submit'] = array(
|
||||
'#value' => t('Save Entity'),
|
||||
'#type' => 'submit',
|
||||
);
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax callback for mandrill_activity_mapping_form().
|
||||
*/
|
||||
function mandrill_activity_mapping_form_callback($form, &$form_state) {
|
||||
return $form['drupal_entity'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Validation callback for mandrill_activity_entity_form().
|
||||
*/
|
||||
function mandrill_activity_entity_form_validate($form, &$form_state) {
|
||||
$extant_mc_entities = entity_load('mandrill_activity_entity');
|
||||
$form_id = $form_state['mandrill_activity_entity']->mandrill_activity_entity_id;
|
||||
$form_bundle = $form_state['values']['bundle'];
|
||||
$form_entity_id = $form_state['values']['entity_type'];
|
||||
foreach ($extant_mc_entities as $extant_ent) {
|
||||
if ($form_bundle == $extant_ent->bundle &&
|
||||
$form_entity_id == $extant_ent->entity_type &&
|
||||
$form_id != $extant_ent->mandrill_activity_entity_id) {
|
||||
form_set_error(
|
||||
'bundle',
|
||||
t('A Mandrill Activity Entity already exists for this Bundle. Either select a different Bundle or edit the !link for this bundle.',
|
||||
array(
|
||||
'!link' => l(t('existing Mandrill Activity Entity'), "admin/config/services/mandrill/activity/manage/{$extant_ent->name}"),
|
||||
)
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Submit handler for mandrill_activity_entity_form().
|
||||
*/
|
||||
function mandrill_activity_entity_form_submit($form, &$form_state) {
|
||||
$values = $form_state['values'];
|
||||
if ($form_state['op'] == 'add' || $form_state['op'] == 'clone') {
|
||||
$dummy = entity_create($form_state['values']['entity_type'], array('type' => $form_state['values']['bundle']));
|
||||
$uri = entity_uri($form_state['values']['entity_type'], $dummy);
|
||||
$values['entity_path'] = $uri['path'];
|
||||
$activity_entity = entity_create('mandrill_activity_entity', $values);
|
||||
}
|
||||
else {
|
||||
$activity_entity = $form_state['mandrill_activity_entity'];
|
||||
foreach ($values as $key => $val) {
|
||||
$activity_entity->{$key} = $val;
|
||||
}
|
||||
}
|
||||
$activity_entity->save();
|
||||
|
||||
// Ensure the new local task appears on the entity.
|
||||
menu_rebuild();
|
||||
$form_state['redirect'] = 'admin/config/services/Mandrill/activity';
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all possible Drupal properties for a given entity type.
|
||||
*
|
||||
* @string $entity_type
|
||||
* Name of entity whose properties to list.
|
||||
* @string $entity_bundle
|
||||
* Entity bundle to get properties for.
|
||||
*
|
||||
* @return array
|
||||
* List of entities that can be used as an #options list.
|
||||
*/
|
||||
function mandrill_activity_email_fieldmap_options($entity_type, $entity_bundle = NULL) {
|
||||
$options = array('' => t('-- Select --'));
|
||||
|
||||
$properties = entity_get_all_property_info($entity_type);
|
||||
if (isset($entity_bundle)) {
|
||||
$info = entity_get_property_info($entity_type);
|
||||
$properties = $info['properties'];
|
||||
if (isset($info['bundles'][$entity_bundle])) {
|
||||
$properties += $info['bundles'][$entity_bundle]['properties'];
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($properties as $key => $property) {
|
||||
$type = isset($property['type']) ? entity_property_extract_innermost_type($property['type']) : 'text';
|
||||
$is_entity = ($type == 'entity') || (bool) entity_get_info($type);
|
||||
// Leave entities out of this.
|
||||
if (!$is_entity) {
|
||||
if (isset($property['field']) && $property['field'] && !empty($property['property info'])) {
|
||||
foreach ($property['property info'] as $sub_key => $sub_prop) {
|
||||
$options[$property['label']][$key . ':' . $sub_key] = $sub_prop['label'];
|
||||
}
|
||||
}
|
||||
else {
|
||||
$options[$key] = $property['label'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $options;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
name = Mandrill Activity
|
||||
description = View activity for an email address associated with any entity.
|
||||
package = Mandrill
|
||||
core = 7.x
|
||||
|
||||
dependencies[] = mandrill
|
||||
dependencies[] = entity
|
||||
|
||||
files[] = lib/mandrill_activity.entity.inc
|
||||
files[] = lib/mandrill_activity.ui_controller.inc
|
||||
|
||||
|
||||
; Information added by Drupal.org packaging script on 2014-05-09
|
||||
version = "7.x-1.6"
|
||||
core = "7.x"
|
||||
project = "mandrill"
|
||||
datestamp = "1399658028"
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
<?php
|
||||
/**
|
||||
* @file
|
||||
* Install hooks for mandrill_activity.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements hook_schema().
|
||||
*/
|
||||
function mandrill_activity_schema() {
|
||||
|
||||
$schema['mandrill_activity_entity'] = array(
|
||||
'description' => 'Mandrill activity enabled entities.',
|
||||
'fields' => array(
|
||||
'mandrill_activity_entity_id' => array(
|
||||
'type' => 'serial',
|
||||
'not null' => TRUE,
|
||||
'description' => 'Primary Key: Unique mandrill_activity_entity entity ID.',
|
||||
),
|
||||
'name' => array(
|
||||
'description' => 'The machine-readable name of this mandrill_activity_entity.',
|
||||
'type' => 'varchar',
|
||||
'length' => 128,
|
||||
'not null' => TRUE,
|
||||
),
|
||||
'label' => array(
|
||||
'description' => 'The human-readable name of this mandrill_activity_entity.',
|
||||
'type' => 'varchar',
|
||||
'length' => 128,
|
||||
'not null' => TRUE,
|
||||
),
|
||||
'entity_type' => array(
|
||||
'description' => 'The Drupal entity type (e.g. "node", "user").',
|
||||
'type' => 'varchar',
|
||||
'length' => 128,
|
||||
'not null' => TRUE,
|
||||
'default' => '',
|
||||
),
|
||||
'bundle' => array(
|
||||
'description' => 'The Drupal bundle (e.g. "page", "user")',
|
||||
'type' => 'varchar',
|
||||
'length' => 128,
|
||||
'not null' => TRUE,
|
||||
'default' => '',
|
||||
),
|
||||
'entity_path' => array(
|
||||
'description' => 'The path to view individual entities of the selected type.',
|
||||
'type' => 'varchar',
|
||||
'length' => 128,
|
||||
'not null' => TRUE,
|
||||
'default' => '',
|
||||
),
|
||||
'email_property' => array(
|
||||
'description' => 'The property that contains the email address to track',
|
||||
'type' => 'varchar',
|
||||
'length' => 128,
|
||||
'not null' => TRUE,
|
||||
'default' => '',
|
||||
),
|
||||
'enabled' => array(
|
||||
'type' => 'int',
|
||||
'not null' => TRUE,
|
||||
'default' => 0,
|
||||
'size' => 'tiny',
|
||||
'description' => 'Whether or not this Mandrill activity stream is enabled.',
|
||||
),
|
||||
// Following fields are for supporting exportable status.
|
||||
'locked' => array(
|
||||
'description' => 'A boolean indicating whether the administrator may delete this mapping.',
|
||||
'type' => 'int',
|
||||
'not null' => TRUE,
|
||||
'default' => 0,
|
||||
'size' => 'tiny',
|
||||
),
|
||||
'status' => array(
|
||||
'type' => 'int',
|
||||
'not null' => TRUE,
|
||||
// Set the default to ENTITY_CUSTOM without using the constant as it is
|
||||
// not safe to use it at this point.
|
||||
'default' => 0x01,
|
||||
'size' => 'tiny',
|
||||
'description' => 'The exportable status of the entity.',
|
||||
),
|
||||
'module' => array(
|
||||
'description' => 'The name of the providing module if the entity has been defined in code.',
|
||||
'type' => 'varchar',
|
||||
'length' => 255,
|
||||
'not null' => FALSE,
|
||||
),
|
||||
),
|
||||
'primary key' => array('mandrill_activity_entity_id'),
|
||||
'unique keys' => array(
|
||||
'name' => array('name'),
|
||||
'entity_type_bundle' => array(
|
||||
'entity_type',
|
||||
'bundle',
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
return $schema;
|
||||
}
|
||||
@@ -0,0 +1,198 @@
|
||||
<?php
|
||||
/**
|
||||
* @file
|
||||
* Main module functions for mandrill_activity.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements hook_entity_info().
|
||||
*/
|
||||
function mandrill_activity_entity_info() {
|
||||
$return = array(
|
||||
'mandrill_activity_entity' => array(
|
||||
'label' => t('Mandrill Activity Entity'),
|
||||
'controller class' => 'EntityAPIControllerExportable',
|
||||
'entity class' => 'MandrillActivityEntity',
|
||||
'base table' => 'mandrill_activity_entity',
|
||||
'uri callback' => 'entity_class_uri',
|
||||
'fieldable' => FALSE,
|
||||
'exportable' => TRUE,
|
||||
'module' => 'mandrill_activity',
|
||||
'entity keys' => array(
|
||||
'id' => 'mandrill_activity_entity_id',
|
||||
'name' => 'name',
|
||||
'label' => 'label',
|
||||
),
|
||||
// Enable the entity API's admin UI.
|
||||
'admin ui' => array(
|
||||
'path' => 'admin/config/services/mandrill/activity',
|
||||
'file' => 'mandrill_activity.admin.inc',
|
||||
'controller class' => 'MandrillActivityUIController',
|
||||
),
|
||||
'label callback' => 'entity_class_label',
|
||||
'access callback' => 'mandrill_activity_entity_access',
|
||||
),
|
||||
);
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Access callback for mandrill_activity_entity.
|
||||
*/
|
||||
function mandrill_activity_entity_access() {
|
||||
return user_access('administer mandrill activity');
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_menu().
|
||||
*/
|
||||
function mandrill_activity_menu() {
|
||||
$items = array();
|
||||
$mandrill_activity_entities = mandrill_activity_load();
|
||||
foreach ($mandrill_activity_entities as $mandrill_activity_entity) {
|
||||
$arg = substr_count($mandrill_activity_entity->entity_path, '/');
|
||||
$items[$mandrill_activity_entity->entity_path . '%entity_object/mandrill_activity'] = array(
|
||||
'title' => 'Mandrill Activity',
|
||||
'load arguments' => array($mandrill_activity_entity->entity_type),
|
||||
'page callback' => 'mandrill_activity_page',
|
||||
'page arguments' => array($arg, $mandrill_activity_entity),
|
||||
'access callback' => 'mandrill_activity_access',
|
||||
'access arguments' => array($mandrill_activity_entity),
|
||||
'type' => MENU_LOCAL_TASK,
|
||||
);
|
||||
}
|
||||
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Access callback for activity menu items.
|
||||
*/
|
||||
function mandrill_activity_access(MandrillActivityEntity $mandrill_activity_entity) {
|
||||
if ($mandrill_activity_entity->enabled && user_access('access Mandrill activity')) {
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a single mandrill_activity_entity or all of them if no name provided.
|
||||
*
|
||||
* @string $name
|
||||
* Machine name of Mandrill Activity Entity to load.
|
||||
*
|
||||
* @return MandrillActivityEntity|array
|
||||
* Array of MandrillActivityEntity's or a single MandrillActivityEntity.
|
||||
*/
|
||||
function mandrill_activity_load($name = NULL) {
|
||||
$types = entity_load_multiple_by_name('mandrill_activity_entity', isset($name) ? array($name) : FALSE);
|
||||
return isset($name) ? reset($types) : $types;
|
||||
}
|
||||
|
||||
/**
|
||||
* Content for the Mandrill log tab on entity instance pages.
|
||||
*
|
||||
* @object $entity
|
||||
* Entity to load activity for.
|
||||
*
|
||||
* @param MandrillActivityEntity $mandrill_activity_entity
|
||||
* Loaded MandrillActivityEntity object.
|
||||
*
|
||||
* @return array
|
||||
* Render array.
|
||||
*/
|
||||
function mandrill_activity_page($entity, MandrillActivityEntity $mandrill_activity_entity) {
|
||||
$entity_wrapper = entity_metadata_wrapper($mandrill_activity_entity->entity_type, $entity);
|
||||
$email_property = $mandrill_activity_entity->email_property;
|
||||
$email_property_array = explode(':', $email_property);
|
||||
$parent = $entity_wrapper;
|
||||
foreach ($email_property_array as $drupal_field) {
|
||||
if ($parent instanceof EntityListWrapper) {
|
||||
$child_wrapper = $parent->get(0)->{$drupal_field};
|
||||
}
|
||||
else {
|
||||
$child_wrapper = $parent->{$drupal_field};
|
||||
}
|
||||
$parent = $child_wrapper;
|
||||
}
|
||||
$email = $parent->value();
|
||||
// Validate email address.
|
||||
if (!valid_email_address($email)) {
|
||||
return array(
|
||||
'error_notice' => array(
|
||||
'#markup' => t('%email does not contain a valid email address. Unable to lookup Mandrill activity history without a valid email.',
|
||||
array('%email' => $email_property)
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
$header = array(
|
||||
t('Subject'),
|
||||
t('Timestamp'),
|
||||
t('State'),
|
||||
t('Opens'),
|
||||
t('Clicks'),
|
||||
t('Tags'),
|
||||
);
|
||||
$rows = array();
|
||||
|
||||
// Loop through all activities, creating rows for each.
|
||||
$activity = mandrill_activity_get_activity($email);
|
||||
foreach ($activity as $sent_email) {
|
||||
$rows[] = array(
|
||||
$sent_email['subject'],
|
||||
format_date($sent_email['ts'], 'short'),
|
||||
$sent_email['state'],
|
||||
$sent_email['opens'],
|
||||
$sent_email['clicks'],
|
||||
implode(', ', $sent_email['tags']),
|
||||
);
|
||||
}
|
||||
|
||||
$display['mandrill_activity'] = array(
|
||||
'message' => array(
|
||||
'#markup' => t('The 100 most recent Emails sent to %email via Mandrill.', array('%email' => $email)),
|
||||
),
|
||||
'activity' => array(
|
||||
'#theme' => 'table',
|
||||
'#header' => $header,
|
||||
'#rows' => $rows,
|
||||
),
|
||||
);
|
||||
|
||||
return $display;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return all activity on all lists for a given email address.
|
||||
*
|
||||
* @string $email
|
||||
* Email to load Mandrill activity for.
|
||||
*
|
||||
* @return array
|
||||
* Array of activity.
|
||||
*/
|
||||
function mandrill_activity_get_activity($email) {
|
||||
$mandrill = mandrill_get_api_object();
|
||||
return $mandrill->messages_search("email:{$email}");
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_permission().
|
||||
*/
|
||||
function mandrill_activity_permission() {
|
||||
$return = array();
|
||||
|
||||
$return['access mandrill activity'] = array(
|
||||
'title' => t('Access Mandrill activity'),
|
||||
'description' => t('View own Mandrill activity history.'),
|
||||
);
|
||||
$return['administer mandrill activity'] = array(
|
||||
'title' => t('Administer Mandrill activity entities'),
|
||||
'description' => t('Add, Delete, and Configure Mandrill Activity entity settings.'),
|
||||
);
|
||||
return $return;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
name = Mandrill Reports
|
||||
description = "Providing reporting on activity through Mandrill."
|
||||
core = 7.x
|
||||
package = MailChimp
|
||||
|
||||
dependencies[] = mandrill
|
||||
|
||||
; Information added by Drupal.org packaging script on 2014-05-09
|
||||
version = "7.x-1.6"
|
||||
core = "7.x"
|
||||
project = "mandrill"
|
||||
datestamp = "1399658028"
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
(function ($) {
|
||||
|
||||
Drupal.behaviors.mandrill_reports = {
|
||||
attach: function (context, settings) {
|
||||
google.load("visualization", "1", {packages:["corechart"], "callback":drawCharts});
|
||||
|
||||
function drawCharts() {
|
||||
var dataTableVol = new google.visualization.DataTable();
|
||||
dataTableVol.addColumn('datetime', Drupal.t('Date'));
|
||||
dataTableVol.addColumn('number', Drupal.t('Delivered'));
|
||||
dataTableVol.addColumn('number', Drupal.t('Bounced'));
|
||||
dataTableVol.addColumn('number', Drupal.t('Rejected'));
|
||||
|
||||
for (var key in settings.mandrill_reports.volume) {
|
||||
dataTableVol.addRow([
|
||||
new Date(settings.mandrill_reports.volume[key]['date']),
|
||||
settings.mandrill_reports.volume[key]['sent'],
|
||||
settings.mandrill_reports.volume[key]['bounced'],
|
||||
settings.mandrill_reports.volume[key]['rejected']
|
||||
]);
|
||||
}
|
||||
|
||||
var options = {
|
||||
pointSize: 5,
|
||||
hAxis: {format: 'MM/dd/y hh:mm aaa'}
|
||||
};
|
||||
|
||||
var chart = new google.visualization.LineChart(document.getElementById('mandrill-volume-chart'));
|
||||
chart.draw(dataTableVol, options);
|
||||
|
||||
var dataTableEng = new google.visualization.DataTable();
|
||||
dataTableEng.addColumn('datetime', Drupal.t('Date'));
|
||||
dataTableEng.addColumn('number', Drupal.t('Open rate'));
|
||||
dataTableEng.addColumn('number', Drupal.t('Click rate'));
|
||||
|
||||
for (var key in settings.mandrill_reports.engagement) {
|
||||
dataTableEng.addRow([
|
||||
new Date(settings.mandrill_reports.engagement[key]['date']),
|
||||
settings.mandrill_reports.engagement[key]['open_rate'],
|
||||
settings.mandrill_reports.engagement[key]['click_rate']
|
||||
]);
|
||||
}
|
||||
|
||||
var chart = new google.visualization.LineChart(document.getElementById('mandrill-engage-chart'));
|
||||
chart.draw(dataTableEng, options);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
})(jQuery);
|
||||
@@ -0,0 +1,255 @@
|
||||
<?php
|
||||
/**
|
||||
* @file
|
||||
* Main module functions for mandrill_reports.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements hook_menu().
|
||||
*/
|
||||
function mandrill_reports_menu() {
|
||||
$items = array();
|
||||
$items['admin/reports/mandrill'] = array(
|
||||
'title' => 'Mandrill',
|
||||
'page callback' => 'mandrill_reports_dashboard_page',
|
||||
'access arguments' => array('view mandrill reports'),
|
||||
'description' => 'View Mandrill dashboard.',
|
||||
);
|
||||
$items['admin/reports/mandrill/dashboard'] = array(
|
||||
'title' => 'Dashboard',
|
||||
'type' => MENU_DEFAULT_LOCAL_TASK,
|
||||
'weight' => -10,
|
||||
);
|
||||
$items['admin/reports/mandrill/summary'] = array(
|
||||
'title' => 'Account summary',
|
||||
'page callback' => 'mandrill_reports_summary_page',
|
||||
'access arguments' => array('view mandrill reports'),
|
||||
'description' => 'View account summary.',
|
||||
'type' => MENU_LOCAL_TASK,
|
||||
);
|
||||
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_permission().
|
||||
*/
|
||||
function mandrill_reports_permission() {
|
||||
return array(
|
||||
'view mandrill reports' => array(
|
||||
'title' => t('View Mandrill reports'),
|
||||
'description' => t('View all Mandrill reports.'),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an associative array containing raw stats.
|
||||
*
|
||||
* @return array
|
||||
* Associative array containing report data.
|
||||
*/
|
||||
function mandrill_reports_data() {
|
||||
if ($cache = cache_get('mandrill_report_data')) {
|
||||
return $cache->data;
|
||||
}
|
||||
|
||||
$data = array();
|
||||
$api = mandrill_get_api_object();
|
||||
|
||||
if ($api) {
|
||||
// Basic user info.
|
||||
$data['user'] = $api->users_info();
|
||||
|
||||
// Tags.
|
||||
$tags = $api->tags_list();
|
||||
foreach ($tags as $tag) {
|
||||
if (!empty($tag['tag'])) {
|
||||
$data['tags'][$tag['tag']] = $api->tags_info($tag['tag']);
|
||||
$data['tags'][$tag['tag']]['time_series'] = $api->tags_time_series($tag['tag']);
|
||||
}
|
||||
}
|
||||
|
||||
// All time.
|
||||
$data['all_time_series'] = $api->tags_all_time_series();
|
||||
|
||||
// Senders: data is not being used, and the API currently (3/12/13) behaves
|
||||
// badly if you have a bad email address anywhere in your sender history, so
|
||||
// commenting out for now:
|
||||
$senders = $api->senders_list();
|
||||
foreach ($senders as $sender) {
|
||||
try {
|
||||
$data['senders'][$sender['address']] = $api->senders_info($sender['address']);
|
||||
$data['senders'][$sender['address']]['time_series'] = $api->senders_time_series($sender['address']);
|
||||
}
|
||||
catch (MandrillException $e) {
|
||||
watchdog('mandrill', 'An error occurred requesting sender information from Mandrill for address %address. "%message"', array(
|
||||
'%address' => $sender['address'],
|
||||
'%message' => $e->getMessage(),
|
||||
), WATCHDOG_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
// Urls.
|
||||
$urls = $api->urls_list();
|
||||
foreach ($urls as $url) {
|
||||
// Api has been intermittently tacking on incomplete $url arrays,
|
||||
// so we have to check validity first:
|
||||
if (isset($url['url'])) {
|
||||
$data['urls'][$url['url']] = $url;
|
||||
$data['urls'][$url['url']]['time_series'] = $api->urls_time_series($url['url']);
|
||||
}
|
||||
}
|
||||
cache_set('mandrill_report_data', $data, 'cache', CACHE_TEMPORARY);
|
||||
}
|
||||
else {
|
||||
drupal_set_message(t('Please enter a Mandrill API key to use reports.'));
|
||||
drupal_goto('admin/config/services/mandrill');
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Page callback for rendering stats.
|
||||
*
|
||||
* @return array
|
||||
* Render array.
|
||||
*/
|
||||
function mandrill_reports_dashboard_page() {
|
||||
$data = mandrill_reports_data();
|
||||
$settings = array();
|
||||
// All time series chart data.
|
||||
foreach ($data['all_time_series'] as $series) {
|
||||
$settings['mandrill_reports']['volume'][] = array(
|
||||
'date' => $series['time'],
|
||||
'sent' => $series['sent'],
|
||||
'bounced' => $series['hard_bounces'] + $series['soft_bounces'],
|
||||
'rejected' => $series['rejects'],
|
||||
);
|
||||
$settings['mandrill_reports']['engagement'][] = array(
|
||||
'date' => $series['time'],
|
||||
'open_rate' => $series['sent'] == 0 ? 0 : $series['unique_opens'] / $series['sent'],
|
||||
'click_rate' => $series['sent'] == 0 ? 0 : $series['unique_clicks'] / $series['sent'],
|
||||
);
|
||||
}
|
||||
|
||||
// Url table.
|
||||
$rows = array();
|
||||
$header = array(
|
||||
t('URL'),
|
||||
t('Delivered'),
|
||||
t('Unique clicks'),
|
||||
t('Total Clicks'),
|
||||
);
|
||||
foreach ($data['urls'] as $url) {
|
||||
$percent = number_format($url['unique_clicks'] / $url['sent'], 2) * 100;
|
||||
$rows[] = array(
|
||||
l($url['url'], $url['url']),
|
||||
$url['sent'],
|
||||
$url['unique_clicks'] . "({$percent}%)",
|
||||
$url['clicks']);
|
||||
}
|
||||
|
||||
$path = drupal_get_path('module', 'mandrill_reports');
|
||||
$render = array(
|
||||
'#attached' => array(
|
||||
'js' => array(
|
||||
array(
|
||||
'data' => 'https://www.google.com/jsapi',
|
||||
'type' => 'external',
|
||||
),
|
||||
$path . '/mandrill_reports.js',
|
||||
array(
|
||||
'data' => $settings,
|
||||
'type' => 'setting',
|
||||
),
|
||||
),
|
||||
),
|
||||
'message' => array(
|
||||
'#markup' => t(
|
||||
'The following reports are based on Mandrill data from the last 30 days. For more comprehensive data, please visit your !dashboard. !cache to ensure the data is current.',
|
||||
array(
|
||||
'!dashboard' => l(t('Mandrill Dashboard'), 'https://mandrillapp.com/'),
|
||||
'!cache' => l(t('Clear your cache'), 'admin/config/development/performance'),
|
||||
)
|
||||
),
|
||||
),
|
||||
'volume' => array(
|
||||
'#prefix' => '<h2>' . t('Sending Volume') . '</h2>',
|
||||
'#markup' => '<div id="mandrill-volume-chart"></div>',
|
||||
),
|
||||
'engagement' => array(
|
||||
'#prefix' => '<h2>' . t('Average Open and Click Rate') . '</h2>',
|
||||
'#markup' => '<div id="mandrill-engage-chart"></div>',
|
||||
),
|
||||
'urls' => array(
|
||||
'#prefix' => '<h2>' . t('Tracked URLs') . '</h2>',
|
||||
'#theme' => 'table',
|
||||
'#header' => $header,
|
||||
'#rows' => $rows,
|
||||
),
|
||||
);
|
||||
|
||||
return $render;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays summary information for the active API user.
|
||||
*/
|
||||
function mandrill_reports_summary_page() {
|
||||
$data = mandrill_reports_data();
|
||||
$info = $data['user'];
|
||||
|
||||
$header = array(
|
||||
t('Range'),
|
||||
t('Sent'),
|
||||
t('hard_bounces'),
|
||||
t('soft_bounces'),
|
||||
t('Rejects'),
|
||||
t('Complaints'),
|
||||
t('Unsubs'),
|
||||
t('Opens'),
|
||||
t('unique_opens'),
|
||||
t('Clicks'),
|
||||
t('unique_clicks'),
|
||||
);
|
||||
|
||||
$rows = array();
|
||||
foreach ($info['stats'] as $key => $stat) {
|
||||
$rows[] = array(
|
||||
str_replace('_', ' ', $key),
|
||||
$stat['sent'],
|
||||
$stat['hard_bounces'],
|
||||
$stat['soft_bounces'],
|
||||
$stat['rejects'],
|
||||
$stat['complaints'],
|
||||
$stat['unsubs'],
|
||||
$stat['opens'],
|
||||
$stat['unique_opens'],
|
||||
$stat['clicks'],
|
||||
$stat['unique_clicks'],
|
||||
);
|
||||
}
|
||||
|
||||
$render = array(
|
||||
'info' => array(
|
||||
'#theme' => 'table',
|
||||
'#rows' => array(
|
||||
array(t('Username'), $info['username']),
|
||||
array(t('Reputation'), $info['reputation']),
|
||||
array(t('Hourly quota'), $info['hourly_quota']),
|
||||
array(t('Backlog'), $info['backlog']),
|
||||
),
|
||||
'#header' => array(t('Attribute'), t('Value')),
|
||||
'#caption' => t('Active API user information.'),
|
||||
),
|
||||
'stats' => array(
|
||||
'#theme' => 'table',
|
||||
'#rows' => $rows,
|
||||
'#header' => $header,
|
||||
'#caption' => t("This table contains an aggregate summary of the account's sending stats."),
|
||||
),
|
||||
);
|
||||
|
||||
return $render;
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
/**
|
||||
* @file
|
||||
* Mandrill Template entity class
|
||||
*/
|
||||
|
||||
class MandrillTemplateMap extends Entity {
|
||||
public
|
||||
$mandrill_template_map_entity_id,
|
||||
$name,
|
||||
$label,
|
||||
$mailsystem_key,
|
||||
$template_id,
|
||||
$main_section,
|
||||
$sections;
|
||||
|
||||
/**
|
||||
* Return a new entity instance of type mandrill_template_map.
|
||||
*/
|
||||
public function __construct(array $values = array()) {
|
||||
parent::__construct($values, 'mandrill_template_map');
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify URI.
|
||||
*/
|
||||
protected function defaultUri() {
|
||||
return array('path' => 'admin/config/services/mandrill/templates/' . $this->identifier());
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the arguments that are required for sending templates.
|
||||
*
|
||||
* @return array
|
||||
* An associative array containing message template arguments.
|
||||
*/
|
||||
public function message_send_arguments($message) {
|
||||
return array(
|
||||
'id' => $this->template_id,
|
||||
'template_content' => array(
|
||||
'0' => array(
|
||||
'name' => $this->main_section,
|
||||
'content_postprocess' => 'html',
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
/**
|
||||
* @file
|
||||
* The UI controller for the template map entity.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Override EntityDefaultUIController to customize our menu items.
|
||||
*/
|
||||
class MandrillTemplateMapUIController extends EntityDefaultUIController {
|
||||
|
||||
/**
|
||||
* Overrides EntityDefaultUIController::hook_menu().
|
||||
*/
|
||||
public function hook_menu() {
|
||||
$items = parent::hook_menu();
|
||||
$items[$this->path]['description'] = 'Manage Mandrill Template Mapping entity settings.';
|
||||
$items[$this->path]['type'] = MENU_LOCAL_TASK;
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides EntityDefaultUIController::overviewTableHeaders().
|
||||
*/
|
||||
protected function overviewTableHeaders($conditions, $rows, $additional_header = array()) {
|
||||
$additional_header[] = t('Mandrill Template');
|
||||
$additional_header[] = t('Primary Content Zone');
|
||||
$additional_header[] = t('In Use By');
|
||||
$header = parent::overviewTableHeaders($conditions, $rows, $additional_header);
|
||||
return $header;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides EntityDefaultUIController::overviewTableRow().
|
||||
*/
|
||||
protected function overviewTableRow($conditions, $id, $entity, $additional_cols = array()) {
|
||||
$additional_cols[] = $entity->template_id;
|
||||
$additional_cols[] = $entity->main_section;
|
||||
$additional_cols[] = $entity->mailsystem_key;
|
||||
return parent::overviewTableRow($conditions, $id, $entity, $additional_cols);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,207 @@
|
||||
<?php
|
||||
/**
|
||||
* @file
|
||||
* Administrative forms for Mandrill Template module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Return a form for adding/editing a Mandrill template map.
|
||||
*/
|
||||
function mandrill_template_map_form($form, &$form_state, MandrillTemplateMap $map = NULL, $op = 'edit') {
|
||||
$form_state['op'] = $op;
|
||||
if ($form_state['op'] == 'clone') {
|
||||
$map->label .= ' (cloned)';
|
||||
$map->name = '';
|
||||
}
|
||||
// Store the existing map for updating on submit.
|
||||
if (isset($map)) {
|
||||
$form_state['map'] = $map;
|
||||
}
|
||||
else {
|
||||
$form_state['op'] = 'add';
|
||||
}
|
||||
|
||||
$form['label'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => t('Label'),
|
||||
'#description' => t('The name of this Template Mapping.'),
|
||||
'#size' => 35,
|
||||
'#maxlength' => 32,
|
||||
'#default_value' => $map ? $map->label : '',
|
||||
'#required' => TRUE,
|
||||
);
|
||||
|
||||
// Machine-readable list name.
|
||||
$form['name'] = array(
|
||||
'#type' => 'machine_name',
|
||||
'#default_value' => isset($map->name) ? $map->name : '',
|
||||
'#maxlength' => 32,
|
||||
'#machine_name' => array(
|
||||
'exists' => 'mandrill_template_map_load_entities',
|
||||
'source' => array('label'),
|
||||
),
|
||||
'#description' => t('A unique machine-readable name for this template map. It must only contain lowercase letters, numbers, and underscores.'),
|
||||
);
|
||||
|
||||
$form['map_settings'] = array(
|
||||
'#type' => 'fieldset',
|
||||
'#title' => t('Template Map Settings'),
|
||||
'#collapsible' => FALSE,
|
||||
'#attributes' => array(
|
||||
'id' => array('mandrill-template-mapping'),
|
||||
),
|
||||
);
|
||||
|
||||
$templates = mandrill_get_templates();
|
||||
$template_names = array();
|
||||
foreach ($templates as $template) {
|
||||
$template_names[$template['slug']] = $template;
|
||||
}
|
||||
// Check if the currently configured template still exists.
|
||||
if (!empty($map->template_id) && !array_key_exists($map->template_id, $template_names)) {
|
||||
drupal_set_message(t('The configured Mandrill template is no longer available, please select a valid one.'), 'warning');
|
||||
}
|
||||
if (!empty($templates)) {
|
||||
$options = array('' => t('-- Select --'));
|
||||
foreach ($templates as $template) {
|
||||
$options[$template['slug']] = $template['name'];
|
||||
}
|
||||
$form['map_settings']['template_id'] = array(
|
||||
'#type' => 'select',
|
||||
'#title' => t('Email Template'),
|
||||
'#description' => t('Select a Mandrill template.'),
|
||||
'#options' => $options,
|
||||
'#default_value' => isset($map->template_id) ? $map->template_id : '',
|
||||
'#required' => TRUE,
|
||||
'#ajax' => array(
|
||||
'callback' => 'mandrill_template_map_form_callback',
|
||||
'wrapper' => 'mandrill-template-mapping',
|
||||
),
|
||||
);
|
||||
$form_template_id = & $form_state['values']['template_id'];
|
||||
|
||||
if (!$form_template_id && isset($map->mandrill_template_map_entity_id)) {
|
||||
$form_template_id = $map->template_id;
|
||||
}
|
||||
|
||||
if ($form_template_id) {
|
||||
$regions = array('' => t('-- Select --')) + _mandrill_parse_regions($template_names[$form_template_id]['publish_code']);
|
||||
$form['map_settings']['main_section'] = array(
|
||||
'#type' => 'select',
|
||||
'#title' => t('Template region'),
|
||||
'#description' => t('Select the template region to use for email content. <i>Note that you can populate more regions by attaching an array to your message with the index "mandrill_template_content", using region names as indexes to the content for that region.'),
|
||||
'#options' => $regions,
|
||||
'#default_value' => isset($map->main_section) ? $map->main_section : '',
|
||||
'#required' => TRUE,
|
||||
);
|
||||
}
|
||||
$usable_keys = mandrill_template_map_usage();
|
||||
$module_names = mandrill_get_module_key_names();
|
||||
$mandrill_in_use = FALSE;
|
||||
$available_modules = FALSE;
|
||||
$mailsystem_options = array('' => t('-- None --'));
|
||||
foreach ($usable_keys as $key => $sys) {
|
||||
$mandrill_in_use = TRUE;
|
||||
if ($sys === NULL || (isset($map) && $sys == $map->mandrill_template_map_entity_id)) {
|
||||
$mailsystem_options[$key] = $module_names[$key];
|
||||
$available_modules = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if ($mandrill_in_use) {
|
||||
$form['mailsystem_key'] = array(
|
||||
'#type' => 'select',
|
||||
'#title' => t('Email key'),
|
||||
'#description' => t(
|
||||
'Select a module and mail key to use this template for outgoing email. Note that if an email has been selected in another Template Mapping, it will not appear in this list. These keys are defined through the !MailSystem interface.',
|
||||
array('!MailSystem' => l(t('MailSystem'), 'admin/config/system/mailsystem'))
|
||||
),
|
||||
'#options' => $mailsystem_options,
|
||||
'#default_value' => isset($map->mailsystem_key) ? $map->mailsystem_key : '',
|
||||
);
|
||||
if (!$available_modules) {
|
||||
drupal_set_message(t("All email-using modules that have been assigned to Mandrill are already assigned to other template maps"), 'warning');
|
||||
}
|
||||
}
|
||||
|
||||
if (!$mandrill_in_use) {
|
||||
drupal_set_message(t("You have not assigned any Modules to use Mandrill: to use this template, make sure Mandrill is assigned in Mailsystem."), 'warning');
|
||||
}
|
||||
}
|
||||
else {
|
||||
$form['email_options']['#description'] = t('The template selection is only available if the Mandrill API is correctly configured and available.');
|
||||
}
|
||||
|
||||
$form['actions'] = array('#type' => 'actions');
|
||||
$form['actions']['save'] = array(
|
||||
'#type' => 'submit',
|
||||
'#value' => t('Save'),
|
||||
);
|
||||
$form['actions']['cancel'] = array(
|
||||
'#type' => 'link',
|
||||
'#title' => t('Cancel'),
|
||||
'#href' => 'admin/config/services/mandrill/templates',
|
||||
);
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate handler for mandrill_template_map().
|
||||
*/
|
||||
function mandrill_template_map_form_validate($form, &$form_state) {
|
||||
$values = $form_state['values'];
|
||||
// Test to see if mandrill_template_map value will exceed row length of 255
|
||||
// characters
|
||||
if (strlen($values['mailsystem_key']) > 255) {
|
||||
form_set_error('mailsystem_key', t('The length of the mailsytem_key name is too long.'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Submit handler for mandrill_template_map(), creates the entity.
|
||||
*/
|
||||
function mandrill_template_map_form_submit($form, &$form_state) {
|
||||
$values = $form_state['values'];
|
||||
if ($form_state['op'] == 'add' || $form_state['op'] == 'clone') {
|
||||
$map = entity_create('mandrill_template_map', $values);
|
||||
}
|
||||
else {
|
||||
$map = $form_state['mandrill_template_map'];
|
||||
foreach ($values as $key => $val) {
|
||||
$map->{$key} = $val;
|
||||
}
|
||||
}
|
||||
$map->save();
|
||||
drupal_set_message(t('Mandrill template mapping saved.'));
|
||||
$form_state['redirect'] = 'admin/config/services/mandrill/templates';
|
||||
}
|
||||
|
||||
/**
|
||||
* Javascript callback for the mandrill_template_map_form.
|
||||
*/
|
||||
function mandrill_template_map_form_callback($form, &$form_state) {
|
||||
return $form['map_settings'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a Mandrill template to extract its regions.
|
||||
*
|
||||
* The Mandrill API does not provide an elegant data structure
|
||||
* containing the mc:edit tags for a given template, but rather
|
||||
* a big pile of ugly HTML containing the tags. We need to parse
|
||||
* through it.
|
||||
*/
|
||||
function _mandrill_parse_regions($html, $tag = 'mc:edit') {
|
||||
$instances = array();
|
||||
$offset = 0;
|
||||
$inst = NULL;
|
||||
while ($offset = strpos($html, $tag, $offset)) {
|
||||
$start = 1 + strpos($html, '"', $offset);
|
||||
$length = strpos($html, '"', $start) - $start;
|
||||
$inst = substr($html, $start, $length);
|
||||
$instances[$inst] = $inst;
|
||||
$offset = $start + $length;
|
||||
}
|
||||
return $instances;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
name = Mandrill Template
|
||||
description = "Use Mandrill templates for messages sent through Mandrill."
|
||||
core = 7.x
|
||||
package = MailChimp
|
||||
|
||||
configure = admin/config/services/mandrill/templates
|
||||
|
||||
dependencies[] = entity (>=1.0)
|
||||
dependencies[] = mandrill
|
||||
|
||||
files[] = lib/mandrill_template_map.entity.inc
|
||||
files[] = lib/mandrill_template_map.ui_controller.inc
|
||||
|
||||
; Information added by Drupal.org packaging script on 2014-05-09
|
||||
version = "7.x-1.6"
|
||||
core = "7.x"
|
||||
project = "mandrill"
|
||||
datestamp = "1399658028"
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Install, update and uninstall functions for the mandrill_template module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements hook_schema().
|
||||
*/
|
||||
function mandrill_template_schema() {
|
||||
$schema['mandrill_template_map'] = array(
|
||||
'description' => 'The base table for the mandrill template module.',
|
||||
'fields' => array(
|
||||
'mandrill_template_map_entity_id' => array(
|
||||
'description' => 'The primary identifier for a mandrill_template_map.',
|
||||
'type' => 'serial',
|
||||
'unsigned' => TRUE,
|
||||
'not null' => TRUE,
|
||||
),
|
||||
'name' => array(
|
||||
'description' => 'The name of this mandrill_template_map',
|
||||
'type' => 'varchar',
|
||||
'length' => 255,
|
||||
'not null' => TRUE,
|
||||
'default' => '',
|
||||
),
|
||||
'label' => array(
|
||||
'description' => 'The label for this mandrill_template_map',
|
||||
'type' => 'varchar',
|
||||
'length' => 255,
|
||||
'not null' => TRUE,
|
||||
'default' => '',
|
||||
),
|
||||
'mailsystem_key' => array(
|
||||
'description' => 'The mailsystem_key that is using this mandrill_template_map.',
|
||||
'type' => 'varchar',
|
||||
'length' => 255,
|
||||
'not null' => FALSE,
|
||||
'default' => '',
|
||||
),
|
||||
'template_id' => array(
|
||||
'description' => 'The unique identifier of the Mandrill Template this mapping uses.',
|
||||
'type' => 'varchar',
|
||||
'length' => 255,
|
||||
'not null' => TRUE,
|
||||
'default' => '',
|
||||
),
|
||||
'main_section' => array(
|
||||
'description' => 'The name of the section where primary email content should go.',
|
||||
'type' => 'varchar',
|
||||
'length' => 255,
|
||||
'not null' => TRUE,
|
||||
'default' => '',
|
||||
),
|
||||
'author_uid' => array(
|
||||
'description' => 'The uid of the user who created this mandrill_template_map.',
|
||||
'type' => 'int',
|
||||
'not null' => TRUE,
|
||||
'default' => 0,
|
||||
),
|
||||
'sections' => array(
|
||||
'description' => 'An array of content sections for the template.',
|
||||
'type' => 'blob',
|
||||
'size' => 'big',
|
||||
'not null' => TRUE,
|
||||
'serialize' => TRUE,
|
||||
),
|
||||
'created' => array(
|
||||
'description' => 'The Unix timestamp when the mandrill_template_map was created.',
|
||||
'type' => 'int',
|
||||
'not null' => TRUE,
|
||||
'default' => 0,
|
||||
),
|
||||
'updated' => array(
|
||||
'description' => 'The Unix timestamp when the mandrill_template_map was most recently saved.',
|
||||
'type' => 'int',
|
||||
'not null' => TRUE,
|
||||
'default' => 0,
|
||||
),
|
||||
// Following fields are for supporting exportable status.
|
||||
'status' => array(
|
||||
'type' => 'int',
|
||||
'not null' => TRUE,
|
||||
// Set the default to ENTITY_CUSTOM without using the constant as it is
|
||||
// not safe to use it at this point.
|
||||
'default' => 0x01,
|
||||
'size' => 'tiny',
|
||||
'description' => 'The exportable status of the entity.',
|
||||
),
|
||||
'module' => array(
|
||||
'description' => 'The name of the providing module if the entity has been defined in code.',
|
||||
'type' => 'varchar',
|
||||
'length' => 255,
|
||||
'not null' => FALSE,
|
||||
),
|
||||
),
|
||||
'indexes' => array(
|
||||
'mandrill_template_map_updated' => array('updated'),
|
||||
'mandrill_template_map_created' => array('created'),
|
||||
'mandrill_template_map_author' => array('author_uid'),
|
||||
),
|
||||
'unique keys' => array(
|
||||
'mandrill_template_map_entity_id' => array('mandrill_template_map_entity_id'),
|
||||
),
|
||||
'foreign keys' => array(
|
||||
'mandrill_template_map_author' => array(
|
||||
'table' => 'users',
|
||||
'columns' => array('author_uid' => 'uid'),
|
||||
),
|
||||
),
|
||||
'primary key' => array('mandrill_template_map_entity_id'),
|
||||
);
|
||||
|
||||
return $schema;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extends the mailsystem_key field to support longer template key names.
|
||||
*/
|
||||
function mandrill_template_update_7001() {
|
||||
db_change_field('mandrill_template_map', 'mailsystem_key', 'mailsystem_key',
|
||||
array(
|
||||
'description' => 'The mailsystem_key that is using this mandrill_template_map.',
|
||||
'type' => 'varchar',
|
||||
'length' => 255,
|
||||
'not null' => FALSE,
|
||||
'default' => '',
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,218 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Enables Drupal to send email using Mandrill's template system.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements hook_entity_info().
|
||||
*/
|
||||
function mandrill_template_entity_info() {
|
||||
$return = array(
|
||||
'mandrill_template_map' => array(
|
||||
'label' => t('Mandrill Template Map'),
|
||||
'plural label' => t('Mandrill Template Maps'),
|
||||
'controller class' => 'EntityAPIControllerExportable',
|
||||
'entity class' => 'MandrillTemplateMap',
|
||||
'base table' => 'mandrill_template_map',
|
||||
'uri callback' => 'entity_class_uri',
|
||||
'fieldable' => FALSE,
|
||||
'exportable' => TRUE,
|
||||
'module' => 'mandrill_template',
|
||||
'access callback' => 'mandrill_template_map_access',
|
||||
'entity keys' => array(
|
||||
'id' => 'mandrill_template_map_entity_id',
|
||||
'label' => 'label',
|
||||
'name' => 'name',
|
||||
),
|
||||
'admin ui' => array(
|
||||
'path' => 'admin/config/services/mandrill/templates',
|
||||
'file' => 'mandrill_template.admin.inc',
|
||||
'controller class' => 'MandrillTemplateMapUIController',
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Access callback for mandrill_template_map.
|
||||
*
|
||||
* @return bool
|
||||
* True if current user has acces to template maps, else false
|
||||
*/
|
||||
function mandrill_template_map_access() {
|
||||
$a = user_access('configure mandrill templates');
|
||||
$b = variable_get('mandrill_api_key');
|
||||
return $a & !empty($b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_permission().
|
||||
*/
|
||||
function mandrill_template_permission() {
|
||||
return array(
|
||||
'configure mandrill templates' => array(
|
||||
'title' => t('Configure Mandrill Templates'),
|
||||
'description' => t('Select & configure which Mandrill Templates to use for messages going through Mandrill.'),
|
||||
"restrict access" => FALSE,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a single mandrill_template_map or all of them if no name provided.
|
||||
*
|
||||
* @param null $name
|
||||
* name of the template map entity
|
||||
*
|
||||
* @return array
|
||||
* array of template_map entities
|
||||
*/
|
||||
function mandrill_template_map_load_entities($name = NULL) {
|
||||
$maps = entity_load_multiple_by_name('mandrill_template_map', isset($name) ? array($name) : FALSE);
|
||||
return isset($name) ? reset($maps) : $maps;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells you which template_map is configured for a mailsystem key, if any.
|
||||
*
|
||||
* Will search for a default-system mapping if none is availble for a given key.
|
||||
*
|
||||
* @param string $mailsystem
|
||||
* Mail key to search for a template mapping.
|
||||
*
|
||||
* @return entity
|
||||
* Mandrill template map.
|
||||
*/
|
||||
function mandrill_template_map_load_by_mailsystem($mailsystem) {
|
||||
// Append the default-system condition as a fallback.
|
||||
$params = array($mailsystem, 'default-system');
|
||||
$query = new EntityFieldQuery();
|
||||
$query_result = $query
|
||||
->entityCondition('entity_type', 'mandrill_template_map')
|
||||
->propertyCondition('mailsystem_key', $params, 'IN')
|
||||
->execute();
|
||||
|
||||
if (!empty($query_result['mandrill_template_map'])) {
|
||||
$template_maps = entity_load('mandrill_template_map', array_keys($query_result['mandrill_template_map']));
|
||||
if (count($template_maps) > 1) {
|
||||
foreach ($template_maps as $template_map) {
|
||||
if ($template_map->mailsystem_key == $mailsystem) {
|
||||
return $template_map;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
return reset($template_maps);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all mailsystem keys pointed at mandrill and their template mappings.
|
||||
*
|
||||
* @return array
|
||||
* Returns an array with indexes matching each module which is assigned
|
||||
* to use Mandrill for email sends, and values equal to the template_map_ids
|
||||
* that are assigned to those modules. If no template maps are assigned, the
|
||||
* value is set to NULL.
|
||||
*/
|
||||
function mandrill_template_map_usage() {
|
||||
$system_assignments = mailsystem_get();
|
||||
// Filter out the systems that aren't using Mandrill:
|
||||
foreach ($system_assignments as $system => $assignment) {
|
||||
if ($assignment != 'MandrillMailSystem') {
|
||||
unset($system_assignments[$system]);
|
||||
}
|
||||
else {
|
||||
$system_assignments[$system] = NULL;
|
||||
}
|
||||
}
|
||||
$maps = mandrill_template_map_load_entities();
|
||||
foreach ($maps as $map) {
|
||||
if (isset($map->mailsystem_key) && array_key_exists($map->mailsystem_key, $system_assignments)) {
|
||||
$system_assignments[$map->mailsystem_key] = $map->mandrill_template_map_entity_id;
|
||||
}
|
||||
}
|
||||
uksort($system_assignments, '_mandrill_template_map_mailsystem_sort');
|
||||
return $system_assignments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_mandrill_mail_alter().
|
||||
*
|
||||
* Determine if an email is configured to use a Mandrill template and change the
|
||||
* mandrill_send_function parameter as needed.
|
||||
*/
|
||||
function mandrill_template_mandrill_mail_alter(&$mandrill_params, $message) {
|
||||
$template_map = mandrill_template_map_load_by_mailsystem($message['id']);
|
||||
if ($template_map) {
|
||||
$mandrill_params['function'] = 'mandrill_template_sender';
|
||||
$mandrill_params['args'] = array(
|
||||
'template_id' => $template_map->template_id,
|
||||
'template_content' => array(
|
||||
array(
|
||||
'name' => $template_map->main_section,
|
||||
'content' => $message['body'],
|
||||
),
|
||||
),
|
||||
);
|
||||
if (isset($message['mandrill_template_content'])) {
|
||||
$mandrill_params['args']['template_content'] = array_merge($message['mandrill_template_content'], $mandrill_params['args']['template_content']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a templated Mandrill message.
|
||||
*
|
||||
* This function checks for appropriate settings in the message, then uses the
|
||||
* template API call to send the message if the settings are valid.
|
||||
*
|
||||
* @param array $message
|
||||
* Mandrill message to send.
|
||||
* @param string $template_id
|
||||
* Name of the template to use.
|
||||
* @param array $template_content
|
||||
* Associative array mapping template regions and content.
|
||||
*
|
||||
* @return array
|
||||
* Message response.
|
||||
*
|
||||
* @throws MandrillException
|
||||
*/
|
||||
function mandrill_template_sender($message, $template_id, $template_content) {
|
||||
if ($mailer = mandrill_get_api_object()) {
|
||||
return $mailer->messages_send_template($template_id, $template_content, $message);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple sorting algorithm to organize mailsystems arrays in a logical way.
|
||||
*
|
||||
* @param string $a
|
||||
* a mailsystem key name
|
||||
* @param string $b
|
||||
* a mailsystem key name
|
||||
*
|
||||
* @return int
|
||||
* Negative if $a should come before $b, else positive.
|
||||
*/
|
||||
function _mandrill_template_map_mailsystem_sort($a, $b) {
|
||||
$first = "default-system";
|
||||
$last = "mandrill_test";
|
||||
if ($a == $first || $b == $last) {
|
||||
return -1;
|
||||
}
|
||||
if ($b == $first || $a == $last) {
|
||||
return 1;
|
||||
}
|
||||
// Otherwise sort alphabetically, case-agnostic
|
||||
return strcasecmp($a, $b);
|
||||
}
|
||||
Reference in New Issue
Block a user