PluginProbe
TablePress – Tables in WordPress made easy / 3.4
TablePress – Tables in WordPress made easy v3.4
3.4 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 All 45 releases
← All changes | classes/class-import.php +60 -13 2.3.2 → 3.4 View file →
@@ -7,8 +7,10 @@
7 7 * @author Tobias Bäthge
8 8 * @since 1.0.0
9 9 */
10 10
11 +declare(strict_types=1);
12 +
11 13 use TablePress\Import\File;
12 14
13 15 // Prohibit direct script loading.
14 16 defined( 'ABSPATH' ) || die( 'No direct script access allowed!' );
@@ -25,14 +27,14 @@
25 27 */
26 28 class TablePress_Import {
27 29
28 30 /**
29 - * Instance of the TablePress Legacy Importer.
31 + * Instance of the TablePress Legacy or PHPSpreadsheet Importer.
30 32 *
31 33 * @since 1.0.0
32 - * @var TablePress_Import_Legacy
34 + * @var TablePress_Import_Legacy|TablePress_Import_PHPSpreadsheet
33 35 */
34 - protected $importer;
36 + protected object $importer;
35 37
36 38 /**
37 39 * Import configuration (mainly the data from the Import form).
38 40 *
@@ -38,9 +40,9 @@
38 40 *
39 41 * @since 2.0.0
40 42 * @var array<string, mixed>
41 43 */
42 - protected $import_config = array();
44 + protected array $import_config = array();
43 45
44 46 /**
45 47 * Whether ZIP archive support is available (which it always is, as PclZip is used as a fallback).
46 48 *
@@ -45,11 +47,10 @@
45 47 * Whether ZIP archive support is available (which it always is, as PclZip is used as a fallback).
46 48 *
47 49 * @since 1.0.0
48 50 * @deprecated 2.3.0 ZIP support is now always available, either through `ZipArchive` or through `PclZip`.
49 - * @var bool
50 51 */
51 - public $zip_support_available = true;
52 + public bool $zip_support_available = true;
52 53
53 54 /**
54 55 * List of table names/IDs for use when replacing/appending existing tables (except for the JSON format).
55 56 *
@@ -55,9 +56,9 @@
55 56 *
56 57 * @since 2.0.0
57 58 * @var array<string, string[]>
58 59 */
59 - protected $table_names_ids = array();
60 + protected array $table_names_ids = array();
60 61
61 62 /**
62 63 * Runs the import process for a given import configuration.
63 64 *
@@ -131,8 +132,11 @@
131 132 if ( in_array( $ip, $blocked_ips, true ) ) {
132 133 return new WP_Error( 'table_import_url_host_blocked', '', array( 'url' => $this->import_config['url'], 'ip' => $ip ) );
133 134 }
134 135
136 + // Automatically adjust URLs of common services to point to a direct download URL.
137 + $this->import_config['url'] = $this->fix_common_url_mistakes( $this->import_config['url'] );
138 +
135 139 /**
136 140 * Load WP file functions to be sure that `download_url()` exists, in particular during Cron requests.
137 141 */
138 142 require_once ABSPATH . 'wp-admin/includes/file.php';
@@ -185,8 +189,45 @@
185 189 return $import_files;
186 190 }
187 191
188 192 /**
193 + * Fixes common mistakes in URLs from popular services to point to a direct download URL.
194 + *
195 + * Currently supports Google Sheets, Microsoft OneDrive, and Dropbox.
196 + * See https://tablepress.org/tutorials/ for more specific instructions on how to get the correct URL.
197 + *
198 + * @since 3.2.4
199 + *
200 + * @param string $url URL that shall be fixed.
201 + * @return string Fixed URL.
202 + */
203 + protected function fix_common_url_mistakes( string $url ): string {
204 + /**
205 + * Filters whether common URL mistakes shall be fixed automatically.
206 + *
207 + * @since 3.2.4
208 + *
209 + * @param bool $fix_common_url_mistakes Whether to fix common URL mistakes. Default true.
210 + */
211 + if ( ! apply_filters( 'tablepress_import_fix_common_url_mistakes', true ) ) {
212 + return $url;
213 + }
214 +
215 + if ( str_starts_with( $url, 'https://docs.google.com/spreadsheets/' ) && str_ends_with( $url, '/edit?usp=sharing' ) ) {
216 + // Google Sheets "Sharing URL" to direct download URL.
217 + $url = str_replace( '/edit?usp=sharing', '/export?format=csv', $url );
218 + } elseif ( str_starts_with( $url, 'https://1drv.ms/' ) && ! str_ends_with( $url, '&download=1' ) ) {
219 + // OneDrive shared link to direct download link.
220 + $url .= '&download=1';
221 + } elseif ( str_starts_with( $url, 'https://www.dropbox.com/' ) && str_ends_with( $url, '&dl=0' ) ) {
222 + // Dropbox shared link to direct download link.
223 + $url = str_replace( '&dl=0', '&dl=1', $url );
224 + }
225 +
226 + return $url;
227 + }
228 +
229 + /**
189 230 * Replaces ZIP archives in the import files with a list of their contents.
190 231 *
191 232 * ZIP files are removed from the list and their contents are added to the end of the list.
192 233 *
@@ -204,8 +245,12 @@
204 245 continue;
205 246 }
206 247
207 248 $file->extension = strtolower( pathinfo( $file->name, PATHINFO_EXTENSION ) );
249 + if ( '' === $file->extension ) {
250 + // If the file name has no extension, try to get it from the location (as WordPress tries adding an extension to that based on the MIME type, e.g. when downloading files).
251 + $file->extension = strtolower( pathinfo( $file->location, PATHINFO_EXTENSION ) );
252 + }
208 253
209 254 if ( function_exists( 'mime_content_type' ) ) {
210 255 $mime_type = mime_content_type( $file->location );
211 256 if ( false !== $mime_type ) {
@@ -286,16 +331,16 @@
286 331 * @return File[]|WP_Error List of files to import that were extracted from the ZIP file or WP_Error on failure.
287 332 */
288 333 protected function extract_zip_file_ziparchive( File $zip_file ) /* : array|WP_Error */ {
289 334 $archive = new ZipArchive();
290 - $archive_opened = $archive->open( $zip_file->location, ZIPARCHIVE::CHECKCONS );
335 + $archive_opened = $archive->open( $zip_file->location, ZipArchive::CHECKCONS );
291 336
292 - // If the ZIP file can't be opened with ZIPARCHIVE::CHECKCONS, try again without.
337 + // If the ZIP file can't be opened with ZipArchive::CHECKCONS, try again without.
293 338 if ( true !== $archive_opened ) {
294 339 $archive_opened = $archive->open( $zip_file->location );
295 340 }
296 341
297 - // If the ZIP file can't even be opened without ZIPARCHIVE::CHECKCONS, bail.
342 + // If the ZIP file can't even be opened without ZipArchive::CHECKCONS, bail.
298 343 if ( true !== $archive_opened ) {
299 344 return new WP_Error( 'table_import_error_zip_open', '', array( 'ziparchive_error' => $archive_opened ) );
300 345 }
301 346
@@ -373,9 +418,9 @@
373 418
374 419 require_once ABSPATH . 'wp-admin/includes/class-pclzip.php';
375 420
376 421 $archive = new PclZip( $zip_file->location );
377 - $archive_files = $archive->extract( PCLZIP_OPT_EXTRACT_AS_STRING ); // @phpstan-ignore-line PclZip::extract() uses `func_get_args()` to handle optional arguments.
422 + $archive_files = $archive->extract( PCLZIP_OPT_EXTRACT_AS_STRING ); // @phpstan-ignore arguments.count (PclZip::extract() uses `func_get_args()` to handle optional arguments.)
378 423
379 424 reset_mbstring_encoding();
380 425
381 426 // If the ZIP file can't be opened, bail.
@@ -510,10 +555,12 @@
510 555 TablePress::load_file( 'class-import-base.php', 'classes' );
511 556
512 557 // Choose the Table Import library based on the PHP version and the filter hook value.
513 558 if ( $use_legacy_import_class ) {
559 + // @phpstan-ignore assign.propertyType (The `load_class()` method returns `object` and not a specific type.)
514 560 $this->importer = TablePress::load_class( 'TablePress_Import_Legacy', 'class-import-legacy.php', 'classes' );
515 561 } else {
562 + // @phpstan-ignore assign.propertyType (The `load_class()` method returns `object` and not a specific type.)
516 563 $this->importer = TablePress::load_class( 'TablePress_Import_PHPSpreadsheet', 'class-import-phpspreadsheet.php', 'classes' );
517 564 }
518 565
519 566 // If there is more than one valid import file, ignore the chosen existing table for replacing/appending.
@@ -633,9 +680,9 @@
633 680 if ( '' === $format ) {
634 681 $format = 'csv';
635 682 }
636 683
637 - if ( ! isset( $this->importer->import_formats[ $format ] ) ) {
684 + if ( ! in_array( $format, $this->importer->import_formats, true ) ) { // @phpstan-ignore property.notFound (`$this->importer` is an instance of `TablePress_Import_Legacy` which has the property `import_formats`.)
638 685 return new WP_Error( 'table_import_legacy_unknown_format', '', $file->name );
639 686 }
640 687
641 688 $table = $this->importer->import_table( $format, $data );
@@ -656,9 +703,9 @@
656 703 * @return array<string, mixed>|WP_Error Loaded table on success (either with all properties or just 'data'), WP_Error on failure.
657 704 */
658 705 protected function load_table_from_file_phpspreadsheet( File $file ) /* : array|WP_Error */ {
659 706 // Convert File object to array, as those are not yet used outside of this class.
660 - return $this->importer->import_table( $file ); // @phpstan-ignore-line
707 + return $this->importer->import_table( $file ); // @phpstan-ignore return.type (This is an instance of TablePress_Import_PHPSpreadsheet which does not return false.)
661 708 }
662 709
663 710 /**
664 711 * Imports a loaded table into TablePress.