PluginProbe
TablePress – Tables in WordPress made easy / 2.1.7
TablePress – Tables in WordPress made easy v2.1.7
3.3.4 3.3.3 3.3.2 3.3.1 trunk 1.12 1.14 1.9.2 2.0.4 2.1.7 2.1.8 2.2 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.3 2.3.1 2.3.2 2.4 2.4.1 2.4.2 2.4.3 2.4.4 All 44 releases
tablepress / classes / class-import-legacy.php

class-import-legacy.php in TablePress – Tables in WordPress made easy 2.1.7, at classes/class-import-legacy.php

323 lines 8.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * TablePress Table Import Class
4 *
5 * @package TablePress
6 * @subpackage Export/Import
7 * @author Tobias Bäthge
8 * @since 1.0.0
9 */
10
11 // Prohibit direct script loading.
12 defined( 'ABSPATH' ) || die( 'No direct script access allowed!' );
13
14 /**
15 * TablePress Table Import Class
16 *
17 * @package TablePress
18 * @subpackage Export/Import
19 * @author Tobias Bäthge
20 * @since 1.0.0
21 */
22 class TablePress_Import_Legacy extends TablePress_Import_Base {
23
24 /**
25 * File/Data Formats that are available for import.
26 *
27 * @since 1.0.0
28 * @var array
29 */
30 public $import_formats = array();
31
32 /**
33 * Whether HTML import support is available in the PHP installation on the server.
34 *
35 * @since 1.0.0
36 * @var bool
37 */
38 public $html_import_support_available = false;
39
40 /**
41 * Data to be imported.
42 *
43 * @since 1.0.0
44 * @var string
45 */
46 protected $import_data;
47
48 /**
49 * Imported table.
50 *
51 * @since 1.0.0
52 * @var array|false
53 */
54 protected $imported_table = false;
55
56 /**
57 * Initialize the Import class.
58 *
59 * @since 1.0.0
60 */
61 public function __construct() {
62 if ( class_exists( 'DOMDocument', false ) && function_exists( 'simplexml_import_dom' ) && function_exists( 'libxml_use_internal_errors' ) ) {
63 $this->html_import_support_available = true;
64 }
65
66 // Initiate here, because function call not possible outside a class method.
67 $this->import_formats = array();
68 $this->import_formats['csv'] = __( 'CSV - Character-Separated Values', 'tablepress' );
69 if ( $this->html_import_support_available ) {
70 $this->import_formats['html'] = __( 'HTML - Hypertext Markup Language', 'tablepress' );
71 }
72 $this->import_formats['json'] = __( 'JSON - JavaScript Object Notation', 'tablepress' );
73 $this->import_formats['xls'] = __( 'XLS - Microsoft Excel 97-2003 (experimental)', 'tablepress' );
74 $this->import_formats['xlsx'] = __( 'XLSX - Microsoft Excel 2007-2019 (experimental)', 'tablepress' );
75 }
76
77 /**
78 * Import a table.
79 *
80 * @since 1.0.0
81 *
82 * @param string $format Import format.
83 * @param string $data Data to import.
84 * @return array|false Table array on success, false on error.
85 */
86 public function import_table( $format, $data ) {
87 $this->import_data = apply_filters( 'tablepress_import_table_data', $data, $format );
88
89 if ( ! in_array( $format, array( 'xlsx', 'xls' ), true ) ) {
90 $this->fix_table_encoding();
91 }
92
93 switch ( $format ) {
94 case 'csv':
95 $this->import_csv();
96 break;
97 case 'html':
98 $this->import_html();
99 break;
100 case 'json':
101 $this->import_json();
102 break;
103 case 'xlsx':
104 $this->import_xlsx();
105 break;
106 case 'xls':
107 $this->import_xls();
108 break;
109 default:
110 return false;
111 }
112
113 // Make sure that cells are stored as strings.
114 array_walk_recursive(
115 $this->imported_table['data'],
116 static function( &$cell_content, $col_idx ) {
117 $cell_content = (string) $cell_content;
118 }
119 );
120
121 return $this->imported_table;
122 }
123
124 /**
125 * Import CSV data.
126 *
127 * @since 1.0.0
128 */
129 protected function import_csv() {
130 $csv_parser = TablePress::load_class( 'CSV_Parser', 'csv-parser.class.php', 'libraries' );
131 $csv_parser->load_data( $this->import_data );
132 $delimiter = $csv_parser->find_delimiter();
133 $data = $csv_parser->parse( $delimiter );
134 $this->pad_array_to_max_cols( $data );
135 $this->normalize_line_endings( $data );
136 $this->imported_table = array( 'data' => $data );
137 }
138
139 /**
140 * Import HTML data.
141 *
142 * @since 1.0.0
143 */
144 protected function import_html() {
145 if ( ! $this->html_import_support_available ) {
146 return;
147 }
148
149 TablePress::load_file( 'html-parser.class.php', 'libraries' );
150 $table = HTML_Parser::parse( $this->import_data );
151
152 if ( is_wp_error( $table ) ) {
153 $this->imported_table = false;
154 return;
155 }
156
157 $this->pad_array_to_max_cols( $table['data'] );
158 $this->normalize_line_endings( $table['data'] );
159 $this->imported_table = $table;
160 }
161
162 /**
163 * Import JSON data.
164 *
165 * @since 1.0.0
166 */
167 protected function import_json() {
168 $json_table = json_decode( $this->import_data, true );
169
170 // Check if JSON could be decoded.
171 if ( is_null( $json_table ) ) {
172 $json_error = json_last_error_msg();
173 $output = '<strong>' . __( 'The imported file contains errors:', 'tablepress' ) . "</strong><br /><br />JSON error: {$json_error}<br />";
174 wp_die( $output, 'Import Error', array( 'response' => 200, 'back_link' => true ) );
175 }
176
177 // Specifically cast to an array again.
178 $json_table = (array) $json_table;
179
180 if ( isset( $json_table['data'] ) ) {
181 // JSON data contained a full export.
182 $table = $json_table;
183 } else {
184 // JSON data contained only the data of a table, but no options.
185 $table = array( 'data' => array() );
186 foreach ( $json_table as $row ) {
187 $table['data'][] = array_values( (array) $row );
188 }
189 }
190
191 $this->pad_array_to_max_cols( $table['data'] );
192 $this->imported_table = $table;
193 }
194
195 /**
196 * Import Microsoft Excel 97-2003 data.
197 *
198 * @since 1.1.0
199 */
200 protected function import_xls() {
201 $excel_reader = TablePress::load_class( 'Spreadsheet_Excel_Reader', 'excel-reader.class.php', 'libraries', $this->import_data );
202
203 // Loop through Excel file and retrieve value and colspan/rowspan properties for each cell.
204 $sheet = 0; // 0 means first sheet of the Workbook
205 $table = array();
206 $num_rows = $excel_reader->rowcount( $sheet );
207 $num_columns = $excel_reader->colcount( $sheet );
208 for ( $row = 1; $row <= $num_rows; $row++ ) {
209 $table_row = array();
210 for ( $column = 1; $column <= $num_columns; $column++ ) {
211 $cell = array();
212 $cell['rowspan'] = $excel_reader->rowspan( $row, $column, $sheet );
213 $cell['colspan'] = $excel_reader->colspan( $row, $column, $sheet );
214 $cell['val'] = $excel_reader->val( $row, $column, $sheet );
215 $table_row[] = $cell;
216 }
217 $table[] = $table_row;
218 }
219
220 // Transform colspan/rowspan properties to TablePress equivalent (cell content).
221 foreach ( $table as $row_idx => $row ) {
222 foreach ( $row as $col_idx => $cell ) {
223 if ( 1 === $cell['rowspan'] && 1 === $cell['colspan'] ) {
224 continue;
225 }
226
227 if ( 1 < $cell['colspan'] ) {
228 for ( $i = 1; $i < $cell['colspan']; $i++ ) {
229 $table[ $row_idx ][ $col_idx + $i ]['val'] = '#colspan#';
230 }
231 }
232 if ( 1 < $cell['rowspan'] ) {
233 for ( $i = 1; $i < $cell['rowspan']; $i++ ) {
234 $table[ $row_idx + $i ][ $col_idx ]['val'] = '#rowspan#';
235 }
236 }
237
238 if ( 1 < $cell['rowspan'] && 1 < $cell['colspan'] ) {
239 for ( $i = 1; $i < $cell['rowspan']; $i++ ) {
240 for ( $j = 1; $j < $cell['colspan']; $j++ ) {
241 $table[ $row_idx + $i ][ $col_idx + $j ]['val'] = '#span#';
242 }
243 }
244 }
245 }
246 }
247
248 // Flatten value property to two-dimensional array.
249 foreach ( $table as &$row ) {
250 foreach ( $row as &$cell ) {
251 $cell = $cell['val'];
252 }
253 unset( $cell );
254 }
255 unset( $row );
256
257 $this->imported_table = array( 'data' => $table );
258 }
259
260 /**
261 * Import Microsoft Excel 2007-2019 data.
262 *
263 * @since 1.1.0
264 */
265 protected function import_xlsx() {
266 TablePress::load_file( 'simplexlsx.class.php', 'libraries' );
267 $xlsx_file = \Shuchkin\SimpleXLSX::parse( $this->import_data, true );
268
269 if ( ! $xlsx_file ) {
270 $output = '<strong>' . __( 'The imported file contains errors:', 'tablepress' ) . '</strong><br /><br />' . \Shuchkin\SimpleXLSX::parseError() . '<br />';
271 wp_die( $output, 'Import Error', array( 'response' => 200, 'back_link' => true ) );
272 }
273
274 $this->imported_table = array( 'data' => $xlsx_file->rows() );
275 }
276
277 /**
278 * Fixes the encoding to UTF-8 for the entire string that is to be imported.
279 *
280 * @since 1.0.0
281 *
282 * @link http://stevephillips.me/blog/dealing-php-and-character-encoding
283 */
284 protected function fix_table_encoding() {
285 // Check and remove possible UTF-8 Byte-Order Mark (BOM).
286 $bom = pack( 'CCC', 0xef, 0xbb, 0xbf );
287 if ( 0 === strncmp( $this->import_data, $bom, 3 ) ) {
288 $this->import_data = substr( $this->import_data, 3 );
289 // If data has a BOM, it's UTF-8, so further checks unnecessary.
290 return;
291 }
292
293 // Require the iconv() function for the following checks.
294 if ( ! function_exists( 'iconv' ) ) {
295 return;
296 }
297
298 // Check for possible UTF-16 BOMs ("little endian" and "big endian") and try to convert the data to UTF-8.
299 if ( "\xFF\xFE" === substr( $this->import_data, 0, 2 ) || "\xFE\xFF" === substr( $this->import_data, 0, 2 ) ) {
300 // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
301 $data = @iconv( 'UTF-16', 'UTF-8', $this->import_data );
302 if ( false !== $data ) {
303 $this->import_data = $data;
304 return;
305 }
306 }
307
308 // Detect the character encoding and convert to UTF-8, if it's different.
309 if ( function_exists( 'mb_detect_encoding' ) ) {
310 $current_encoding = mb_detect_encoding( $this->import_data, 'ASCII, UTF-8, ISO-8859-1' );
311 if ( 'UTF-8' !== $current_encoding ) {
312 // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
313 $data = @iconv( $current_encoding, 'UTF-8', $this->import_data );
314 if ( false !== $data ) {
315 $this->import_data = $data;
316 return;
317 }
318 }
319 }
320 }
321
322 } // class TablePress_Import_Legacy
323