PluginProbe
WPBot – AI ChatBot for Live Support, Lead Generation, WordPress Automation, AI Services / 8.8.1
WPBot – AI ChatBot for Live Support, Lead Generation, WordPress Automation, AI Services v8.8.1
8.8.1 8.8.0 8.7.9 8.7.8 8.7.7 8.7.6 8.7.5 8.7.4 8.7.3 8.7.2 8.7.1 8.7.0 8.6.9 8.6.8 8.6.7 8.6.6 8.6.5 8.6.4 8.6.2 8.6.1 8.6.0 8.5.9 8.5.8 8.5.7 8.5.6 All 537 releases
chatbot / addons / automator / includes / actions / csv-creator-actions.php

csv-creator-actions.php in WPBot – AI ChatBot for Live Support, Lead Generation, WordPress Automation, AI Services 8.8.1, at addons/automator/includes/actions/csv-creator-actions.php

253 lines 9.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * CSV Creator Actions
4 *
5 * @package WPbot_Automator
6 */
7
8 namespace WPbot_Automator\Actions;
9
10 use WPbot_Automator\Core\Tables;
11
12 if ( ! defined( 'ABSPATH' ) ) {
13 exit;
14 }
15
16 /**
17 * Class CSV_Creator_Actions
18 *
19 * Provides three actions that build CSV files and save them to the WordPress
20 * media library. Each action returns an array merged into $trigger_data so
21 * downstream nodes can reference:
22 *
23 * {csv_url} — public URL of the saved CSV file
24 * {csv_attachment_id} — WordPress attachment post ID
25 * {csv_filename} — filename of the saved CSV file
26 */
27 class CSV_Creator_Actions extends Action {
28
29 public function __construct() {
30 $this->id = 'csv_creator';
31 $this->group = __( 'CSV Creator', 'wpbot-automator' );
32 }
33
34 public function execute( $action_data, $trigger_data ) {
35 $action_id = isset( $action_data['actionId'] ) ? $action_data['actionId'] : '';
36
37 switch ( $action_id ) {
38 case 'csv_from_table': return $this->csv_from_table( $action_data, $trigger_data );
39 case 'csv_from_json': return $this->csv_from_json( $action_data, $trigger_data );
40 case 'csv_from_array': return $this->csv_from_array( $action_data, $trigger_data );
41 default: return false;
42 }
43 }
44
45 // ── Sub-actions ──────────────────────────────────────────────────────────
46
47 /**
48 * Export all (or filtered) records from a wpbot Table to CSV.
49 *
50 * Config fields: table_id, filter_col (opt), filter_val (opt), filename (opt).
51 */
52 private function csv_from_table( $action_data, $trigger_data ) {
53 global $wpdb;
54
55 $config = isset( $action_data['config'] ) ? $action_data['config'] : array();
56 $table_id = absint( $this->parse_tokens( isset( $config['table_id'] ) ? $config['table_id'] : '', $trigger_data ) );
57
58 if ( ! $table_id ) {
59 return array( 'success' => false, 'message' => 'CSV Creator: table_id is required.' );
60 }
61
62 $table = Tables::get_table_meta_by_id( $table_id );
63 if ( ! $table ) {
64 return array( 'success' => false, 'message' => 'CSV Creator: table not found (' . $table_id . ').' );
65 }
66
67 $ut = Tables::get_user_table( $table['slug'] );
68 $filter_col = sanitize_key( $this->parse_tokens( isset( $config['filter_col'] ) ? $config['filter_col'] : '', $trigger_data ) );
69 $filter_val = sanitize_text_field( $this->parse_tokens( isset( $config['filter_val'] ) ? $config['filter_val'] : '', $trigger_data ) );
70
71 $where = '';
72 $query_params = array();
73 $valid_slugs = wp_list_pluck( $table['columns'], 'slug' );
74
75 if ( $filter_col && '' !== $filter_val && in_array( $filter_col, $valid_slugs, true ) ) {
76 $where = 'WHERE `' . esc_sql( $filter_col ) . '` LIKE %s';
77 $query_params[] = '%' . $wpdb->esc_like( $filter_val ) . '%';
78 }
79
80 $sql = "SELECT * FROM `{$ut}` {$where} ORDER BY id ASC";
81 $records = $query_params
82 ? $wpdb->get_results( $wpdb->prepare( $sql, ...$query_params ), ARRAY_A )
83 : $wpdb->get_results( $sql, ARRAY_A );
84
85 // Build header row from column definitions.
86 $headers = array( 'id' );
87 foreach ( $table['columns'] as $col ) {
88 $headers[] = $col['name'];
89 }
90 $headers[] = 'created_at';
91
92 // Build CSV rows.
93 $csv_rows = array( $headers );
94 foreach ( $records ?: array() as $rec ) {
95 $row = array( $rec['id'] ?? '' );
96 foreach ( $table['columns'] as $col ) {
97 $row[] = $rec[ $col['slug'] ] ?? '';
98 }
99 $row[] = $rec['created_at'] ?? '';
100 $csv_rows[] = $row;
101 }
102
103 $raw_filename = isset( $config['filename'] ) ? $this->parse_tokens( $config['filename'], $trigger_data ) : '';
104 $filename = sanitize_file_name( $raw_filename ) ?: ( sanitize_title( $table['name'] ) . '_' . gmdate( 'Y-m-d' ) . '.csv' );
105
106 return $this->save_csv( $csv_rows, $filename );
107 }
108
109 /**
110 * Convert a JSON array-of-objects string to CSV.
111 *
112 * Config fields: json_data (supports tokens like {response}), filename (opt).
113 *
114 * Expected input: '[{"col1":"val","col2":"val"}, ...]'
115 */
116 private function csv_from_json( $action_data, $trigger_data ) {
117 $config = isset( $action_data['config'] ) ? $action_data['config'] : array();
118 $json_raw = $this->parse_tokens( isset( $config['json_data'] ) ? $config['json_data'] : '', $trigger_data );
119
120 // Strip markdown code-fences in case the data came from an AI action.
121 $json_raw = preg_replace( '/^```(?:json)?\s*/i', '', trim( $json_raw ) );
122 $json_raw = preg_replace( '/\s*```$/', '', $json_raw );
123
124 $data = json_decode( $json_raw, true );
125
126 if ( ! is_array( $data ) || empty( $data ) ) {
127 return array( 'success' => false, 'message' => 'CSV Creator: json_data is not a valid JSON array.' );
128 }
129
130 // Flatten any nested objects one level deep.
131 $first_item = reset( $data );
132 if ( ! is_array( $first_item ) ) {
133 // Scalar array — wrap each value.
134 $data = array_map( function( $v ) { return array( 'value' => $v ); }, $data );
135 $first_item = reset( $data );
136 }
137
138 $headers = array_keys( $first_item );
139 $csv_rows = array( $headers );
140
141 foreach ( $data as $row ) {
142 $csv_rows[] = array_map( function( $h ) use ( $row ) {
143 $v = isset( $row[ $h ] ) ? $row[ $h ] : '';
144 return is_array( $v ) ? wp_json_encode( $v ) : (string) $v;
145 }, $headers );
146 }
147
148 $raw_filename = isset( $config['filename'] ) ? $this->parse_tokens( $config['filename'], $trigger_data ) : '';
149 $filename = sanitize_file_name( $raw_filename ) ?: ( 'export_' . gmdate( 'Y-m-d_His' ) . '.csv' );
150
151 return $this->save_csv( $csv_rows, $filename );
152 }
153
154 /**
155 * Convert a JSON array-of-arrays string to CSV.
156 *
157 * Config fields: array_data, headers (comma-separated, opt), filename (opt).
158 *
159 * Expected input: '[["Alice","[email protected]"],["Bob","[email protected]"]]'
160 */
161 private function csv_from_array( $action_data, $trigger_data ) {
162 $config = isset( $action_data['config'] ) ? $action_data['config'] : array();
163 $raw = $this->parse_tokens( isset( $config['array_data'] ) ? $config['array_data'] : '', $trigger_data );
164
165 // Strip markdown fences.
166 $raw = preg_replace( '/^```(?:json)?\s*/i', '', trim( $raw ) );
167 $raw = preg_replace( '/\s*```$/', '', $raw );
168
169 $data = json_decode( $raw, true );
170
171 if ( ! is_array( $data ) || empty( $data ) ) {
172 return array( 'success' => false, 'message' => 'CSV Creator: array_data is not a valid JSON array.' );
173 }
174
175 $csv_rows = array();
176
177 // Optional custom headers.
178 $raw_headers = isset( $config['headers'] ) ? $this->parse_tokens( $config['headers'], $trigger_data ) : '';
179 if ( ! empty( $raw_headers ) ) {
180 $csv_rows[] = array_map( 'trim', explode( ',', $raw_headers ) );
181 }
182
183 foreach ( $data as $row ) {
184 if ( is_array( $row ) ) {
185 $csv_rows[] = array_values( $row );
186 } elseif ( is_scalar( $row ) ) {
187 $csv_rows[] = array( $row );
188 }
189 }
190
191 $raw_filename = isset( $config['filename'] ) ? $this->parse_tokens( $config['filename'], $trigger_data ) : '';
192 $filename = sanitize_file_name( $raw_filename ) ?: ( 'export_' . gmdate( 'Y-m-d_His' ) . '.csv' );
193
194 return $this->save_csv( $csv_rows, $filename );
195 }
196
197 // ── Shared helper ────────────────────────────────────────────────────────
198
199 /**
200 * Build a CSV string from a 2D array and save it to the media library.
201 *
202 * @param array $rows Two-dimensional array; first row is the header.
203 * @param string $filename Target filename including .csv extension.
204 * @return array Action result array with success, csv_url, csv_attachment_id, csv_filename.
205 */
206 private function save_csv( array $rows, $filename ) {
207 require_once ABSPATH . 'wp-admin/includes/file.php';
208 require_once ABSPATH . 'wp-admin/includes/media.php';
209 require_once ABSPATH . 'wp-admin/includes/image.php';
210
211 // Render CSV content in memory.
212 ob_start();
213 $fh = fopen( 'php://output', 'w' );
214 foreach ( $rows as $row ) {
215 fputcsv( $fh, $row );
216 }
217 fclose( $fh );
218 $csv_content = ob_get_clean();
219
220 // Upload to WordPress uploads directory.
221 $upload = wp_upload_bits( $filename, null, $csv_content );
222 if ( ! empty( $upload['error'] ) ) {
223 //error_log( 'WPbot CSV_Creator: upload failed — ' . $upload['error'] );
224 return array( 'success' => false, 'message' => 'CSV upload failed: ' . $upload['error'] );
225 }
226
227 // Register as a media library attachment.
228 $attachment_id = wp_insert_attachment(
229 array(
230 'post_mime_type' => 'text/csv',
231 'post_title' => sanitize_file_name( $filename ),
232 'post_content' => '',
233 'post_status' => 'inherit',
234 ),
235 $upload['file']
236 );
237
238 if ( is_wp_error( $attachment_id ) ) {
239 //error_log( 'WPbot CSV_Creator: attachment insert failed — ' . $attachment_id->get_error_message() );
240 return array( 'success' => false, 'message' => 'Could not add CSV to media library.' );
241 }
242
243 return array(
244 'success' => true,
245 'csv_url' => $upload['url'],
246 'csv_attachment_id' => $attachment_id,
247 'csv_filename' => $filename,
248 'csv_path' => $upload['file'],
249 'csv_row_count' => max( 0, count( $rows ) - 1 ), // exclude header
250 );
251 }
252 }
253