diff --git a/backend/src/Controllers/PostsController.php b/backend/src/Controllers/PostsController.php
index 2d90ff997..b5d2550fa 100644
--- a/backend/src/Controllers/PostsController.php
+++ b/backend/src/Controllers/PostsController.php
@@ -146,6 +146,8 @@ public function register_routes() {
],
]
);
+
+
}
/**
@@ -240,8 +242,8 @@ public function posts_count( $request ) {
$response = [];
foreach ( $post_types as $slug => $label ) {
- $counts = wp_count_posts( $slug );
- $counts->total = $counts->publish + $counts->draft + $counts->pending + $counts->private + $counts->future;
+ $counts = wp_count_posts( $slug );
+ $counts->total = $counts->publish + $counts->draft + $counts->pending + $counts->private + $counts->future;
$response[ $slug ] = $counts;
}
@@ -441,4 +443,5 @@ public function delete_post( $request ) {
]
);
}
+
}
diff --git a/backend/src/Controllers/PostsImportController.php b/backend/src/Controllers/PostsImportController.php
new file mode 100644
index 000000000..abdd90506
--- /dev/null
+++ b/backend/src/Controllers/PostsImportController.php
@@ -0,0 +1,336 @@
+view = $view;
+ }
+
+ /**
+ * Register routes.
+ */
+ public function register_routes() {
+ $this->route(
+ '/posts/import',
+ [
+ [
+ 'methods' => WP_REST_Server::CREATABLE,
+ 'callback' => [ $this, 'import_posts' ],
+ 'permission_callback' => function () {
+ return current_user_can( 'edit_published_posts' );
+ },
+ ],
+ ]
+ );
+ }
+
+ /*Import posts */
+
+ public function import_posts( $request ) {
+ $file = $request->get_file_params();
+
+ global $wpdb;
+
+ $uri = wp_upload_dir();
+ $target_dir = $uri;
+ $target_file = $target_dir['path'] . basename( $file['file']['name'] );
+ $filename = basename( $file['file']['name'] );
+ $file_type = pathinfo( $target_file, PATHINFO_EXTENSION );
+ $default_max_upload_size = $this->return_bytes( ini_get( 'upload_max_filesize' ) );
+
+ // Allow certain file formats
+ if ( $file_type !== 'xml' ) {
+
+ return rest_ensure_response(
+ [
+ 'error' => true,
+ 'message' => __( 'Sorry, only XML files are allowed.' ),
+ ]
+ );
+
+ } else {
+ if ( is_numeric( $default_max_upload_size ) && $file['file']['size'] > $default_max_upload_size ) {
+
+ return rest_ensure_response(
+ [
+ 'error' => true,
+ 'message' => __( 'Sorry, your file is too large.' ),
+ ]
+ );
+
+ }
+ }
+
+ if ( move_uploaded_file( $file['file']['tmp_name'], $target_file ) ) {
+
+ $xml_data = $this->XMLtoArray( file_get_contents( $target_file ) );
+
+ $post_arr = [];
+ if ( $this->isAssoc( $xml_data['RSS']['CHANNEL']['ITEM'] ) ) {
+ $post_arr[] = $xml_data['RSS']['CHANNEL']['ITEM'];
+ } else {
+ $post_arr = $xml_data['RSS']['CHANNEL']['ITEM'];
+ }
+
+ $sucess_imp_count = 0;
+ $fail_imp_count = 0;
+
+ foreach ( $post_arr as $property ) {
+
+ $current_user = wp_get_current_user();
+ $post_data = [
+ 'comment_status' => $property['WP:COMMENT_STATUS'],
+ 'ping_status' => $property['WP:PING_STATUS'],
+ 'post_author' => $current_user->ID,
+ 'post_content' => $property['DESCRIPTION'] ? $property['DESCRIPTION'] : '',
+ 'post_excerpt' => $property['EXCERPT:ENCODED'] ? $property['EXCERPT:ENCODED'] : '',
+ 'post_name' => $property['WP:POST_NAME'],
+ 'post_status' => $property['WP:STATUS'],
+ 'post_title' => $property['TITLE'],
+ 'post_type' => $property['WP:POST_TYPE'],
+ 'to_ping' => $property['WP:PING_STATUS'],
+ 'menu_order' => $property['WP:MENU_ORDER'],
+ ];
+
+ if ( ! function_exists( 'post_exists' ) ) {
+ require_once ABSPATH . 'wp-admin/includes/post.php';
+ }
+ if ( 0 === post_exists( $property['TITLE'], '', '', $property['WP:POST_TYPE'] ) ) {
+
+ /* Import Attachments */
+
+ if ( $property['WP:POST_TYPE'] === 'attachment' ) {
+
+ $file = $property['WP:ATTACHMENT_URL'];
+ $filename = basename( $file );
+ $read_file = file_get_contents( $file );
+
+ $upload_file = wp_upload_bits( $filename, null, $read_file );
+
+ if ( ! $upload_file['error'] ) {
+
+ $wp_filetype = wp_check_filetype( $filename, null );
+ $post_data['post_mime_type'] = $wp_filetype['type'];
+ $attachment_id = wp_insert_attachment( $post_data, $upload_file['file'] );
+ if ( ! is_wp_error( $attachment_id ) ) {
+ require_once( ABSPATH . 'wp-admin' . '/includes/image.php' );
+ $attachment_data = wp_generate_attachment_metadata( $attachment_id, $upload_file['file'] );
+ wp_update_attachment_metadata( $attachment_id, $attachment_data );
+ }
+
+ $sucess_imp_count++;
+
+ }
+ } else {
+ $new_post_id = wp_insert_post( $post_data );
+ wp_set_post_terms( $new_post_id, null, 'category' );
+ $post_meta = $property['WP:POSTMETA'];
+ $post_cat = $property['CATEGORY'];
+
+ if ( is_array( $post_meta ) && count( $post_meta ) !== 0 ) {
+ foreach ( $post_meta as $meta_info ) {
+
+ $meta_key = $meta_info['WP:META_KEY'] ? $meta_info['WP:META_KEY'] : '';
+ $meta_value = $meta_info['WP:META_VALUE'] ? addslashes( $meta_info['WP:META_VALUE'] ) : '';
+ if ( $meta_key !== '' && $meta_value !== '' ) {
+
+ $wpdb->query( "INSERT INTO {$wpdb->postmeta} (post_id, meta_key, meta_value) values ({$new_post_id}, '{$meta_key}', '{$meta_value}')" ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
+
+ }
+ }
+ }
+
+ if ( is_array( $post_cat ) && count( $post_cat ) !== 0 ) {
+
+ foreach ( $post_cat as $category ) {
+
+ $term = term_exists( $category['content'], $category['DOMAIN'] );
+
+ wp_set_post_terms( $new_post_id, [ $term['term_taxonomy_id'] ], $category['DOMAIN'], true );
+
+ }
+ }
+
+ $sucess_imp_count++;
+ }
+ } else {
+ $fail_imp_count++;
+
+ }
+ }
+
+ $post_fail_msg = __( 'Post Imported Failed!' );
+
+ if ( $sucess_imp_count > 1 ) {
+ $post_success_msg = $sucess_imp_count . ' ' . ucfirst( $property['WP:POST_TYPE'] ) . __( ' Imported Successfully!' );
+ } elseif ( $sucess_imp_count === 1 ) {
+ $post_success_msg = ucfirst( $property['WP:POST_TYPE'] ) . __( ' Imported Successfully!' );
+ } else {
+ $post_success_msg = '';
+ }
+
+ if ( $fail_imp_count > 1 ) {
+ $post_fail_msg = $fail_imp_count . ' ' . ucfirst( $property[' WP:POST_TYPE '] ) . __( ' Already exist or unable to Import!' );
+ } elseif ( $fail_imp_count === 1 ) {
+ $post_fail_msg = ucfirst( $property['WP:POST_TYPE'] ) . __( ' Already exist or unable to Import!' );
+ } else {
+ $post_fail_msg = '';
+ }
+
+ return rest_ensure_response(
+ [
+ 'success' => true,
+ 'message' => $post_success_msg . ' ' . $post_fail_msg,
+ ]
+ );
+
+ } else {
+
+ return rest_ensure_response(
+ [
+ 'error' => true,
+ 'message' => __( 'Sorry, there was an error uploading your file.' ),
+ ]
+ );
+ }
+
+ }
+
+ /*
+ This function read XML data and convert into array
+ */
+
+ public function XMLtoArray( $xml ) {
+ $xml_parser = xml_parser_create();
+ xml_parse_into_struct( $xml_parser, $xml, $vals );
+ xml_parser_free( $xml_parser );
+
+ $_tmp = '';
+ foreach ( $vals as $xml_elem ) {
+ $x_tag = $xml_elem['tag'];
+ $x_level = $xml_elem['level'];
+ $x_type = $xml_elem['type'];
+ if ( $x_level !== 1 && $x_type === 'close' ) {
+ if ( isset( $multi_key[ $x_tag ][ $x_level ] ) ) {
+ $multi_key[ $x_tag ][ $x_level ] = 1;
+ } else {
+ $multi_key[ $x_tag ][ $x_level ] = 0;
+ }
+ }
+ if ( $x_level !== 1 && $x_type === 'complete' ) {
+ if ( $_tmp === $x_tag ) {
+ $multi_key[ $x_tag ][ $x_level ] = 1;
+ }
+
+ $_tmp = $x_tag;
+ }
+ }
+
+ foreach ( $vals as $xml_elem ) {
+ $x_tag = $xml_elem['tag'];
+ $x_level = $xml_elem['level'];
+ $x_type = $xml_elem['type'];
+ if ( $x_type === 'open' ) {
+ $level[ $x_level ] = $x_tag;
+ }
+
+ $start_level = 1;
+ $php_stmt = '$xml_array';
+ if ( $x_type === 'close' && $x_level !== 1 ) {
+ $multi_key[ $x_tag ][ $x_level ]++;
+ }
+
+ while ( $start_level < $x_level ) {
+ $php_stmt .= '[$level[' . $start_level . ']]';
+ if ( isset( $multi_key[ $level[ $start_level ] ][ $start_level ] ) && $multi_key[ $level[ $start_level ] ][ $start_level ] ) {
+ $php_stmt .= '[' . ( $multi_key[ $level[ $start_level ] ][ $start_level ] - 1 ) . ']';
+ }
+
+ $start_level++;
+ }
+ $add = '';
+ if ( isset( $multi_key[ $x_tag ][ $x_level ] ) && $multi_key[ $x_tag ][ $x_level ] && ( $x_type === 'open' || $x_type === 'complete' ) ) {
+ if ( ! isset( $multi_key2[ $x_tag ][ $x_level ] ) ) {
+ $multi_key2[ $x_tag ][ $x_level ] = 0;
+ } else {
+ $multi_key2[ $x_tag ][ $x_level ]++;
+ }
+
+ $add = '[' . $multi_key2[ $x_tag ][ $x_level ] . ']';
+ }
+ if ( isset( $xml_elem['value'] ) && trim( $xml_elem['value'] ) !== '' && ! array_key_exists( 'attributes', $xml_elem ) ) {
+ if ( $x_type === 'open' ) {
+ $php_stmt_main = $php_stmt . '[$x_type]' . $add . '[\'content\'] = $xml_elem[\'value\'];';
+ } else {
+ $php_stmt_main = $php_stmt . '[$x_tag]' . $add . ' = $xml_elem[\'value\'];';
+ }
+
+ eval( $php_stmt_main );
+
+ }
+ if ( array_key_exists( 'attributes', $xml_elem ) ) {
+ if ( isset( $xml_elem['value'] ) ) {
+ $php_stmt_main = $php_stmt . '[$x_tag]' . $add . '[\'content\'] = $xml_elem[\'value\'];';
+ eval( $php_stmt_main );
+ }
+ foreach ( $xml_elem['attributes'] as $key => $value ) {
+ $php_stmt_att = $php_stmt . '[$x_tag]' . $add . '[$key] = $value;';
+ eval( $php_stmt_att );
+ }
+ }
+ }
+ return $xml_array;
+ }
+
+ /*
+ This function checks the array is associate or not.
+ */
+
+ public function isAssoc( array $arr ) {
+ if ( [] === $arr ) {
+ return false;
+ } else {
+ return array_keys( $arr ) !== range( 0, count( $arr ) - 1 );
+ }
+ }
+
+ /*
+ This function convert string formatted data size value into bytes.
+ */
+
+ function return_bytes( $val ) {
+ $val = trim( $val );
+
+ if ( is_numeric( $val ) ) {
+ return $val;
+ }
+
+ $last = strtolower( $val[ strlen( $val ) - 1 ] );
+ $val = substr( $val, 0, -1 ); // necessary since PHP 7.1; otherwise optional
+
+ switch ( $last ) {
+ // The 'G' modifier is available since PHP 5.1.0
+ case 'g':
+ $val *= 1024;
+ case 'm':
+ $val *= 1024;
+ case 'k':
+ $val *= 1024;
+ }
+
+ return $val;
+ }
+
+
+}
diff --git a/backend/src/Providers/RestServiceProvider.php b/backend/src/Providers/RestServiceProvider.php
index 09c93e9db..8ed4a780a 100644
--- a/backend/src/Providers/RestServiceProvider.php
+++ b/backend/src/Providers/RestServiceProvider.php
@@ -13,6 +13,7 @@
use FL\Assistant\Controllers\NotificationsController;
use FL\Assistant\Controllers\PostsController;
use FL\Assistant\Controllers\PostsExportController;
+use FL\Assistant\Controllers\PostsImportController;
use FL\Assistant\Controllers\SearchController;
use FL\Assistant\Controllers\TermsController;
use FL\Assistant\Controllers\UpdatesController;
@@ -39,6 +40,7 @@ class RestServiceProvider extends ServiceProviderAbstract {
NotificationsController::class,
PostsController::class,
PostsExportController::class,
+ PostsImportController::class,
TermsController::class,
UpdatesController::class,
UsersController::class,
diff --git a/package-lock.json b/package-lock.json
index 46fd28d9a..8b64a5d18 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -6268,12 +6268,14 @@
"balanced-match": {
"version": "1.0.0",
"bundled": true,
- "dev": true
+ "dev": true,
+ "optional": true
},
"brace-expansion": {
"version": "1.1.11",
"bundled": true,
"dev": true,
+ "optional": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@@ -6288,17 +6290,20 @@
"code-point-at": {
"version": "1.1.0",
"bundled": true,
- "dev": true
+ "dev": true,
+ "optional": true
},
"concat-map": {
"version": "0.0.1",
"bundled": true,
- "dev": true
+ "dev": true,
+ "optional": true
},
"console-control-strings": {
"version": "1.1.0",
"bundled": true,
- "dev": true
+ "dev": true,
+ "optional": true
},
"core-util-is": {
"version": "1.0.2",
@@ -6415,7 +6420,8 @@
"inherits": {
"version": "2.0.3",
"bundled": true,
- "dev": true
+ "dev": true,
+ "optional": true
},
"ini": {
"version": "1.3.5",
@@ -6427,6 +6433,7 @@
"version": "1.0.0",
"bundled": true,
"dev": true,
+ "optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
@@ -6441,6 +6448,7 @@
"version": "3.0.4",
"bundled": true,
"dev": true,
+ "optional": true,
"requires": {
"brace-expansion": "^1.1.7"
}
@@ -6448,12 +6456,14 @@
"minimist": {
"version": "0.0.8",
"bundled": true,
- "dev": true
+ "dev": true,
+ "optional": true
},
"minipass": {
"version": "2.3.5",
"bundled": true,
"dev": true,
+ "optional": true,
"requires": {
"safe-buffer": "^5.1.2",
"yallist": "^3.0.0"
@@ -6472,6 +6482,7 @@
"version": "0.5.1",
"bundled": true,
"dev": true,
+ "optional": true,
"requires": {
"minimist": "0.0.8"
}
@@ -6552,7 +6563,8 @@
"number-is-nan": {
"version": "1.0.1",
"bundled": true,
- "dev": true
+ "dev": true,
+ "optional": true
},
"object-assign": {
"version": "4.1.1",
@@ -6564,6 +6576,7 @@
"version": "1.4.0",
"bundled": true,
"dev": true,
+ "optional": true,
"requires": {
"wrappy": "1"
}
@@ -6685,6 +6698,7 @@
"version": "1.0.2",
"bundled": true,
"dev": true,
+ "optional": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
diff --git a/src/apps/fl-import/app.js b/src/apps/fl-import/app.js
new file mode 100644
index 000000000..2d012328a
--- /dev/null
+++ b/src/apps/fl-import/app.js
@@ -0,0 +1,50 @@
+import React from 'react'
+import { __ } from '@wordpress/i18n'
+import { Page, Nav } from 'assistant/ui'
+import { ImportDropUploader } from './import'
+
+export const ImportApp = ( { match, history } ) => (
+