PluginProbe
seQura / 4.0.0
seQura v4.0.0
4.3.4 4.3.3 4.3.2 4.3.1 trunk 2.0.0 2.0.10 2.0.11 2.0.12 2.0.5 2.0.6 2.0.7 2.0.8 2.0.9 3.0.0 3.0.2 3.0.5 3.0.6 3.0.7 3.1.0 3.1.1 3.2.0 3.2.1 3.2.2 4.0.0 All 30 releases
sequra / src / Repositories / Migrations / class-migration-install-300.php

class-migration-install-300.php in seQura 4.0.0, at src/Repositories/Migrations/class-migration-install-300.php

361 lines 10.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Post install migration for version 3.0.0 of the plugin.
4 *
5 * @package SeQura/WC
6 * @subpackage SeQura/WC/Repositories
7 */
8
9 namespace SeQura\WC\Repositories\Migrations;
10
11 use Exception;
12 use SeQura\Core\BusinessLogic\AdminAPI\AdminAPI;
13 use SeQura\Core\BusinessLogic\AdminAPI\Connection\Requests\ConnectionRequest;
14 use SeQura\Core\BusinessLogic\AdminAPI\Connection\Requests\OnboardingRequest;
15 use SeQura\Core\BusinessLogic\AdminAPI\CountryConfiguration\Requests\CountryConfigurationRequest;
16 use SeQura\Core\BusinessLogic\AdminAPI\GeneralSettings\Requests\GeneralSettingsRequest;
17 use SeQura\Core\BusinessLogic\AdminAPI\PromotionalWidgets\Requests\WidgetSettingsRequest;
18 use SeQura\Core\BusinessLogic\Domain\Multistore\StoreContext;
19 use SeQura\WC\Repositories\Repository;
20 use Throwable;
21
22 /**
23 * Post install migration for version 3.0.0 of the plugin.
24 */
25 class Migration_Install_300 extends Migration {
26
27 /**
28 * Order repository.
29 *
30 * @var Repository
31 */
32 private $order_repository;
33
34 /**
35 * Entity repository.
36 *
37 * @var Repository
38 */
39 private $entity_repository;
40
41 /**
42 * Queue repository.
43 *
44 * @var Repository
45 */
46 private $queue_repository;
47
48 /**
49 * Store context
50 *
51 * @var StoreContext
52 */
53 private $store_context;
54
55 /**
56 * Get the plugin version when the changes were made.
57 */
58 public function get_version(): string {
59 return '3.0.0';
60 }
61
62 /**
63 * Constructor
64 *
65 * @param \wpdb $wpdb Database instance.
66 */
67 public function __construct(
68 \wpdb $wpdb,
69 Repository $order_repository,
70 Repository $entity_repository,
71 Repository $queue_repository,
72 StoreContext $store_context
73 ) {
74 parent::__construct( $wpdb );
75 $this->order_repository = $order_repository;
76 $this->entity_repository = $entity_repository;
77 $this->queue_repository = $queue_repository;
78 $this->store_context = $store_context;
79 }
80
81 /**
82 * Run the migration.
83 *
84 * @throws Throwable|Critical_Migration_Exception
85 */
86 public function run(): void {
87 $this->add_new_tables_to_database();
88 $woocommerce_sequra_settings = (array) \get_option( 'woocommerce_sequra_settings', array() );
89 if ( ! empty( $woocommerce_sequra_settings ) ) {
90 $this->fetch_deployments();
91 $this->migrate_connection_configuration( $woocommerce_sequra_settings );
92 $this->migrate_general_settings_configuration( $woocommerce_sequra_settings );
93 $this->migrate_country_configuration( $woocommerce_sequra_settings );
94 $this->migrate_widget_configuration( $woocommerce_sequra_settings );
95 }
96 }
97
98 /**
99 * Add new tables to the database.
100 *
101 * @throws Throwable|Critical_Migration_Exception
102 */
103 private function add_new_tables_to_database(): void {
104 /**
105 * Repository instances.
106 *
107 * @var Repository[] $repos
108 */
109 $repos = array(
110 $this->order_repository,
111 $this->entity_repository,
112 $this->queue_repository,
113 );
114
115 foreach ( $repos as $repo ) {
116 // Skip this migration if the table already exists.
117 if ( $repo->table_exists() ) {
118 continue;
119 }
120
121 try {
122 $repo->create_table();
123 } catch ( Throwable $e ) {
124 throw new Critical_Migration_Exception( \esc_html( "Could not create the table \"{$repo->get_table_name()}\". {$e->getMessage()}" ) );
125 }
126 }
127 }
128
129 /**
130 * Check if the entity exists in the database.
131 */
132 private function entity_exists( string $type ): bool {
133 $table_name = \esc_sql( $this->entity_repository->get_table_name() );
134 // @phpstan-ignore-next-line
135 $query = $this->db->prepare( 'SELECT id FROM ' . $table_name . ' WHERE `type` = %s LIMIT 1', $type );
136 $result = $this->db->get_results( $query );
137 return is_array( $result ) && count( $result ) > 0;
138 }
139
140 /**
141 * Fetch deployment targets and save them to the database
142 *
143 * @throws \Exception
144 */
145 private function fetch_deployments(): void {
146 $response = AdminAPI::get()
147 ->deployments( $this->store_context->getStoreId() )
148 ->getAllDeployments();
149
150 if ( ! $response->isSuccessful() ) {
151 throw new Exception( 'Error fetching deployment targets' );
152 }
153 }
154
155 /** Migrate connection settings from v2
156 *
157 * @param string[] $settings
158 * @throws Throwable|Exception
159 */
160 private function migrate_connection_configuration( array $settings ): void {
161 if ( $this->entity_exists( 'ConnectionData' ) ) {
162 // Skip this migration if the data is already set.
163 return;
164 }
165
166 $env_mapping = array(
167 '0' => 'live',
168 '1' => 'sandbox',
169 );
170
171 if ( ! isset( $settings['env'], $settings['user'], $settings['password'] )
172 || ! array_key_exists( $settings['env'], $env_mapping ) ) {
173 // Skip this migration if the data isn't set or valid.
174 return;
175 }
176
177 $response = AdminAPI::get()
178 ->connection( $this->store_context->getStoreId() )
179 ->connect(
180 new OnboardingRequest(
181 array(
182 new ConnectionRequest(
183 $env_mapping[ $settings['env'] ],
184 '',
185 strval( $settings['user'] ),
186 strval( $settings['password'] ),
187 'sequra'
188 ),
189 ),
190 true
191 )
192 );
193
194 if ( ! $response->isSuccessful() ) {
195 throw new Exception( 'Error migrating connection settings' );
196 }
197 }
198
199 /**
200 * Translate the widget style identifier to the new format if it is needed.
201 * If no identifier is provided, the default widget style is returned.
202 */
203 private function get_widget_style( ?string $style = null ): string {
204 if ( is_string( $style ) && json_decode( $style, true ) !== null ) {
205 return $style; // Already in the new format.
206 }
207
208 $default_widget_style = '{"alignment":"center","amount-font-bold":"true","amount-font-color":"#1C1C1C","amount-font-size":"15","background-color":"white","border-color":"#B1AEBA","border-radius":"","class":"","font-color":"#1C1C1C","link-font-color":"#1C1C1C","link-underline":"true","no-costs-claim":"","size":"M","starting-text":"only","type":"banner"}';
209
210 $map = array(
211 'L' => '{"alignment":"left"}',
212 'R' => '{"alignment":"right"}',
213 'legacy' => '{"type":"legacy"}',
214 'legacyL' => '{"type":"legacy","alignment":"left"}',
215 'legacyR' => '{"type":"legacy","alignment":"right"}',
216 'minimal' => '{"type":"text","branding":"none","size":"S","starting-text":"as-low-as"}',
217 'minimalL' => '{"type":"text","branding":"none","size":"S","starting-text":"as-low-as","alignment":"left"}',
218 'minimalR' => '{"type":"text","branding":"none","size":"S","starting-text":"as-low-as","alignment":"right"}',
219 );
220
221 return null === $style || ! isset( $map[ $style ] ) ? $default_widget_style : $map[ $style ];
222 }
223
224 /** Migrate country settings from v2
225 *
226 * @param string[] $settings
227 * @throws Throwable|Exception
228 */
229 private function migrate_country_configuration( array $settings ): void {
230 if ( $this->entity_exists( 'CountryConfiguration' ) || ! isset( $settings['merchantref'] ) ) {
231 return;
232 }
233
234 $merchant_id = strval( $settings['merchantref'] );
235 $table_name = \esc_sql( $this->entity_repository->get_table_name() );
236 $raw_results = $this->db->get_results(
237 // @phpstan-ignore-next-line
238 $this->db->prepare( 'SELECT `index_2` FROM ' . $table_name . ' WHERE `type` = %s AND `index_1` = %s AND `index_3` = %s', 'Credentials', $this->store_context->getStoreId(), $merchant_id ),
239 ARRAY_A
240 );
241
242 $country_configurations = array();
243 if ( is_array( $raw_results ) ) {
244 foreach ( $raw_results as $row ) {
245 if ( ! isset( $row['index_2'] ) ) {
246 continue;
247 }
248 $country_configurations[] = array(
249 'countryCode' => strval( $row['index_2'] ),
250 'merchantId' => $merchant_id,
251 );
252 }
253 }
254
255 $response = AdminAPI::get()
256 ->countryConfiguration( $this->store_context->getStoreId() )
257 ->saveCountryConfigurations(
258 new CountryConfigurationRequest( $country_configurations )
259 );
260 if ( ! $response->isSuccessful() ) {
261 throw new Exception( 'Error migrating country settings' );
262 }
263 }
264
265 /** Migrate general settings from v2
266 *
267 * @param string[] $settings
268 * @throws Throwable|Exception
269 */
270 private function migrate_general_settings_configuration( array $settings ): void {
271
272 if ( $this->entity_exists( 'GeneralSettings' ) ) {
273 return;
274 }
275
276 $allowed_ip_addresses = array();
277 foreach ( explode( ',', strval( $settings['test_ips'] ?? '' ) ) as $ip ) {
278 $ip = trim( $ip );
279 if ( ! empty( $ip ) ) {
280 $allowed_ip_addresses[] = $ip;
281 }
282 }
283
284 $response = AdminAPI::get()
285 ->generalSettings( $this->store_context->getStoreId() )
286 ->saveGeneralSettings(
287 new GeneralSettingsRequest(
288 true,
289 false,
290 $allowed_ip_addresses,
291 null,
292 null,
293 strval( $settings['default_service_end_date'] ?? 'P1Y' )
294 )
295 );
296
297 if ( ! $response->isSuccessful() ) {
298 throw new Exception( 'Error general settings' );
299 }
300 }
301
302 /** Migrate widget settings from v2
303 *
304 * @param string[] $settings
305 * @throws Throwable|Exception
306 */
307 private function migrate_widget_configuration( array $settings ): void {
308
309 if ( $this->entity_exists( 'WidgetSettings' ) ) {
310 return;
311 }
312
313 $enabled = false;
314 $default_sel_for_alt_price = '.woocommerce-variation-price .price>.amount,.woocommerce-variation-price .price ins .amount';
315 $default_sel_for_alt_price_trigger = '.variations';
316 $sel_for_default_location = '.summary>.price';
317 $custom_locations = array();
318 foreach ( $settings as $key => $value ) {
319 if ( false !== strpos( $key, 'enabled_in_product_' ) ) {
320 $enabled_in_product = 'yes' === $value;
321 $enabled = $enabled || $enabled_in_product;
322 $product_campaign = str_replace( 'enabled_in_product_', '', $key );
323 $parts = explode( '_', $product_campaign, 2 );
324
325 $custom_locations[] = array(
326 'selForTarget' => $settings[ "dest_css_sel_$product_campaign" ] ?? $sel_for_default_location,
327 'product' => $parts[0],
328 'displayWidget' => $enabled_in_product,
329 'widgetStyles' => $this->get_widget_style( $settings[ "widget_theme_$product_campaign" ] ?? null ),
330 );
331 }
332 }
333
334 $response = AdminAPI::get()
335 ->widgetConfiguration( $this->store_context->getStoreId() )
336 ->setWidgetSettings(
337 new WidgetSettingsRequest(
338 $enabled,
339 false,
340 false,
341 $this->get_widget_style(),
342 $settings['price_css_sel'] ?? '',
343 $sel_for_default_location,
344 '',
345 '',
346 '',
347 '',
348 '',
349 '',
350 $default_sel_for_alt_price,
351 $default_sel_for_alt_price_trigger,
352 $custom_locations
353 )
354 );
355
356 if ( ! $response->isSuccessful() ) {
357 throw new Exception( 'Error migrating widget settings' );
358 }
359 }
360 }
361