I don't know whether this is a problem with your (outstanding) module or whether it is something else on my page causing a conflict. I recently added an ajax element to my node form page (which contains a number of formatter-selector autocomplete/nodereference fields. Anyway, once I submit, process and return results (loading them into an external-sourced iframe on the page), anytime I try to reference a node in one of the fields using field-level (not global-level) formatter selector options it triggers an "An HTTP 500 error occurred" alert popup, and apache records this error:

PHP Fatal error: Unsupported operand types in ../aef_formatter_selector/aef_formatter_selector.module on line 613

Any idea?

thanks

Comments

dellis’s picture

hmm... guessing it has to do with the $_POST value changing from the time the form is loaded to the time the formatter selector widget is working on it...
lines 610-613:

  $form += array(
    '#post' => $_POST,
    '#programmed' => FALSE,
  );

Although I am not sure how to solve the problem... the $_POST data that I generate isn't related to drupal.. is there a way to reset this (or are you storing all of the previews in $_POST?)

update: hmmm... You use the same function in aef_image--that one has a descriptor: "// Build the new form against the incoming $_POST values so that we can render the new element."

I wonder whether, since I'm pushing my $_POST data into an iframe within a dialog box, there might be a way to differentiate between my $_POST and the formatter_selector's $_POST... or whether there is another way to recover the $form_state values to rebuild the drupal $_POST data...?

dellis’s picture

Would it be possible to substitute $form_state['values'] for $_POST?

dellis’s picture

Title: php fatal error: unsupported operand types » $_POST vs. $form_state values issue
dellis’s picture

Title: $_POST vs. $form_state values issue » PHP Fatal error: Unsupported operand types
dellis’s picture

This is a print_r of my $form values for a nodereference/aef_formatter_selector-enabled field taken during the autocomplete formatter lookup function... is this right? It seems odd that you are storing the actual text string in the nid element instead of just the nid "3970"...

[field_main_left_top] => Array
(
 [0] => Array
                (
                    [nid] => Array
                        (
                            [nid] => Aged 9,000 Years, Ancient Beer Finally Hits Stores [nid:3970]
                        )

                    [formatter] => Array
                        (
                            [formatter] => custom_formatters_image_wrapped_text_sidebar
                        )

                    [_weight] => 1
                )

)

I'm still at a loss... basically, if I load my "Edition" node form, I can use your aef_selector autocomplete widgets without issue. But as soon as I use AJAX to add a new node to the database in a modal (iframe) box, any attempt to use your aef_selector autocomplete widgets fails.

It still seems like something is missing that you are relying on, but I haven't got a clue as to what it is. Absolutely any suggestions for what to try/do next would be hugely appreciated.

Thanks

ndeschildre’s picture

Hello,

The error comes because in:

  $form += array(
    '#post' => $_POST,
    '#programmed' => FALSE,
  );

$form is empty, meaning

$form = form_get_cache($form_build_id, $form_state);

has failed. This is surprising since this part is based on the CCK AHAH behavior (CCK updating itself in AJAX, for example when you upload an image with an imagefield).
That is something I would like you to test: In the testcase where the Formatter Selector is failing (because trying to update itself in AJAX), I would like you to test an imagefield upload which will also update itself in AJAX.

Concerning

[field_main_left_top] => Array
(
       [0] => Array
                (
                    [nid] => Array
                        (
                            [nid] => Aged 9,000 Years, Ancient Beer Finally Hits Stores [nid:3970]
                        )

                    [formatter] => Array
                        (
                            [formatter] => custom_formatters_image_wrapped_text_sidebar
                        )

                    [_weight] => 1
                )

)

,
this is normal, nodereference is processing [nid][nid] = title [nid:nid] in their validate function, and replace it by [nid] = nid. You are too early to see it.

Meanwhile, I'll try to reproduce that.

Cheers,
Nicolas

dellis’s picture

I am trying to narrow down the issue--seems like I'm learning a little bit more at each step. I've been making extensive use of watchdog() error reporting statements--inserting a ton of them into aef_formatter_selector.module trying to find the exact issue that I'm having. I've triggered these messages in parallel for your widget without my "add a node from an iframe code", and then also with my "add a node from an iframe" code.

