Skip to content

Commit

Permalink
Merge pull request #335 from moreonion/m2t-send
Browse files Browse the repository at this point in the history
New module for sending m2t emails in a cron-job
  • Loading branch information
torotil authored Aug 20, 2024
2 parents 64fb495 + 68a3f8d commit 3241088
Show file tree
Hide file tree
Showing 6 changed files with 489 additions and 0 deletions.
11 changes: 11 additions & 0 deletions campaignion_m2t_send/campaignion_m2t_send.info
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
name = Match to target send
description = Send M2T messages asynchronously
core = 7.x
package = Campaignion

dependencies[] = psr0:psr0
dependencies[] = campaignion:campaignion_email_to_target
dependencies[] = little_helpers:little_helpers
dependencies[] = ultimate_cron:ultimate_cron
dependencies[] = variable:variable
dependencien[] = webform:webform
105 changes: 105 additions & 0 deletions campaignion_m2t_send/campaignion_m2t_send.install
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
<?php

use Drupal\campaignion_m2t_send\Submission;

/**
* Implements hook_install().
*
* Migrate flags stored in webform_submitted_data.
*/
function campaignion_m2t_send_install() {
$types = _campaignion_m2t_send_content_types();
$sql = <<<SQL
INSERT INTO {campaignion_m2t_send}
SELECT nid, sid, cid, no, NULL, NULL
FROM {node} n
INNER JOIN {webform_submissions} s USING (nid)
INNER JOIN {webform_component} c USING(nid)
INNER JOIN {webform_submitted_data} d USING(nid, sid, cid)
WHERE n.type IN(:types) AND c.type='e2t_selector'
SQL;
db_query($sql, [':types' => $types]);
$nids = db_select('campaignion_m2t_send', 'm')
->fields('m', ['nid'])
->groupBy('nid')
->execute()
->fetchCol();
$nodes = entity_load('node', $nids);

foreach (Submission::iterate($nodes) as $submission) {
foreach (array_keys($submission->webform->componentsByType('e2t_selector')) as $cid) {
foreach ($submission->valuesByCid($cid) as $no => $data) {
$m = unserialize($data);
if ($m['sent'] ?? NULL) {
db_update('campaignion_m2t_send')
->condition('nid', $submission->nid)
->condition('sid', $submission->sid)
->condition('cid', $cid)
->condition('no', $no)
->fields(['sent_at' => 0, 'target_email' => $m['target']['email']])
->execute();
}
}
}
}
}

/**
* Implements hook_schema().
*/
function campaignion_m2t_send_schema() {
$tables['campaignion_m2t_send'] = [
'description' => 'Stores the send status of email to target emails.',
'fields' => [
'nid' => [
'description' => 'The node identifier of a webform.',
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
],
'sid' => [
'description' => 'The unique identifier for this submission.',
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
],
'cid' => [
'description' => 'The identifier for this component within this node, starts at 0 for each node.',
'type' => 'int',
'size' => 'small',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
],
'no' => [
'description' => 'Usually this value is 0, but if a field has multiple values (such as a time or date), it may require multiple rows in the database.',
'type' => 'varchar',
'length' => 128,
'not null' => TRUE,
'default' => '0',
],
'target_email' => [
'description' => 'Email address of the target the email was sent to.',
'type' => 'varchar',
'length' => 256,
'not null' => FALSE,
],
'sent_at' => [
'desrciption' => 'The timestamp for when the email was sent (if)',
'type' => 'int',
'not null' => FALSE,
],
],
'primary key' => ['nid', 'sid', 'cid', 'no'],
'indexes' => [
'node' => ['nid'],
'submission' => ['sid'],
'component' => ['nid', 'sid', 'cid'],
'unsent' => ['nid', 'sent_at'],
'target' => ['target_email'],
],
];
return $tables;
}
129 changes: 129 additions & 0 deletions campaignion_m2t_send/campaignion_m2t_send.module
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
<?php

/**
* @file
* Hook and callback implementations for this module.
*/

use Drupal\campaignion_email_to_target\Channel\EmailNoSend;
use Drupal\campaignion_m2t_send\SendMessagesCron;
use Drupal\little_helpers\Services\Container;
use Drupal\little_helpers\Webform\Submission;

