I am trying to create a node based on a custom form submission. Everything works great except for the images that get uploaded.
I can capture them fine and set them in the form object cache. When I pass the data into the function to create the node, I get this error:
"The specified file could not be copied, because no file by that name exists. Please check that you supplied the correct filename."
I also receive the error multiple times, despite only submitting one or two images at a time.
Here is the code I am using. $uploads is passed in and is an array of file objects returned from file_save_upload() in a previous step:
if (isset($uploads)) {
foreach ($uploads as $upload) {
if (isset($upload)) {
$file = new stdClass;
$file->uid = 1;
$file->uri = $upload->filepath;
$file->filemime = file_get_mimetype($upload->uri);
$file->status = 1;
$file = file_copy($file, 'public://images');
$node->field_image[$node->language][] = (array) $file;
}
}
}
node_save($node);
I also tried this:
if (isset($uploads)) {
foreach ($uploads as $upload) {
$upload->status = 1;
file_save($upload);
$node->field_image[$node->language][] = (array) $upload;
}
}
}
node_save($node);
The second causes a duplicate key error in MySQL on the URI field. Both of these examples I saw in tutorials, but neither are working?
For Drupal 7, I played around with this quite a bit and found the best way (and only way that I've got working) was to use Entity metadata wrappers
I used a managed file form element like so:
// Add file upload widget
// Use the #managed_file FAPI element to upload a document.
$form['response_document'] = array(
'#title' => t('Attach a response document'),
'#type' => 'managed_file',
'#description' => t('Please use the Choose file button to attach a response document<br><strong>Allowed extensions: pdf doc docx</strong>.'),
'#upload_validators' => array('file_validate_extensions' => array('pdf doc docx')),
'#upload_location' => 'public://my_destination/response_documents/',
);
I also pass along the $node object in my form as a value
$form['node'] = array('#type' => 'value', '#value' => $node);
Then in my submission handler I simply do the following:
$values = $form_state['values'];
$node = $values['node'];
// Load the file and save it as a permanent file, attach it to our $node.
$file = file_load($values['response_document']);
if ($file) {
$file->status = FILE_STATUS_PERMANENT;
file_save($file);
// Attach the file to the node.
$wrapper = entity_metadata_wrapper('node', $node);
$wrapper->field_response_files[] = array(
'fid' => $file->fid,
'display' => TRUE,
'description' => $file->filename,
);
node_save($node);
}
i used your code to upload a file in the file field to a content("document" in my case) and it's worked. Just had to add a value for field_document_file 'display' in the code.
here is the exact script i used:
<?php
// Bootstrap Drupal
define('DRUPAL_ROOT', getcwd());
require_once './includes/bootstrap.inc';
require_once './includes/file.inc';
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
// Construct the new node object.
$path = 'Documents/document1.doc';
$filetitle = 'test';
$filename = 'document1.doc';
$node = new StdClass();
$file_temp = file_get_contents($path);
//Saves a file to the specified destination and creates a database entry.
$file_temp = file_save_data($file_temp, 'public://' . $filename, FILE_EXISTS_RENAME);
$node->title = $filetitle;
$node->body[LANGUAGE_NONE][0]['value'] = "The body of test upload document.\n\nAdditional Information";
$node->uid = 1;
$node->status = 1;
$node->type = 'document';
$node->language = 'und';
$node->field_document_files = array(
'und' => array(
0 => array(
'fid' => $file_temp->fid,
'filename' => $file_temp->filename,
'filemime' => $file_temp->filemime,
'uid' => 1,
'uri' => $file_temp->uri,
'status' => 1,
'display' => 1
)
)
);
$node->field_taxonomy = array('und' => array(
0 => array(
'tid' => 76
)
));
node_save($node);
?>
Kevin, that's what I found in the Drupal doc's under http://drupal.org/node/201594 below in the comments. But I am not sure at all. I try the same, so please let me know what you found out.
$path = './sites/default/files/test.jpg';
$filetitle = 'test';
$filename = 'test.jpg';
$node = new StdClass();
$file_temp = file_get_contents($path);
$file_temp = file_save_data($file_temp, 'public://' . $filename, FILE_EXISTS_RENAME);
$node->title = $filetitle;
$node->uid = 1;
$node->status = 1;
$node->type = '[content_type]';
$node->language = 'und';
$node->field_images = array(
'und' => array(
0 => array(
'fid' => $file_temp->fid,
'filename' => $file_temp->filename,
'filemime' => $file_temp->filemime,
'uid' => 1,
'uri' => $file_temp->uri,
'status' => 1
)
)
);
$node->field_taxonomy = array('und' => array(
0 => array(
'tid' => 76
)
));
node_save($node);
Related
Preview only works for new nodes before saving, but after I saved the node, edit and click preview:
Preview trimmed & Preview full version both show the last saved state instead.
Any advise how I can check what might prevent it or whether it's set up correctly?
FYI /modules/node/node.pages.inc:
function theme_node_preview($variables) {
$node = $variables['node'];
$output = '<div class="preview">';
$preview_trimmed_version = FALSE;
$elements = node_view(clone $node, 'teaser');
$trimmed = drupal_render($elements);
$elements = node_view($node, 'full');
$full = drupal_render($elements);
...
$enter code hereform['actions']['preview'] = array(
'#access' => variable_get('node_preview_' . $node->type, DRUPAL_OPTIONAL) != DRUPAL_DISABLED,
'#type' => 'submit',
'#value' => t('Preview'),
'#weight' => 10,
'#submit' => array('node_form_build_preview'),
I'm new at Drupal 7, so I have a question.
I have my own content type Writers that includes such fields as Title, Years of life, Photo, Description.
I have a task to display 3 random Writers at page. Actual I've done it with help of Views module, but I want to do it myself.
So I created my own module random_content like that:
<?php
function random_content_help($path, $arg) {
switch ($path) {
case "admin/help#random_content":
return '<p>'. t("Displays random content") .'</p>';
break;
}
}
function random_content_block_info() {
$blocks['random_content'] = array(
'info' => t('Random content'),
'cache' => DRUPAL_CACHE_PER_ROLE,
);
return $blocks;
}
function random_content_contents() {
$query = db_select('node', 'n')
->fields('n', array('nid', 'title'))
->condition('type', 'writers')
->orderBy('rand()')
->range(0,3)
->execute();
return $query;
}
function random_content_block_view($delta = '') {
switch($delta){
case 'random_content':
$block['subject'] = t('Random content');
if(user_access('access content')) {
$result = random_content_contents();
$items = array();
foreach ($result as $node){
$items[] = array(
'data' => l($node->title, 'node/' . $node->nid) . '</br>',
);
}
if (empty($items)) {
$block['content'] = t('No data availible.');
} else {
$block['content'] = theme('item_list', array(
'items' => $items));
}
}
}
return $block;
}
As you can see, I've learned only to add links to particular content. But how can I display full information including Title, Years of life, Photo and Description?
To display the full node, or parts of it you need to load the node. E.g.
$my_node = node_load($nid);
$render_array = array();
$render_array['title'] = array(
'#type' => 'markup',
'#markup' => $my_node->title
);
$author = field_get_items('node', $my_node, 'field_author','und');
$render_array['author'] = array(
'#type' => 'markup',
'#markup' => $author[0]['safe_value']
);
// or as some like to do it
$render_array['author'] = array(
'#type' => 'markup',
'#markup' => $my_node->field_author['und'][0]['value']
);
echo drupal_render($render_array);
Note the 'und' constant means the language is undefined. If you have translation/language enabled and different content for different languages you would have to use 'en', 'de' etc. for the appropriate language.
You can also let drupal render the node and then manipulate or retrieve individual items. Like this
$my_node = node_load($nid);
$build = node_view($my_node,'full');
$build['body'][0]['#markup'] = $build['body'][0]['#markup'].' some addition';
$build['field_author'][0]['#markup'] = $build['field_author'][0]['#markup'].' my favorite';
echo drupal_render($build);
The advantage of using this latter method is that then the whole themeing engine kicks in, and all hooks that are set to act on the content etc. Of course, if you only want to retrieve values you don't need that.
Note also, I assume your author field is named field_author. You should check that in the field edit window for the content type.
I created a plugin as 3rd party to acomodate system with wordpress website on main site. So the scenario is:
when user hit submit on the system it will also added to wordpress website, it's working perfect, no problem at all. but when i try to set the featured image through wp_insert_attachment it keep me give a URL like
http://xxxxx.com/wp-content/uploads/http://xxxxx.com/system/media/.../xx.jpg
what i want to be is only http://xxxxx.com/system/media/.../xx.jpg saved as featured image, is it possible to do so?
here is my current script
if($pt == "pictures"){
$filename_url = $_GET["dml_file"];
$mime = wp_check_filetype($filename_url, null);
$data = array(
'post_mime_type' => $mime['type'],
'post_title' => preg_replace('/\.[^.]+$/', '', basename($_GET["dml_file"])),
'post_content' => '',
'post_status' => 'inherit'
);
$attachment_id = wp_insert_attachment($data, $filename_url, $pid);
update_post_meta($pid, $custom_field, $attachment_id);
}else{
update_post_meta($pid, $custom_field, $_GET["dml_file"]);
}
I have tried to use file_get_contents and file_put_contents to create image in WP installation, but I don't want that way.
The system is submitting this:
http://user:pass!#localhost/wp-content/plugins/dml3rdparty/dmlsubmit.php?dml_save=save&dml_file=http://xxx.xxx.xxx.xxx/dml/assets/media/Accreditation/download.d15bdf4e9e.jpg&dml_type=Print Quality Photos&dml_description=test|download.jpg&dml_status=publish
From wp_insert_attachment documentation (my emphasis in bold):
$filename
(string) (optional) Location of the file on the server. Use absolute path and not the URI of the file. The file MUST be on the uploads directory. See wp_upload_dir()
Default: false
Much probably, you can solve this with media_handle_sideload().
This function gets the file content using cURL:
function my_file_get_contents($url){
$options = array(
CURLOPT_AUTOREFERER => true,
CURLOPT_HEADER => false,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_CONNECTTIMEOUT => 120,
CURLOPT_TIMEOUT => 120,
CURLOPT_MAXREDIRS => 10
);
$ch = curl_init($url);
curl_setopt_array($ch,$options);
$data = curl_exec($ch);
curl_close($ch);
return $data;
}
This function uses the above to get the image, saves it to the uploads folder, and sets it as a featured image for a post:
function my_featured_image($image_url,$post_id){
$upload_dir = wp_upload_dir();
$image_data = my_file_get_contents($image_url);
$filename = strtok($image_url, '?');
$filename = basename($filename);
if(wp_mkdir_p($upload_dir["path"])){
$file = $upload_dir["path"]."/".$filename;
}else{
$file = $upload_dir["basedir"]."/".$filename;
}
file_put_contents($file, $image_data);
$wp_filetype = wp_check_filetype($filename,null);
$post_author = get_post_field("post_author",$post_id);
$attachment = array(
"post_author" => $post_author,
"post_mime_type" => $wp_filetype["type"],
"post_title" => sanitize_file_name($filename),
"post_content" => "",
"post_status" => "inherit"
);
$attach_id = wp_insert_attachment($attachment,$file,$post_id);
require_once(ABSPATH."wp-admin/includes/image.php");
$attach_data = wp_generate_attachment_metadata($attach_id,$file);
$res1 = wp_update_attachment_metadata($attach_id,$attach_data);
$res2 = set_post_thumbnail($post_id, $attach_id);
}
Call with:
my_featured_image($image_url,$post_id);
Not sure where the problem is in the following form used in a template file in Drupal7. Help is highly appreciated. The problems are the following:
1. The variables $title and $surname are not passed over to the form's default value.
=> Error Message: Notice: Undefined variable: title in form_user_information()
=> Error Message: Notice: Undefined variable: surname in form_user_information()
2. There's a Warning: strpos() expects parameter 1 to be string, array given in drupal_strip_dangerous_protocols()
Thanks in advance.
<?php
//Load User data:
global $user;
$uid = $user->uid;
$account = user_load($uid);
//Get User data:
$title = 'Mrs.';
print $title . '<br><br>'; //Result: Value is printed and not empty!
$surname = check_plain($account->field_vorname['und']['0']['value']);
//$surname = 'Tom';
print $surname . '<br><br>'; //Result: Both values are printed and are not empty!
function form_user_information($form, &$form_state) {
//Form
$form['#action'][] = request_uri();
$form['#id'][] = 'form_user_information';
$form['#validate'][] = 'form_user_information_validators';
$form['#submit'][] = 'form_user_information_submit';
$form['#prefix'] = '<div id="form_user_information">';
$form['#suffix'] = '</div>';
//Select-Field: https://api.drupal.org/api/drupal/developer!topics!forms_api_reference.html/7#select
$form['Title'] = array(
'#type' => 'select',
'#title' => t('Title'),
'#options' => array(
'Frau' => t('Mr.'),
'Herr' => t('Mrs.'),
),
'#default_value' => $title,
);
$form['surname'] = array(
'#type' => 'textfield',
'#maxlength' => 50,
'#size' => 40,
'#required' => TRUE,
'#title' => t('Surname'),
//'#attributes' => array('placeholder' => $surname),
'#default_value' => $surname,
);
$form['actions'] = array('#type' => 'actions');
$form['actions']['submit'] = array('#type' => 'submit', '#value' => 'Confirm data');
return $form;
}
//print form
$form = drupal_get_form('form_user_information');
print drupal_render($form);
//Form Validation:
function form_user_information_validators($form, &$form_state) {
if ($form_state['values']['surname'] == '') {
form_set_error('surname', t('Please enter your surname.'));
}
}
//Form Submit:
function form_user_information_submit($form, &$form_state) {
//...
}
//get form information
echo "<pre>".print_r($form,true)."</pre>";
?>
1) Set the global variables $title and $surname with global scope:
//Get User data:
$global $title = ...
$global $surname = ...
Otherwise set all these variables (including $user) inside the function form_user_information which is the best practice.
I would also suggest not use $title as variable name because it may cause problems with already defined $title of the $page variable. Instead use something like $user_title.
2) Which line does this come from?
Guess this issue can be closed. See the 2 comments. Thanks Theodoros for your help.
Is it possible to add an image to a node programmatically?
Here is an example code using which you can use with node_save
$filepath = drupal_realpath('misc/druplicon.png');
// Create managed File object and associate with Image field.
$file = (object) array(
'uid' => 1,
'uri' => $filepath,
'filemime' => file_get_mimetype($filepath),
'status' => 1,
);
// We save the file to the root of the files directory.
$file = file_copy($file, 'public://');
$node->field_image[LANGUAGE_NONE][0] = (array)$file;
`
An easier way:
$filename = 'image.txt';
$image = file_get_contents('http://www.ibiblio.org/wm/paint/auth/gogh/gogh.white-house.jpg');
$file = file_save_data($image, 'public://' . $filename, FILE_EXISTS_RENAME);
$node->field_image = array(LANGUAGE_NONE => array('0' => (array)$file));
This is what worked for me:
$file_temp = file_get_contents('public://someimage.jpg');
// Saves a file to the specified destination and creates a database entry.
$file_temp = file_save_data($file_temp, 'public://' . 'someimage.jpg', FILE_EXISTS_RENAME);
$node->field_page_image = array(
'und' => array(
0 => array(
'fid' => $file_temp->fid,
'filename' => $file_temp->filename,
'filemime' => $file_temp->filemime,
'uid' => 1,
'uri' => $file_temp->uri,
'status' => 1,
'display' => 1
)
)
);
Here's one extra bit that tripped me up for a while: this will attach the image to the node, and if you're adding the image then you're okay. However, if you're updating an image, and you care about displaying it on a page, then one extra step is needed before calling node_save():
image_path_flush($node->field_image['und'][0]['uri']);
This will regenerate all of that image's styles.
$node->field_image[LANGUAGE_NONE][0] = (array)$file;
I tried this with a multilingual site. It failed fairly... but horribly.
I had to specify the language in question. Simply put, this worked instead:
$node->field_image['en'][0] = (array)$file;
Without it, the attached file was viewable in the 'view' screen but not in the 'edit' screen.
Yes, make it part of the $node object when you save it. Save it using node_save().
This works for me:
define('DRUPAL_ROOT', $_SERVER['DOCUMENT_ROOT']);
require_once DRUPAL_ROOT . '/includes/bootstrap.inc';
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
$node = node_load(99);
$filename = 'image.txt';
chdir(DRUPAL_ROOT);
$image = file_get_contents('http://www.ibiblio.org/wm/paint/auth/gogh/gogh.white-house.jpg');
$file = file_save_data($image, 'public://' . $filename, FILE_EXISTS_RENAME);
$node->field_imagen_producto = array(LANGUAGE_NONE => array('0' => (array)$file));
node_save($node);
Just going to paste my solution here as well, I needed to create a new node, and upload an image programmatically.
$filepath = variable_get('file_public_path') . '/xmas_banner.jpg';
$file_temp = file_get_contents($filepath);
$file_temp = file_save_data($file_temp, file_default_scheme() . '://' .'xmas_banner_nl.jpg', FILE_EXISTS_RENAME);
$node = new stdClass();
$node->type = 'carousel'; // custom content type
$node->title = 'XMAS NL';
$node->field_banner_image[LANGUAGE_NONE][0] = (array) $file_temp;
$node->uid = 1;
$node->status = 0;
$node->active = 0;
$node->promote = 0;
node_save($node);