| 1 |
<?php |
| 2 |
|
| 3 |
/** |
| 4 |
* Suppress "error - 0 - No summary was found for this file" on phpdoc generation |
| 5 |
* |
| 6 |
* @package WPDataAccess\Utilities |
| 7 |
*/ |
| 8 |
|
| 9 |
namespace WPDataAccess\Utilities { |
| 10 |
|
| 11 |
use WPDataAccess\Data_Dictionary\WPDA_Dictionary_Exist; |
| 12 |
use WPDataAccess\List_Table\WPDA_List_Table; |
| 13 |
use WPDataAccess\WPDA; |
| 14 |
|
| 15 |
/** |
| 16 |
* Class WPDA_Import |
| 17 |
* |
| 18 |
* Imports a script file that contains exactly one insert into statement (can insert multiple records). Only |
| 19 |
* insert statements are allowed. Insert is only allowed into the table name provided in constructor. Subqueries |
| 20 |
* are not allowed (checked with explain). |
| 21 |
* |
| 22 |
* @author Peter Schulz |
| 23 |
* @since 1.0.0 |
| 24 |
*/ |
| 25 |
class WPDA_Import { |
| 26 |
|
| 27 |
/** |
| 28 |
* URL where to post data |
| 29 |
* |
| 30 |
* @var string |
| 31 |
*/ |
| 32 |
protected $url; |
| 33 |
|
| 34 |
/** |
| 35 |
* Database schema name |
| 36 |
* |
| 37 |
* @var string |
| 38 |
*/ |
| 39 |
protected $schema_name; |
| 40 |
|
| 41 |
/** |
| 42 |
* Database table name |
| 43 |
* |
| 44 |
* @var string |
| 45 |
*/ |
| 46 |
protected $table_name; |
| 47 |
|
| 48 |
/** |
| 49 |
* Indicates where imports are allowed |
| 50 |
* |
| 51 |
* @var string 'on' or 'off' |
| 52 |
*/ |
| 53 |
protected $allow_imports; |
| 54 |
|
| 55 |
/** |
| 56 |
* WPDA_Import constructor |
| 57 |
* |
| 58 |
* Checks if imports are allowed. Throws an exception if imports are not allowed. |
| 59 |
* |
| 60 |
* @param string $page Page where to post data (url). |
| 61 |
* @param string $schema_name Database schema name. |
| 62 |
* @param string $table_name Database table name. |
| 63 |
* |
| 64 |
* @throws \Exception Throws exception if export is disabled. |
| 65 |
* @since 1.0.0 |
| 66 |
*/ |
| 67 |
public function __construct( $page, $schema_name, $table_name ) { |
| 68 |
|
| 69 |
if ( ! WPDA::is_wpda_table( $table_name ) ) { |
| 70 |
// Check access rights for non WPDA tables. |
| 71 |
if ( 'on' !== WPDA::get_option( WPDA::OPTION_BE_ALLOW_IMPORTS ) ) { |
| 72 |
// Prevent import object being created: exception must be handled in calling method. |
| 73 |
throw new \Exception( __( 'ERROR: Not authorized', 'wp-data-access' ) ); |
| 74 |
} |
| 75 |
// Disable import for views. |
| 76 |
$wpda_dictionary_exists = new WPDA_Dictionary_Exist( $schema_name, $table_name ); |
| 77 |
if ( $wpda_dictionary_exists->is_view() ) { |
| 78 |
// Prevent import object being created: exception must be handled in calling method. |
| 79 |
throw new \Exception( __( 'ERROR: Import not possible on views', 'wp-data-access' ) ); |
| 80 |
} |
| 81 |
} |
| 82 |
|
| 83 |
$this->url = $page; |
| 84 |
$this->schema_name = $schema_name; |
| 85 |
$this->table_name = $table_name; |
| 86 |
|
| 87 |
} |
| 88 |
|
| 89 |
/** |
| 90 |
* Checks if request is valid and allowed |
| 91 |
* |
| 92 |
* If the requested import is valid and allowed, the import file is loaded and its content imported. |
| 93 |
* |
| 94 |
* @since 1.0.0 |
| 95 |
*/ |
| 96 |
public function check_post() { |
| 97 |
|
| 98 |
// Check if import was requested. |
| 99 |
// Import is not possible for WPDA_List_Table::LIST_BASE_TABLE (view in mysql information_schema). |
| 100 |
if ( WPDA_List_Table::LIST_BASE_TABLE !== $this->table_name && |
| 101 |
isset( $_REQUEST['action'] ) && 'import' === sanitize_text_field( wp_unslash( $_REQUEST['action'] ) ) // input var okay. |
| 102 |
) { |
| 103 |
// Security check. |
| 104 |
$wp_nonce = isset( $_REQUEST['_wpnonceimport'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['_wpnonceimport'] ) ) : '?'; // input var okay. |
| 105 |
if ( ! wp_verify_nonce( $wp_nonce, "wpda-import-{$this->table_name}" ) ) { |
| 106 |
wp_die( __( 'ERROR: Not authorized', 'wp-data-access' ) ); |
| 107 |
} |
| 108 |
|
| 109 |
if ( isset( $_FILES['filename'] ) ) { |
| 110 |
// phpcs:disable |
| 111 |
$temp_file_name = sanitize_text_field( $_FILES['filename']['tmp_name'] ); // For Windows: do NOT unslash! |
| 112 |
// phpcs:enable |
| 113 |
|
| 114 |
if ( UPLOAD_ERR_OK === $_FILES['filename']['error'] |
| 115 |
&& is_uploaded_file( $temp_file_name ) |
| 116 |
) { |
| 117 |
// Get file content. |
| 118 |
$wpda_import = new WPDA_Import_File( $temp_file_name ); |
| 119 |
|
| 120 |
// Check if errors should be shown. |
| 121 |
$hide_errors = isset( $_REQUEST['hide_errors'] ) ? |
| 122 |
sanitize_text_field( wp_unslash( $_REQUEST['hide_errors'] ) ) : 'off'; // input var okay. |
| 123 |
|
| 124 |
// Process file content. |
| 125 |
$wpda_import->import( $this->schema_name, $this->table_name, $hide_errors ); |
| 126 |
} |
| 127 |
} else { |
| 128 |
// File upload failed: inform user. |
| 129 |
$msg = new WPDA_Message_Box( |
| 130 |
array( |
| 131 |
'message_text' => __( 'File upload failed', 'wp-data-access' ), |
| 132 |
'message_type' => 'error', |
| 133 |
'message_is_dismissible' => false, |
| 134 |
) |
| 135 |
); |
| 136 |
$msg->box(); |
| 137 |
} |
| 138 |
} |
| 139 |
|
| 140 |
} |
| 141 |
|
| 142 |
/** |
| 143 |
* Adds an import button |
| 144 |
* |
| 145 |
* @param string $label Button label. |
| 146 |
* @param string $class Button CSS class. |
| 147 |
* |
| 148 |
* @since 1.0.0 |
| 149 |
*/ |
| 150 |
public function add_button( $label = '', $class = 'page-title-action' ) { |
| 151 |
$storage_type = |
| 152 |
WPDA::is_wpda_table( $this->table_name ) ? |
| 153 |
__( 'current respository table', 'wp-data-access' ) : |
| 154 |
__( 'table', 'wp-data-access' ) . " {$this->table_name}"; |
| 155 |
$title = sprintf( __( 'Allows only imports into %s', 'wp-data-access' ), $storage_type ); |
| 156 |
?> |
| 157 |
<button type="button" |
| 158 |
onclick="jQuery('#upload_file_container').show()" |
| 159 |
class="wpda_tooltip <?php echo esc_attr( $class ); ?>" |
| 160 |
title="<?php echo esc_attr( $title ); ?>"> |
| 161 |
<i class="fas fa-cloud-upload wpda_icon_on_button"></i> |
| 162 |
<?php echo '' === $label ? __( 'Import', 'wp-data-access' ) : esc_attr( $label ); ?> |
| 163 |
</button> |
| 164 |
<?php |
| 165 |
} |
| 166 |
|
| 167 |
/** |
| 168 |
* Adds an import container |
| 169 |
* |
| 170 |
* The container contains an upload form. The container is hidden by default. When the button created in |
| 171 |
* {@see WPDA_Import::add_button()} is clicked, the container is shown. |
| 172 |
* |
| 173 |
* @since 1.0.0 |
| 174 |
*/ |
| 175 |
public function add_container() { |
| 176 |
$file_uploads_enabled = @ini_get( 'file_uploads' ); |
| 177 |
?> |
| 178 |
<script type='text/javascript'> |
| 179 |
function before_submit_upload() { |
| 180 |
if (jQuery('#filename').val() == '') { |
| 181 |
alert('<?php echo __( 'No file to import!', 'wp-data-access' ); ?>'); |
| 182 |
return false; |
| 183 |
} |
| 184 |
if (!(jQuery('#filename')[0].files[0].size < <?php echo esc_attr( WPDA::convert_memory_to_decimal( @ini_get( 'upload_max_filesize' ) ) ); ?>)) { |
| 185 |
alert("<?php echo __( 'File exceeds maximum size of', 'wp-data-access' ); ?> <?php echo esc_attr( @ini_get( 'upload_max_filesize' ) ); ?>!"); |
| 186 |
return false; |
| 187 |
} |
| 188 |
} |
| 189 |
</script> |
| 190 |
|
| 191 |
<div id="upload_file_container" style="display: none"> |
| 192 |
<div> </div> |
| 193 |
<div> |
| 194 |
<?php if ( $file_uploads_enabled ) { ?> |
| 195 |
<form id="form_import_table" method="post" action="<?php echo esc_attr( $this->url ); ?>" |
| 196 |
enctype="multipart/form-data"> |
| 197 |
<fieldset class="wpda_fieldset" style="position:relative;padding:20px;padding-top:10px;padding-bottom:10px"> |
| 198 |
<legend> |
| 199 |
<span> |
| 200 |
<?php echo __( sprintf( 'SUPPORTS ONLY DATA IMPORTS FOR TABLE `%s`', esc_attr( $this->table_name ) ), 'wp-data-access' ); ?> |
| 201 |
</span> |
| 202 |
</legend> |
| 203 |
<p> |
| 204 |
<?php |
| 205 |
echo __( 'Supports only file type', 'wp-data-access' ) . ' <strong>sql</strong>. ' . __( 'Maximum supported file size is', 'wp-data-access' ) . ' <strong>' . esc_attr( @ini_get( 'upload_max_filesize' ) ) . '</strong>.'; |
| 206 |
?> |
| 207 |
</p> |
| 208 |
<input type="file" name="filename" id="filename" class="wpda_tooltip" accept=".sql"> |
| 209 |
<label style="vertical-align:baseline;"> |
| 210 |
<input type="checkbox" name="hide_errors" style="vertical-align:sub;" checked> |
| 211 |
<?php echo __( 'Hide errors', 'wp-data-access' ); ?> |
| 212 |
</label> |
| 213 |
<p> |
| 214 |
<button type="submit" |
| 215 |
class="button button-primary" |
| 216 |
onclick="return before_submit_upload()"> |
| 217 |
<i class="fas fa-code wpda_icon_on_button"></i> |
| 218 |
<?php echo __( 'Import file', 'wp-data-access' ); ?> |
| 219 |
</button> |
| 220 |
<button type="button" |
| 221 |
onclick="jQuery('#upload_file_container').hide()" |
| 222 |
class="button button-secondary"> |
| 223 |
<i class="fas fa-times-circle wpda_icon_on_button"></i> |
| 224 |
<?php echo __( 'Cancel', 'wp-data-access' ); ?> |
| 225 |
</button> |
| 226 |
</p> |
| 227 |
<input type="hidden" name="wpdaschema_name" value="<?php echo esc_attr( $this->schema_name ); ?>"> |
| 228 |
<input type="hidden" name="table_name" value="<?php echo esc_attr( $this->table_name ); ?>"> |
| 229 |
<input type="hidden" name="action" value="import"> |
| 230 |
<?php wp_nonce_field( "wpda-import-{$this->table_name}", '_wpnonceimport', false ); ?> |
| 231 |
</fieldset> |
| 232 |
</form> |
| 233 |
<?php } else { ?> |
| 234 |
<p> |
| 235 |
<strong><?php echo __( 'ERROR', 'wp-data-access' ); ?></strong> |
| 236 |
</p> |
| 237 |
<p class="wpda_list_indent"> |
| 238 |
<?php |
| 239 |
echo __( 'Your configuration does not allow file uploads!', 'wp-data-access' ); |
| 240 |
echo ' '; |
| 241 |
echo __( 'Set', 'wp-data-access' ); |
| 242 |
echo ' <strong>'; |
| 243 |
echo __( 'file_uploads', 'wp-data-access' ); |
| 244 |
echo '</strong> '; |
| 245 |
echo __( 'to', 'wp-data-access' ); |
| 246 |
echo ' <strong>'; |
| 247 |
echo __( 'On', 'wp-data-access' ); |
| 248 |
echo '</strong> (<a href="https://wpdataaccess.com/docs/getting-started/known-limitations/">'; |
| 249 |
echo __( 'see documentation', 'wp-data-access' ); |
| 250 |
echo '</a>).'; |
| 251 |
?> |
| 252 |
</p> |
| 253 |
<?php } ?> |
| 254 |
</div> |
| 255 |
<div> </div> |
| 256 |
</div> |
| 257 |
|
| 258 |
<?php |
| 259 |
|
| 260 |
} |
| 261 |
|
| 262 |
} |
| 263 |
|
| 264 |
} |
| 265 |
|