Completed
Push — master ( 28470d...dc2e38 )
by Simon
01:37
created

PartialSubmissionJob::processSubmissions()   B

Complexity

Conditions 4
Paths 4

Size

Total Lines 25
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 25
rs 8.5806
cc 4
eloc 20
nc 4
nop 3
1
<?php
2
3
namespace Firesphere\PartialUserforms\Jobs;
4
5
use Firesphere\PartialUserforms\Models\PartialFieldSubmission;
6
use Firesphere\PartialUserforms\Models\PartialFormSubmission;
7
use Firesphere\PartialUserforms\Services\DateService;
8
use SilverStripe\Control\Director;
9
use SilverStripe\Control\Email\Email;
10
use SilverStripe\Core\Injector\Injector;
11
use SilverStripe\ORM\ArrayList;
12
use SilverStripe\ORM\DataList;
13
use SilverStripe\ORM\FieldType\DBDatetime;
14
use SilverStripe\SiteConfig\SiteConfig;
15
use SilverStripe\UserForms\Model\UserDefinedForm;
16
use Symbiote\QueuedJobs\Services\AbstractQueuedJob;
17
use Symbiote\QueuedJobs\Services\QueuedJobService;
18
19
/**
20
 * Class PartialSubmissionJob
21
 * @package Firesphere\PartialUserforms\Jobs
22
 */
