Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 17 additions & 16 deletions .github/skills/architecture/hook-architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,43 +45,44 @@

### Header Hooks

| Hook | Parameters | Purpose |
| --------------------------------------- | ----------------------------- | -------------------------------------------------------- |
| Hook | Parameters | Purpose |
| -------------------------------------------------- | ----------------------------- | -------------------------------------------------------- |
| `fe_csv_import_export_basic_post_fields` | `$fields, $scope` | Customize basic export fields (ID, title, content, etc.) |
| `fe_csv_import_export_additional_post_fields` | `$fields, $scope` | Customize 'all' scope additional fields |
| `fe_csv_import_export_filter_taxonomy_objects` | `$taxonomy_objects, $args` | Filter taxonomy objects before header creation |
| `fe_csv_import_export_filter_custom_field_headers` | `$headers, $meta_keys, $args` | Customize custom field headers (Pro: enhanced features) |

### Query Hooks

| Hook | Parameters | Purpose |
| ----------------------------- | -------------------- | ---------------------------------------------- |
| Hook | Parameters | Purpose |
| ---------------------------------------- | -------------------- | ---------------------------------------------- |
| `fe_csv_import_export_sample_query_args` | `$query_args, $args` | Customize sample post query for meta discovery |
| `fe_csv_import_export_export_query_args` | `$query_args, $args` | Customize main export query |

### Import Hooks

| Hook | Parameters | Purpose |
| ---------------------------- | ------------------------- | -------------------------------------- |
| `fe_csv_import_export_pre_ajax_import` | `$result, $_POST` | Preflight import request validation |
| `fe_csv_import_export_user_can_import` | `$allowed` | Override import capability checks |
| `fe_csv_import_export_before_import` | `$args` | Pre-import preparation |
| `fe_csv_import_export_import_row` | `$row_data, $args` | Per-row data transformation |
| `fe_csv_import_export_after_import` | `$stats, $args` | Post-import cleanup |
| `fe_csv_import_export_cancelled_import` | `$cancelled, $session_id` | Override import cancellation detection |
| Hook | Parameters | Purpose |
| -------------------------------------------- | --------------------------------------- | -------------------------------------------------- |
| `fe_csv_import_export_pre_ajax_import` | `$result, $_POST` | Preflight import request validation |
| `fe_csv_import_export_user_can_import` | `$allowed` | Override import capability checks |
| `fe_csv_import_export_before_import` | `$args` | Pre-import preparation |
| `fe_csv_import_export_import_row` | `$row_data, $args` | Per-row data transformation |
| `fe_csv_import_export_after_import` | `$stats, $args` | Post-import cleanup |
| `fe_csv_import_export_cancelled_import` | `$cancelled, $session_id` | Override import cancellation detection |
| `fe_csv_import_export_import_max_batch_size` | `$max_batch_size, $total_rows, $config` | Customize maximum import batch size (default: 500) |

### Export Hooks

| Hook | Parameters | Purpose |
| ---------------------------- | ------------------------- | -------------------------------------- |
| Hook | Parameters | Purpose |
| --------------------------------------- | ------------------------- | -------------------------------------- |
| `fe_csv_import_export_pre_ajax_export` | `$result, $_POST` | Preflight export request validation |
| `fe_csv_import_export_user_can_export` | `$allowed` | Override export capability checks |
| `fe_csv_import_export_cancelled_export` | `$cancelled, $session_id` | Override export cancellation detection |

### Import Processing Hooks

| Hook | Parameters | Purpose |
| ------------------------------------ | ----------------------------------- | ---------------------------------- |
| Hook | Parameters | Purpose |
| ----------------------------------------------- | ----------------------------------- | ---------------------------------- |
| `fe_csv_import_export_import_row_context` | `$context, $row_data, $args` | Customize row context creation |
| `fe_csv_import_export_import_persist_result` | `$result, $post_data, $context` | Modify post persistence result |
| `fe_csv_import_export_taxonomy_term_resolution` | `$term_ids, $term_value, $taxonomy` | Customize taxonomy term resolution |
Expand Down
2 changes: 1 addition & 1 deletion AGENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
**FE CSV Import & Export** is a WordPress plugin for CSV import/export.
Supports custom post types, custom taxonomies, and custom fields.

