Issues (68)

src/Tasks/CompressEmailBodiesTask.php (1 issue)

Severity
1
<?php
2
3
namespace LeKoala\EmailTemplates\Tasks;
4
5
use SilverStripe\ORM\DB;
6
use SilverStripe\Dev\BuildTask;
7
use LeKoala\EmailTemplates\Models\SentEmail;
8
use SilverStripe\Control\Director;
9
use SilverStripe\Core\Config\Config;
10
use SilverStripe\ORM\Connect\MySQLDatabase;
11
use SilverStripe\ORM\Queries\SQLUpdate;
12
13
/**
14
 *
15
 * Finds all non-compressed sent email bodies and compresses them
16
 *
17
 * Requires the gzip extension
18
 *
19
 * @author gurucomkz
20
 */
21
class CompressEmailBodiesTask extends BuildTask
22
{
23
    private static $segment = 'CompressEmailBodiesTask';
0 ignored issues
show
The private property $segment is not used, and could be removed.
Loading history...
24
25
    protected $title = "Compress Email Bodies task";
26
    protected $description = "Finds all non-compressed sent email bodies and compresses them";
27
28
    public function isEnabled()
29
    {
30
        return Director::is_cli() && parent::isEnabled() && function_exists('gzdeflate') && Config::forClass(SentEmail::class)->get('compress_body');
31
    }
32
33
    public function run($request)
34
    {
35
        $table = SentEmail::singleton()->baseTable();
36
        $fromWhere = "FROM \"$table\" WHERE \"Body\" NOT LIKE '" . SentEmail::COMPRESSED_SIGNATURE . "%'";
37
        $total = DB::query("SELECT COUNT(ID) $fromWhere")->value();
38
39
        if (!$total) {
40
            echo "No non-compressed emails found\n";
41
            return;
42
        }
43
44
        $nonCompressed = DB::query("SELECT ID, \"Body\" $fromWhere");
45
46
        echo "Found " . $total . " non-compressed emails\n";
47
48
        foreach ($nonCompressed as $pos => $row) {
49
            if (!$row['Body']) {
50
                echo "Email with ID {$row['ID']} has no body\n";
51
                continue;
52
            }
53
            $compressed = gzdeflate($row['Body'] ?? '');
54
            if ($compressed === false) {
55
                echo "\tFailed to compress email with ID {$row['ID']}\n";
56
                continue;
57
            }
58
59
            $base64compressed = SentEmail::COMPRESSED_SIGNATURE . base64_encode($compressed);
60
61
            SQLUpdate::create($table, [
62
                'Body' => $base64compressed,
63
            ], [
64
                'ID' => $row['ID'],
65
            ])->execute();
66
67
            $this->progress($pos, $total);
68
        }
69
70
        // optimise table
71
        $this->optimizeTable();
72
        echo "\n";
73
    }
74
75
    public function optimizeTable()
76
    {
77
        $table = SentEmail::singleton()->baseTable();
78
        echo "\nOptimizing $table table...\n";
79
        $db = DB::get_conn();
80
        if ($db instanceof MySQLDatabase) {
81
            DB::query("OPTIMIZE TABLE \"$table\"");
82
        } elseif (get_class($db) == "SilverStripe\PostgreSQL\PostgreSQLDatabase") {
83
            DB::query("VACUUM FULL \"$table\"");
84
        } else {
85
            echo "Database not supported for optimization\n";
86
        }
87
    }
88
89
    const PROGRRESS_SPINNER = [
90
        '⠋',
91
        '⠙',
92
        '⠹',
93
        '⠼',
94
        '⠴',
95
        '⠦',
96
        '⠧',
97
        '⠇',
98
    ];
99
100
    public function progress($pos, $total)
101
    {
102
        if ($total) {
103
            $percent = round($pos / $total * 100, 2);
104
            $percentInt = floor($percent);
105
106
            $spinner = "\rConverting: [";
107
            $spinner .= str_repeat('■', (int)floor($percentInt / 5));
108
            $edge = self::PROGRRESS_SPINNER[$pos % count(self::PROGRRESS_SPINNER)];
109
            $spinner .= "$edge";
110
            $spinner .= str_repeat(' ', 40 - strlen($spinner));
111
            $spinner .= "] $percent%   ";
112
            echo $spinner;
113
            if ($percentInt > 0 && $percentInt % 100 == 0) {
114
                echo "\n";
115
            }
116
        }
117
    }
118
}
119