Wordpress upload post and attach file (wp_insert_post and wp_insert_attachment)

2.1k views Asked by At

My current Custom Wordpress theme doesn't allow me to attach an image / .pdf by <form> to a post.

This form (method="POST") has a 'subject' and 'textarea' field and ofcourse an input type="file".

What does work is create a post by using: 'wp_insert_post'

  • and get the ID of the newest post

What somewhat works after uploading the form:

  • get the image to reserve space at myWebsiteUrl/wp-admin -> media (but it doesn't show up, rather a Wordpress template image, which is all grey, is shown).

What doesn't work is getting the uploaded file to insert itself to the 'wp-content/uploads' folder so I can attach it to the new post. Later on I want to get the post and show it on another page and style it by using CSS

Furthermore in SQL database: when I go to: wp_posts and then observe column 'post_content', the post is there, but nothing (not even template code of the image) is shown other then the form subject and textarea content.

This is a custom Wordpress theme (which I have made). My page templates are stored in de folder called 'pages' and within those pages I require the page parts from the folder called 'pageParts'.

  • my theme dir: "./wp-content/theme/myTheme/"
  • the (view) page is in: "myTheme/pages/upload.php"
  • and the FORM HTML code (partial) is required_once into that (view) from: "myTheme/pageParts/uploadPart.php"

Now for the code (PHP 8)

My html form file:

<?php session_start(); ?>
<html>
 <body>
  <form action="../pages/uploadenPagesGet.php" method="POST" enctype="multipart/form-data">
    <input id="titelText" name="titel" type="text" placeholder="Titel">
    <select id="mainSelect" name="selectedOnderwerp">
     <option value="5">Constructions</option>
    </select>
    <textarea name="berichtTextarea" placeholder="Please enter your message&#46;&#46;&#46;"></textarea>
    <input id="buttonSubmit" class="buttonGold buttonSubmit center" type="submit" value="Save">
  </form>
 </body>
</html>

uploadenPagesGet.php

session_start();
// required for uploading
require_once '../../../../wp-load.php';
require_once '../../../../wp-admin/includes/file.php';

require_once( ABSPATH . '../../../wp-admin/includes/image.php' );
require_once( ABSPATH . '../../../wp-admin/includes/media.php' );

// Retrieve the FORM data:
global $user_ID;
global $post;
global $post_id;

$titel             = $_POST ['titel'                    ];
$selectedOnderwerp = $_POST ['selectedOnderwerp'        ];
$berichtTextarea   = $_POST ['berichtTextarea'          ];
$uploadedFileValue = $_FILES['uploadedFileValue'        ];
$filename          = $_FILES['uploadedFileValue']["name"];

//Preparing the INSERT with the FORM data:

$new_post = array(
  'post_title' => $titel,
  'post_content' => $berichtTextarea,
  'post_status' => 'publish',
  'post_date' => date('Y-m-d H:i:s'),
  'post_author' => $user_ID,
  'post_type' => 'post',
  'post_category' => array($selectedOnderwerp),
);

// And then I successfully create a post which is visible in Wordpres's Posts on the front and backend

$post_id = wp_insert_post($new_post);

// Now it is correct that I haven't sanitized anything at this point, but that is beyond the scope of what I'm
// asking. I will do that and much more (for example CSRF) after this ticket is resolved. 
// I kindly urge you to to not advice me on security. 

//So the data (all except the $_FILES) are uccesfully posted. Now I get the ID of my post

$currentPostID = $post_id;
echo $currentPostID; // display's the ID of the post.
//exit;     remove the comment to see the ID if needed, and or uncomment to post succesfully.


//set and place image in upload folder: 
$file_id = $uploadedFileValue;
$post_id = $currentPostID;
$file = wp_handle_upload( $file_id, $post_id);

//Define upload
$wp_upload_dir = wp_upload_dir();

// check absolute filename
$filetype = wp_check_filetype( basename( $filename ), null );

//Create array of data to attach the the Wordpress hook later

$attachment = array(
  'guid'           => $wp_upload_dir['url'] . '/' . basename( $filename ),
  'post_mime_type' => $filetype['type'],
  'post_title'     => preg_replace( '/\.[^.]+$/', '', basename( $filename ) ),
  'post_content'   => '',
  'post_status'    => 'inherit'
);

//insert data into the hook
$attachment_id = wp_insert_attachment( $attachment, $filename, $currentPostID);

//Attach previous information to the hook:
$attach_data = wp_generate_attachment_metadata( $attachment_id, get_attached_file( $attachment_id ));

//execute hooks by updating:
wp_update_attachment_metadata( $attachment_id, $attach_data );

Unfortunately the above returns gives error:

getimagesize(myWebsite.com/wp-content/uploads/clouds2.png): 
Failed to open stream: No such file or directory in (myWebsite.com/wp-content/wp-includes/media.php) on line 5165 

Warning: exif_imagetype(myWebsite.com/wp-content/uploads/clouds2.png): Failed to open stream: No such file or directory in (myWebsite.com/wp-includes/functions.php) on line 3245 

Warning: fopen(myWebsite.com/wp-content/uploads/clouds2.png): Failed to open stream: No such file or directory in (myWebsite.com/wp-includes/functions.php) on line 3268

I have tried the following urls in research:

And many more but for the sake of the length of this article: two StackOverflow posts which answers strangely enough do not apply to me.

Thank you for still being here and and I hope you can help me by resolving the issue please.

1

There are 1 answers

0
AndradeL On BEST ANSWER

The issue has been resolved.

By the help of the Wordpress moderator, I have been able to resolve the issue:

Issue resolved

Just for safekeeping:

Your post was spot on and I could commit and stick to that, rather then switching between certain hooks, not knowing wether they were to be used or not (just as wp_insert_attachment).

I have succesfully created a post, by uploading text from my form and by attaching an image by doing a upload (input type='file'). Then I successfully got the image to be added to MEDIA and then to attach it's ID to the post. Then to post that content on a page.

The following is information sent from the HTML form to my php file.

The following code is just plain, without the security features.

session_start();

Based on my current directory path:
// 
require ('../includes/functions.php');
require_once('../../../../wp-load.php');

// required for uploading
require_once('../../../../wp-admin/includes/file.php'  );
require_once('../../../../wp-admin/includes/image.php' );
require_once('../../../../wp-admin/includes/media.php' );

// END requirements uploaden

//The following $_POSTS are coming from my HTML form

$titel             = $_POST['titel'];
$selectedOnderwerp = $_POST['selectedOnderwerp'];//subject
$berichtTextarea   = $_POST['berichtTextarea']; //textarea
$uploadedFileValue = $_FILES['uploadedFileValue']; //<input type = 'file' name='uploadedFileValue'>
$filename          = $_FILES['uploadedFileValue']["name"]; //name of the file
$fileType          = $_FILES['uploadedFileValue']["type"];

Not persé needed (the globals)

global $user_ID;
global $post;
global $post_id;
// The data for the post
   $new_post = array(
  'post_title'    => $titel,
  'post_content'  => $berichtTextarea,
  'post_status'   => 'publish',
  'post_date'     => date('Y-m-d H:i:s'),
  'post_author'   => $user_ID,
  'post_type'     => 'post',
  'post_category' => array($selectedOnderwerp),
  'post_author'   => get_current_user_id(),
);

Now create the post

$post_id = wp_insert_post($new_post);

Get the current POST ID

$currentPostID = $post_id;

echo $currentPostID;

And attach the attachmentFile to the post_id

// once more, 'uploadedFileValue' is the name of my input file in html form
$attachment_id = media_handle_upload( 'uploadedFileValue', $post_id );

// from here I redirect  the user
header( 'location: ../pages/page-overzicht.php');
exit;

Then to display that post:

In have created an attachPost.php with the following content attachPost.php

<?php
session_start();
  require_once( '../../../../wp-load.php');

  // required for gettinng attachments

  require_once(  '../../../../wp-includes/post.php'   );
  require_once(  '../../../../wp-includes/plugin.php' );
  require_once(  '../../../../wp-includes/media.php'  );

Then in page-display.php

<?php
include_once '../pages/attachPost.php';
$xy = query_posts( 'post_type=post&posts_per_page=10');
?>

You can do the styling by yourself, just plain php:

<div class="itemClusterContainer">
  <?php
      foreach($xy as $va => $key) :?>
        <div class="itemCluster">
            <div>
                <img src="../img/body/MediaVormgeven-en-Ict.svg" alt="gears">
            </div>
            <span class="itemClusterTextClass"><?php echo $key->post_title;?></span>

   

<br>
                <a class="buttonMain" href="../pages/page-article.php?id=<?php echo $key->ID;?>">Bekijk</a>
            <br>
        </div>

  <?php endforeach ?>
 </div>

The above was a sumary page, when you click on the actual button you get the data of the post as following on

page-article.php

<?php
session_start();
include_once './attachPost.php';
$postIdNumber = $_GET['id'] // from the button you have clicked to come here;

//Get the media
$mediaArticle = get_attached_media( '', $postIdNumber);

$postIdNumber = get_post( $postIdNumber );
$title = $postIdNumber->post_title;
?>

Show the title


<div id="wpBericht" class="itemCluster">

              <?php
               $postContent = get_post( $postIdNumber );
               if($postContent)
                 {
                   $title = $postContent->post_content;
                   echo $title;
                   echo '<br><br><br>';
                 }
                else{
                  echo 'Er is geen bericht aan de post toegevoegd <br><br>';
                }

              ?>
       </div>

Show the content of the upload, somewhat modified for here

<?php

            foreach ($mediaArticle as $articleInfo => $key)
            {
              if ($key->post_mime_type === 'image/png' || $key->post_mime_type === 'image/jpg' || $key->post_mime_type === 'image/jpeg'){?>
                      <img class="imageSecTwo" src="<?php echo $key->guid; ?>" />
                      <p>
                        <a href="<?php echo $key->guid;?>" download>
                        Download&#58; <u><?php echo $key->post_title;?></u>
                        </a>
                      </p>
                    <?php
                  }
                else{
                  echo 'Deze post has no attachment';
                }

            }

    ?>

I am very happy with your spot on help. If this forum allowed me to +rep you I would have done so.

God bless you @bcworkz