query( $wpdb->prepare( "INSERT INTO %i (source_id, target_locale, translated_text, status, provider, model, source_revision, created_by, created_at, updated_at) VALUES (%d, %s, %s, %s, NULLIF(%s, ''), NULLIF(%s, ''), {$revisionSql}, NULLIF(%d, 0), %s, %s) ON DUPLICATE KEY UPDATE translated_text = VALUES(translated_text), status = VALUES(status), provider = VALUES(provider), model = VALUES(model), source_revision = VALUES(source_revision), created_by = VALUES(created_by), updated_at = VALUES(updated_at)", array_merge( array( $table ), $args ) ) ); // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber, PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.DirectDatabaseQuery return false !== $result; } /** * Один перевод. * * @param int $sourceId Исходная строка. * @param string $locale Целевой язык. * @return array|null */ public function find( int $sourceId, string $locale ): ?array { global $wpdb; if ( ! Locale::isValid( $locale ) ) { return null; } $table = Schema::table( 'translations' ); // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery $row = $wpdb->get_row( $wpdb->prepare( "SELECT id, source_id, target_locale, translated_text, status, provider, model, created_by, created_at, updated_at FROM %i WHERE source_id = %d AND target_locale = %s", $table, $sourceId, $locale ), ARRAY_A ); // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery return is_array( $row ) ? $row : null; } /** * Удаляет все переводы на указанный язык. * * Исходные строки остаются: удаляются только переводы, поэтому список * в админке не опустеет и переводить заново можно с того же места. * * @param string $locale Целевой язык. * @return int Сколько переводов удалено. */ public function deleteAllForLocale( string $locale ): int { global $wpdb; if ( ! Locale::isValid( $locale ) ) { return 0; } $table = Schema::table( 'translations' ); // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery $deleted = $wpdb->query( $wpdb->prepare( 'DELETE FROM %i WHERE target_locale = %s', $table, $locale ) ); // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery return max( 0, (int) $deleted ); } /** * Удаляет перевод строки на язык. * * @param int $sourceId Исходная строка. * @param string $locale Целевой язык. */ public function delete( int $sourceId, string $locale ): bool { global $wpdb; if ( ! Locale::isValid( $locale ) ) { return false; } // phpcs:ignore WordPress.DB.DirectDatabaseQuery return false !== $wpdb->delete( Schema::table( 'translations' ), array( 'source_id' => $sourceId, 'target_locale' => $locale, ), array( '%d', '%s' ) ); } }