I'm trying to write the form function which will return the preview of node, before it'll be created.
I've custom ctools multipage wizard form and I've so far the following form function:

/**
 * Implementation of CTools multipage API callback
 */
function foo_preview_node($form, $form_state) {
  $node = ctools_object_cache_get('foo', 'node'); // get the latest node object from the cache
  $node->in_preview = TRUE;
  $build = node_view($node, 'full');
  $form['preview'] = array(
      '#type' => 'item',
      '#markup' => drupal_render($build),
  );
  return $form;
}

Before I've tried as well:

 function foo_preview_node($form, $form_state) {
   $node = ctools_object_cache_get('foo', 'node'); // get the latest node object from the cache
  node_build_content($node, 'full'); // Populate $node->content with a render() array.
  $build = $node->content;
  unset($node->content); // // We don't need duplicate rendering info in node->content.
  $type = 'node';
  $build += array(
    '#theme' => $type,
    '#node' => $node,
    '#view_mode' => 'full',
    '#language' => NULL,
    // 'build_mode' => NODE_BUILD_PREVIEW,
  // $form_state['node_preview'] = TRUE;
  drupal_alter(array('node_view', 'entity_view'), $build, $type); // entity module dependency
  return array_merge($form, $build);
 }

but it was even worse.
The node was created by following code:

$node = new stdClass(); // We create a new node object
$node->type = 'foo'; // We set content type
$node->workflow = FOO_STATE_PENDING; // set default workflow state for Pending (5)
node_object_prepare($node);
// added some additional fields to that object during wizard
ctools_object_cache_set('foo', 'node', $node);

Note: that the object doesn't contain $nid object, because it weren't created yet.
Unfortunately there are two disadvantages of above method.
First of all, I've the following Notice errors:

Notice: Undefined property: stdClass::$nid in node_build_content() (line 1359 of modules/node/node.module).
Notice: Undefined property: stdClass::$nid in node_build_content() (line 1360 of modules/node/node.module).
Notice: Undefined property: stdClass::$nid in node_uri() (line 249 of modules/node/node.module).
Notice: Undefined property: stdClass::$nid in template_preprocess_node() (line 1499 of modules/node/node.module).
Notice: Undefined property: stdClass::$nid in include() (line 81 of themes/bartik/templates/node.tpl.php).
Notice: Undefined property: stdClass::$uri in theme_file_link() (line 727 of modules/file/file.module).
Notice: Undefined property: stdClass::$filemime in theme_file_icon() (line 765 of modules/file/file.module).
Notice: Undefined property: stdClass::$filemime in file_icon_path() (line 809 of modules/file/file.module).
Notice: Undefined property: stdClass::$filemime in file_icon_map() (line 852 of modules/file/file.module).
Notice: Undefined property: stdClass::$filemime in file_icon_path() (line 824 of modules/file/file.module).
Notice: Undefined property: stdClass::$filemime in file_icon_path() (line 824 of modules/file/file.module).
Notice: Undefined property: stdClass::$filemime in file_icon_path() (line 824 of modules/file/file.module).
Notice: Undefined property: stdClass::$filemime in file_icon_path() (line 824 of modules/file/file.module).
Notice: Undefined property: stdClass::$filemime in theme_file_link() (line 734 of modules/file/file.module).
Notice: Undefined property: stdClass::$filesize in theme_file_link() (line 734 of modules/file/file.module).
Notice: Undefined property: stdClass::$filename in theme_file_link() (line 740 of modules/file/file.module).

and:

Notice: Trying to get property of non-object in file_field_presave() (line 220 of modules/file/file.field.inc).
Notice: Undefined property: stdClass::$uri in file_save() (line 570 of includes/file.inc).

Secondly I've sometimes some weird fatal errors when saving the node after saving the node object, like:

PDOException: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '' for key 'uri': INSERT INTO {file_managed} (filesize, status, timestamp) VALUES (:db_insert_placeholder_0, :db_insert_placeholder_1, :db_insert_placeholder_2); Array ( [:db_insert_placeholder_0] => 0 [:db_insert_placeholder_1] => 1 [:db_insert_placeholder_2] => 1337349423 ) in drupal_write_record() (line 7013 of /Users/kenorb/Sites/AAT/docroot/includes/common.inc).

which could be related to the following bug:
#1163740: PDOException: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '' for key 2: INSERT INTO {file_managed}
Any suggestions or better ways of returning the form of node preview before the node creation?
Thanks.

Comments

kenorb’s picture

Issue summary: View changes

added few details

kenorb’s picture

Title: The right way to render preview of node object before the creation » The right way to programatically render the preview of node object before the creation
kenorb’s picture

Issue summary: View changes

add more details

damien tournoud’s picture

There is no good way, do whatever node_preview() does (including calling _field_invoke_multiple('load', 'node', array($node->nid => $node));).

damien tournoud’s picture

Issue summary: View changes

added more details

kenorb’s picture

Status: Closed (fixed) » Active

This is my latest version, fixing some filename field not rendering properly and some notice errors:

function foo_preview_node($form, $form_state) {
  $node = clone ctools_object_cache_get('foo', 'node'); // get the latest node object from the cache
  $node->in_preview = TRUE;
  _field_invoke_multiple('load', 'node', array(NULL => $node)); // additional stuff from other modules
  field_attach_prepare_view('node', array(NULL => &$node), 'full'); // lets field types and formatters load additional data needed for display
  $build = @node_view($node, 'full');
  $form['preview'] = array(
      '#type' => 'item',
      // '#title' => 'optional title',
      '#markup' => drupal_render($build),
  );
  return $form;
}
kenorb’s picture

Issue summary: View changes

improved sentence for better understanding

kenorb’s picture

Status: Active » Fixed

Status: Fixed » Closed (fixed)

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

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

I need to generate the render array for a node prior to it having been saved, and I also get PHP throwing a notice about $nid not existing.

This seems to really be the only community discussion on the matter that I can see thus far.
Not sure exactly how this issue was 'resolved'.

--

Setting the nid to NULL prior to calling node_view avoids the 'notice' messages being thrown.

$node->nid = NULL;