The function where I'm seeing the problem (aef_formatter_selector_get_formatters) is full of these alerts:
1) placed at the beginning of the function with a print_r($_POST) value: Looks OK in both
2) place just after the $form_state = array('submitted' => FALSE): Looks the SAME in both
3) placed just after the $form_build_id variable is given the value of $_POST['form_build_id']: Looks OK in both
4) placed just after $form = form_get_cache($form_build_id, $form_state): Looks OK in yours, in mine the message value (print_r($form)) is empty...
5) placed just after the $form += array('#post' => $_POST, '#programmed' => FALSE,): Looks OK in yours, in mine the alert was never triggered--no watchdog command was issued
6) placed just after $form = form_builder($_POST['form_id'], $form, $form_state): Looks OK in yours, mine never triggers the alert

So it looks like the form_get_cache function is not generating the results I need AFTER I've added a custom node within an external-sourced iFrame modal above the original node form.

ndeschildre’s picture

Hey,

I have just tried to use formatter selector on an external iframe (via the module AEF Embedded Edit), works great here.

I think it would help me if you could precise your usecase. What exactly is this custom node in an external sourced iframe, how it is placed ?
Maybe a few screenshot may help?

Cheers,
Nicolas

dellis’s picture

Interesting, I added an uberimage field to that form... it works by default, but as soon as I try to add a node through my own ajax, then try uberimage again it gives the same error alert--my guess is that it is doing the same thing. I'll cut some screenshots for you now.

Thank you for your help!

ndeschildre’s picture

And also please add the javascript code of your own AJAX, and the corresponding PHP code. Seems this is what is messing things.

ndeschildre’s picture

Oh, I just tilted.

Could you desactivate your Drupal page cache (set to 0mn) in admin/settings/performance, and try again?
(If it happen to fix things, you can look at [searching for the real address], otherwise don't bother, it's a tricky Drupal issue)

dellis’s picture

mmm... no luck with turning off page cache... still the error...

Okay, so I've posted a video of the user-side of things to help explain what I'm doing: http://vimeo.com/13517842 (it isn't finished converting yet)

Then... here is the code:

The "Search content from NPR.org" page is the external php file loaded into an external-sourced iFrame, the js on that page that starts the problem is:

$(".clicker").live('click', function() {
    $(this).after('<div id="dje-npr-api"><img src="http://myurl.org/sites/default/files/admin/loader.gif" style="width:20px; height:auto; margin:0 auto; padding-top:20px;"/></div>');
    var nprStoryId = $(this).parent().attr('id');
    var v;
      
 $.getJSON(
  'http://api.npr.org/query?callback=?',
  {
    apiKey: 'xxxxxxxxxxxxxxxxxxx',
    numResults: 1,
    output: 'JSON',
    id: nprStoryId
  },
  function( data ) {
    if ( data && data.list ) {
      $.each( data.list.story, function(i,v) {
        $.ajax({  
          type: "POST",  
          url: "http://dev.myurl.org/ypm_npr_item_add_json",
          data: v,
          cache: true,
          async: false,
          success: function(html){
            $('#'+nprStoryId).find('.clicker').html('added').css({backgroundColor:'lightblue'});
            $('#dje-npr-api').remove();
            $(".npr-api-results").html(html);
          },
          error: function(){
            $('.npr-api-results').html('Failed to Add the Record.');
          }
        });   
      
      });
    }
  }
 );
 return true;   
});
ndeschildre’s picture

Thanks for the data. Unfortunately, I'm not seeing the video!

dellis’s picture

The php was long, so I figured I'd separate it out (I'm sorry about this--there is a lot of stuff going on, but basically I'm just creating a few different nodes and relating them to eachother). From the function that is called by: http://dev.myurl.org/ypm_npr_item_add_json (the path referenced in the js):



