My aim is to import all XML files from a folder inside the WordPress installation (/data/*.xml)
To achieve this, I added action in functions.php:
/**
* Show 'insert posts' button on backend
*/
add_action( "admin_notices", function() {
echo "<div class='updated'>";
echo "<p>";
echo "To insert the posts into the database, click the button to the right.";
echo "<a class='button button-primary' style='margin:0.25em 1em' href='{$_SERVER["REQUEST_URI"]}&insert_mti_posts'>Insert Posts</a>";
echo "</p>";
echo "</div>";
});
Here's my code:
/**
* Create and insert posts from CSV files
*/
add_action( "admin_init", function() {
global $wpdb;
// I'd recommend replacing this with your own code to make sure
// the post creation _only_ happens when you want it to.
if ( ! isset( $_GET["insert_mti_posts"] ) ) {
return;
}
// Change these to whatever you set
$getposttype = array(
"custom-post-type" => "cikkek"
);
// Get the data from all those XMLs!
$posts = function() {
$xmlfiles = glob( __DIR__ . "/data/*.xml" );
$data = array();
$errors = array();
// Get array of XML files
foreach ( $xmlfiles as $key=>$xmlfile ) {
$xml = simplexml_load_file($xmlfile);
$xmldata = json_decode(json_encode($xml), true);
$posttitle = $xmldata['THIR']['CIM'];
$postlead = $xmldata['THIR']['LEAD'];
$postcontent = $xmldata['THIR']['HIRSZOVEG'];
$data = array(
$key => array(
"title" => $posttitle,
"description" => $postlead,
"content" => $postcontent
)
);
$data[] = $post;
};
if ( ! empty( $errors ) ) {
// ... do stuff with the errors
}
return $data;
};
// Simple check to see if the current post exists within the
// database. This isn't very efficient, but it works.
$post_exists = function( $title ) use ( $wpdb, $getposttype ) {
// Get an array of all posts within our custom post type
$posts = $wpdb->get_col( "SELECT post_title FROM {$wpdb->posts} WHERE post_type = '{$getposttype["custom-post-type"]}'" );
// Check if the passed title exists in array
return in_array( $title, $posts );
};
foreach ( $posts() as $post ) {
// If the post exists, skip this post and go to the next one
if ( $post_exists( $post["title"] ) ) {
continue;
}
// Insert the post into the database
$post["id"] = wp_insert_post( array(
"post_title" => $post["title"],
"post_content" => $post["content"],
"post_type" => $getposttype["custom-post-type"],
"post_status" => "draft"
));
}
});
Issue 1:
The code kind of works, but it only inserts the first .XML into the WordPress database. I don't understand why, as I loop through all of them and send back an array.
Issue 2: The code checks the title of the given XML and matches it up against the database -> should not add it if it's the same content. Unfortunately, it does.
Issue 3: I think this is because the admin_init action, but unfortunately, the import runs each time I refresh the admin. I only want it to run, if I click the Insert Posts button in admin. Is there another hook that is better suited for this?
$data = array(
replaces$data
, it does not add stuff to the array, it sets the array. So rather than adding posts to the array, it's setting the array as if it's a whole new array with 1 item. It has nothing to do with theadmin_init
hook. As I've said elsewhere in your other question, your use of a closure/anonymous function to read in the data in XML in a loop, then a second loop to create the post massively overcomplicates things. A single loop would be significantly easier to understand/write, more reliable, and faster