-
Notifications
You must be signed in to change notification settings - Fork 21
/
Copy pathBudgetRecommendationTable.php
157 lines (133 loc) · 3.49 KB
/
BudgetRecommendationTable.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
<?php
declare( strict_types=1 );
namespace Automattic\WooCommerce\GoogleListingsAndAds\DB\Table;
use Automattic\WooCommerce\GoogleListingsAndAds\DB\Table;
defined( 'ABSPATH' ) || exit;
/**
* Class BudgetRecommendationTable
*
* @package Automattic\WooCommerce\GoogleListingsAndAds\DB\Tables
*/
class BudgetRecommendationTable extends Table {
/**
* Whether the initial data has been loaded
*
* @var bool
*/
public $has_loaded_initial_data = false;
/**
* Get the schema for the DB.
*
* This should be a SQL string for creating the DB table.
*
* @return string
*/
protected function get_install_query(): string {
return <<< SQL
CREATE TABLE `{$this->get_sql_safe_name()}` (
id bigint(20) NOT NULL AUTO_INCREMENT,
currency varchar(3) NOT NULL,
country varchar(2) NOT NULL,
daily_budget int(11) NOT NULL,
PRIMARY KEY (id),
UNIQUE KEY country_currency (country, currency)
) {$this->get_collation()};
SQL;
}
/**
* Install the Database table.
*
* Add data if there is none.
*/
public function install(): void {
parent::install();
// Load the data if the table is empty.
// phpcs:ignore WordPress.DB.PreparedSQL
$result = $this->wpdb->get_row( "SELECT COUNT(*) AS count FROM `{$this->get_sql_safe_name()}`" );
if ( empty( $result->count ) ) {
$this->load_initial_data();
}
}
/**
* Reload initial data.
*
* @return void
*/
public function reload_data(): void {
if ( $this->exists() && ! $this->has_loaded_initial_data ) {
$this->truncate();
$this->load_initial_data();
}
}
/**
* Get the un-prefixed (raw) table name.
*
* @return string
*/
public static function get_raw_name(): string {
return 'budget_recommendations';
}
/**
* Get the columns for the table.
*
* @return array
*/
public function get_columns(): array {
return [
'id' => true,
'currency' => true,
'country' => true,
'daily_budget' => true,
];
}
/**
* Load packaged recommendation data on the first install of GLA.
*
* Inserts 500 records at a time.
*/
private function load_initial_data(): void {
$path = $this->get_root_dir() . '/data/budget-recommendations.csv';
$chunk_size = 500;
if ( file_exists( $path ) ) {
$csv = array_map( 'str_getcsv', file( $path ) );
// Remove the headers
array_shift( $csv );
if ( empty( $csv ) ) {
return;
}
$values = [];
$placeholders = [];
// Build placeholders for each row, and add values to data array
foreach ( $csv as $row ) {
if ( empty( $row ) ) {
continue;
}
$row_placeholders = [];
foreach ( $row as $value ) {
$values[] = $value;
$row_placeholders[] = is_numeric( $value ) ? '%d' : '%s';
}
$placeholders[] = '(' . implode( ', ', $row_placeholders ) . ')';
if ( count( $placeholders ) >= $chunk_size ) {
$this->insert_chunk( $placeholders, $values );
$placeholders = [];
$values = [];
}
}
$this->insert_chunk( $placeholders, $values );
}
$this->has_loaded_initial_data = true;
}
/**
* Insert a chunk of budget recommendations
*
* @param string[] $placeholders
* @param array $values
*/
private function insert_chunk( array $placeholders, array $values ): void {
$sql = "INSERT INTO `{$this->get_sql_safe_name()}` (country,daily_budget,currency) VALUES\n";
$sql .= implode( ",\n", $placeholders );
// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
$this->wpdb->query( $this->wpdb->prepare( $sql, $values ) );
}
}