Feature #3623

WP Post to PDF Plug-in Banner

Added by Andrew McKinney over 4 years ago. Updated about 4 years ago.

Priority name:
Category name:
WordPress Plugins
Target version:
Start date:
Due date:
% Done:


Estimated time:


Hi Team!

I've recently activated the WP Post to PDF plugin for one of my sites and noticed that the Commons logo shows up at the top of the first page when you generate a PDF. As a faculty liaison in the New Media Lab I've also fielded this question recently, specifically for a journal hosted on the Commons that would like to have their own logo display. There's a place in the plugin's settings under "PDF formatting options" (see attached screenshot) where it looks like you can change that banner image, but it just shows the Commons banner logo and won't allow you to change it. Is this something that must be changed at the site wide level (ie. can only have one image for the whole multisite installation) or is there any way that the Commons team can make that banner image changeable per individual site?




#1 Updated by Boone Gorges over 4 years ago

It would take some non-trivial work to make this happen. See #2682.

#2 Updated by Boone Gorges over 4 years ago

  • Category name set to WordPress Plugins
  • Status changed from New to Assigned
  • Assignee set to Daniel Jones
  • Target version set to Future release

Looking into this a bit more, it appears that we have not updated this plugin since installing it. Indeed, the plugin has not been updated by its author in a couple years. For this reason, I think we can consider forking it.

Dan, I'm reassigning this ticket to you. Could you dissect this plugin a bit to see how it's currently determining the banner image to use? Then think a bit about how to make this blog-specific, and configurable by the user. Ideally there would be some sort of upload interface, or some integration with the media library. Can you take a little time (no more than, say, an hour) to look at the code and report back with some thoughts about feasibility?

#3 Updated by Daniel Jones over 4 years ago

Looks like this would be pretty easy - on the post_updated action, the plugin calls a "generate_pdf_file" function, which includes a file called tcpdf.php, which in turn includes a file called tcpdf_config.php, which defines a constant called PDF_HEADER_LOGO that right now is set in staticly, but I think we could define it based on a plugin option. Right now it's set to the static location of the logo image file.

I think we would just have to go into the plugin's options page and change what's in there now to be integrated with WP's media uploader and save the uploaded image's location in a plugin option which we could then reference in the config file. Seems like that integration w/the media uploader is the hardest part, but there are a bunch of tutorials on it, or maybe someone on the team already has experience with that.

Let me know if that makes sense, and what you think should happen next.

#4 Updated by Boone Gorges over 4 years ago

Thanks for looking at this, Dan. The technical details here sound fine. I'm more concerned about what the actual workflow will look like, which I suppose will depend on the details of how you integrate the uploader. I have done this a bit before (as has Ray, who I've added as a watcher) and have found it to be moderately difficult. You might spend a bit of time trying to make it work for your purpose, but if you start hitting walls, it probably makes sense to consider a simple form with an input type="file", and the necessary form-handling logic on the back end.

#5 Updated by Daniel Jones over 4 years ago

So I think I have this working now - I added a file upload to the plugin options page, and if someone uploads an image, it'll replace the existing file with the new one, even if the filetype uploaded doesn't match .png, which is what it ends up saved as. The user first has to click "Save Changes," and then "Save and Reset PDF Cache" in order for it to work though, which I think is the case for any formatting changes.

There's all kinds of validation stuff to do still, which I don't have a lot of experience with. It'd be good to limit it to certain file types and a certain maximum file size, and to produce errors for the user based on those tests. I'd be happy teach myself, but it might be faster for someone else to take it on. Let me know!

#6 Updated by Daniel Jones over 4 years ago

I think I have this working now using wp_handle_upload (thanks pointing me in the right direction, Boone!). I'm only allowing jpeg, png, and gif files but could change that. One issue that I wasn't able to resolve is that the way the plugin was written, the file it uses for the header logo is hard to update (as in change its location), so instead I just overwrite that same file with the new upload. This means some forced file-type conversion since the original is a png. I tested with uploading other file types though and it seems to work fine.

Also - the error strings that get returned aren't ideal (e.g., "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form." for when it's too large), but I think they work okay. Let me know if I should work on overriding them or anything else.

Here's the changeset:

#7 Updated by Boone Gorges over 4 years ago

Thanks, Dan! The upload code itself looks good.

