|
| 1 | +<?php |
| 2 | + |
| 3 | +namespace Drupal\campaignion_csv\Exporter; |
| 4 | + |
| 5 | +use Drupal\campaignion_csv\Exporter\WebformFormatted\Column; |
| 6 | +use Drupal\campaignion_csv\Files\CsvFileInterface; |
| 7 | +use Drupal\campaignion_csv\Timeframe; |
| 8 | +use Drupal\little_helpers\Webform\Submission; |
| 9 | + |
| 10 | +/** |
| 11 | + * Export messages sent to targets. |
| 12 | + */ |
| 13 | +class TargetMessageExporter { |
| 14 | + |
| 15 | + /** |
| 16 | + * The timeframe for the current export. |
| 17 | + * |
| 18 | + * @var \Drupal\campaignion_csv\Timeframe |
| 19 | + */ |
| 20 | + protected $timeframe; |
| 21 | + |
| 22 | + /** |
| 23 | + * Mapping of column headers to data paths. |
| 24 | + * |
| 25 | + * @var string[] |
| 26 | + */ |
| 27 | + protected $mapping; |
| 28 | + |
| 29 | + /** |
| 30 | + * Submission columns to export in addition to the target / message data. |
| 31 | + * |
| 32 | + * @var \Drupal\campaignion_csv\Exporter\WebformFormatted\Column[] $columns |
| 33 | + */ |
| 34 | + protected $columns; |
| 35 | + |
| 36 | + /** |
| 37 | + * Create a new exporter based on the info. |
| 38 | + */ |
| 39 | + public static function fromInfo(array $info) { |
| 40 | + $info += [ |
| 41 | + 'columns' => [], |
| 42 | + 'mapping' => [ |
| 43 | + 'cid' => 'cid', |
| 44 | + 'Salutation' => 'target.salutation', |
| 45 | + 'Area / Constituency' => 'target.area.name', |
| 46 | + 'Area type' => 'target.area.type', |
| 47 | + 'Area code' => 'target.area.gss_code', |
| 48 | + 'Country' => 'target.area.country__name', |
| 49 | + 'Display name' => 'message.display', |
| 50 | + 'To-name' => 'message.toName', |
| 51 | + 'Subject' => 'message.subject', |
| 52 | + 'Header' => 'message.header', |
| 53 | + 'Message' => 'message.message', |
| 54 | + 'Footer' => 'message.footer', |
| 55 | + ], |
| 56 | + ]; |
| 57 | + foreach ($info['columns'] as $label => $column_info) { |
| 58 | + $column_info['label'] = $label; |
| 59 | + $columns[] = Column::fromInfo($column_info); |
| 60 | + } |
| 61 | + return new static($info['timeframe'], $columns, $info['mapping']); |
| 62 | + } |
| 63 | + |
| 64 | + /** |
| 65 | + * Create a new instance. |
| 66 | + * |
| 67 | + * @param \Drupal\campaignion_csv\Timeframe $timeframe |
| 68 | + * Export data for submissions within this timeframe. |
| 69 | + * @param \Drupal\campaignion_csv\Exporter\WebformFormatted\Column[] $columns |
| 70 | + * Submission columns to export in addition to the target / message data. |
| 71 | + * @param string[] $mapping |
| 72 | + * Mapping of column headers to data paths in the e2t_selector data. |
| 73 | + */ |
| 74 | + public function __construct(Timeframe $timeframe, array $columns, array $mapping) { |
| 75 | + $this->timeframe = $timeframe; |
| 76 | + $this->columns = $columns; |
| 77 | + $this->mapping = $mapping; |
| 78 | + } |
| 79 | + |
| 80 | + /** |
| 81 | + * Iterate through submitted data of e2t_selector components. |
| 82 | + */ |
| 83 | + protected function readSubmittedData() { |
| 84 | + $last_sid = 0; |
| 85 | + list($start, $end) = $this->timeframe->getTimestamps(); |
| 86 | + $sql_sids = <<<SQL |
| 87 | +SELECT s.nid, s.sid, c.cid |
| 88 | +FROM webform_submissions s |
| 89 | + INNER JOIN webform_component c USING(nid) |
| 90 | +WHERE s.is_draft=0 AND c.type='e2t_selector' AND s.submitted BETWEEN :start AND :end AND s.sid>:last_sid |
| 91 | +GROUP BY s.sid |
| 92 | +ORDER BY s.sid |
| 93 | +LIMIT 100 |
| 94 | +SQL; |
| 95 | + $args = [':start' => $start, ':end' => $end - 1]; |
| 96 | + while ($rows = db_query($sql_sids, [':last_sid' => $last_sid] + $args)->fetchAll()) { |
| 97 | + foreach ($rows as $row) { |
| 98 | + $submission = Submission::load($row->nid, $row->sid); |
| 99 | + $values = array_map('unserialize', $submission->valuesByCid($row->cid)); |
| 100 | + foreach ($values as $value) { |
| 101 | + $value['cid'] = $row->cid; |
| 102 | + yield [$submission, $value]; |
| 103 | + } |
| 104 | + $last_sid = $row->sid; |
| 105 | + } |
| 106 | + drupal_static_reset('webform_get_submission'); |
| 107 | + } |
| 108 | + } |
| 109 | + |
| 110 | + /** |
| 111 | + * Write the data to the CsvFile. |
| 112 | + */ |
| 113 | + public function writeTo(CsvFileInterface $file) { |
| 114 | + $header = array_map(function ($v) { |
| 115 | + return $v->label; |
| 116 | + }, $this->columns); |
| 117 | + $file->writeRow(array_merge($header, array_keys($this->mapping))); |
| 118 | + |
| 119 | + foreach ($this->readSubmittedData() as $pair) { |
| 120 | + list($submission, $value) = $pair; |
| 121 | + $row = []; |
| 122 | + foreach ($this->columns as $column) { |
| 123 | + $row[] = $column->value($submission); |
| 124 | + } |
| 125 | + $value_row = array_map(function ($path) use ($value) { |
| 126 | + return drupal_array_get_nested_value($value, explode('.', $path)) ?? ''; |
| 127 | + }, $this->mapping); |
| 128 | + $file->writeRow(array_merge($row, $value_row)); |
| 129 | + } |
| 130 | + } |
| 131 | + |
| 132 | +} |
0 commit comments