How to update a file field in Drupal 7 - file

In hook_user_update I'm retrieving a facebook profile pic and saving a record in the file_managed table. That much is going well. But I also want to save a record for a file field attached to the user entity. Normally what I do in these hooks is assign the values to $edit['field_something'], and I think that's the correct way to do this. That has always worked for other field types, but it is not working for the file field. You can see toward the end of the function where I dump the vars to confirm that I have something suitable to assign to $edit['field_something'] -- at least, I think it's suitable. I get no errors, but no record is created in the field_data_field_image table. What am I missing? Thank you!
/**
* Implementation of hook_user_update().
*
*/
function hifb_user_update(&$edit, $account, $category) {
if (empty($account->field_image['und'])) {
$fbid = $edit['field_facebook_id']['und'][0]['value'];
if (!empty($fbid)) {
$url = 'http://graph.facebook.com/' . $fbid . '/picture?type=large';
if ($file_contents = file_get_contents($url)) {
$size = getimagesize($url);
$ext = image_type_to_extension($size[2]);
$filename = 'fb_' . $fbid . '_u_' . $account->uid . $ext;
$uri = file_default_scheme() . '://' . $filename;
// Saves the file to the default files directory and creates the record in files_managed table.
$file = file_save_data($file_contents, $uri, FILE_EXISTS_REPLACE);
//var_dump($file); die;
/* Here's an example from the var_dump: object(stdClass)#120 (8) { ["fid"]=> string(3) "576" ["uri"]=> string(30) "public://fb_767816596_u_1.jpeg" ["filename"]=> string(21) "fb_767816596_u_1.jpeg" ["filemime"]=> string(10) "image/jpeg" ["uid"]=> string(1) "1" ["status"]=> int(1) ["timestamp"]=> int(1339686244) ["filesize"]=> int(2919) } */
// Creates record in field_data_field_image table??
$edit['field_image']['und'][0] = (array)$file;
}
}
}
}

I believe the reason it doesn't work is because in hook_user_update, the update has already occurred. So setting a value for $edit has no effect. The same code that I posted in the question works fine in hook_user_presave.

Related

Finding out what is in an array of Hash (on a server)

I am using a 3rd party shopping cart solution that runs on a server (SellerDeck). I have some code that runs on the server to format a shopping basket with basic product data (quantity, price, name). I need to find some more data which I think is held in 2 arrays of hashes. I dont know what is contained in these 2 arrays so I would like to convert the array to a string and output via the existing code that puts it in a cookie on the client which I can then view. The 2 arrays are $pCartItem and $pProduct (see code at the bottom for how they are used).
The string $cartStr (bottom of the code) is output onto the client in a cookie by another part of the code.
I would like to covert the 2 arrays into 2 strings which can be concatenated onto $cartStr. I can then read the contents on my local pc (client). My issue is I am very unfamiliar with perl and know how to do the conversion.
I tried adding :
my $MiniCrtS=" ";
my $MiniCartElmt;
foreach $MiniCartElmt (#{$pProduct}) {
$MiniCrtS=$MiniCrtS . $MiniCartElmt;
}
and then changed the $cartStr from:
HTML::Entities::encode(substr($pProduct->{'NAME'},0,$abrv))
to:
HTML::Entities::encode(substr($MiniCrtS,0,$abrv))
but this change makes the code crash when run.
Any ideas on what I am doing wrong or an alternative to find out the data in the arrays?
Many thanks Tony
The relevant code is:
sub miniCart
{
use HTML::Entities ();
my $Self = shift;
my $abrv=12; # number of characters to abbreviate item name
my $defaultCur="£"; # currency symbol to include
my $cartStr="ss=" . $::g_sSearchScript . "cur=" . $defaultCur;
my $pCartItem;
foreach $pCartItem (#{$Self->{_CartList}})
{
my ($Status, $Message, $pProduct) = GetProduct($pCartItem->{'PRODUCT_REFERENCE'}, $pCartItem->{'SID'});
if ($Status == $::FAILURE)
{
return ($Status, $Message, []);
}
elsif ($Status == $::NOTFOUND)
{
next;
}
my #Prices = $Self->GetCartItemPrice($pCartItem);
$cartStr=$cartStr . "&!" . $pCartItem->{'QUANTITY'} . "x" . HTML::Entities::encode($pCartItem->{'PRODUCT_REFERENCE'}) . ">" . HTML::Entities::encode(substr($pProduct->{'NAME'},0,$abrv)) . ">" . $Prices[2]/100;
}
return $cartStr;
}
To get a dump of a data structure, you can use Data::Dumper.
I'd use it as follows:
use Data::Dumper qw( );
sub dumper {
local $Data::Dumper::Indent = 0;
local $Data::Dumper::Sortkeys = 1;
local $Data::Dumper::Terse = 1;
local $Data::Dumper::Useqq = 1;
return Data::Dumper::Dumper($_[0]);
}
warn("pProduct: " . dumper($pProduct));
This will log it the string produced to the web server's error log, but you could also return it in a cookie if that's what you really want.

FAL insertion into sys_file TYPO3

I'm trying to insert a file into TYPO3 db through frontend using core functions or FileRepository, exactly into sys_file table.
While investigating I've seen few solutions like,
$storageRepository = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Resource\\StorageRepository');
$storage = $storageRepository->findByUid(1);
$fileObject = $storage->addFile('/tmp/myfile', $storage->getRootLevelFolder(), 'newFile');
echo $fileObject->getIdentifier(); // Should output "/newFile"
But I still can't find this addFile() in storageRepository class. Am I missing some thing here?
The line $storageRepository->findByUid(1) return a ResourceStorage Object with the Method addFile().
Here is a Documenttion of this class.
https://typo3.org/api/typo3cms/class_t_y_p_o3_1_1_c_m_s_1_1_core_1_1_resource_1_1_resource_storage.html
#mario Thanks. By the way I've achieved what I planned. Here's what I did..
public function uploadFile($uploadedfile) {
$storage = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Resource\\StorageRepository');
$filePath = 'uploads/tx_fileupload/'.$uploadedfile['updata']['name'];
$title = $uploadedfile['updata']['name'];
$size = $uploadedfile['updata']['size'];
// Moving the physical file to destined folder
\TYPO3\CMS\Core\Utility\GeneralUtility::upload_copy_move($uploadedfile['updata']['tmp_name'],$filePath);
// Adding a record in sys_file_storage
$fileObject = $storage->createLocalStorage($uploadedfile['updata']['name'],$uploadedfile['updata']['tmp_name'],$filePath,'');
// Inserting file in sys_file
$repositoryFileObject = \TYPO3\CMS\Core\Resource\ResourceFactory::getInstance()->retrieveFileOrFolderObject($filePath);
return $repositoryFileObject;
}
Now moving onto adding corresponding sys_file_reference record.

drupal_write_record doesn't take object

In drupal 6 i used to do something like this:
<?php
/*
* CLASS Example
*/
class example {
var $id = NULL;
var $title;
var $body;
.....
// Save
function save() {
$primary_key = ($this->id == NULL ? NULL : 'id');
if (drupal_write_record('mytabble', $this, $primary_key)) {
return TRUE;
} else {
return FALSE;
}
}
}
?>
This worked quite well. But in Drupal 7, the drupal_write_record only takes an array and no longer the object $this. The new db_merge also only takes an array.
Since i want to save the properties of my object to the database, the above code was very handy and generic for all kinds of classes.
Is there an alternative way to write an object to database, or a method to place objectproperties into a an array?
Any help will be appreciated!
Robert
drupal_write_record does take an object or an array. Guess your problem is caused somewhere else.
drupal_write_record($table, &$record, $primary_keys = array())
$record: An object or array representing the record to write, passed in by reference. If inserting a new record, values not provided in $record will be populated in $record and in the database with the default values from the schema, as well as a single serial (auto-increment) field (if present). If updating an existing record, only provided values are updated in the database, and $record is not modified.
More info on drupal_write_record for D7.

drupal 7 - attach file to a node by code

I wanted to associate a file to a node. so far so good. create a cck type file, and the problem was solved. but I can not do this, I do not want the user to choose the file. the file in question is already in the system.
I have tried to place the file as # default_value field and hide it with the hook_form_FORM_ID_alter, but failed.
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;
}
}
anyone have any suggestions?
Don't use #prefix and #suffix to hide it. Instead, set #access to false - that way, people can't fiddle with the form. You can set the value in hook_nodeapi or a submit function, or set the type to 'value' and the #value to your file.

