Go to main content

Textpattern CMS support forum

You are not logged in. Register | Login | Help

#1 2014-11-07 23:10:23

ingleslenobel
Member
Registered: 2014-10-16
Posts: 88

txp:php, $variable[blah] and database input

May I ask something dippy – there must be some obvious answer.

If I do:

mysql_query("UPDATE " . $cmtx_mysql_table_prefix . "`pages` SET `modified` = '1413463129'  WHERE `id` = '289'");

this query works

But this query fails, because I think it’s in an array?

mysql_query("UPDATE `" . $cmtx_mysql_table_prefix . "pages` SET `modified` = '" . $variable['pagesaved'] . "' WHERE `identifier` = '" . $variable['pagename'] . "'"); 

What would people suggest to get those values working into that query? $variable[‘blah’] being the global in txp:php

Thank you very much,

-Johan

Last edited by ingleslenobel (2014-11-07 23:27:02)

Offline

#2 2014-11-08 09:33:10

Bloke
Developer
From: Leeds, UK
Registered: 2006-01-29
Posts: 11,250
Website GitHub

Re: txp:php, $variable[blah] and database input

Did you import $variable form the global scope before you tried to use it?

global $variable;
dmp($variable);

will show you if your txp:variables have been brought into your PHP and set to what you expect.

Also, remember to escape your input to minimise the risk of injection attacks:

mysql_query("UPDATE `" . $cmtx_mysql_table_prefix . "pages`
   SET `modified` = '" . doSlash($variable['pagesaved']) .
   "' WHERE `identifier` = '" . doSlash($variable['pagename']) . "'");

You can also maybe look at the core’s safe_update() for simple (non-table join) queries:

safe_update(table_name, set_parameters, where_clause);

so, for example:

safe_update('ingles_pages',
   "`modified` = " . doQuote(doSlash($variable['pagesaved'])),
   "`identifier` = " . doQuote(doSlash($variable['pagename'])));

That call will automatically prefix your table name with any prefix defined during setup too.

EDIT: And if we change the way we interact with the database (as we move to PDO, for example), it’ll shield your code for a little bit. We’ll probably end up deprecating the safe_* calls eventually in lieu of a proper class approach to database interaction, though in the medium term we’ll keep them around and retrofit them with our internal database classes so your code will continue to work without having to change everything when PHP remove the mysql_* calls.

Hope that helps.


The smd plugin menagerie — for when you need one more gribble of power from Textpattern. Bleeding-edge code available on GitHub.

Txp Builders – finely-crafted code, design and Txp

Offline

#3 2014-11-08 14:10:37

ingleslenobel
Member
Registered: 2014-10-16
Posts: 88

Re: txp:php, $variable[blah] and database input

This is the fuller block:

echo "COMMENTS (" . $total . ")</a></div><br break='both'>"; 
global $variable;
$variable['pagesaved'] = '<txp:posted format="%s" />';
$variable['pagename'] = '<txp:custom_field name="comlabel" />';
echo "showme: $variable[pagesaved] | $variable[pagename]";
echo "<br>";
echo "vardumps: ";
var_dump($variable['pagename']);
var_dump($variable['pagesaved']);
dmp($variable);

and this works fine:

 mysql_query("UPDATE " . $cmtx_mysql_table_prefix . "`pages` SET `modified` = '1415400981'  WHERE `id` = '289'");

But I just can’t get anything working passing in pagesaved or pagename. Stumped. example here

Last edited by ingleslenobel (2014-11-08 14:11:37)

Offline

#4 2014-11-08 14:47:22

ingleslenobel
Member
Registered: 2014-10-16
Posts: 88

Re: txp:php, $variable[blah] and database input

even if I try this:

$thepagesaved = '<txp:posted format="%s" />';
echo "test - $thepagesaved";
mysql_query("UPDATE " . $cmtx_mysql_table_prefix . "`pages` SET `modified` = '" . $thepagesaved . "'  WHERE `id` = '289'");

