Passed
Push — trunk ( 9c2f71...32e8e5 )
by Christian
10:51 queued 12s
created

CustomerNewsletterSalesChannelsUpdater::updateCustomerEmailRecipient()   A

Complexity

Conditions 5
Paths 9

Size

Total Lines 40
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 24
nc 9
nop 1
dl 0
loc 40
rs 9.2248
c 0
b 0
f 0
1
<?php declare(strict_types=1);
2
3
namespace Shopware\Core\Content\Newsletter\DataAbstractionLayer\Indexing;
4
5
use Doctrine\DBAL\Connection;
6
use Shopware\Core\Content\Newsletter\SalesChannel\NewsletterSubscribeRoute;
7
use Shopware\Core\Framework\DataAbstractionLayer\Doctrine\RetryableQuery;
8
use Shopware\Core\Framework\Uuid\Uuid;
9
10
/**
11
 * @package customer-order
12
 */
13
class CustomerNewsletterSalesChannelsUpdater
14
{
15
    /**
16
     * @internal
17
     */
18
    public function __construct(private Connection $connection)
19
    {
20
    }
21
22
    /**
23
     * @param array<string> $ids
24
     */
25
    public function update(array $ids, bool $reverseUpdate = false): void
26
    {
27
        if (empty($ids)) {
28
            return;
29
        }
30
31
        $ids = array_unique($ids);
32
33
        $tableTemplate = <<<'SQL'
34
UPDATE `customer`, `newsletter_recipient` SET `customer`.`newsletter_sales_channel_ids` = (
35
    SELECT CONCAT(
36
        '{',
37
        GROUP_CONCAT(
38
            CONCAT(
39
                JSON_QUOTE(LOWER(HEX(`newsletter_recipient`.`id`))),
40
                ':',
41
                JSON_QUOTE(LOWER(HEX(`newsletter_recipient`.`sales_channel_id`)))
42
            )
43
        ),
44
        '}'
45
    )
46
    FROM `newsletter_recipient`
47
    WHERE `newsletter_recipient`.`email` = `customer`.`email`
48
    AND `newsletter_recipient`.`status` IN (:states)
49
)
50
WHERE `newsletter_recipient`.`email` = `customer`.`email`
51
AND #table#.`id` IN (:ids)
52
SQL;
53
54
        $resetTemplate = <<<'SQL'
55
UPDATE `customer`
56
LEFT JOIN `newsletter_recipient` ON `newsletter_recipient`.`email` = `customer`.`email`
57
SET `customer`.`newsletter_sales_channel_ids` = NULL
58
WHERE #table#.`id` IN (:ids)
59
SQL;
60
61
        $parameters = [
62
            'ids' => Uuid::fromHexToBytesList($ids),
63
            'states' => [NewsletterSubscribeRoute::STATUS_DIRECT, NewsletterSubscribeRoute::STATUS_OPT_IN],
64
        ];
65
66
        $replacement = [
67
            '#table#' => $reverseUpdate ? '`customer`' : '`newsletter_recipient`',
68
        ];
69
70
        $sql = str_replace(
71
            array_keys($replacement),
72
            array_values($replacement),
73
            $tableTemplate
74
        );
75
76
        $resetSql = str_replace(
77
            array_keys($replacement),
78
            array_values($replacement),
79
            $resetTemplate
80
        );
81
82
        RetryableQuery::retryable($this->connection, function () use ($resetSql, $parameters): void {
83
            $this->connection->executeStatement(
84
                $resetSql,
85
                $parameters,
86
                ['ids' => Connection::PARAM_STR_ARRAY]
87
            );
88
        });
89
90
        RetryableQuery::retryable($this->connection, function () use ($sql, $parameters): void {
91
            $this->connection->executeStatement(
92
                $sql,
93
                $parameters,
94
                ['ids' => Connection::PARAM_STR_ARRAY, 'states' => Connection::PARAM_STR_ARRAY]
95
            );
96
        });
97
    }
98
99
    /**
100
     * @param array<string> $ids
101
     */
102
    public function delete(array $ids): void
103
    {
104
        $sqlTemplate = <<<'SQL'
105
SELECT `customer`.`id`
106
FROM `customer`
107
WHERE #expressions#
108
SQL;
109
110
        $expressions = [];
111
        foreach ($ids as $id) {
112
            $expressions[] = 'JSON_EXTRACT(`customer`.`newsletter_sales_channel_ids`, \'$."' . $id . '"\') IS NOT NULL';
113
        }
114
115
        $replacement = [
116
            '#expressions#' => implode(' OR ', $expressions),
117
        ];
118
119
        $sql = str_replace(
120
            array_keys($replacement),
121
            array_values($replacement),
122
            $sqlTemplate
123
        );
124
125
        $customerIds = RetryableQuery::retryable($this->connection, function () use ($sql): array {
126
            return $this->connection->fetchFirstColumn($sql);
127
        });
128
129
        if (empty($customerIds)) {
130
            return;
131
        }
132
133
        $this->update(Uuid::fromBytesToHexList($customerIds), true);
134
    }
135
136
    /**
137
     * @param array<string> $ids
138
     */
139
    public function updateCustomersRecipient(array $ids): void
140
    {
141
        $ids = array_unique($ids);
142
143
        $customers = $this->connection->fetchAllAssociative(
144
            'SELECT newsletter_sales_channel_ids, email, first_name, last_name FROM customer WHERE id IN (:ids)',
145
            ['ids' => Uuid::fromHexToBytesList($ids)],
146
            ['ids' => Connection::PARAM_STR_ARRAY]
147
        );
148
149
        $parameters = [];
150
151
        foreach ($customers as $customer) {
152
            if (!$customer['newsletter_sales_channel_ids']) {
153
                continue;
154
            }
155
156
            $parameters[] = [
157
                'newsletter_ids' => array_keys(
158
                    json_decode((string) $customer['newsletter_sales_channel_ids'], true)
159
                ),
160
                'email' => $customer['email'],
161
                'first_name' => $customer['first_name'],
162
                'last_name' => $customer['last_name'],
163
            ];
164
        }
165
166
        if (empty($parameters)) {
167
            return;
168
        }
169
170
        foreach ($parameters as $parameter) {
171
            RetryableQuery::retryable($this->connection, function () use ($parameter): void {
172
                $this->connection->executeStatement(
173
                    'UPDATE newsletter_recipient SET email = (:email), first_name = (:firstName), last_name = (:lastName) WHERE id IN (:ids)',
174
                    [
175
                        'ids' => Uuid::fromHexToBytesList($parameter['newsletter_ids']),
176
                        'email' => $parameter['email'],
177
                        'firstName' => $parameter['first_name'],
178
                        'lastName' => $parameter['last_name'],
179
                    ],
180
                    ['ids' => Connection::PARAM_STR_ARRAY],
181
                );
182
            });
183
        }
184
    }
185
}
186