function ypm_npr_item_add() {
  // Partner Variables from POST
  $org_Abbr = $_POST['organization'][0]['orgAbbr'];
  $org_URL = $_POST['organization'][0]['website']['$text'];
  // partner node
  // add partner  node if the partner organization from v.organization[0].orgAbbr.$text <> a partner already in the db
  if(!empty($org_Abbr)){
  $s_part = "SELECT * FROM node n WHERE n.title LIKE '%s'";
  $r_part = db_query($s_part, $org_Abbr);  // 'PBS' must come from organization orgAbbr
  $partnernid = '';
  while($partner = db_fetch_array($r_part)) {
    $partner = node_load($partner['nid']);
  // print 'this partner already exists: '. $partner->title;
    $partnernid = $partner->nid;
   }
  if($partnernid == ''){
  // print 'added new partner';
    $partnode = new stdClass();
    $partnode->is_new=1;
    $partnode->title = $org_Abbr;  // will be v.title.$text
    $partnode->type = "partner";
    $partnode->uid = 1;
    $partnode->status = 1;
    $partnode->comment = 0;
    $partnode->created = time();
    $partnode->changed = time();
  
    // add partner CCK fields...
     $partnode->field_partner_edited[0]['value'] = 'Automatic';
     $partnode->field_ypm_menu_external_website[0]['url'] = $org_URL; // v.organization[0].website.$text
     
  node_save($partnode);
  $partnernid = $partnode->nid;
  }
  } else {
    $org_Abbr = 'NPR';
    $s_part = "SELECT * FROM node n WHERE n.title LIKE '%s'";
    $r_part = db_query($s_part, $org_Abbr);  // 'PBS' must come from organization orgAbbr
    $partnernid = '';
    while($partner = db_fetch_array($r_part)) {
      $partner = node_load($partner['nid']);
      $partnernid = $partner->nid;
   }
  }

  // end partner node
  
  // Person Profile Variables from POST
  $pp_name = $_POST['byline'][0]['name']['$text'];
  $pp_URL = $_POST['byline'][0]['link'][0]['$text'];
  if(empty($pp_name)) {
    $pp_name = 'NPR Contributor';
  }
  // add if <> exist already (matching byline from npr with person titles in the db)
 // person profile node
 $s_part = "SELECT * FROM node n WHERE n.title LIKE '%s'";
  $r_part = db_query($s_part, $pp_name);  // 'Person name' must come from v.byline[0].name.$text
  $personnid = '';
  while($person = db_fetch_array($r_part)) {
    $person = node_load($person['nid']);
  // print 'this person already exists: '. $person->nid;
   $personnid = $person->nid;
   continue;
   }
  if($personnid == ''){
 // print 'added new person'; 
  $pnode = new stdClass();
    $pnode->is_new=1;
    $pnode->title = $pp_name;  // will be v.title.$text
    $pnode->type = "person_profile";
    $pnode->uid = 1;
    $pnode->status = 1;
    $pnode->comment = 0;
    $pnode->created = time();
    $pnode->changed = time();
    $pnode->field_person_organization[0]['value'] = $org_Abbr;
    $pnode->field_person_website[0]['url'] = $pp_URL;
    $pnode->field_partner_association[0][nid] = $partnernid; 
    node_save($pnode);
    $personnid = $pnode->nid;  
   }

 // end person profile node
  
 // audio node = $anode
   $page_title = $_POST['title']['$text'];
   // Audio Variables from POST
   $audio_mp3 = $_POST['audio'][0]['format']['mp3']['$text'];
   // $pp_URL = $_POST['byline'][0]['link'][0]['$text'];
   $audio_file = basename($audio_mp3);
   $audio_ext = substr($audio_file, strrpos($audio_file, '.') + 1);
   $audio_ext = substr($audio_ext, 0, 3);
   if($audio_ext == 'mp3') {
 
    $anode = new stdClass();
    $anode->is_new=1;
    $anode->title = $page_title;  // will be v.audio[0].title.$text (if it exists, otherwise it could be v.slug.$text)
    $anode->type = "audio_asset";
    $anode->uid = 1;
    $anode->status = 1;
    $anode->comment = 0;
    $anode->created = time();
    $anode->changed = time();
    // AUDIO NODE CCK
    
    // field_audio_asset -- I need to set the provider to "npr" and modify the page template to account for the larger npr player if the audio asset's reference is pointing to an npr file
    $anode->field_audio_asset[0]['embed'] = $audio_mp3;  // v.audio[0].format.mp3.$text;
    $anode->field_audio_asset[0]['value'] = $audio_mp3;  
    $anode->field_audio_asset[0]['provider'] = 'npr';
    $anode->field_audio_asset[0]['data']['emaudio_custom_url_data_version'] = 1;
    $anode->field_audio_asset[0]['data']['url'] = $audio_mp3;
    $anode->field_audio_credit[0][nid] = $personnid;
    node_save($anode);
    $audionid = $anode->nid;
   } elseif($audio_ext == 'm3u') {
 
 
     // pulling .mp3 file out of .m3u link
     $mp3_link = '!http://.+\.(?:mp3)!Ui';
     $string = file_get_contents($_POST['audio'][0]['format']['mp3']['$text']);
     $matches = array();
     preg_match_all($mp3_link, $string, $matches);
     $has_audio_mp3 = $matches[0][0];
     
 
 
    $anode = new stdClass();
    $anode->is_new=1;
    $anode->title = $page_title;  // will be v.audio[0].title.$text (if it exists, otherwise it could be v.slug.$text)
    $anode->type = "audio_asset";
    $anode->uid = 1;
    $anode->status = 1;
    $anode->comment = 0;
    $anode->created = time();
    $anode->changed = time();
    // AUDIO NODE CCK
    
    // field_audio_asset -- I need to set the provider to "npr" and modify the page template to account for the larger npr player if the audio asset's reference is pointing to an npr file
    $anode->field_audio_asset[0]['embed'] = $has_audio_mp3;  // v.audio[0].format.mp3.$text;
    $anode->field_audio_asset[0]['value'] = $has_audio_mp3;  
    $anode->field_audio_asset[0]['provider'] = 'npr';
    $anode->field_audio_asset[0]['data']['emaudio_custom_url_data_version'] = 1;
    $anode->field_audio_asset[0]['data']['url'] = $has_audio_mp3;
    $anode->field_audio_credit[0][nid] = $personnid;
    node_save($anode);
    $audionid = $anode->nid;
   } else {
    $audionid = '';
   }
   // end audio node
    
   // adding main image file
   // Image Variables from POST
  $image_src = $_POST['image'][0]['src'];
   if(!empty($image_src)) {
 
// echo '<br /><h2>FILE INFORMATION</h2><br />';
    $img = $image_src;
    $dest = 'sites/default/files/';
    $name = basename($img);
    $name = substr($name, 0, stripos($name, "?"));
    $stem = substr($name, 0, stripos($name, "."));
    $name_rand = $stem . rand(1,100);
    $ext = substr($name, strrpos($name, '.') + 1);
    $name = $name_rand . '.' . $ext;
    $trimname = $name;
    
   // print '<br />'. $trimname;
    $remotefile = file_get_contents($img);
    $localfile = file_put_contents($dest.'/'.$trimname, $remotefile);
    
    $file_drupal_path =  $trimname;
   // $imagesize = getimagesize($dest.'/'. $file_drupal_path);
   // $file->filemime = $imagesize['mime'];
    $file = new stdClass();
    
    if($ext == 'jpg'){
      $file->filemime = 'image/jpeg';
    }
    if($ext == 'gif'){
      $file->filemime = 'image/gif';
    }
    if($ext == 'png'){
      $file->filemime = 'image/gif';
    } 
    
    $file->filename = basename($file_drupal_path);
    $file->filepath = $dest . $file_drupal_path;
    $file->filesize = filesize($dest.'/'. $file_drupal_path);
    $file->uid = 1;
    $file->status = FILE_STATUS_PERMANENT;
    $file->timestamp = time();
    drupal_write_record('files', $file);
    $file->fid = db_result(db_query("SELECT fid FROM {files} WHERE filepath = '%s'", $file->filepath));
  

  $mainimagefile = 'http://dev.myurl.org/' .$file->filepath;
  list($imgwidth, $imgheight, $imgtype, $imgattr) = getimagesize($mainimagefile);
  //print $imgwidth;
  $filenid = $file->fid;

   } else {
    $filenid = '';
   }

 // end adding main image file
    
    // begin adding sidebar image
     // Image Variables from POST
  $image_side_src = $_POST['image'][1]['src'];
   if(!empty($image_side_src)) {
 
    $img = $image_side_src;
    $dest = 'sites/default/files/';
    $name = basename($img);
    $name = substr($name, 0, stripos($name, "?"));
    $stem = substr($name, 0, stripos($name, "."));
    $name_rand = $stem . rand(1,100);
    $ext = substr($name, strrpos($name, '.') + 1);
    $name = $name_rand . '.' . $ext;
    $trimname = $name;
    
    $remotefile = file_get_contents($img);
    $localfile = file_put_contents($dest.'/'.$trimname, $remotefile);
    
    $file2->filemime = "image/".$ext;
    $file_drupal_path =  $trimname;
    $file2 = new stdClass();
    
    if($ext == 'jpg'){
      $file2->filemime = 'image/jpeg';
    }
    if($ext == 'gif'){
      $file2->filemime = 'image/gif';
    }
    if($ext == 'png'){
      $file2->filemime = 'image/gif';
    }  
    
    $file2->filename = basename($file_drupal_path);
    $file2->filepath = $dest . $file_drupal_path;
    $file2->filesize = filesize($dest.'/'. $file_drupal_path);
    $file2->uid = 1;
    $file2->status = FILE_STATUS_PERMANENT;
    $file2->timestamp = time();
    drupal_write_record('files', $file2);
    $file2->fid = db_result(db_query("SELECT fid FROM {files} WHERE filepath = '%s'", $file2->filepath));

    $filenid_side = $file2->fid;
    } else {
    $filenid_side = '';
    }
    
    // end adding sidebar image
    
    
    // Page Variables from POST
    //$page_title = $_POST['title']['$text'];  // also exists under audio node
    $page_img_title = $_POST['image'][0]['title']['$text'];
    $page_img_caption = $_POST['image'][0]['caption']['$text'];
    $page_img_credits = $_POST['image'][0]['producer']['$text'];   
    $page_img_side_title = $_POST['image'][1]['title']['$text'];
    $page_img_side_caption = $_POST['image'][1]['caption']['$text'];
    $page_img_side_credits = $_POST['image'][1]['producer']['$text'];
    $page_air_date = substr($_POST['show'][0]['showDate']['$text'], 0, 16);
    $npr_show = '';
    $page_pullquote = $_POST['pullQuote'][0]['text']['$text'];
    $page_pullquote_source = $_POST['pullQuote'][0]['person']['$text'];
  
  if(!empty($_POST['image'][0]['provider']['$text'])){
    $page_img_credits .= ' - '. $_POST['image'][0]['provider']['$text'];
  }
    $page_subheading = $_POST['miniTeaser']['$text'];
    $page_teaser = $_POST['teaser']['$text'];
  if($org_Abbr == 'NPR'){
    if(!empty($_POST['show'][0]['program']['$text'])){
      $npr_show = $_POST['show'][0]['program']['$text'];
      $page_body = '<div class="from-npr" style="width:460px; text-transform:uppercase; font-size:.8em; clear;both; font-style:italic; text-align:right;">From '. $npr_show .' on <a href="'. $_POST['link'][0]['$text'] . '" target="_blank"><img title="NPR" src="http://www.myurl.org/sites/default/files/icon_npr_big.gif" /></a></div>';
    } else {
      $page_body = '<div class="from-npr" style="width:460px; text-transform:uppercase; font-size:.8em; clear;both; font-style:italic; text-align:right;">From <a href="'. $_POST['link'][0]['$text'] . '" target="_blank"><img title="NPR" src="http://www.myurl.org/sites/default/files/icon_npr_big.gif" /></a></div>';          
    }
  
  }
  if(!empty($npr_show)){
  if(!empty($page_air_date)) {
    $page_related_link = '<div class="npr-broadcast-information" style="padding:0px 0px 18px 0px; font-weight:bold;">Aired during ' . $npr_show . ' on '. $page_air_date . '</div>';
  }
  }
  if(!empty($_POST['relatedLink'][0]['caption']['$text'])) {
    $page_related_link .= '<div class="npr-related-links"><div class="npr-related-links-header" style="padding-bottom:6px;">Also from <img title="NPR" src="http://www.myurl.org/sites/default/files/icon_npr_small.jpg"/></div><ul>';
    
    foreach($_POST['relatedLink'] as $rlink) {
       $page_related_link .= '<li><a href="' .$rlink['link'][0]['$text'] . '" target="_blank">'. $rlink['caption']['$text'] . '</a></li>'; 
    }  
    
    $page_related_link .= '</ul></div>';
  }
  
  foreach($_POST['textWithHtml']['paragraph'] as $body_para) {
    $page_body .= '<p>'. $body_para['$text'] . '</p>';
  }
  $page_body .= '<p><a href="'. $_POST['link'][0]['$text'] . '" target="_blank">Link to Original Article on NPR.org</a></p>';
  //print 'form id: '. $_POST['form_build_id'];
 // page node = $node
  $node = new stdClass();
    $node->is_new=1;
    $node->title = $page_title;
    $node->body = $page_body;
    $node->type = "page";
    $node->uid = 1;
    $node->teaser = $page_teaser;
    $node->filter = 1;
    $node->format = 3;
    $node->status = 1;
    $node->comment = 2;
    $node->created = time();
    $node->changed = time();
   $aefdata = array(
      'ypm_page_feature' => array (
        'x'=>0,
        'y'=>0,
        'width' => $imgwidth,
        'height' => $imgheight
      )
    );
  $result = image_get_info('http://dev.myurl.org/'.$mainimagefile);
   //print 'file: '. $mainimagefile . '<br />';
   $s_aefdata = (binary)serialize($aefdata);
   
   // field_page_main_image
   $node->field_page_main_image[0]['nid'] = 0;
   $node->field_page_main_image[0]['fid'] = $filenid;
   $node->field_page_main_image[0]['data'] = $s_aefdata;
  // $node->field_page_main_image[0]['data'] = NULL;
   $node->field_page_main_image[0]['title'] = $page_img_title;
   $node->field_page_main_image[0]['legend'] = $page_img_caption;
   $node->field_page_main_image[0]['credits'] = $page_img_credits;
    
   // field_page_related_content_image
   $node->field_page_related_content_image[0]['nid'] = $filenid_side;
   $node->field_page_related_content_image[0]['fid'] = $filenid_side;
   $node->field_page_related_content_image[0]['data'] = NULL;
   $node->field_page_related_content_image[0]['title'] = $page_img_side_title;
   $node->field_page_related_content_image[0]['legend'] = $page_img_side_caption;
   $node->field_page_related_content_image[0]['credits'] = $page_img_side_credits;
   
   // field_page_subheading
   $node->field_page_subheading[0]['value'] = $page_subheading;
   $node->field_page_subheading[0]['format'] = 1;
   
   // field_page_status
   $node->field_page_status[0][value] = 'Current';
     
   // field_page_publish_date
   $node->field_page_publish_date[0]['value'] = date('Y-m-d\Tg:i:s', time());
   $node->field_page_publish_date[0]['timezone'] = 'America/New_York';
   $node->field_page_publish_date[0]['timezone_db'] = 'UTC';
   $node->field_page_publish_date[0]['date_type'] = 'date';

   // field_page_author
   $node->field_page_author[0][nid] = $personnid;
   
   // field_page_audio_reference
   $node->field_audio_reference[0]['nid'] = $audionid;
   
   // field_page_partner_association
   $node->field_page_partner_association[0]['value'] = $partnernid;
   
   // field_page_related_content_blurb
   $node->field_page_related_content_blurb[0]['value'] = $page_related_link;
   $node->field_page_related_content_blurb[0]['format'] = 3;
   
   // field_page_pull_quote
   if(!empty($page_pullquote)) {
   $node->field_page_pull_quote[0]['value'] = $page_pullquote;
   if(!empty($page_pullquote_source)) {
    $node->field_pull_quote_attribution[0]['value'] = $page_pullquote_source;
   }
   
   }   
   // field_page_channel_reference -- will likely grab a comma delineated list from the url querystring--as driven by the drop-down list of options, then format the array into php
   $node->field_page_channel_reference[0][nid] = 0; // loop through as many URL params as there are...
   node_save($node);
 
  // End Page Node
}

