|
| 1 | +<?php |
| 2 | + |
| 3 | +namespace Drupal\campaignion_csv\Exporter; |
| 4 | + |
| 5 | +use Drupal\campaignion_csv\Files\CsvFileInterface; |
| 6 | +use Drupal\campaignion_csv\Timeframe; |
| 7 | + |
| 8 | +/** |
| 9 | + * Export per-node message stats for email-to-target targets. |
| 10 | + */ |
| 11 | +class TargetStatsExporter { |
| 12 | + |
| 13 | + /** |
| 14 | + * The timeframe for the current export. |
| 15 | + * |
| 16 | + * @var \Drupal\campaignion_csv\Timeframe |
| 17 | + */ |
| 18 | + protected $timeframe; |
| 19 | + |
| 20 | + /** |
| 21 | + * Create a new exporter based on the info. |
| 22 | + */ |
| 23 | + public static function fromInfo(array $info) { |
| 24 | + return new static($info['nid'], $info['timeframe']); |
| 25 | + } |
| 26 | + |
| 27 | + /** |
| 28 | + * Create a new instance. |
| 29 | + * |
| 30 | + * @param int $nid |
| 31 | + * The node to export target stats for. |
| 32 | + * @param \Drupal\campaignion_csv\Timeframe $timeframe |
| 33 | + * Export data for submissions within this timeframe. |
| 34 | + */ |
| 35 | + public function __construct(int $nid, Timeframe $timeframe) { |
| 36 | + $this->timeframe = $timeframe; |
| 37 | + $this->nid = $nid; |
| 38 | + } |
| 39 | + |
| 40 | + /** |
| 41 | + * Create a sorted list of targets and message counts. |
| 42 | + */ |
| 43 | + protected function readTargetData() { |
| 44 | + list($start, $end) = $this->timeframe->getTimestamps(); |
| 45 | + $sql = <<<SQL |
| 46 | +SELECT s.sid, d.data |
| 47 | +FROM webform_submissions s |
| 48 | + INNER JOIN webform_component c USING(nid) |
| 49 | + INNER JOIN webform_submitted_data d USING(nid, sid, cid) |
| 50 | +WHERE s.nid=:nid AND s.is_draft=0 AND c.type='e2t_selector' AND s.submitted BETWEEN :start AND :end AND s.sid>:last_sid |
| 51 | +LIMIT 10000 |
| 52 | +SQL; |
| 53 | + $last_sid = 0; |
| 54 | + $args = [':start' => $start, ':end' => $end - 1, ':nid' => $this->nid]; |
| 55 | + $targets = []; |
| 56 | + while ($rows = db_query($sql, $args + [':last_sid' => $last_sid])->fetchAll()) { |
| 57 | + foreach ($rows as $row) { |
| 58 | + $data = unserialize($row->data); |
| 59 | + $target = $data['target']; |
| 60 | + if (!isset($targets[$target['id']])) { |
| 61 | + $targets[$target['id']]['# messages'] = 0; |
| 62 | + } |
| 63 | + $targets[$target['id']] += array_filter([ |
| 64 | + 'ID' => $target['id'], |
| 65 | + 'Display name' => $data['message']['display'], |
| 66 | + 'Salutation' => $target['salutation'], |
| 67 | + 'Party' => $target['party'] ?? $target['political_affiliation'] ?? '', |
| 68 | + 'Area / Constituency' => $target['area']['name'] ?? '', |
| 69 | + 'Area type' => $target['area']['type'] ?? '', |
| 70 | + 'Area code' => $target['area']['gss_code'] ?? '', |
| 71 | + 'Country' => $target['area']['country__name'] ?? $target['constituency']['country']['name'] ?? '', |
| 72 | + ]); |
| 73 | + $targets[$target['id']]['# messages'] += 1; |
| 74 | + $last_sid = $row->sid; |
| 75 | + } |
| 76 | + } |
| 77 | + usort($targets, function ($a, $b) { |
| 78 | + // Exchanging b and a here reverses the sort order: big values first. |
| 79 | + return $b['# messages'] <=> $a['# messages']; |
| 80 | + }); |
| 81 | + return $targets; |
| 82 | + } |
| 83 | + |
| 84 | + /** |
| 85 | + * Write the data to the CsvFile. |
| 86 | + */ |
| 87 | + public function writeTo(CsvFileInterface $file) { |
| 88 | + $header = [ |
| 89 | + 'ID', |
| 90 | + 'Display name', |
| 91 | + 'Salutation', |
| 92 | + 'Party', |
| 93 | + 'Area / Constituency', |
| 94 | + 'Area type', |
| 95 | + 'Area code', |
| 96 | + 'Country', |
| 97 | + '# messages', |
| 98 | + ]; |
| 99 | + $file->writeRow($header); |
| 100 | + |
| 101 | + foreach ($this->readTargetData() as $target) { |
| 102 | + $row = array_map(function ($key) use ($target) { |
| 103 | + return $target[$key] ?? ''; |
| 104 | + }, $header); |
| 105 | + $file->writeRow($row); |
| 106 | + } |
| 107 | + } |
| 108 | + |
| 109 | +} |
0 commit comments