The file location seems a bit funky, though. `WP_CONTENT_DIR` . '/uploads/wp-post-to-pdf-logo.png'` will be shared between all sites on the network. This means that if I upload a custom banner on my site, it'll override yours on a different site, which seems pretty messy. Can we abstract out the upload path generation so that it's multisite-aware? Use `wp_upload_dir()` to get a base upload directory that is specific to the current blog. You'll also need to change the `generate_pdf()` function so that it looks in the right place.

#8 Updated by Daniel Jones over 4 years ago

Good point Boone - sorry I didn't catch that. I made some changes that I think should fix the issue - saved the path and the url for the uploaded file in the plugin settings, and changed the generate_pdf_file() function to look for those options instead of the defined HEADER_LOGO constant. Had to add in some testing in case there wasn't a file uploaded yet, too. Let me know if you think this works:

And thanks again!

#9 Updated by Boone Gorges over 4 years ago

Hey Dan - This is looking much better, and I think is probably fine as-is. Here are a few kinda pedantic points to consider - if you think they're good ideas, feel free to explore them:

- Storing the full header file path and URL is redundant in a way that can be harmful in certain circumstances. For example, if someone wants to use our domain mapping feature, it will mean that the URL of their blog changes, which would make the URL stored in the options table incorrect (it would result in a 301 redirect). Storing the full file path can cause problems in a distribution plugin because it's not friendly to site migration: if someone dumps the database tables and imports them to a new server, the paths will probably be wrong. A more flexible option is to store only the filename, and concatenate the path at runtime.
- In fact, though, it may not be necessary to store anything in an option. The original implementation of the plugin used a static filename for the header image. You're storing the filename of the uploaded file. If you adopted the original strategy - rename the file to some standard name when uploading - you wouldn't need to store anything.
- Dynamic path generation would solve another problem: getting rid of old header files. Now, if I uploaded a header logo, but then replace it a number of times with different files, they'll remain in the upload directory. Harmless, but a bit sloppy, at least if you're not going to offer any way to access those old header logos. If you use the same filename, you can overwrite the old file - a self-cleaning feature :)
- There appears to be no fallback image support. That is, if there is no user-provided image, there'll be no image at all. This is OK for the Commons (probably ideal, actually), but may not be great for the distrubition plugin.

Again, none of these are critical, certainly not for use on the Commons. But if we want to prepare a patch to send to the plugin author - which would be very nice to do, I think - implementing the suggestions above would comply better with best practices. What do you think?

#10 Updated by Daniel Jones about 4 years ago

Thanks for this feedback, Boone. I think it makes a lot of sense. I made changes so that the plugin doesn't use options to store the header logo, and dynamically generates the path & url for it where it's needed. I just use one file name to store the images, so that they overwrite each other. One question I have - doing that meant renaming everything to wpptopdf-header.png, no matter if the original extension was .gif, .jpg, etc. Is that considered an okay thing to do? Seems to work fine. Here's the changeset:

I had a couple of thoughts related to the fallback image:
1. It might actually be nice to include an option to remove the header image without replacing it, in case a user decides they'd like to have no image after having uploaded one. I'm thinking the best way to do this would be a link-looking line of text that says "Remove header image" that would be hooked up to some javascript that would first remove the image from being displayed on the options page and would also set a hidden checkbox that could parsed by PHP and used to delete the file stored as the header image.
2. I think it could be nice to provide a fallback, but not sure what it would be - there isn't a standardized way of storing site header images as far as I can tell, and I don't think it'd be great to have a "PDF produced by WP Post to PDF" banner, either. Do you have any thoughts?

Thanks for encouraging me to poke around with this.

#11 Updated by Boone Gorges about 4 years ago

Awesome - this is looking great.

Regarding the file extension: In most cases, the browser will display the image properly even with the wrong extension, but it's not particularly good practice. I'd suggest either (a) writing logic that enforces that either a png or jpg can be exist at the same time with the file name wptopdf-header, and then detecting which of those is present before outputting the HTML, or (b) enforcing that only a png (or whatever) can be uploaded.

I like your "remove header image" idea a lot. Instead of messing with JS, use a URL query arg `` and have a listener hooked to 'admin_init' that will detect this query arg and remove the image as appropriate. Make sure you use WP nonces if you do this - look up usage of `wp_nonce_url()` and `check_admin_referer()`.

I think you're right about default header images. No one will want them. Let's leave it out.

#12 Updated by Daniel Jones about 4 years ago

Been working on the remove image link and came up against an issue where the query arg in the URL doesn't go away when you resubmit the form, so if you remove the header image, then upload another one (not sure why someone would do that but I'm sure someone would) and re-submit the form, it just deletes the image again. You'd have to leave the options page and come back in order to be able to upload a new image. Is that okay? Can't figure out an easy way around it.

#13 Updated by Boone Gorges about 4 years ago

After handling the form submission, `wp_redirect()` to the same URL, minus the query var.

#14 Updated by Daniel Jones about 4 years ago

Oh great that's a huge help! Thanks.

I got the remove header image link working with wp_redirect(), and decided to make it so that users can only upload JPEGs (either jpg or jpeg), which I force to be .jpeg. The message the user sees is a little confusing if they try upload a png, bmp, etc. (says it's for "Security reasons," but I didn't see a clean way of customizing the message for these particular cases. Is it okay to just convert .jpg to .jpeg? Or is that still not recommended. If it's an issue I can work on another solution. Here's the changeset:

Let me know if you think this works!

#15 Updated by Boone Gorges about 4 years ago

  • Target version changed from Future release to 1.8

This is looking great, Dan. For completeness's sake, could you also add a nonce check for protection against CSRF attacks? Check out this page (to add to a URL, and then to verify).

#16 Updated by Daniel Jones about 4 years ago

Oh yes sorry I forgot to add this with my last commit! Here's the changeset, let me know if I implemented this right:

#17 Updated by Boone Gorges about 4 years ago

Check looks good, but make sure that you use && on line 69 rather than the bitwise operator & - we'll get false positives otherwise :)

#19 Updated by Boone Gorges about 4 years ago

  • Status changed from Assigned to Resolved

Also available in: Atom PDF