all that goes into the database is “0”. Not the date like I’d expect. Stumped!

As you can see from here , it shows “test – “ and the value fine. But beyond that, nada.

Last edited by ingleslenobel (2014-11-08 14:50:39)

Offline

#5 2014-11-08 15:02:52

ingleslenobel
Member
Registered: 2014-10-16
Posts: 88

Re: txp:php, $variable[blah] and database input

What I don’t get is why, when I do “dmp($thepagesaved);”, I get “<txp:posted format=”%s” />”, not the value. Is this the reason it doesn’t work, it is trying to insert “<txp:posted format=”%s” />” rather than the value?

Offline

#6 2014-11-08 15:26:22

michaelkpate
Moderator
From: Avon Park, FL
Registered: 2004-02-24
Posts: 1,379
Website GitHub Mastodon

Re: txp:php, $variable[blah] and database input

Instead of

$variable['pagesaved'] = '<txp:posted format="%s" />';
$variable['pagename'] = '<txp:custom_field name="comlabel" />';

why not just use:

<txp:variable name="pagesaved" value='<txp:posted format="%s" />' />
<txp:variable name="pagename" value='<txp:custom_field name="comlabel" />' />

somewhere near but outside the php block?

Offline

#7 2014-11-08 15:34:24

ingleslenobel
Member
Registered: 2014-10-16
Posts: 88

Re: txp:php, $variable[blah] and database input

Thanks, let me try that

Offline

#8 2014-11-08 15:51:39

ruud
Developer Emeritus
From: a galaxy far far away
Registered: 2006-06-04
Posts: 5,068
Website

Re: txp:php, $variable[blah] and database input

Instead of

$variable['pagesaved'] = '<txp:posted format="%s" />';
$variable['pagename'] = '<txp:custom_field name="comlabel" />';

you could use:

