I'm not sure I agree with the sentiments, but yes I've read why it's not wanted in core or even listed as a contributed module.  I've managed to work around it with editing templates files this far, but I'm currently stuck on something (I'm trying to port a site over that uses webform2pdf - but generates QR codes in that PDF from a separate library.)  As far as I've been able to tell, there's no workaround for this particular case.

But that's a whole different problem that wouldn't need solving if I could get the PHP filter working.  I've tried porting it over with coder-updgrade and some manual changes after that (admittedly not up my alley, but at least it's a small module.)   

Unfortunately, the module seems to rely on making changes to the 'filter_format' directory which existed in Drupal 7, but not in Backdrop.  I'm really not a big database guy, but I've done my best to try and find anything similar in Backdrop tables and I can't.  I don't mind workarounds (and that'll be my next post) if it's futile, but I think the workaround is too based off what I've tried.

Surely someone has overcome this?  There's surprisingly few posts and no resolution on them.

Any help very much appreciated, I have to get past this somehow.

Accepted answer

You don't need to do anything with the files "filter.format.xxx.json". Here's what you do (I've verified this).

Begin with your PHP module that you've run through coder_upgrade to Backdropify it.

Comment out or delete function php_enable(). You won't need it. (You can also remove function php_help(), which is now superfluous, but it will be ignored if you leave it in.)

You should now be able to enable the module in Backdrop.

Go to permissions and give the "PHP filter" permission to your super-user (and NOT TO ANYONE ELSE).

Now go to Admin > Configuration > Content Authoring > Text editors and formats > Add text format.

Create a new text format called "PHP filter" and select "PHP evaluator" (plus any other filters needed, like the "Replace tokens" to use the webform tokens) for it. Save configuration. (This will create the new filter config file, so you don't need to worry about that.)

Now you can use this formatter with your PHP code and it should work. Try it out first by creating a Page node with some PHP content.

(I feel a little like I'm explaining how to synthesize nitroglycerine, so let me stress again: be careful with your permissions on who can use this filter, because anyone who can use it can pwn your entire site.)

Most helpful answers

Hi @greenstick,

I suspect the issue you're running into is that in D7, filter formats were stored in the `filter_format` table, whereas in Backdrop, they're stored in a config file, whose name will be something like `filter.format.something.json` (and if you're upgrading from D7, "something" is probably an integer).

So in the D7 module, there's function `php_enable()`, that attempts to tinker with that now-nonexistent table, hence badness.

If that's the issue, I think you can just comment out that code, which is trying to automatically create the text format, and you can just manually create the text format that contains the PHP filter once you've enabled the module.

Does that work?

(Of course, the usual warnings about how dangerous a PHP text filter can be, which is why it was removed from Backdrop.)

BTW, I'd be curious to know a bit more about how this works with webform2pdf, and wondering if adding a hook to webform2pdf would provide a safer/more structured way for you to accomplish what you're after.

Comments

bugfolder's picture

Hi @greenstick,

I suspect the issue you're running into is that in D7, filter formats were stored in the `filter_format` table, whereas in Backdrop, they're stored in a config file, whose name will be something like `filter.format.something.json` (and if you're upgrading from D7, "something" is probably an integer).

So in the D7 module, there's function `php_enable()`, that attempts to tinker with that now-nonexistent table, hence badness.

If that's the issue, I think you can just comment out that code, which is trying to automatically create the text format, and you can just manually create the text format that contains the PHP filter once you've enabled the module.

Does that work?

(Of course, the usual warnings about how dangerous a PHP text filter can be, which is why it was removed from Backdrop.)

BTW, I'd be curious to know a bit more about how this works with webform2pdf, and wondering if adding a hook to webform2pdf would provide a safer/more structured way for you to accomplish what you're after.

Thanks for the quick reply!

I have yet to try your suggestion out but will  shortly, but thought I'd get back promptly too on at least the second part.

In my case, the 'content of the PDF document' in D7 in addition to the usual stuff had the following as well:

 <?php
// Require QR Code Library:
require_once($_SERVER['DOCUMENT_ROOT'] . '/phpqrcode/qrlib.php');

// Set Temporary Directory For QR Images:
$tempDir = file_directory_temp() . '/';

$separator = '";';

$codeContents =
'"pr","' . $submission->data[3][0] . $separator .  
'"cl","' . $submission->data[4][0] . $separator .
'"ds","' . $submission->data[13][0] . $separator .
'"cs","' . $submission->data[24][0] . $separator .
'"tx","' . $submission->data[8][0] . $separator .  
'"fn","' . $submission->data[1][0] . $separator .
'"ln","' . $submission->data[2][0] . $separator .
'"gn","' . $submission->data[5][0] . $separator .
'"db","' . date("dmY", strtotime($submission->data[6][0])) . $separator .
'"hl","' . $submission->data[7][0] . $separator .
'"ho","' . $submission->data[15][0] . $separator .
'"ht","' . $submission->data[9][0] . $separator .
'"lu","' . date("dmY", strtotime($submission->data[10][0])) . $separator .
'"pc","' . $submission->data[11][0] . $separator .  
'"dc","' . date("dmY", strtotime($submission->data[12][0])) . $separator .
'"ps","' . $submission->data[16][0] . $separator .
'"hh","' . $hhistory . $separator .
'"sd","' . format_date($submission->completed, 'custom', 'dmY') . '"';

    // Generate unique filename with md5.
    $fileName = 'qr_'.md5($codeContents).'.png';
    
    $pngAbsoluteFilePath = $tempDir.$fileName;
    $urlRelativeFilePath = $tempDir.$fileName;    
    
    
    // Generate QR Code:
    QRcode::png($codeContents, $pngAbsoluteFilePath, QR_ECLEVEL_L, 10);

echo '<img src="' . $urlRelativeFilePath. '" />';

?>

That would allow me to display a QR code with the phpqrcode library by referencing the now generated file from the temp directory.

There were a couple of other small PHP things in there too - but for me that's the problem I need to overcome.  As this gets built on the fly and there's really no hard coded 'template' underneath it (as far as I can tell) I'm really not sure of a workaround - where else can the PHP go? 

Thus far after moving to backdrop I can usually get around this sort of thing (getting PHP in) with specific node templates and including the code in there, and if I could pull in the submitted fields to some kind of external file I'd do it here too - just doesn't seem to be the way things work.  (Though maybe I'm missing something, wouldn't be the first time!)

bugfolder's picture

Thanks for the explanation. It looks like the shortest way to getting what you want would be the PHP module (shudder), but a cleaner way would be to write a custom module that implements the custom PHP code and inserts it into the HTML generated by the formatted text using an existing hook.

bugfolder's picture

Take a look at how webform2pdf implements hook_tokens() and hook_token_info_alter(). You could probably create a custom token that would generate the QR code in the way you're after.

I'd certainly prefer to do it cleaner, I just have no idea how to go about it to be honest - have never written a module and even getting past that hurdle, I'm unsure as to how I'd go about interacting with that (looking at your tokens suggestion now though thanks, little over my head but might make more sense fresh in the morning.)
I think I see what you're saying though I'm still lost on how I'd actually implement it (for now at least.)

But I can't figure out how to do the (shudder) PHP filter thing either if I went down that road, there are indeed files filter.format.full_html.json, filter.format.plain_text.json and a third in my config directory - but I got lost pretty quick with 'manually create the text format that contains the PHP filter' - just to see what happens I did copy the file under a different name and changed a couple of things in it (and it does show by name when editing content) - but how does that get tied into the php module (if stripping that stuff away gets it working - haven't tried just yet) so it can do it's function php_eval($code) thing?

Thanks for all the help thus far, I'll try out the 'good' way tomorrow but might need to fall back on the filter in the meantime until I can get it sorted. (It's just a localhost effort here at the moment so I'm not terribly worried at least until it goes live, just not a great time to scratch my head for a week!)

Will post back one way or the other tomorrow.  Probably after failing and switching from coffee to beer!

bugfolder's picture

You don't need to do anything with the files "filter.format.xxx.json". Here's what you do (I've verified this).

Begin with your PHP module that you've run through coder_upgrade to Backdropify it.

Comment out or delete function php_enable(). You won't need it. (You can also remove function php_help(), which is now superfluous, but it will be ignored if you leave it in.)

You should now be able to enable the module in Backdrop.

Go to permissions and give the "PHP filter" permission to your super-user (and NOT TO ANYONE ELSE).

Now go to Admin > Configuration > Content Authoring > Text editors and formats > Add text format.

Create a new text format called "PHP filter" and select "PHP evaluator" (plus any other filters needed, like the "Replace tokens" to use the webform tokens) for it. Save configuration. (This will create the new filter config file, so you don't need to worry about that.)

Now you can use this formatter with your PHP code and it should work. Try it out first by creating a Page node with some PHP content.

(I feel a little like I'm explaining how to synthesize nitroglycerine, so let me stress again: be careful with your permissions on who can use this filter, because anyone who can use it can pwn your entire site.)

Perfect!  And thank you so much for the very detailed explanation/walkthrough.  I will still see if I can get away from it taking a module route when I have some more time to learn (if so, maybe you could add as an extension to WF2PDF?), but this is a lifesaver for now for sure.

I don't want to curse myself by saying so, but I've been using the PHP filter with no problems on dozens of sites (in D7) for years.  That said - for others who come across this, as bugfolder said - never never ever give these permissions to other users, it does allow people to run arbitrary code which could do all sorts of bad things to your site and database, and of course watch what you run using it yourself (though that could be said for modules too I imagine.)

Now about that nitroglycerine recipe - was that salted or unsalted butter?

bugfolder's picture

Let me know how it works!

In thinking about how best to accomplish this, I think the clean way would be to create a module that generates the QR code as replacement for token text; that would allow it to be placed in the PDF generated by WF2PDF module without modifying the latter.

As for the nitro recipe, I find that extra-virgin olive oil gives the best results, while throwing in some fresh garlic adds a delightful lingering after-bouquet to the rubble.

I'm not really sure, one thing I'll say from my case is some of the particular fields were taking up a lot of 'space' using their full names, so while the data needed to be as-is, things like "clients name" were changed to "cn" to use a lot less space. 

That might not work for some people, depends on the point of using a QR code I imagine, but it just gets re-mapped over here when it's scanned for my purpose.  (Point being it'd be nice if it was possible to not use the token names in full as an option, you can end up with some real large squares.)  Also, might not want ALL the token replacements in the code for one reason or another.

If that was sorted with a new token ([qrfields] or something) then that'd be awesome.  But it'd be awesome if I drove a monster truck too I suppose, and don't know how to do either.