23
class PartialSubmissionJob extends AbstractQueuedJob
24
{
25
26
    /**
27
     * The generated CSV files
28
     * @var array
29
     */
30
    protected $files = [];
31
32
    /**
33
     * @var SiteConfig
34
     */
35
    protected $config;
36
37
    /**
38
     * @var array
39
     */
40
    protected $addresses;
41
42
43
    /**
44
     * Prepare the data
45
     */
46
    public function setup()
47
    {
48
        parent::setup();
49
        $this->config = SiteConfig::current_site_config();
50
        $this->validateEmails();
51
    }
52
53
    /**
54
     * Only add valid email addresses
55
     */
56
    protected function validateEmails()
57
    {
58
        $email = $this->config->SendMailTo;
59
        $result = Email::is_valid_address($email);
60
        if ($result) {
61
            $this->addresses[] = $email;
62
        }
63
        if (strpos($email, ',') !== false) {
64
            $emails = explode(',', $email);
65
            foreach ($emails as $address) {
66
                $result = Email::is_valid_address(trim($address));
67
                if ($result) {
68
                    $this->addresses[] = trim($address);
69
                } else {
70
                    $this->addMessage($address . _t(__CLASS__ . '.invalidMail', ' is not a valid email address'));
71
                }
72
            }
73
        }
74
    }
75
76
    /**
77
     * @return string
78
     */
79
    public function getTitle()
80
    {
81
        return _t(__CLASS__ . '.Title', 'Export partial submissions to Email');
82
    }
83
84
    /**
85
     * Do some processing yourself!
86
     */
87
    public function process()
88
    {
89
        if (!$this->config->SendDailyEmail) {
90
            $this->addMessage(_t(__CLASS__ . '.NotActive', 'Daily exports are not enabled'));
91
            $this->isComplete = true;
92
93
            return;
94
        }
95
        if (!count($this->addresses)) {
96
            $this->addMessage(_t(__CLASS__ . '.EmailError', 'Can not process without valid email'));
97
            $this->isComplete = true;
98
99
            return;
100
        }
101
102
        $userDefinedForms = $this->getParents();
103
104
        /** @var UserDefinedForm $form */
105
        foreach ($userDefinedForms as $form) {
106
            $fileName = _t(__CLASS__ . '.Export', 'Export of ') .
107
                $form->Title . ' - ' .
108
                DBDatetime::now()->Format(DBDatetime::ISO_DATETIME);
109
            $file = '/tmp/' . $fileName . '.csv';
110
            $this->files[] = $file;
111
            $this->buildCSV($file, $form);
112
        }
113
114
        $this->sendEmail();
115
116
        $this->isComplete = true;
117
    }
118
119
    /**
120
     * @return ArrayList
121
     */
122
    protected function getParents()
123
    {
124
        /** @var DataList|PartialFormSubmission[] $exportForms */
125
        $allSubmissions = PartialFormSubmission::get()->filter(['IsSend' => false]);
126
        /** @var ArrayList|UserDefinedForm[] $parents */
127
        $userDefinedForms = ArrayList::create();
128
129
        /** @var PartialFormSubmission $submission */
130
        /** @noinspection ForeachSourceInspection */
131
        foreach ($allSubmissions as $submission) {
132
            // Due to having to support Elemental ElementForm, we need to manually get the parent
133
            // It's a bit a pickle, but it works
134
            $parentClass = $submission->ParentClass;
135
            $parent = $parentClass::get()->byID($submission->UserDefinedFormID);
136
            if ($parent &&
137
                $parent->ExportPartialSubmissions &&
138
                !$userDefinedForms->find('ID', $parent->ID)
139
            ) {
140
                $userDefinedForms->push($parent);
141
            }
142
            $submission->destroy();
143
        }
144
145
        return $userDefinedForms;
146
    }
147
148
    /**
149
     * @param string $file
150
     * @param UserDefinedForm $form
151
     * @throws \SilverStripe\ORM\ValidationException
152
     */
153
    protected function buildCSV($file, $form)
154
    {
155
        $resource = fopen($file, 'w+');
156
        /** @var DataList|PartialFormSubmission[] $submissions */
157
        $submissions = PartialFormSubmission::get()->filter(['UserDefinedFormID' => $form->ID]);
158
        $headerFields = $form
159
            ->Fields()
160
            ->exclude(['Name:PartialMatch' => 'EditableFormStep'])
161
            ->column('Title');
162
        fputcsv($resource, $headerFields);
163
164
        if ($submissions->count()) {
165
            $this->processSubmissions($form, $submissions, $resource);
166
        }
167
        fclose($resource);
168
    }
169
170
    /**
171
     * @param UserDefinedForm $form
172
     * @param DataList|PartialFormSubmission[] $submissions
173
     * @param resource $resource
174
     * @throws \SilverStripe\ORM\ValidationException
175
     */
176
    protected function processSubmissions($form, $submissions, $resource)
177
    {
178
        $editableFields = $form
179
            ->Fields()
180
            ->exclude(['Name:PartialMatch' => 'EditableFormStep'])
181
            ->map('Name', 'Title')
182
            ->toArray();
183
        $submitted = [];
0 ignored issues
show
Unused Code introduced by
$submitted is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
184
        foreach ($submissions as $submission) {
185
            $submitted = [];
186
            $values = $submission->PartialFields()->map('Name', 'Value')->toArray();
187
            $i = 0;
188
            foreach ($editableFields as $field => $title) {
189
                if (isset($values[$field])) {
190
                    $submitted[] = $values[$field];
191
                } else {
192
                    $submitted[] = '';
193
                }
194
                $i++;
195
            }
196
            fputcsv($resource, $submitted);
197
            $submission->IsSend = true;
198
            $submission->write();
199
        }
200
    }
201
202
    /**
203
     * Send out the email(s)
204
     */
205
    protected function sendEmail()
206
    {
207
        /** @var Email $mail */
208
        $mail = Email::create();
209
        $mail->setSubject('Partial form submissions of ' . DBDatetime::now()->Format(DBDatetime::ISO_DATETIME));
210
        foreach ($this->files as $file) {
211
            $mail->addAttachment($file);
212
        }
213
        $from = $this->config->SendMailFrom ?: 'site@' . Director::host();
214
215
        $mail->setFrom($from);
216
        foreach ($this->addresses as $address) {
217
            $mail->setTo($address);
218
            $mail->setBody('Please see attached CSV files');
219
            $mail->send();
220
        }
221
    }
222
223
    /**
224
     * @throws \Exception
225
     */
226
    public function afterComplete()
227
    {
228
        // Remove the files created in the process
229
        foreach ($this->files as $file) {
230
            unlink($file);
231
        }
232
233
        parent::afterComplete();
234
        if ($this->config->CleanupAfterSend) {
235
            $this->cleanupSubmissions();
236
        }
237
        if ($this->config->SendDailyEmail) {
238
            $this->createNewJob();
239
        }
240
    }
241
242
    /**
243
     * Remove submissions that have been sent out
244
     */
245
    protected function cleanupSubmissions()
246
    {
247
        /** @var DataList|PartialFormSubmission[] $forms */
248
        $forms = PartialFormSubmission::get()->filter(['IsSend' => true]);
249
        foreach ($forms as $form) {
250
            /** @var DataList|PartialFieldSubmission[] $fields */
251
            $fields = PartialFieldSubmission::get()->filter(['ID' => $form->PartialFields()->column('ID')]);
252
            $fields->removeAll();
253
            $form->delete();
254
            $form->destroy();
255
        }
256
    }
257
258
    /**
259
     * Create a new queued job for tomorrow
260
     * @throws \Exception
261
     */
262
    protected function createNewJob()
263
    {
264
        $job = new self();
265
        /** @var QueuedJobService $queuedJob */
266
        $queuedJob = Injector::inst()->get(QueuedJobService::class);
267
        $tomorrow = DateService::getTomorrow();
268
        $queuedJob->queueJob($job, $tomorrow->Format(DBDatetime::ISO_DATETIME));
269
    }
270
271
    /**
272
     * @return array
273
     */
274
    public function getMessages()
275
    {
276
        return $this->messages;
277
    }
278
279
    /**
280
     * @return array
281
     */
282
    public function getAddresses()
283
    {
284
        return $this->addresses;
285
    }
286
287
    /**
288
     * @param string $address
289
     */
290
    public function addAddress($address)
291
    {
292
        if (Email::is_valid_address($address)) {
293
            $this->addresses[] = $address;
294
        }
295
    }
296
297
    /**
298
     * @return SiteConfig
299
     */
300
    public function getConfig()
301
    {
302
        return $this->config;
303
    }
304
}
305