/**
* Implements hook_little_helpers_services().
*/
function campaignion_m2t_send_little_helpers_services() {
$info['campaignion_m2t_send.SendMessagesCron'] = [
'class' => SendMessagesCron::class,
'arguments' => [
'!campaignion_m2t_send_enabled_nodes',
'!campaignion_m2t_send_cron_time_limit',
],
];
return $info;
}

/**
* Implements hook_cronapi().
*/
function campaignion_m2t_send_cronapi($op, $job = NULL) {
$items['campaignion_m2t_send'] = [
'description' => 'Send M2T messages of selected nodes',
'rule' => '*+@ 8-23 * * *',
'weight' => 100,
'callback' => '_campaignion_m2t_send_run',
'arguments' => ['campaignion_m2t_send.SendMessagesCron'],
];
return $items;
}

/**
* Helper function to load a cron service and invoke it.
*/
function _campaignion_m2t_send_run($service) {
Container::get()->loadService($service)->run();
}

/**
* Helper function to get all M2T content types.
*
* @return str[] Array of node type machine names.
*/
function _campaignion_m2t_send_content_types() {
$types = &drupal_static(__FUNCTION__);
if ($types === NULL) {
$info = array_filter(module_invoke_all('campaignion_action_info'), function ($i) {
return ($i['channel'] ?? NULL) == EmailNoSend::class;
});
$types = array_keys($info);
}
return $types;
}

/**
* Implements hook_webform_submission_insert().
*/
function campaignion_m2t_send_webform_submission_insert($node, $submission) {
if (!in_array($node->type, _campaignion_m2t_send_content_types())) {
return;
}
$s = new Submission($node, $submission);
foreach ($s->webform->componentsByType('e2t_selector') as $component) {
$values = $s->valuesByCid($component['cid']);
db_delete('campaignion_m2t_send')
->condition('nid', $node->nid)
->condition('sid', $submission->sid)
->condition('cid', $component['cid'])
->condition('no', array_keys($values), 'NOT IN')
->execute();
foreach ($values as $no => $value) {
db_merge('campaignion_m2t_send')->key([
'nid' => $node->nid,
'sid' => $submission->sid,
'cid' => $component['cid'],
'no' => $no,
])->execute();
}
}
}

/**
* Implements hook_webform_submission_load().
*/
function campaignion_m2t_send_webform_submission_load(&$submissions) {
$data_sql = <<<SQL
SELECT nid, sid, cid, no, data
FROM {webform_submitted_data} d
INNER JOIN {campaignion_m2t_send} m USING(nid, sid, cid, no)
WHERE sid IN(:sids) AND sent_at IS NULL
SQL;
foreach (db_query($data_sql, [':sids' => array_keys($submissions)]) as $d) {
$submissions[$d->sid]->m2t_unsent_messages[] = $d;
}
}

/**
* Implements hook_webform_submission_update().
*/
function campaignion_m2t_send_webform_submission_update($node, $submission) {
campaignion_m2t_send_webform_submission_insert($node, $submission);
}

/**
* Implements hook_webform_submission_delete().
*/
function campaignion_m2t_send_webform_submission_delete($node, $submission) {
db_delete('campaignion_m2t_send')
->condition('sid', $submission->sid)
->execute();
}

/**
* Implements hook_node_delete().
*/
function campaignion_m2t_send_node_delete($node) {
db_delete('campaignion_m2t_send')
->condition('nid', $node->nid)
->execute();
}
26 changes: 26 additions & 0 deletions campaignion_m2t_send/campaignion_m2t_send.variable.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

/**
* @file
* Information about configuration variables defined by this module.
*/

/**
* Implements hook_variable_info().
*/
function campaignion_m2t_send_variable_info($options) {
$v['campaignion_m2t_send_cron_time_limit'] = [
'title' => t('Time limit for M2T send cron-jobs'),
'description' => t('When a m2t send cron-job has been running for more than this amount of seconds no new batch will be started during this cron-run.'),
'type' => 'number',
'default' => 20,
'localize' => FALSE,
];
$v['campaignion_m2t_send_enabled_nodes'] = [
'title' => t('Enabled nodes'),
'description' => t('Only send emails for these nodes.'),
'type' => 'unknown',
'default' => [],
];
return $v;
}
Loading

0 comments on commit 3241088

Please sign in to comment.