It is confusing as if I manually upload the PDF file into WordPress, the image is generated nicely. It is only in the command line that the error occurs. Is there another way to SSH into the Local Box and have use exactly the same environment as the WordPress install? Clearly everything is working if it can do it in the admin panels.
Regular images work well.
System Details
6.1.2
MacOS BigSur
Thanks for any help / pointers!
PS I am automating the upload of several thousand PDF files so am unable to just manually import each one.
I’m not able to generate a preview of a PDF file even in the wp-admin, but I think that’s because of this bug related to Imagick in Local’s PHP lightning services:
The confusing part to me is that the error you mention references ghostscript which I think Imagick uses if present, so that makes me think that at least some of Imagick is working for you on your machine.
Thanks for looking into this, Ben. I had to change the PHP version to 7.4.1 in Local to make the image previews generate. It was after changing to this version I realised that they weren’t generated over the cli.
If I bump it to version 8.0.0 I get another error:
Failed loading /Users/djave_co/Library/Application Support/Local/lightning-services/php-8.0.0+2/bin/darwin/lib/php/extensions/no-debug-non-zts-20200930/opcache.so: dlopen(/Users/djave_co/Library/Application Support/Local/lightning-services/php-8.0.0+2/bin/darwin/lib/php/extensions/no-debug-non-zts-20200930/opcache.so, 9): Symbol not found: _zend_cannot_pass_by_reference
Referenced from: /Users/djave_co/Library/Application Support/Local/lightning-services/php-8.0.0+2/bin/darwin/lib/php/extensions/no-debug-non-zts-20200930/opcache.so
Expected in: flat namespace
in /Users/djave_co/Library/Application Support/Local/lightning-services/php-8.0.0+2/bin/darwin/lib/php/extensions/no-debug-non-zts-20200930/opcache.so
Xdebug requires Zend Engine API version 420200930.
The Zend Engine API version 320190902 which is installed, is outdated.
Found 8 images to regenerate.
1/8 Skipped thumbnail regeneration for "Detective-Digiduck—150" (ID 33733).
2/8 Skipped thumbnail regeneration for "Ditectif-Digihwyaden" (ID 33727).
3/8 Skipped thumbnail regeneration for "Detective-Digiduck—150" (ID 33726).
4/8 Regenerated thumbnails for "thumbnail2" (ID 33725).
5/8 Regenerated thumbnails for "DLs_hero_image_no_quote_FINAL" (ID 33724).
6/8 Regenerated thumbnails for "4_stats" (ID 33723).
7/8 Regenerated thumbnails for "thumbnail2" (ID 33722).
8/8 Regenerated thumbnails for "thumbnail2" (ID 33721).
The successful generations are only images, not PDFs.
Thanks for that push in the right direction! The good news is, I was able to replicate what you’re seeing on PHP 7.4.1 as well as PHP 8.0!
The less-good news is that I’m not 100% sure why that’s the case since that gs_init.ps file does exist. I was thinking that maybe the system installed version of Ghostscript was being used, but even temporarily renaming the gs binary didn’t help.
If I were to guess, it might be that the space in the path of .../Application Support/... is causing issues. Either way, I’m not sure how quickly, or even if it’s possible that this sort of thing can be fixed.
I think that in order to get you unblocked, you have one of two options:
Deploy the site somewhere under an actual Linux environment and try running the wpcli script again
Thanks for looking into it. I found the Regenerate Thumbnails plugin wouldn’t work if the PDFs were already present in WordPress with no images.
For my project, it is an automated node importer for a project that is going live quite soon so it wasn’t possible to wait. I found a pretty horrible work around I had to do for each PDF file, maybe it might help someone in future.
// CreatePDFThumbnail.js
import shell from "shelljs";
import config from "../config.js";
export default async (id, pdfPath, title) => {
shell.cd(config.wpInstall, { silent: true });
let jpgName = pdfPath.split("/").pop().replace(".pdf", "-thumbnail.jpg");
let jpgPath = `~/temp-files/${jpgName}`;
// Manually create the jpg thumbnail
let command = `gs -o ${jpgPath} -sDEVICE=jpeg -dLastPage=1 ${pdfPath}`;
let createJpg = shell.exec(command);
// Find the size of the original image (again, imagemagik isn't really an option)
let getSize = shell.exec(`file ${jpgPath}`);
const sizeRegex = /, (\d+)x(\d+),/gm;
var reg = sizeRegex.exec(getSize.stdout);
const width = reg[1];
const height = reg[2];
console.log({ width, height });
// Import it, and capture the ID
command = `wp media import ${jpgPath} --post_id=${id} --title="${title} thumb" --porcelain`;
let output = shell.exec(command);
let uploadId = output.stdout.trim();
console.log({ uploadId });
// When the thumbnail is uploaded, the metadata created is nearly what we want for the PDF thumb
command = `wp post get ${uploadId} --fields=guid`;
let postCommand = shell.exec(command);
let file = postCommand.stdout
.split("\n")
.filter((line) => line.indexOf(".jpg") >= 0)
.map((line) => line.split("\t")[1])[0]
.split("/")
.pop();
command = `wp post meta get ${uploadId} _wp_attachment_metadata --format=json`;
let metadata = shell.exec(command, { silent: true });
metadata = JSON.parse(metadata.trim());
// However there are a few bits we don't need
delete metadata.image_meta;
delete metadata.file;
delete metadata.width;
delete metadata.height;
// and its missing the all important full size image
metadata.sizes.full = {
height,
width,
file,
"mime-type": metadata.sizes.thumbnail["mime-type"],
};
console.log(metadata);
// Now we can set the metadata of the PDF file, using what we got from the jpg
console.log(`Setting meta data for ${id}`);
command = `wp post meta update ${id} _wp_attachment_metadata ${JSON.stringify(
JSON.stringify(metadata)
)} --format=json`;
console.log(command);
let updatedata = shell.exec(command);
// And finally delete the records from the thumbnail in the database (all record data is stored with the PDF now)
let postsQuery = `wp db query "DELETE FROM \"wp_posts\" WHERE \"id\" = ${uploadId};" --socket="~/Library/Application Support/Local/run/Ri0gz2LNO/mysql/mysqld.sock"`;
let metaQuery = `wp db query "DELETE FROM \"wp_postmeta\" WHERE \"post_id\" = ${uploadId};" --socket="~/Library/Application Support/Local/run/Ri0gz2LNO/mysql/mysqld.sock"`;
shell.exec(postsQuery);
shell.exec(metaQuery);
return true;
};