WordPress: Pass variables by reference with apply_filter

WordPress has this great filtering system which allows you to write plugins. Yesterday, I was writing a plugin that has the ability for other plugins to change it's behaviour.

For the particular functionality, it would be very nice to use two parameters, which should both be changable.

Standard PHP

In standard PHP, you could do:

function doit($in, &$var2){
    $var2=true;
    return $in+1;
}
 
$changed=false;
echo doit(1,$changed);
echo $changed;

Pass by reference: Not working with WordPress

The WordPress apply_filter and add_filter functions do not allow variable passing by reference. Therefore, the following code will not work.

function doit($in, &$var2){
    $var2=true;
    return $in+1;
}
 
add_filter('myfilter','doit',10,2);
$changed=false;
echo apply_filters('myfilter',1,$changed);
echo $changed;

Dirty solution

You could use $GLOBALS to overcome this problem. I would not recommend this method, as it's not flexible, not safe to re-use and requires the function and the main code to be synchronized.

function doit($in){
    global $changed;
    $changed=true;
    return $in+1;
}
 
add_filter('myfilter','doit');
$changed=false;
echo apply_filters('myfilter',1);
echo $changed;

The good solution

The correct solution to this problem, is to combine all variabled in one array, and use this array as the first variable.

Example 1: For a few parameters

function doit($in){
    list($in,$var2)=$in;
    $var2=true;
    return array($in,$var);
}
 
add_filter('myfilter','doit');
$changed=false;
list($in,$changed)=apply_filters('myfilter',array(1,$changed));
echo $in;
echo $changed;

Example 2: For more complex situations

function doit($in){
    $in['changed']=true;
    $in['in']+=1;
    return $in;
}
 
add_filter('myfilter','doit');
$changed=false;
$in=1;
extract(  apply_filters('myfilter',compact('in','changed'))  );
echo $in;
echo $changed;

This last method may impose a security risk if you use third party plugins.

© GeekLabInfo WordPress: Pass variables by reference with apply_filter is a post from GeekLab.info. You are free to copy materials from GeekLab.info, but you are required to link back to https://www.geeklab.info

1 Star2 Stars3 Stars4 Stars5 Stars (7 votes, average: 3.71 out of 5)
Loading...

WordPress spam filtering: improved.

On this WordPress blog, I'm running the WP Hashcash plugin to prevent spam. Recently, I've seen a lot more spam, I guess spambots now recognise WPHC encryption.

WPHC encryption could be upgraded to withstand spam again. But new bots will break new encryption. The biggest problem is that all blogs using WPHC use the same javascript to decode the key. If only you could be a liiiiittle different from other blogs, standard bots wouldn't have a chance.

My solution is to include a few filters in WPHC. This allows for weblog owners to write a tiny plugin to have slightly different antispam than other weblogs. For instance, at this moment, my extension is as simple as:

<?php
/*
Plugin Name: WPHC Extension
Plugin URI: https://www.geeklab.info/2010/04/wordpress-spam-filtering/
Description:
Author: GeekLab.info
Version: 1.0
Author URI: https://www.geeklab.info
License: GPL
*/
function wphc_jskey_ext($js){
for($i = 0; $i < count($js); $i++)
$js[$i]--;
return $js;
}
function wphc_getjs_ext($in){
return preg_replace(';//WPHC2;','wphc_data[i]=wphc_data[i]+1;',$in);
}
add_filter('wphc_jskey', 'wphc_jskey_ext');
add_filter('wphc_getjs', 'wphc_getjs_ext');
?>

You may use substraction, addition, xor, byte-swapping or any other method you like to improve security. The security is not so much what is done to the key, but that the routine is slightly different from other blogs.

Changes to WP Hashcash required for this to work:
Patch file (only changes)
Whole file

© GeekLabInfo WordPress spam filtering: improved. is a post from GeekLab.info. You are free to copy materials from GeekLab.info, but you are required to link back to https://www.geeklab.info

1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading...

Magento and safe mode

The e-commerce application magento, for some reason, expects to have a lot of permissions on every server. One thing I stumbled upon when trying to install magento, was the creation of /tmp/magento/var.

Since /tmp could be shared between all users, this may not be the safest way. That's why my servers don't allow access to /tmp, but have a personal /tmp-style directory instead.

I got the error:
[Thu Feb 04 21:24:21 2010] [error] [client 1.2.3.4] PHP Warning: file_exists() [function.file-exists]: open_basedir restriction in effect. File(/tmp/magento/var) is not within the allowed path(s): (/blah/blah/website.com:/usr/share/pear:/var/www/error) in /blah/blah/website.com/app/code/core/Mage/Core/Model/Config/Options.php on line 214

The fix is very, very easy. But since I couldn't find anyone else posting the exact fix, I thought I'd do it.

in app/code/core/Mage/Core/Model/Config/Options.php on line 137, you find:
public function getSysTmpDir()
{
return sys_get_temp_dir();
}

Change it to:
public function getSysTmpDir()
{
return $_SERVER['DOCUMENT_ROOT'].'/your_secret_tmp_dir/';
}

© GeekLabInfo Magento and safe mode is a post from GeekLab.info. You are free to copy materials from GeekLab.info, but you are required to link back to https://www.geeklab.info

1 Star2 Stars3 Stars4 Stars5 Stars (2 votes, average: 3.00 out of 5)
Loading...