Drupal 7 | Preserve file after entity_wrapper unset? - drupal

Question is quite simple: How to preserve file on server and in file tables, so its fid is still valid after unsetting/changing value with entity wrapper?
$ewrapper = entity_metadata_wrapper('node', $sourceNode);
unset($sourceNode->field_image[$sourceNode->language][0]);
$ewrapper->save();
Now the related file is deleted as soon as the above is called. Same happends if I use:
$ewrapper->field_image->set($newImage);
In this case I need to keep the old image.
Thanks for your help guys!

I think that you should change file status from FILE_STATUS_TEMPORARY to FILE_STATUS_PERMANENT. Check out this answer here:
https://api.drupal.org/comment/23493#comment-23493
Basically, there is no file_set_status() function, like Drupal 6 had one, but now this code should do the same job:
// First obtain a file object, for example by file_load...
$file = file_load(10);
// Or as another example, the result of a file_save_upload...
$file = file_save_upload('upload', array(), 'public://', FILE_EXISTS_REPLACE);
// Now you can set the status
$file->status = FILE_STATUS_PERMANENT;
// And save the status.
file_save($file);
So, you load file object one or another way, change it's status property and save object back again.

Related

Edit an existing Pastebin document via API

I am trying to write a function in LUA to edit my pastebin code.
I can use this code to make a HTTP post:
http.post(string url, string postData [, table headers])
I can also use this code for a HTTP get:
http.get(string url [, table headers])
on the Pastebin website https://pastebin.com/api are information about using the API.
I am not sure, if this website can help me to solve my problem.
Does someone know how to fill the headers table?
this is the program i tried:
headers = {}
headers["api_dev_key"]= 'myDevKey...'; // your api_developer_key
headers["api_paste_code"] = 'my edited text'; // your paste text
headers["api_paste_private"] = '0'; // 0=public 1=unlisted 2=private
headers["api_paste_name"] = 'justmyfilename.php'; // name or title of your paste
headers["api_paste_expire_date"] = '10M';
headers["api_paste_format"] = 'php';
headers["api_user_key"] = ''; // if an invalid or expired api_user_key is used, an error will spawn. If no api_user_key is used, a guest paste will be created
headers["api_paste_name"] = myPastebinName;
headers["api_paste_code"] = myPastebinPassword;
http.get("https://pastebin.com/edit/dQMDfbkM", headers)
unfortunately this is not working and on the pastebin API help site is no exsample for editing a paste. just for creating a new one.
for me it is also not clear if I have to use post or get
There is no API for editing pastes directly.
You can only delete old paste and create new with updated text.

Hooks: processDatamap_preProcessFieldArray()

I am about porting an Extention from T3-6.2 to T3-7.6+
public function processDatamap_preProcessFieldArray(
&$fieldArray, $table, $id,
\TYPO3\CMS\Core\DataHandling\DataHandler &$pObj
) {
// t3_origuid is set? Yes, ist a Copy
if(isset($fieldArray['t3_origuid']) && $table=='mytable') {
$fieldArray['field1']++;
$fieldArray['filed2']--;
}
}
BUT:
To tell if it is a copy or not this needs the field 't3_origuid' in my record. It is not a standard field but if present it is filled by typo3.
Where does this filed come from? My I use this witout further problems?
If you know a hook/better way, (Slot, Signal?) to use in this case in T3 7.6+ please let me know.
Thanks a lot,
Christian.
This field is used by the sys extension workspace. If you change a tt_content element inside a workspace the original uid will be stored inside the field. So the changes,when they will be published, can be applied to the original element.

Edit xml File and save it from c#

