Extend replacement to CCK fields (beyond teaser and body) - usefull in conjonction with filefield insert
nico059 - October 16, 2009 - 15:21
| Project: | FileField Paths |
| Version: | 6.x-1.x-dev |
| Component: | Code |
| Category: | feature request |
| Priority: | normal |
| Assigned: | Unassigned |
| Status: | closed |
Description
Hi folks,
First congratulation of all your hard work for this filefiled_path.
I would like to suggest this piece of code to extend the replacement of the path beyond teaser and body, when a new file is inserted by "filefield insert" before the save of the node (when the path is still in a temporary location)
Sorry, this is not the good patch format, I still need to configure my SVN etc ... but i think this code is of interest for other drupaler !
In file filefield_paths.module, function filefield_paths_filefield_paths_process_file
<?php
// Finalize files if necessary
if (dirname($file['filepath']['new']) != dirname($file['field']['filepath']) || $file['filename']['new'] != $file['field']['filename']) {
if (filefield_paths_file_move($file)) {
// Fix reference to old paths in Body and Teaser and CCK
$file['filepath']['new'] = str_replace($file['filename']['old'], $file['filename']['new'], $file['filepath']['new']);
$pattern = array(
'regex' => str_replace('/', '\/', file_directory_path()) .'(.*?)'. str_replace('/', '\/', str_replace(file_directory_path(), '', $file['filepath']['old'])),
'regex_enc' => str_replace('/', '\/', drupal_urlencode(file_directory_path())) .'(.*?)'. str_replace('/', '\/', str_replace(drupal_urlencode(file_directory_path()), '', drupal_urlencode($file['filepath']['old']))),
'replace' => file_directory_path() .'$1'. str_replace(file_directory_path(), '', $file['filepath']['new']),
);
// if module cck is activated
if (module_exists('content')) {
// loop through the field of this content type and check if field is set this node
$fields = content_fields(NULL, $node->type);
foreach($fields as $fieldname => $field){
// handle only the field text (perhaps other filed type need this too ?)
if($field['type']=='text' && !empty($node->{$fieldname}[0]['value'])){
// handle multiple values (if no multiple, only one loop with key=0)
foreach($node->{$fieldname} as $key => $value){
// do the preg_replace only if value is set
if(isset($node->{$fieldname}[$key]['value'])){
$tmp = $node->{$fieldname}[$key]['value'];
$tmp = preg_replace('/'. $pattern['regex'] .'/s', $pattern['replace'], $tmp);
$tmp = preg_replace('/'. $pattern['regex_enc'] .'/s', $pattern['replace'], $tmp);
if ($tmp != $node->{$fieldname}[$key]['value']) {
$node->{$fieldname}[$key]['value'] = $tmp;
$update->node = TRUE;
}
}
}
}
}
}
...
?>See below the full function attached. You will see I move the definition of pattern outside the "if (isset($node->body)) { ... "
Regards.

#1
#2
Hi nico59,
I will take a look at this and see what I can do.
I actually have done some work on this particular section over the last few days that I would like to commit, so this code could be perfectly timed.
Cheers,
Deciphered.
#3
A (heavily) modified version of your code has been implemented and seems to work fine. It will be in the next developmental build.
Cheers,
Deciphered.
#4
Committed to DRUPAL-6--1.
#5
Thx Deciphered for your follow up.
I will test dev version asap.
Just a question for the $update->node:
<?phpif (${$field} != $data) {
$data = ${$field};
// Mark node for update.
if ($field == 'body' || $field == 'teaser') {
$update->node = TRUE;
}
}
?>
What I understand is the $update->node is only set to TRUE for the body and teaser, and won't be set to TRUE for the other CCK field. Does the data of the CCK field will be updated anyway to the Database ? I will check that and leave you a feedback here.
Cheers,
Nico
PS: I hope you a good spring time in australia ... here in canada the winter is comming soon ... 3" of snow last week ... brrrr ....
#6
Hi nico059,
$update->nodebeing set toTRUEis only necessary for$node->bodyand$node->teaser, below the code that saves the node as required there is a section that saves CCK data which is triggered on the condition that CCK is installed.Originally I did have a second trigger,
$update->cck(or similar), but if I recall correctly it introduced other issues.Let me know how you go with the testing.
And yes, we're having an ok spring, but honestly I'd prefer the snow :)
Cheers,
Deciphered.
#7
Hi,
I have this error :
warning: Invalid argument supplied for foreach() in D:\xampplite\htdocs\pgvl\sites\all\modules\filefield_paths\filefield_paths.module on line 551.warning: Invalid argument supplied for foreach() in D:\xampplite\htdocs\pgvl\sites\all\modules\filefield_paths\filefield_paths.module on line 551.
... repeating .... (around 20 times)
This occured because in line 549:
<?php$cck = content_fields(NULL, $node->type);
?>
return ALL the CCK field of ALL the content type defined on my drupal site, and not only the CCK field of THE CURRENT content_type.
See the code here, if the first parameter is NULL: http://drupalcontrib.org/api/function/content_fields
A work around could be this one: modifying the line 551 to become:
<?phpif ($field['type'] == 'text' && !empty($node->{$name}[0]['value']) ) {
?>
An issue/solution is opened in content.module: http://drupal.org/node/619106
I think it's legitimate to call content_fields(NULL, "content_type_name") and hopping to get only the content_type_name fileds
Regards,
#8
I have opened a new issue on Filefield_paths: #618958: Invalid argument on CCK fields unrelated to Node type with a suggested patch.
#9
or ... as suggested by markus_petrux: http://drupal.org/node/619106#comment-2209674
<?phpif (module_exists('content')) {
$cck = content_types($node->type);
foreach ($cck['fields'] as $name => $field) {
if ($field['type'] == 'text') {
...
?>
And it works ! tada !
The CCK function to use in this case is content_types (instead of content_fields)
Cheers.
#10
Re-opening issue.
#11
Thanks guys, I should have checked the code a bit later, but I didn't actually witness the error so I just made an assumption.
Committed to DRUPAL-6--1.
#12
The latest change does not follow the suggested code in that the
foreach()is not being applied to$cck['fields']hence what ends up in $name => $field is wrong.#13
Sorry guys,
I've been putting all my time into the Drupal 7 port, so clearly my testing efforts are being neglected. On it properly right now.
Cheers,
Deciphered.
#14
Ok, this time for sure.
Tested, works, not seeing any errors, committed.
Cheers,
Deciphered.
#15
#16
No problemo !
Nice to see filefield_paths with #D7CX !
#17
Glad to hear :)
I had always planned to make it available, and had even ported it a few times already, there was even a Dev build available since Feb, but I didn't want to mark it as #D7CX until tokens made it into core and I had time to do a proper port.
I will likely make the dev build available from the project page within the next week or so, there are a few little issues left, but it does generally work as expected at the moment.
Cheers,
Deciphered.
#18
Automatically closed -- issue fixed for 2 weeks with no activity.