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

    // 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.

Comments

nico059’s picture

deciphered’s picture

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.

deciphered’s picture

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.

deciphered’s picture

Status: Needs review » Fixed

Committed to DRUPAL-6--1.

nico059’s picture

Thx Deciphered for your follow up.

I will test dev version asap.

Just a question for the $update->node:

            if (${$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 ....

deciphered’s picture

Hi nico059,

$update->node being set to TRUE is only necessary for $node->body and $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.

nico059’s picture

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:
$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:
if ($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,

sp3boy’s picture

I have opened a new issue on Filefield_paths: #618958: Invalid argument on CCK fields unrelated to Node type with a suggested patch.

nico059’s picture

or ... as suggested by markus_petrux: http://drupal.org/node/619106#comment-2209674

          if (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.

deciphered’s picture

Status: Fixed » Active

Re-opening issue.

deciphered’s picture

Status: Active » Fixed

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.

sp3boy’s picture

Status: Fixed » Needs work

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.

deciphered’s picture

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.

deciphered’s picture

Ok, this time for sure.

Tested, works, not seeing any errors, committed.

Cheers,
Deciphered.

deciphered’s picture

Status: Needs work » Fixed
nico059’s picture

No problemo !
Nice to see filefield_paths with #D7CX !

deciphered’s picture

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.

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.