I have an xml file which contain images url . i am verifying the url whether url is responsive or not. If url is not responsive then i am removing that url from xml. and saving all changes . but i am getting error like
'The process cannot access the file 'E:\1.xml' because it is being used by another process'
xmlTR = new XmlTextReader(#"E:\1.xml");
PrimaryXmlDoc.Load(xmlTR);
foreach (XmlNode node in PrimaryXmlDoc.SelectNodes("/fp-hotel/Images/Url"))
{
if (CheckUrlExists(node.InnerText))
{
}
else
{
XmlElement _xmlElement = PrimaryXmlDoc.DocumentElement;
node.ParentNode.RemoveChild(node);
}
}
PrimaryXmlDoc.Save(#"E:\1.xml");
I assume that you have to Close XmlTextReader before using it second time. If you don't do that, the previous instance will keep your file open and you won't be able to open it again.
EDIT: And that's what happens here is probably that you want to save file before closing it.
Add line:
xmlTR.Close();
before
PrimaryXmlDoc.Save(#"E:\1.xml");

How can I modify the Book Copy module in Drupal 6 to forward the user to a different starting tab once a copy is made?

Example call to copy a book using the Book Copy module in Drupal 6 (assuming a node exists with book id of 142):
www.examplesite.com/book_copy/copy/142
When the above site is called and node 142 is copied it then notifies the user that the book was copied, but starts the user out on the Outline tab for the book copy. I think it would be more intuitive to start the user out on the Edit tab for the book copy so the user can immediately start to edit the information for the book. The outline is less important than setting up the actual initial details for the book which are in the Edit tab.
Does anyone know how I could modify the module to forward the user to the Edit tab? I looked through the code and it's just not clicking. I'm having problems interpreting exactly how this Book Module is working under the hood. Any suggestions will be greatly appreciated. Thanks!
I have no experience with the book_copy module, but looking at the last lines of the book_copy_copy_book() function:
$book = node_load(array('nid' => $newbid));
$book->bookcopydata = array();
$book->bookcopydata['message'] = t('Successfully cloned "%message", now viewing copy.', array('%message' => $message));
if (_book_outline_access($book)) {
$book->bookcopydata['url'] = 'node/'. $newbid .'/outline';
}
else {
$book->bookcopydata['url'] = 'node/'. $newbid;
}
// The function signature is: hook_book_copy_goto_alter(&$data);
drupal_alter("book_copy_goto", $book);
drupal_set_message($book->bookcopydata['message']);
drupal_goto($book->bookcopydata['url']); // requires user has 'administer book outline' or can access personal books
the user would automatically end on the new book page if he did not have the 'administer book outlines' right. If you want the user to always end on the new book edit page, you could just replace the whole if
if (_book_outline_access($book)) { ... }
clause with the assignment from its else part with an adjusted url:
$book->bookcopydata['url'] = 'node/'. $newbid . '/edit';
However, changing a modules code directly is not recommended (update clashes), especially if the module provides a hook to achieve the change you need 'from outside'. So the 'right' way in your situation would be to implement the offered hook_book_copy_goto_alter(&$data) in a custom module in order to adjust the redirection URL to your liking:
function yourModule_book_copy_goto_alter(&$new_book) {
$new_book->bookcopydata['url'] = 'node/'. $new_book->nid . '/edit';
}

Is there a way to wait for asynchronous apps-script function calls before continuing with code?

I am attempting to copy a document in drive, edit it and mail it. Basically like a mail merge.
I take a template document, make a copy, edit the copy and then email it.
Unfortunately the edits are not complete before the email code runs, so the email attaches the copied document before the edits have been made. Is there a way around this?
//make a copy of the template
var templateCopy = DriveApp.getFileById(templateID).makeCopy('newFile', DriveApp.getFolderById(targetFolderID));
//select the contents of the template
var copyBody = DocumentApp.openById(templateCopy.getId())
//replace text: set the date
copyBody.replaceText("%DATE%",'today')
//send email - the email that arrives does not have the date substitution, it still contains the %DATE% tag
GmailApp.sendEmail(targetAddress, 'eggs', 'eggs', {attachments:[copyBody.getAs(MimeType.PDF)]});
edit regarding possible duplicate: SpreadsheetApp.flush() is not relevant as we are not working with a spreadsheet.
Answer:
Use the saveAndClose() method of DocumentApp to force changes before continuing.
More Information:
As per the Apps Script documentation:
Saves the current Document. Causes pending updates to be flushed and applied.
The saveAndClose() method is automatically invoked at the end of script execution for each open editable Document.
A closed Document can't be edited. Use DocumentApp.openById() to reopen a given document for editing.
Implementation:
function documentStuff() {
//make a copy of the template
var templateCopy = DriveApp.getFileById(templateID).makeCopy('newFile',
DriveApp.getFolderById(targetFolderID)
);
//select the contents of the template
var copyBody = DocumentApp.openById(templateCopy.getId());
//replace text: set the date
copyBody.replaceText("%DATE%",'today');
copyBody.saveAndClose();
sendMail(targetAddress, DocumentApp.openById(templateCopy.getId()));
}
function sendMail(targetAddress, file) {
//send email - the email that arrives does not have the date substitution
// it still contains the %DATE% tag
GmailApp.sendEmail(targetAddress, 'eggs', 'eggs', {
attachments: [
file.getAs(MimeType.PDF)]
}
);
}
Splitting the Document and Gmail methods into separate functions also can help with this issue.
References:
Class DocumentApp
.saveAndClose() method of DocumentApp Class

Resources