Filter according to profile
Amitaibu - October 22, 2007 - 08:07
| Project: | Custom filter |
| Version: | 5.x-1.0 |
| Component: | Documentation |
| Category: | support request |
| Priority: | normal |
| Assigned: | Unassigned |
| Status: | closed |
Description
Hi,
Is it possible to have the following:
* In the profile, I've added a field that user selects his working units CM or Inch.
* I'd like to have a filter that can handle something like [cm=1|inch=2.54]. The filter will need to check the settings from the profile, and act accordingly (i.e. show 1cm, or 2.54'').

#1
Yes, it is possible. You can get the unit being used from table {profile_values}. We need two parameters, fid and uid. uid can be retrieved using global variable $user->uid. fid can be retrieved from table {profile_fields}.
Below is the pattern & replacement code. First you must create a filterset, and create a new filter under that filterset. At line 13, $fieldname should be assigned to field name.
Pattern:
/([0-9]+(\.[0-9]*)?)(mm|cm|inch)/iReplacement (with PHP code):
if (! isset($vars->units)) { // following code will execute once
global $user;
$vars->units = array();
// define the conversion table
$vars->units['conv'] = array(
'mm' => 0.1,
'cm' => 1,
'inch' => 2.54);
// get the field name
$fieldname = 'profile_unit'; // <--------- change this according to your field name
// get field ID from table {profile_fields}
$unitfield = db_fetch_array(
db_query("SELECT fid FROM {profile_fields} WHERE name='%s'",
$fieldname));
// get user preferred unit
$unitsel = db_fetch_array(
db_query("SELECT value FROM {profile_values} WHERE fid=%d and uid=%d",
$unitfield['fid'], $user->uid));
// and assign to $vars->units['unit']
$vars->units['unit'] = $unitsel['value'];
}
// the value is in the first bracket
$value = $matches[1];
// the unit is in the third bracket
$unit = $matches[3];
// Converts all values to cm
$valuecm = $value * $vars->units['conv'][$unit];
// Converts cm to user's preferred unit
$value2 = $valuecm / $vars->units['conv'][$vars->units['unit']];
return $value2 . $vars->units['unit'];
#2
Thanks a lot! I'll check it and report back :)
#3
Silly question, but what is the syntax that I should write?
#4
Ok, seems to be a problem there:
When I type "This is 90cm", I get only "This is" and an error:
warning: Division by zero in C:\wamp\www\drupal\modules\customfilter\customfilter.module(1004) : runtime-created function on line 37.Can't it be because in my profile working units appear as CM and Inch (i.e. case sensitive)?
#5
I think so.
Maybe you should change the line 34-37 into:
// Converts all values to cm$valuecm = $value * $vars->units['conv'][strtolower($unit)];
// Converts cm to user's preferred unit
$value2 = $valuecm / $vars->units['conv'][strtolower($vars->units['unit'])];
to convert all units processed into lowercase.
#6
Dude, what a great module!
Here's my final version, for everybody to enjoy...
Name:
Working unitsPattern (that will except 1inch, 1 inch, 1.5 inch):
/([0-9]+(\.[0-9]*)?)[ ]*(mm|cm|meter|inch|yard)/iReplacement text:
if (! isset($vars->units)) { // following code will execute once
global $user;
$vars->units = array();
// define the conversion table
$vars->units['conv'] = array(
'mm' => 0.1,
'cm' => 1,
'centimeter' => 1,
'meter' => 100,
// We'll make inch 2.5 instead of 2.54, and Yard 91.5 instead of 91.44
'inch' => 2.5,
'yard' => 91.4);
// get the field name
$fieldname = 'profile_working_units'; // <--------- change this according to your field name
// get field ID from table {profile_fields}
$unitfield = db_fetch_array(
db_query("SELECT fid FROM {profile_fields} WHERE name='%s'",
$fieldname));
// get user preferred unit
$unitsel = db_fetch_array(
db_query("SELECT value FROM {profile_values} WHERE fid=%d and uid=%d",
$unitfield['fid'], $user->uid));
switch ($unitsel['value']) {
case 'Centimeter':
$unitsel['value']='cm';
break;
case 'Inch':
$unitsel['value']='inch';
break;
}
// and assign to $vars->units['unit']
$vars->units['unit'] = $unitsel['value'];
}
// the value is in the first bracket
$value = $matches[1];
// the unit is in the third bracket
$unit = $matches[3];
// Converts all values to cm
$valuecm = $value * $vars->units['conv'][strtolower($unit)];
// Converts cm to user's preferred unit
$value2 = $valuecm / $vars->units['conv'][strtolower($vars->units['unit'])];
return $value2 . $vars->units['unit'];
And the PHP code enabled.
Cheers!
#7
One problem, though...
Some users have CM in their profile and some Inch. I'd like the created content to show the values for every user according to their preference.
Is this module supposed/ can do this, or should I hack the theme?
#8
If I don't misunderstand, you want the content displayed like this:
Some title
User's working unit: CM
Some text some text some text some text some text some text some text some text some text some text some text some text some text some text some text some text some text some text some text some text some text some text some text some text
We can use ^ to insert the text we want at the top. ^ matches the beginning of the string. So you can create a new filter with this configuration:
Pattern:
/(^)/Replacement:
return "<div class=\"workingunit\">User's working unit: {$vars->units['unit']}</div>";with PHP Code checked.
Create this new filter under the same filterset you're working on, and make sure to set it's weight more than Working units filter, since $vars->units won't be recognized before Working units filter executed.
But I think it would be nicer if you put this working unit information in a block.
#9
I actaully mean something a bit different.
Title: hello world
body:
Some text some text some text 1 Inch some text some text
Now, I'd like the users who have CM defined in their profile to see the text like this:
body:
Some text some text some text 2.54 cm some text some text.
#10
Oh, I'm sorry to misunderstand.
I'm sorry again to say that it is not possible (as long as I know) to do that only using this module. Since a filter will be executed once after we submit the content, we cannot change the content every time the content displayed. And since the current user's settings could affect a content only if the filter executed again, then there is no possible way to do that.
But I think we can get this effect by 2 way:
I'm trying each of this ways. I'll report you if any of these works.
#11
Oh man, thank you so much for your help! waiting to see your results..
#12
Not a developer, but I'm thinking maybe it's possible to use your filter to add for example
<div class="working units>, that later will be replaced with to correct working units.#13
I think we can't use
<div>s nor javascripts, because we need to get $user->uid to know which user is being logged, and we can only do this on the server. The PHP filter solution does work, because it will be executed on the server. I attach the sample working units filter (as plain text file).For this filter to work, you need to turn on PHP Filter in the input format, and make sure it weights more than working units filter, so the PHP script produced could be executed.
The filter works like this:
The customfilter module lacks the function to turn off cache, so that filters will run only when a content submitted. If only this module could turn cache off for particular filterset, then the code you submit on #6 will work as you wish. I'm working on the patch version. Thanks for your question, it really helps me to improve this module.
#14
Sound interseting. One problem, though, is probably security - allowing user to use PHP. You think any posibble way not to use PHP filter for that?
#15
Yes, it is very vulnerable, unless we can create a filter that strips any
<?php ... ?>before our filter executed. I have added option 'cache' in the filterset edit page. The development release should be available soon (within 12 hours - the tarball created every 12 hours). You can try it when available. Using this fixed module, you don't need PHP filter. I've tried your code #6 with cache turned off, and it worked. Note that you should refresh the Input Format for the filter work properly (by saving the configuration again).#16
Ari,
I've imported configuration from #13, but something seems to be written wrong there. Checkout the snapshot - all text is replaced with
1, 'mm' => 0.1, 'cm' => 1, 'm' => 100, 'inch' => 2.5, 'yard' => 91.4, );$unit_aliases = array('cm' => 'centimeter', 'mm' => 'milimeter', 'm' => 'meter', );$unitsel = db_fetch_array( db_query("SELECT value FROM {profile_values} WHERE fid=%d and uid=%d", 1, $user->uid)); $unit_unit = strtolower($unitsel['value']);$aliaskey = array_search($unit_unit, $unit_aliases); if ($aliaskey) $unit_unit = $aliaskey;$unit_precision = 2; ?>#17
Oh, it seems that the PHP evaluator wasn't executed. Please check the:
#18
It works great! but the fact that I've enabled PHP evaluator doesn't mean that there is a security threat? How can I make sure users doesn't use PHP on my site?
#19
You can define a new filter that will flush all
<?php ?>. This filter must be executed first, because we don't want any php code get into PHP evaluator.Filterset: UnPHP
Filter: Strip PHP code
Pattern:
/\<\?php(.*?)\?\>/sReplacement: <code type="php">$1</code>
And you should rearrange the input format in this order:
So that any PHP from users cannot reach PHP evaluator, while PHP produced by Working Units can.
#20
What will happen if user enters
<? php <?php print ('hello'); ?> ?>- does this replace it properly?#21
No, that would be converted into
<code><?php print ('hello');< /code> ?>But I think that's ok, that broken code wouldn't be executed. I think you'd better use the cache option (#15) instead of PHP filter.
#22
Didn't understand this part
p.s. welcome back :)
#23
CustomFilter 5.x-1.2 supports cache option in filterset edit operation. When Drupal saves a content, it can be cached, so that any filter applied to the input only calculated once and then the result cached. Or, we can turn off cache, so that any filter applied to the input will be calculated every time the content viewed.
For working unit case, we can turn off this option, because every unit written should be calculated every time the content viewed. If you're going to use this method, then you can just use your filter in #6, and turn off cache option in the filterset settings.
#24
i am setting the report as fixed because it got an answer.
#25
#26
Automatically closed -- issue fixed for 2 weeks with no activity.