$variable['pagesaved'] = parse('<txp:posted format="%s" />)';
$variable['pagename'] = parse('<txp:custom_field name="comlabel" />');

or:

$variable['pagesaved'] = posted(array('format' => '%s'));
$variable['pagename'] = custom_field(array('name'' => 'comlabel'));

Offline

#9 2014-11-08 18:10:14

ingleslenobel
Member
Registered: 2014-10-16
Posts: 88

Re: txp:php, $variable[blah] and database input

Amazingly enough, I’ve solved it. Couldn’t have managed without:

 $variable['pagesaved'] = posted(array('format' => '%s'));

None of the about 50 attempts I did to use ‘variable’ worked, in the end I just did:

 $thetimevariable = posted(array('format' => '%s'));

Thank you all very much. A lot of the problem here is probably due to it being 2 completely different scripts and passing values, variables and arrays between them just upset one or the other.

Last edited by ingleslenobel (2014-11-08 18:10:36)

Offline

#10 2014-11-08 21:45:59

Bloke
Developer
From: Leeds, UK
Registered: 2006-01-29
Posts: 11,250
Website GitHub

Re: txp:php, $variable[blah] and database input

ingleslenobel wrote #285607:

A lot of the problem here is probably due to it being 2 completely different scripts and passing values, variables and arrays between them just upset one or the other.

Possibly. But passing things around isn’t normally a problem if everything’s imported into your PHP block.

Although I said earlier that using the core functions for database calls is a good idea, may I just sneak in an addendum based on the feedback between then and now. First, some nuggets of information that you’ve no doubt figured out thanks to Ruud’s post, but I’ll expand on them explicitly here for anyone else:

  1. Textpattern tags are not usually parsed inside <txp:php> blocks.
  2. To successfully parse a tag inside a txp:php block, use parse('<txp:some_tag attrib1="value1" ... />');, though that may be (ever so slightly) slower than other methods due to the overhead of invoking the parser.
  3. Each Textpattern txp: tag has a direct equivalent function name that takes an array of attributes as its first argument — at the moment.

The emphasised statement in that third point cannot be stressed strongly enough. With the situation as it stands in Textpattern 4.5.x, those functions exist. From 4.6.0 onwards they are all deprecated and will be removed in some future release require registration before they can be used. The parser itself is still the same at the moment (though there are plans to expand it one day) so option 2 using parse() will still work under 4.6.0 and higher. But in lieu of the one you’ve chosen, you may consider Michael’s suggestion, or go with the parse() option, which is probably the least likely to change but does have the minor performance overhead compared with setting outside then importing $variable.

If you go with Michael’s suggestion (i.e. banking on the fact that the $variable array remains a global component in Textpattern), set the variables using standard tags outside your PHP block using tags-in-attributes :

<txp:variable name="pagesaved" value='<txp:posted format="%s" />' />

or use the tag’s container, which is slightly cleaner in most cases (with the caveat that any line breaks in your container will be stored inside your variable) :

<txp:variable name="pagesaved"><txp:posted format="%s" /></txp:variable>

Then import $variable into your PHP block using the global keyword and use the values from that array, with key indices matching your variable name.

tl;dr: in order of “least likely to change”, using either a) parse(), or b) setting the values outside your PHP block and importing $variable will mean fewer headaches for you when 4.6.0 and above eventually roll in, compared with relying on the tag-as-a-function approach.


The smd plugin menagerie — for when you need one more gribble of power from Textpattern. Bleeding-edge code available on GitHub.

Txp Builders – finely-crafted code, design and Txp

Offline

#11 2014-11-09 11:37:59

ruud
Developer Emeritus
From: a galaxy far far away
Registered: 2006-06-04
Posts: 5,068
Website

Re: txp:php, $variable[blah] and database input

Bloke wrote #285608:

With the situation as it stands in Textpattern 4.5.x, those functions exist. From 4.6.0 onwards they are all deprecated and will be removed in some future release.

Can you elaborate on this? If taghandlers are no longer functions, then this would affect most if not all plugins as well.

The parser itself is still the same at the moment (though there are plans to expand it one day)

Any chance of making plugins first-class citizens (<smd:magic do="something" />)?

Offline

#12 2014-11-09 18:39:30

Bloke
Developer
From: Leeds, UK
Registered: 2006-01-29
Posts: 11,250
Website GitHub

Re: txp:php, $variable[blah] and database input

ruud wrote #285611:

If taghandlers are no longer functions, then this would affect most if not all plugins as well.

Ahem, reading what I wrote I may have been rather off-base, sorry. Post edited for clarity.

As it stands in 4.6.0 you need to register functions so they work as tags. Once that’s done, you’re OK to use them as a tag. At the moment the taghandler throws a warning (well, a lot of warnings!) to say you need to register them. In some distant realm, if you don’t register them then the parser may just deny access to the functions on security grounds. That’ll stop any-php-function-as-tag access without prior registration, which is a good thing.

From that point forward there are a few options. One is to stick with this whitelist approach to global functions, forcing plugins and core to register tags before they can be used. The other route is to move all the functions to a taghandler class and have the parser use ->invoke() style methods on them. If the former stays in place with everything in the global scope, ingleslenobel’s code will be fine. If, however, things change to something like the latter case, then the code may fail in some distant version.

To be honest I can’t see any real reason to move away from a simple registration / whitelist process as it retains backwards compatibility and enhances security enough. But since my crystal ball is a bit cloudy it’s probably best to err on the side of caution. In that case your parse() suggestion is absolutely the right way to go as it’s the least likely to change long term.

Any chance of making plugins first-class citizens (<smd:magic do="something" />)?

To have a scoped (essentially namespaced?) parser to do this kind of thing would be ace.

Patch anyone? :-)


The smd plugin menagerie — for when you need one more gribble of power from Textpattern. Bleeding-edge code available on GitHub.

Txp Builders – finely-crafted code, design and Txp

Offline

Board footer

Powered by FluxBB