Need help parsing results from ldap to csv

I am trying to create a script to generate a csv file with the results of some ldap queries using Net::LDAP but I'm having troubles skipping incomplete lines if one element of the #attributes array is blank.
my #attributes = ('cn', 'mail', 'telephoneNumber');
So for example, if a user has no mail listed, or no telephoneNumber listed, then it should skip the hold field instead of returning:
"Foo Bar",, # this line should be skipped since there is no mail nor telephone
"Bar Foo","bar#foo.com", # this line should be skipped too, no number listed
"John Dever","john_dever#google.com","12345657" # this one is fine, has all values
My loop right now is looking like this:
# Now dump all found entries
while (my $entry = $mesg->shift_entry()){
# Retrieve each fields value and print it
# if attr is multivalued, separate each value
my $current_line = ""; # prepare fresh line
foreach my $a (#attributes) {
if ($entry->exists($a)) {
my $attr = $entry->get_value($a, 'asref' => 1);
my #values = #$attr;
my $val_str = "";
if (!$singleval) {
# retrieve all values and separate them via $mvsep
foreach my $val (#values) {
if ($val eq "") { print "empty"; }
$val_str = "$val_str$val$mvsep"; # add all values to field
}
$val_str =~ s/\Q$mvsep\E$//; # eat last MV-Separator
} else {
$val_str = shift(#values); # user wants only the first value
}
$current_line .= $fieldquot.$val_str.$fieldquot; # add field data to current line
}
$current_line .= $fieldsep; # close field and add to current line
}
$current_line =~ s/\Q$fieldsep\E$//; # eat last $fieldsep
print "$current_line\n"; # print line
}
I have tried code like :
if ($attr == "") { next; }
if (length($attr) == 0) { next; }
and several others without any luck. I also tried simple if () { print "isempty"; } debug tests and its not working. Im not exacly sure how could I do this.
I appreciate any help or pointers you could give me on what am I doing wrong.
Thanks a lot in advance for your help.
UPDATE:
Per chaos request:
my $singleval = 0;
A sample run for this program would return:
Jonathan Hill,Johnathan_Hill#example.com,7883
John Williams,John_Williams#example.com,3453
Template OAP,,
Test Account,,
Template Contracts,,
So what I want to do is to skip all the lines that are missing a field, either email or extension number.
Label your while loop:
Record: while (my $entry = $mesg->shift_entry()){
and use:
next Record;
Your problem is that your next is associated with your foreach. Using the label avoids that.
By the way, $attr == '', though it will work in this case, is bad logic; in perl, == is a numeric comparison. String comparison would be $attr eq ''. Though I'd just use next Record unless $attr.

Resources