dellis’s picture

Sorry about that, the video has 26 minutes left before it is available: http://vimeo.com/13517842
Thanks again.

ndeschildre’s picture

Ok great, last thing I would need before having everything to debug is an output example of http://api.npr.org/query?callback=?, with even better the PHP code corresponding to this.

I'll be leaving for today, but I'll review that tomorrow, with the video incoming.

Thanks,
Nicolas

dellis’s picture

Okay, I've run a query and taken the resulting JSON data and converted it into a php array object--then used a pre print_r to display the results. They can be found in this file: http://www.yourpublicmedia.org/json_data_in_php.txt

This is the $_POST data I get back from the npr api and use to populate the various node values as seen in the php function above--I've stripped out the apiKey, but everything else is as it is delivered. Hope this is what you were looking for...
The video is live now, so you should be able to see it.

Thanks again for your help with this.

ndeschildre’s picture

Hello,

Ok, the video makes things clear, I did already have this problem. The source of the problem is exactly the same one you got when you click "add more" and everything dissapear: cache_get() on the cache_form is failing, either because the entry is no longer here, or because of the code.
There is quite a lot of nodes discussing this, e.g.:
http://drupal.org/node/406050

That is why yesterday I was asking you to try to set the page cache to 0mn. It's a little complicated, but:
On your AJAX call, you make a lot of node_save(). node_save() contains a cache_clear_all() at the end of the function. cache_clear_all() call cache_clear_all('null', 'cache_page/block') which will call

    if (variable_get('cache_lifetime', 0)) {
      // We store the time in the current user's $user->cache variable which
      // will be saved into the sessions table by sess_write(). We then
      // simulate that the cache was flushed for this user by not returning
      // cached data that was cached before the timestamp.
      $user->cache = time();

$user->cache = time(); is the important part.
Then on aef_formatter_selector (or CCK or aef_image or whatever), you have

$form = form_get_cache($form_build_id, $form_state);

In form_get_cache, this is called:

    else {
      if ($user->cache > $cache->created) {
        // This cache data is too old and thus not valid for us, ignore it.
        return 0;
      }
      else {
        $cache->data = db_decode_blob($cache->data);
        if ($cache->serialized) {
          $cache->data = unserialize($cache->data);
        }
      }
    }

Usually $user->cache > $cache->created is false, so that's ok. But here since we went through cache_clear_all because of the node_save, it is now true, thus returning NULL.
Then, since it is failing to fetch the cached form, it is unable to render the part of the form it want to replace, and all dissapear (when you click "Add more") or you get an error (formatter selection).
This problem is one of the very very few design misconception of Drupal: having the cache of forms being treated like all others caches (page, block, ...)

Several things to check:
- Set the page cache to 0mn in settings/performance
- If you are using the memcache module, do not put cache_form in it.
- If you are manually clearing the cache_form table from time to time, do not do it.

Being sure that cache_form is not cleared somehow, and that you have page cache turned off should fix things.

Unfortunately you will probably not want to disable page cache, but first let's try to validate this solution.

Cheers,
Nicolas

dellis’s picture

mmm... thank you for your help (you really know this stuff!). Well, yesterday I had actually "disabled" my page caching and it still caused the same problems. But reading your response again, I activated the page cache and set it to "none" for time--sure enough it worked.

Do you think there might be a workaround for this--or am I in a "don't cache pages" or "don't use my node add code" position?

Thanks again--this is crazy!

ndeschildre’s picture

Indeed you really can't disable page caching, unless you are behind a proxy or CDN (our case).

The (dirty) workaround here would be:

$saved_user_cache = $user->cache;

[all your code containing node_save here]

$user->cache = $saved_user_cache;

That's dirty, and it will still fail if you happen to click "add more" in the middle of the AJAX call, but I'm not seeing a better way without hacking the Drupal core, which is a worse thing.
Drupal is really a well architectured thing, with some very rare bad design decision in it, this is one of them.

Cheers,
Nicolas

dellis’s picture

hmm... I re-activated the cache (refreshing every 15 minutes) tried that the suggestion above, but no luck. Then I added watchdog reports at the beginning of my function to print the original "$user->cache", then the $user->cache after all of my node_save(s) and then finally once I'd reset it... anyway, they were all blank?

ndeschildre’s picture

Of course you put a

global $user;

before?

dellis’s picture

Is it possible that something like passing $User->cache along to my npr_api...php external php file's querystring, dump it into a div on the page, then use jquery to add it to the data array being posted to the php function?

I'm not sure how I would access the $user->cache data from the form page with php though (if this is even a remote possibility)

dellis’s picture

Category: bug » support

ahh... that would be an embarrassed "no"... !!! Looks like that is working for me! Luckily for me I'd rather get a little "dirty" than not get work done at all!!!

Seriously you have just saved me a lot of additional wasted effort. Thank you so much for all of your help.

dellis’s picture

Title: PHP Fatal error: Unsupported operand types » cache_form issue resulting from additional node_save calls
dellis’s picture

Status: Active » Closed (fixed)
ndeschildre’s picture

Category: support » bug
Status: Closed (fixed) » Active

\o/

ndeschildre’s picture

Category: bug » support
Status: Active » Closed (fixed)