web-dev-qa-db-ja.com

コードでノードにファイルを添付する

ファイルをノードに関連付けたかった。ここまでは順調ですね。 cckタイプのファイルを作成すると、問題は解決しました。しかし、これはできません。ユーザーにファイルを選択させたくありません。問題のファイルはすでにシステムにあります。 #default_valueフィールドとしてファイルを配置し、hook_form_FORM_ID_alterで非表示にしようとしましたが、失敗しました。

function my_module_form_node_form_alter(&$form, $form_state, $form_id) {
    if(isset($form['type']) && isset($form['#node'])) {
        $type = $form['#node']->type;

        if(stripos($type, 'node-type') === FALSE)
            return;

        switch($type) :
            case 'node-type_xyz':
                $fid = arg(3);
                $file = file_load($fid);

                // make a cck field_invoice a hidden field
                $form['field_invoice']['#prefix'] = '<div style="display:none;">';
                $form['field_invoice']['#suffix'] = '</div>';

                $form['field_company']['und'][0]['value']['#default_value'] = 'ABC';
                $form['field_account_number']['und'][0]['value']['#default_value'] = '09879';
                break;
        endswitch;
    }
}

誰か提案はありますか?

4
Miguel Borges

これは少しトリッキーになる可能性があります。正しくするにはいくつかの手順があります。最初にノードを作成して保存し、次に2番目のパスとしてノードにファイルを追加します。次に実装例を示します。

/** 
 * Add a file to a field on a node
 * @param int $nid  node ID to add the content to
 * @param string $field_name the machine name of the field to add to 
 * @param string $filedata the raw binary data as a string 
 * @param optional boolean is the attachment an image (should image validation 
 *        be performed)
 */
function mymodule_addfile($nid, $field_name, $filedata, $is_image = FALSE) {
  $node = node_load($nid);

  $field = content_fields($field_name, $node->type);

  // Load up the appropriate validators
  $validators = 
  filefield_widget_upload_validators($field),
  if ($is_image) {
    $validators = array_merge(
      $validators,
      imagefield_widget_upload_validators($field)
    );
  }

  // Where do we store the files?
  $tmp_files_path = file_directory_temp()."/$file_name";
  $files_path     = filefield_widget_file_path($field);

  // Put the file in the temp folder
  $ret = file_put_contents($tmp_files_path,$filedata);
  unset($filedata);
  if ($ret === FALSE) {
    watchdog('mymod_error',"Could not write $nid ($file_name) to temp: $tmp_files_path");
    drupal_set_message("Could not write $nid ($file_name) to temp: $tmp_files_path", 'error');
    return FALSE;
  }

  $path = $files_path.'/'.$file_name;

  // Create the file object
  $file = field_file_save_file($tmp_files_path, $validators, $path);

  if ($file == 0) {
    watchdog('mymod_error',"Failed to save file $file_name");
    drupal_set_message("Failed to save file $file_name",'error');
    return FALSE;
  }

  // Apply the file to the field
  $node->{$field_name}[0] = $file;

  node_save($node);
  return TRUE;
}

A variation on the bottom works too, just assign the result to the file field. 

function _fhi_add_existing_file($file_drupal_path, $uid=1, $status=FILE_STATUS_PERMANENT) {
  $fs       = filesize($file_drupal_path);

  $res = db_query("SELECT fid FROM files WHERE filepath = '%s' AND filesize = '%s'", $filepath, $fs);

  $fid = db_fetch_array($res);

  if ($fid) {
    //drupal_set_message("$filepath already found. fid: $fid");
    $fid = $fid['fid'];
    return field_file_load($fid);
  } else {
    $file=(object)array(
      'filename'  => basename($file_drupal_path),
      'filepath'  => $filepath,
      'filemime'  => file_get_mimetype($file_drupal_path),
      'filesize'  => $fs,
      'uid'       => $uid,
      'status'    => $status,
      'timestamp' => time()
    );

    drupal_write_record('files',$file);
    return field_file_load($file_drupal_path);
  }

}

このコードはインタプリタなしでメモリから抽出されたため(今朝は手に余りにも時間がかかりすぎます)、導入したタイプミスに注意してください。何でもそうですが、このコードの使用によるプードルの死亡の責任はありません。

3
Jason Smith