- **Version**: 0.9.9
- **Version**: 1.0.0
- **License**: GPL-2.0+
- **PHP**: >= 8.1 (recommended)
- **Repository**: https://github.com/firstelementjp/fe-csv-import-export
Expand Down
13 changes: 6 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

![FE CSV Import & Export Banner](https://github.com/firstelementjp/fe-csv-import-export/blob/main/assets/images/img-sns-banner-80.jpg?raw=true)

[![Version](https://img.shields.io/badge/version-0.9.9.4-green.svg)](https://github.com/firstelementjp/fe-csv-import-export/releases)
[![Version](https://img.shields.io/badge/version-1.0.0-green.svg)](https://github.com/firstelementjp/fe-csv-import-export/releases)
[![License](https://img.shields.io/badge/License-GPLv2%2B-blue.svg)](https://www.gnu.org/licenses/gpl-2.0.html)
[![WordPress](https://img.shields.io/badge/WordPress-6.6%2B-blue.svg)](https://wordpress.org/)
[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/firstelementjp/fe-csv-import-export)
Expand All @@ -15,12 +15,11 @@ For end-user guides and full documentation, see the links below.

## ✨ Recent Highlights

- Bundled JavaScript files to reduce HTTP requests and improve page load performance
- Updated export batch planner to use memory_limit for dynamic batch size calculation
- Reduced memory usage for large CSV imports by streaming batch reads and reusing file offsets
- Improved import log tab behavior and preserved recent logs at completion
- Fixed CSV quote parsing for edge cases involving backslash-escaped double quotes in legacy data
- Cleaned up local release workflow so `test-release` and generated minified assets do not remain tracked in Git
- Taxonomy optimization for unchanged terms significantly reduces processing time for update-heavy imports
- Increased default import batch size from 100 to 500 rows to reduce AJAX overhead
- Added configurable batch size limit filter for per-site customization
- Detailed import profiling with WP_DEBUG batch profile logging for performance analysis
- Fixed JavaScript ES module import syntax to resolve browser compatibility issues

## 📖 Overview

Expand Down
14 changes: 0 additions & 14 deletions assets/js/fe-csv-import-export-main.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,6 @@
*
*/

// Import core modules
import './fe-csv-import-export-core.js';

// Import export modules
import './export/fe-csv-import-export/ajax.js';
import './export/fe-csv-import-export/download.js';
import './export/fe-csv-import-export/form.js';
import './export/fe-csv-import-export/ui.js';
import './export/fe-csv-import-export/logs.js';
import './fe-csv-import-export-export-unified.js';
import './export/fe-csv-import-export/original.js';
import './fe-csv-import-export-import.js';
import './fe-csv-import-export-license.js';

/**
* Bootstrap FE CSV Import & Export admin scripts when the DOM is ready.
*/
Expand Down
6 changes: 3 additions & 3 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
> CSV import/export for WordPress with localized admin UI, automatic batch processing, and developer extensibility.

[![License](https://img.shields.io/badge/license-GPL--2.0%2B-blue.svg)](legal.md)
[![Version](https://img.shields.io/badge/version-0.9.9.4-green.svg)](https://github.com/firstelementjp/fe-csv-import-export/releases)
[![Version](https://img.shields.io/badge/version-1.0.0-green.svg)](https://github.com/firstelementjp/fe-csv-import-export/releases)
[![WordPress](https://img.shields.io/badge/WordPress-6.6%2B-blue.svg)](https://wordpress.org/)

FE CSV Import & Export is a WordPress plugin for importing and exporting post data as CSV from the admin area.
Expand All @@ -29,11 +29,11 @@ FE CSV Import & Export is a WordPress plugin for importing and exporting post da

## 📥 Download

[Download fe-csv-import-export-0.9.9.4.zip](https://github.com/firstelementjp/fe-csv-import-export/releases/download/v0.9.9.4/fe-csv-import-export-0.9.9.4.zip){: .download-btn }
[Download fe-csv-import-export-1.0.0.zip](https://github.com/firstelementjp/fe-csv-import-export/releases/download/v1.0.0/fe-csv-import-export-1.0.0.zip){: .download-btn }

## 🚀 Quick Start

1. Download `fe-csv-import-export-0.9.9.4.zip`
1. Download `fe-csv-import-export-1.0.0.zip`
2. Upload and activate the plugin in WordPress
3. Open **Tools → FE CSV Import & Export**
4. Run a small test import or export first
Expand Down
15 changes: 15 additions & 0 deletions docs/changes.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,20 @@
# 📋 Changelog

## [1.0.0] - 2026-06-02

### 🚀 Performance Improvements

- **Taxonomy optimization for unchanged terms** - Import now skips `wp_set_post_terms()` calls when taxonomy terms are unchanged, significantly reducing processing time for update-heavy imports.
- **Increased default batch size** - Default import batch size increased from 100 to 500 rows, reducing AJAX overhead for large imports.
- **Configurable batch size limit** - New `fe_csv_import_export_import_max_batch_size` filter allows per-site customization of the maximum batch size.
- **Detailed import profiling** - Added granular profiling for import phases (preload, row context, row processor, meta/taxonomy preparation and application) with WP_DEBUG batch profile logging.

### 🛠️ Bug Fixes

- **Fixed JavaScript ES module import syntax** - Removed static ES module imports from main JS file to resolve browser syntax errors.

---

## [0.9.9.4] - 2026-05-27

### 🚀 Performance Improvements
Expand Down
2 changes: 1 addition & 1 deletion docs/install.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

## Manual Installation

1. [Download latest version (v0.9.9.4)](https://github.com/firstelementjp/fe-csv-import-export/releases/download/v0.9.9.4/fe-csv-import-export-0.9.9.4.zip)
1. [Download latest version (v1.0.0)](https://github.com/firstelementjp/fe-csv-import-export/releases/download/v1.0.0/fe-csv-import-export-1.0.0.zip)
2. Extract the downloaded ZIP file
3. Upload `fe-csv-import-export` folder to `/wp-content/plugins/`
4. Navigate to **Plugins** in WordPress admin
Expand Down
4 changes: 2 additions & 2 deletions fe-csv-import-export.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* Plugin Name: FE CSV Import & Export
* Plugin URI: https://github.com/firstelementjp/fe-csv-import-export
* Description: Simple yet powerful CSV import/export plugin for WordPress. Supports custom post types, custom taxonomies, and custom fields.
* Version: 0.9.9.4
* Version: 1.0.0
* Author: FirstElement K.K., Daijiro Miyazawa
* Author URI: https://www.firstelement.co.jp/
* License: GPL-2.0+
Expand All @@ -20,7 +20,7 @@
}

// Define plugin constants.
define( 'FE_CSV_IMPORT_EXPORT_VERSION', '0.9.9.4' );
define( 'FE_CSV_IMPORT_EXPORT_VERSION', '1.0.0' );
define( 'FE_CSV_IMPORT_EXPORT_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
define( 'FE_CSV_IMPORT_EXPORT_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
define( 'FE_CSV_IMPORT_EXPORT_BASENAME', plugin_basename( __FILE__ ) );
Expand Down
9 changes: 7 additions & 2 deletions includes/admin/class-fe-csv-import-export-admin-assets.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,12 @@ public function enqueue_scripts( $hook ) {
? (bool) FE_CSV_Import_Export_Settings_Helper::get( 'advanced', 'enable_logs', true )
: true;

// Temporarily force individual files for both debug and production modes
// to resolve dialog opening issue in production mode
$force_individual_files = true;

// Use bundled script for production, individual files for debug mode
if ( $debug_mode ) {
if ( $debug_mode || $force_individual_files ) {
// Debug mode: load individual files for easier debugging
$script_url = static function ( $relative_path ) use ( $suffix ) {
$min_path = preg_replace( '/\.js$/', $suffix . '.js', $relative_path );
Expand Down Expand Up @@ -315,7 +319,8 @@ public function enqueue_scripts( $hook ) {
}

// Localize script (use the main script handle based on mode)
$main_script_handle = $debug_mode ? 'fe-csv-import-export-core' : 'fe-csv-import-export-admin';
// When forcing individual files, always use core handle
$main_script_handle = ( $debug_mode || $force_individual_files ) ? 'fe-csv-import-export-core' : 'fe-csv-import-export-admin';

wp_localize_script(
$main_script_handle,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,82 @@ class FE_CSV_Import_Export_Ajax_Import_Batch_Planner {
* @return int Batch size.
*/
public function get_import_batch_size( int $total_rows, array $config ): int {
$max_execution_time = ini_get( 'max_execution_time' );
$max_execution_time = $max_execution_time ? (int) $max_execution_time : 30;
$max_execution_time = max( 1, $max_execution_time );
if ( $total_rows <= 0 ) {
return 1;
}

$max_execution_time = $this->get_max_execution_time();
$safe_time_limit = $max_execution_time * 0.8;
$avg_time_per_row = 0.02;
$time_based_batch = max( 1, (int) floor( $safe_time_limit / $avg_time_per_row ) );

$safe_time_limit = $max_execution_time * 0.5;
$avg_time_per_row = 0.35;
$time_based_batch = max( 1, (int) floor( $safe_time_limit / $avg_time_per_row ) );
$optimized_batch_size = max( 10, min( 50, $time_based_batch ) );
$memory_limit = $this->convert_memory_limit_to_bytes( (string) ini_get( 'memory_limit' ) );
$memory_limit = max( 64 * 1024 * 1024, $memory_limit );
$available_memory = max( 16 * 1024 * 1024, $memory_limit - ( 48 * 1024 * 1024 ) );
$memory_per_row = 128 * 1024;
$memory_based_batch = max( 1, (int) floor( $available_memory / $memory_per_row ) );

$base_batch_size = max( 1, min( $total_rows, $optimized_batch_size ) );
$optimized_batch_size = min( $time_based_batch, $memory_based_batch, $total_rows );
$max_batch_size = (int) apply_filters( 'fe_csv_import_export_import_max_batch_size', 500, $total_rows, $config );
$max_batch_size = max( 10, $max_batch_size );
$base_batch_size = max( 10, min( $max_batch_size, $optimized_batch_size ) );
$base_batch_size = min( $total_rows, $base_batch_size );

return (int) apply_filters( 'fe_csv_import_export_import_batch_size', $base_batch_size, $total_rows, $config );
}

/**
* Get max execution time with a safe fallback.
*
* @since 0.9.8
* @return int Max execution time in seconds.
*/
private function get_max_execution_time(): int {
$max_execution_time = ini_get( 'max_execution_time' );
$max_execution_time = false === $max_execution_time ? 30 : (int) $max_execution_time;

if ( $max_execution_time <= 0 ) {
return 120;
}

return max( 1, $max_execution_time );
}

/**
* Convert memory limit string to bytes.
*
* @since 0.9.8
* @param string $memory_limit Memory limit string.
* @return int Memory limit in bytes.
*/
private function convert_memory_limit_to_bytes( string $memory_limit ): int {
$memory_limit = strtoupper( trim( $memory_limit ) );

if ( '-1' === $memory_limit ) {
return PHP_INT_MAX;
}

if ( '' === $memory_limit ) {
return 128 * 1024 * 1024;
}

$unit = substr( $memory_limit, -1 );
$value = (int) substr( $memory_limit, 0, -1 );

switch ( $unit ) {
case 'G':
$value *= 1024 * 1024 * 1024;
break;
case 'M':
$value *= 1024 * 1024;
break;
case 'K':
$value *= 1024;
break;
default:
$value = (int) $memory_limit;
}

return $value > 0 ? $value : 128 * 1024 * 1024;
}
}
Loading
Loading