PluginProbe ʕ •ᴥ•ʔ
AI Engine – The Chatbot, AI Framework & MCP for WordPress / 2.1.4
AI Engine – The Chatbot, AI Framework & MCP for WordPress v2.1.4
3.5.7 3.5.6 3.5.5 3.5.4 3.5.3 3.5.2 3.5.1 3.5.0 3.4.9 3.4.8 3.4.7 0.2.1 1.6.91 0.2.2 1.6.92 0.2.3 1.6.93 0.2.4 1.6.94 0.2.5 1.6.95 0.2.6 1.6.96 0.2.7 1.6.97 0.2.8 1.6.98 0.2.9 1.6.99 0.3.0 1.7.0 0.3.1 1.7.1 0.3.2 1.7.2 0.3.3 1.7.3 0.3.4 1.7.4 0.3.5 1.7.5 0.3.6 1.7.6 0.4.0 1.7.7 0.4.1 1.7.8 0.4.2 1.7.9 0.4.3 1.8.0 0.4.4 1.8.1 0.4.5 1.8.2 0.4.6 1.8.3 0.4.7 1.8.4 0.4.8 1.8.5 0.4.9 1.8.6 0.5.0 1.8.7 0.5.1 1.8.8 0.5.2 1.8.9 0.5.3 1.9.0 0.5.4 1.9.1 0.5.5 1.9.2 0.5.6 1.9.3 0.5.7 1.9.4 0.5.8 1.9.5 0.5.9 1.9.6 0.6.0 1.9.7 0.6.1 1.9.8 0.6.2 1.9.81 0.6.3 1.9.82 0.6.4 1.9.83 0.6.5 1.9.84 0.6.6 1.9.85 0.6.7 1.9.86 0.6.8 1.9.87 0.6.9 1.9.88 0.7.0 1.9.89 0.7.1 1.9.90 0.7.2 1.9.91 0.7.3 1.9.92 0.7.4 1.9.93 0.7.5 1.9.94 0.7.6 1.9.95 0.7.7 1.9.96 0.7.8 1.9.97 0.7.9 1.9.98 0.8.0 1.9.99 0.8.1 2.0.0 0.8.2 2.0.1 0.8.3 2.0.2 0.8.4 2.0.3 0.8.5 2.0.4 0.8.6 2.0.5 0.8.7 2.0.6 0.8.8 2.0.7 0.8.9 2.0.8 0.9.0 2.0.9 0.9.2 2.1.0 0.9.3 2.1.1 0.9.4 2.1.2 0.9.5 2.1.3 0.9.6 2.1.4 0.9.7 2.1.5 0.9.8 2.1.6 0.9.81 2.1.7 0.9.82 2.1.8 0.9.83 2.1.9 0.9.84 2.2.0 0.9.85 2.2.1 0.9.86 2.2.2 0.9.87 2.2.3 0.9.88 2.2.4 0.9.89 2.2.5 0.9.9 2.2.51 0.9.91 2.2.52 0.9.92 2.2.53 0.9.93 2.2.54 0.9.94 2.2.56 0.9.95 2.2.57 0.9.96 2.2.6 0.9.97 2.2.60 0.9.98 2.2.61 0.9.99 2.2.62 1.0.0 2.2.63 1.0.01 2.2.70 1.0.1 2.2.80 1.0.2 2.2.81 1.0.3 2.2.90 1.0.4 2.2.91 1.0.5 2.2.92 1.0.6 2.2.93 1.0.7 2.2.94 1.0.8 2.2.95 1.0.9 2.3.0 1.1.0 2.3.1 1.1.1 2.3.2 1.1.2 2.3.3 1.1.3 2.3.4 1.1.4 2.3.5 1.1.5 2.3.6 1.1.6 2.3.7 1.1.7 2.3.8 1.1.8 2.3.9 1.1.9 2.4.0 1.2.0 2.4.1 1.2.1 2.4.2 1.2.2 2.4.3 1.2.21 2.4.4 1.2.3 2.4.5 1.2.30 2.4.6 1.3.0 2.4.7 1.3.1 2.4.8 1.3.2 2.4.9 1.3.3 2.5.0 1.3.31 2.5.1 1.3.32 2.5.2 1.3.33 2.5.3 1.3.34 2.5.4 1.3.35 2.5.5 1.3.36 2.5.6 1.3.37 2.5.7 1.3.38 2.5.8 1.3.39 2.5.9 1.3.40 2.6.0 1.3.41 2.6.1 1.3.42 2.6.2 1.3.43 2.6.3 1.3.44 2.6.5 1.3.45 2.6.6 1.3.46 2.6.7 1.3.47 2.6.8 1.3.48 2.6.9 1.3.49 2.7.0 1.3.50 2.7.1 1.3.51 2.7.2 1.3.52 2.7.3 1.3.53 2.7.4 1.3.54 2.7.5 1.3.56 2.7.6 1.3.57 2.7.7 1.3.58 2.7.8 1.3.59 2.7.9 1.3.60 2.8.0 1.3.61 2.8.1 1.3.62 2.8.2 1.3.63 2.8.3 1.3.64 2.8.4 1.3.65 2.8.5 1.3.66 2.8.6 1.3.67 2.8.7 1.3.68 2.8.8 1.3.69 2.8.9 1.3.70 2.9.0 1.3.71 2.9.1 1.3.72 2.9.2 1.3.73 2.9.3 1.3.74 2.9.4 1.3.75 2.9.5 1.3.76 2.9.6 1.3.77 2.9.7 1.3.78 2.9.8 1.3.79 2.9.9 1.3.80 3.0.0 1.3.81 3.0.1 1.3.82 3.0.2 1.3.83 3.0.3 1.3.84 3.0.4 1.3.85 3.0.5 1.3.86 3.0.6 1.3.87 3.0.7 1.3.88 3.0.8 1.3.89 3.0.9 1.3.90 3.1.0 1.3.91 3.1.1 1.3.92 3.1.2 1.3.93 3.1.3 1.3.94 3.1.4 1.3.95 3.1.5 1.3.96 3.1.6 1.3.97 3.1.7 1.3.98 3.1.8 1.3.99 3.1.9 1.4.0 3.2.0 1.4.1 3.2.1 1.4.2 3.2.2 1.4.3 3.2.3 1.4.4 3.2.4 1.4.5 3.2.5 1.4.6 3.2.6 1.4.7 3.2.7 1.4.8 3.2.8 1.4.9 3.2.9 1.5.0 3.3.0 1.5.1 3.3.1 1.5.2 3.3.2 1.5.3 3.3.3 1.5.4 3.3.4 1.5.5 3.3.5 1.5.6 3.3.6 1.5.7 3.3.7 1.5.8 3.3.8 1.5.9 3.3.9 1.6.0 3.4.0 1.6.1 3.4.1 1.6.2 3.4.2 1.6.3 3.4.3 1.6.5 3.4.4 1.6.51 3.4.5 1.6.52 3.4.6 1.6.53 1.6.54 1.6.55 1.6.56 1.6.57 1.6.58 1.6.59 1.6.60 1.6.61 1.6.62 1.6.63 1.6.64 1.6.65 1.6.66 1.6.67 1.6.68 trunk 1.6.69 0.0.1 1.6.70 0.0.2 1.6.71 0.0.3 1.6.72 0.0.4 1.6.73 0.0.5 1.6.74 0.0.6 1.6.75 0.0.7 1.6.76 0.0.8 1.6.77 0.0.9 1.6.78 0.1.0 1.6.79 0.1.1 1.6.81 0.1.2 1.6.82 0.1.3 1.6.83 0.1.4 1.6.84 0.1.5 1.6.85 0.1.6 1.6.86 0.1.7 1.6.87 0.1.8 1.6.88 0.1.9 1.6.89 0.2.0 1.6.90
ai-engine / classes / modules / files.php
ai-engine / classes / modules Last commit date
chatbot.php 2 years ago discussions.php 2 years ago files.php 2 years ago security.php 2 years ago utilities.php 2 years ago
files.php
273 lines
1 <?php
2
3 class Meow_MWAI_Modules_Files {
4 private $core = null;
5 private $wpdb = null;
6 private $namespace = 'mwai-ui/v1';
7 private $db_check = false;
8 private $table_files = null;
9
10 public function __construct( $core ) {
11 global $wpdb;
12 $this->core = $core;
13 $this->wpdb = $wpdb;
14 $this->table_files = $this->wpdb->prefix . 'mwai_files';
15 add_action( 'rest_api_init', [ $this, 'rest_api_init' ] );
16 if ( !wp_next_scheduled( 'mwai_files_cleanup' ) ) {
17 wp_schedule_event( time(), 'hourly', 'mwai_files_cleanup' );
18 }
19 add_action( 'mwai_files_cleanup', [ $this, 'cleanup_expired_files' ] );
20 }
21
22 public function cleanup_expired_files() {
23 if ( $this->check_db() ) {
24 $current_time = current_time( 'mysql' );
25 $expired_files = $this->wpdb->get_results(
26 "SELECT * FROM $this->table_files WHERE expires IS NOT NULL AND expires < '{$current_time}'"
27 );
28 }
29 $expired_posts = get_posts( [
30 'post_type' => 'attachment',
31 'meta_key' => '_mwai_file_expires',
32 'meta_value' => $current_time,
33 'meta_compare' => '<'
34 ] );
35 $fileIds = [];
36 foreach ( $expired_files as $file ) {
37 $fileIds[] = $file->fileId;
38 }
39 foreach ( $expired_posts as $post ) {
40 $fileIds[] = get_post_meta( $post->ID, '_mwai_file_id', true );
41 }
42 $this->files_processed( $fileIds );
43 }
44
45 public function files_processed( $fileIds ) {
46 if ( !is_array( $fileIds ) ) {
47 $fileIds = [ $fileIds ];
48 }
49 foreach ( $fileIds as $fileId ) {
50 $file = null;
51 if ( $this->check_db() ) {
52 $file = $this->wpdb->get_row( $this->wpdb->prepare( "SELECT *
53 FROM $this->table_files
54 WHERE fileId = %s", $fileId
55 ) );
56 }
57 if ( $file ) {
58 $this->wpdb->delete( $this->table_files, [ 'fileId' => $fileId ] );
59 if ( file_exists( $file->path ) ) {
60 unlink( $file->path );
61 }
62 }
63 else {
64 $posts = get_posts( [ 'post_type' => 'attachment', 'meta_key' => '_mwai_file_id', 'meta_value' => $fileId ] );
65 if ( $posts ) {
66 foreach ( $posts as $post ) {
67 wp_delete_attachment( $post->ID, true );
68 }
69 }
70 }
71 }
72 }
73
74 public function get_path( $fileId ) {
75 $file = null;
76 if ( $this->check_db() ) {
77 $file = $this->wpdb->get_row( $this->wpdb->prepare( "SELECT *
78 FROM $this->table_files
79 WHERE fileId = %s", $fileId
80 ) );
81 }
82 if ( $file ) {
83 return $file->path;
84 }
85 else {
86 $posts = get_posts( [ 'post_type' => 'attachment', 'meta_key' => '_mwai_file_id', 'meta_value' => $fileId ] );
87 if ( $posts ) {
88 foreach ( $posts as $post ) {
89 return get_attached_file( $post->ID );
90 }
91 }
92 }
93 return null;
94 }
95
96 public function get_base64_data( $fileId ) {
97 $path = $this->get_path( $fileId );
98 if ( $path ) {
99 $content = file_get_contents( $path );
100 $data = base64_encode( $content );
101 return $data;
102 }
103 return null;
104 }
105
106 public function get_url( $fileId ) {
107 $file = null;
108 if ( $this->check_db() ) {
109 $file = $this->wpdb->get_row( $this->wpdb->prepare( "SELECT *
110 FROM $this->table_files
111 WHERE fileId = %s", $fileId
112 ) );
113 }
114 if ( $file ) {
115 return $file->url;
116 }
117 else {
118 $posts = get_posts( [ 'post_type' => 'attachment', 'meta_key' => '_mwai_file_id', 'meta_value' => $fileId ] );
119 if ( $posts ) {
120 foreach ( $posts as $post ) {
121 return wp_get_attachment_url( $post->ID );
122 }
123 }
124 }
125 return null;
126 }
127
128 #region REST endpoints
129
130 public function rest_api_init() {
131 register_rest_route( $this->namespace, '/files/upload', array(
132 'methods' => 'POST',
133 'callback' => array( $this, 'rest_upload' ),
134 'permission_callback' => array( $this->core, 'check_rest_nonce' )
135 ) );
136 register_rest_route( $this->namespace, '/files/delete', array(
137 'methods' => 'POST',
138 'callback' => array( $this, 'rest_delete' ),
139 'permission_callback' => array( $this->core, 'check_rest_nonce' )
140 ) );
141 }
142
143 public function commit_file( $path, $target = 'uploads', $expiry = 'never', $filename = null ) {
144 require_once( ABSPATH . 'wp-admin/includes/image.php' );
145 require_once( ABSPATH . 'wp-admin/includes/file.php' );
146 require_once( ABSPATH . 'wp-admin/includes/media.php' );
147
148 $expires = ( $expiry === 'never' || empty( $expiry ) ) ? null : date( 'Y-m-d H:i:s', time() + intval( $expiry ) );
149 $fileId = null;
150 $url = null;
151 if ( empty( $filename ) ) {
152 $parsed_url = parse_url( $path, PHP_URL_PATH );
153 $filename = basename( $parsed_url );
154 $extension = pathinfo( $filename, PATHINFO_EXTENSION );
155 $filename = md5( $filename . date( 'Y-m-d-H-i-s' ) ) . '.' . $extension;
156 }
157 else {
158 $filename = basename( $filename );
159 }
160 $unique_filename = wp_unique_filename( wp_upload_dir()['path'], $filename );
161 $destination = wp_upload_dir()['path'] . '/' . $unique_filename;
162
163 if ( $target === 'uploads' ) {
164 if ( !$this->check_db() ) {
165 throw new Exception('Could not create database table.');
166 }
167 if ( !copy( $path, $destination ) ) {
168 throw new Exception('Could not move the file.');
169 }
170 $url = wp_upload_dir()['url'] . '/' . $unique_filename;
171 $fileId = md5( $url );
172 $this->wpdb->insert( $this->table_files, [
173 'fileId' => $fileId,
174 'type' => 'image',
175 'status' => 'uploaded',
176 'created' => date( 'Y-m-d H:i:s' ),
177 'updated' => date( 'Y-m-d H:i:s' ),
178 'expires' => $expires,
179 'path' => $destination,
180 'url' => $url
181 ]);
182 }
183 else if ( $target === 'library' ) {
184 if ( filter_var( $path, FILTER_VALIDATE_URL ) ) {
185 $tmp = download_url( $path );
186 if ( is_wp_error( $tmp ) ) {
187 throw new Exception( $tmp->get_error_message() );
188 }
189 $file_array = [ 'name' => $unique_filename, 'tmp_name' => $tmp ];
190 }
191 else {
192 $file_array = [ 'name' => $unique_filename, 'tmp_name' => $path ];
193 }
194 $id = media_handle_sideload( $file_array, 0 );
195 if ( is_wp_error( $id ) ) {
196 throw new Exception($id->get_error_message());
197 }
198 $url = wp_get_attachment_url( $id );
199 $fileId = md5( $url );
200 update_post_meta( $id, '_mwai_file_id', $fileId );
201 update_post_meta( $id, '_mwai_file_expires', $expires );
202 }
203
204 return $fileId;
205 }
206
207 public function rest_upload() {
208 if ( empty( $_FILES['file'] ) ) {
209 return new WP_REST_Response( [ 'success' => false, 'message' => 'No file provided.' ], 400 );
210 }
211 $file = $_FILES['file'];
212
213 $fileTypeCheck = wp_check_filetype_and_ext( $file['tmp_name'], $file['name'] );
214 if ( !$fileTypeCheck['type'] ) {
215 return new WP_REST_Response( [ 'success' => false, 'message' => 'Invalid file type.' ], 400 );
216 }
217
218 $local_upload = $this->core->get_option( 'image_local_upload' );
219 $image_expires_seconds = $this->core->get_option( 'image_expires' );
220
221 try {
222 $fileId = $this->commit_file( $file['tmp_name'], $local_upload, $image_expires_seconds, $file['name'] );
223 $url = $this->get_url( $fileId );
224 return new WP_REST_Response( [
225 'success' => true,
226 'data' => [ 'id' => $fileId, 'url' => $url ]
227 ], 200 );
228 } catch ( Exception $e ) {
229 return new WP_REST_Response( [ 'success' => false, 'message' => $e->getMessage() ], 500 );
230 }
231 }
232
233 #endregion
234
235 #region Database functions
236
237 function create_db() {
238 $charset_collate = $this->wpdb->get_charset_collate();
239 $sql = "CREATE TABLE $this->table_files (
240 id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
241 fileId VARCHAR(64) NOT NULL,
242 type VARCHAR(32) NULL,
243 status VARCHAR(32) NULL,
244 created DATETIME NOT NULL,
245 updated DATETIME NOT NULL,
246 expires DATETIME NULL,
247 path TEXT NOT NULL,
248 url TEXT NULL,
249 metadata TEXT NULL,
250 PRIMARY KEY (id),
251 UNIQUE KEY unique_file_id (fileId)
252 ) $charset_collate;";
253 require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
254 dbDelta( $sql );
255 }
256
257 function check_db() {
258 if ( $this->db_check ) {
259 return true;
260 }
261 $sql = $this->wpdb->prepare( "SHOW TABLES LIKE %s", $this->table_files );
262 $table_exists = strtolower( $this->wpdb->get_var( $sql )) === strtolower( $this->table_files );
263 if ( !$table_exists ) {
264 $this->create_db();
265 $table_exists = strtolower( $this->wpdb->get_var( $sql ) ) === strtolower( $this->table_files );
266 }
267 $this->db_check = $table_exists;
268 return $this->db_check;
269 }
270
271 #endregion
272
273 }