Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New module for sending m2t emails in a cron-job #335

Merged
merged 13 commits into from
Aug 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading