| @@ -139,8 +139,52 @@ | ||
| 139 | 139 | return $this->insertRecordReturningId($tableName, $record) !== null; |
| 140 | 140 | } |
| 141 | 141 | |
| 142 | 142 | /** |
| 143 | + * Find a row's id by its business-unique columns. | |
| 144 | + * | |
| 145 | + * Import used to insert every row unconditionally, so re-running it | |
| 146 | + * duplicated everything that had no unique constraint and rejected | |
| 147 | + * everything that had one. Looking the row up first lets the importer | |
| 148 | + * recognise what it has already brought in. | |
| 149 | + * | |
| 150 | + * @param array<string, scalar|null> $criteria column => value (all must match) | |
| 151 | + * @return int|null existing row id, or null when there is no match | |
| 152 | + */ | |
| 153 | + public function findRowIdBy(string $tableName, array $criteria): ?int | |
| 154 | + { | |
| 155 | + global $wpdb; | |
| 156 | + | |
| 157 | + if ($criteria === []) { | |
| 158 | + return null; | |
| 159 | + } | |
| 160 | + | |
| 161 | + $where = []; | |
| 162 | + $values = []; | |
| 163 | + foreach ($criteria as $column => $value) { | |
| 164 | + if (!preg_match('/^[a-zA-Z0-9_]+$/', (string) $column)) { | |
| 165 | + return null; | |
| 166 | + } | |
| 167 | + if ($value === null) { | |
| 168 | + $where[] = "`{$column}` IS NULL"; | |
| 169 | + continue; | |
| 170 | + } | |
| 171 | + $where[] = "`{$column}` = %s"; | |
| 172 | + $values[] = (string) $value; | |
| 173 | + } | |
| 174 | + | |
| 175 | + $sql = "SELECT id FROM `" . esc_sql($tableName) . "` WHERE " . implode(' AND ', $where) . " LIMIT 1"; | |
| 176 | + if ($values !== []) { | |
| 177 | + // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared | |
| 178 | + $sql = $wpdb->prepare($sql, $values); | |
| 179 | + } | |
| 180 | + | |
| 181 | + $id = $wpdb->get_var($sql); | |
| 182 | + | |
| 183 | + return $id !== null ? (int) $id : null; | |
| 184 | + } | |
| 185 | + | |
| 186 | + /** | |
| 143 | 187 | * Insert and return new auto-increment id, or null on failure. |
| 144 | 188 | */ |
| 145 | 189 | public function insertRecordReturningId(string $tableName, array $record): ?int |
| 146 | 190 | { |