Completed
Push — master ( d351a1...00965d )
by Freek
01:34
created

PrepareEmailHtmlAction::trackOpens()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
3
namespace Spatie\EmailCampaigns\Actions;
4
5
use DOMElement;
6
use DOMDocument;
7
use ErrorException;
8
use Illuminate\Support\Str;
9
use Spatie\EmailCampaigns\Models\Campaign;
10
use Spatie\EmailCampaigns\Exceptions\CampaignCouldNotBeSent;
11
use Spatie\EmailCampaigns\Http\Controllers\TrackOpensController;
12
13
class PrepareEmailHtmlAction
14
{
15
    public function execute(Campaign $campaign)
16
    {
17
        $campaign->email_html = $campaign->html;
18
19
        $this->ensureEmailHtmlHasSingleRootElement($campaign);
20
21
        if ($campaign->track_clicks) {
22
            $this->trackClicks($campaign);
23
        }
24
25
        if ($campaign->track_opens) {
26
            $this->trackOpens($campaign);
27
        }
28
29
        $this->replacePlaceholders($campaign);
30
31
        $campaign->save();
32
    }
33
34
    protected function ensureEmailHtmlHasSingleRootElement($campaign)
35
    {
36
        if (! Str::startsWith(trim($campaign->email_html), '<html')) {
37
            $campaign->email_html ='<html>' .  $campaign->email_html;
38
        }
39
40
        if (! Str::endsWith(trim($campaign->email_html), '</html>')) {
41
            $campaign->email_html = $campaign->email_html. '</html>';
42
        }
43
    }
44
45
46
    protected function trackClicks(Campaign $campaign)
47
    {
48
        $dom = new DOMDocument('1.0', 'UTF-8');
49
50
        try {
51
            $dom->loadHTML($campaign->email_html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD | LIBXML_NOWARNING);
52
        } catch (ErrorException $errorException) {
0 ignored issues
show
Bug introduced by
The class ErrorException does not exist. Is this class maybe located in a folder that is not analyzed, or in a newer version of your dependencies than listed in your composer.lock/composer.json?
Loading history...
53
            throw CampaignCouldNotBeSent::invalidContent($campaign, $errorException);
54
        }
55
56
        collect($dom->getElementsByTagName('a'))
57
            ->filter(function (DOMElement $linkElement) {
58
                return Str::startsWith(
59
                    $linkElement->getAttribute('href'),
60
                    ['http://', 'https://']
61
                );
62
            })
63
            ->each(function (DOMElement $linkElement) use ($campaign) {
64
                $originalHref = $linkElement->getAttribute('href');
65
66
                $campaignLink = $campaign->links()->create([
67
                    'original_link' => $originalHref,
68
                ]);
69
70
                $linkElement->setAttribute('href', $campaignLink->url);
71
            });
72
73
        $campaign->email_html = trim($dom->saveHtml());
74
    }
75
76
    protected function trackOpens(Campaign $campaign)
77
    {
78
        $webBeaconUrl = action(TrackOpensController::class, '::campaignSendUuid::');
79
80
        $webBeaconHtml = "<img alt='beacon' src='{$webBeaconUrl}' />";
81
82
        $campaign->email_html = Str::replaceLast('</body>', $webBeaconHtml.'</body>', $campaign->email_html);
83
    }
84
85
    protected function replacePlaceholders(Campaign $campaign): void
86
    {
87
        $webviewUrl = $campaign->webViewUrl();
88
89
        $campaign->email_html = str_replace('::webviewUrl::', $webviewUrl, $campaign->email_html);
90
    }
91
}
92