Can't save node after setting its filedcollection DRUPAL - php

Have such structure:
Node
-> Filed "field_server_supported_hardware" (Fieldcollection)
-> Field "field_hardware_items" (Node reference width checkboxlist)
I want to add one more item in "field_hardware_items" (check one more item in ckeckboxlist).
Here's my code, it doesn't throws errors, but I can't save changes:
$node_wrap = entity_metadata_wrapper('node', $node_id); // our node wrapper
$node_wrap->field_server_supported_hardware[$key_item]->field_hardware_items->offsetSet($new_key, $new_node_item_to_attach); // setting new item
___save_debug($node_wrap->field_server_supported_hardware[$key_item]->field_hardware_items->value()); // if I log "field_hardware_items", it includes new item, and includes it in correct structure.
$node_wrap->save(TRUE); // trying to save node
Then I open the node I saved in admins panel, but checkbox of node with id=$new_node_item_to_attach isn't checked.

Give $node_wrap->revision->set(TRUE) a try before saving it
Apparently the save() function don't take into account the flag to create a new revision on a node on update, so it may be why you don't see the change.

Related

remove an Image programmatically in ezpublish

I have an Object in ezPublish which has an image attribute.
this attribute has an image as value that I want to remove it programmatically in PHP. ( the image value and not attribute itself )
any idea how to do it ?
For versions of eZ Publish (Legacy) prior to Oct 15, 2013, or git tag, 'v2014.03.1' including eZ Publish 4.7 the 'deleteStoredObjectAttribute' method -requires- a non-null second argument value be passed in versions of eZ Publish Legacy before the following commit:
See: https://github.com/ezsystems/ezpublish-legacy/commit/61aaa002c00ccfb86b3e02856b319f54b3405ef8
This includes eZ Publish 4.7 and thus the question author's specific use case. Which is why this answer is more accurate than all others.
Without this second non-null parameter, the aliases image files would be deleted from the filesystem but ... the image aliases information (alias references, meta data, etc) would still exist with the content object attribute content (database storage xml).
Without the second non-parameter the image would appear as still partially existing in the content object but the image preview, (IE: usage of the image path, meta data by the system) would display a broken image and thus then represent a corrupt / incomplete copy of the original content object attribute content.
For maximum Backwards Compatibility, it's best to always pass a non-null second parameter since versions of eZ Publish Legacy beyond 10/15/2013 do not even use the second parameter in any way.
The following is a complete example of the source code required to remove a content object image attribute content (and remove the related meta-data and image file from disk) the best way possible for nearly any version of eZ Publish Legacy.
// The following two variables are filled with dummy values.
// You will need to change the contents of these variables to match
// your actual use case identifiers (Content Object ID / Class Attribute Identifier)
$objectID = 42;
$objectImageAttributeIdentifier = 'profile_image';
$object = eZContentObject::fetch( $objectID );
$objectID = $object->attribute( 'id' );
$objectCurrentVersion = $object->attribute( 'current_version' );
$objectDataMap = $object->attribute( 'data_map' );
if ( isset( $objectDataMap[ $objectImageAttributeIdentifier ] ) )
{
$objectImageAttribute = $objectDataMap[ $objectImageAttributeIdentifier ];
if ( $objectImageAttribute->attribute( 'has_content' ) )
{
$objectImageDataType = $objectImageAttribute->dataType();
$objectImageDataType->deleteStoredObjectAttribute( $objectImageAttribute, $objectCurrentVersion );
eZContentCacheManager::clearContentCacheIfNeeded( $objectID );
}
}
According to eZImageType::customObjectAttributeHTTPAction(), you should use eZImageType::deleteStoredObjectAttribute().
The method's implementation shows how it is done internally. The method won't delete the attribute itself, just the external data (image, aliases, set the xml to empty).

Drupal 7.x: how to create a new node with PHP input format?

I want execute custom PHP script that will delete all nodes of a particular type (Feed items).
How to create a new node with PHP input format, so I can paste code into the node body? Please specify detailed steps.
$node_type = 'Feed items';
//fetch the nodes we want to delete
$result = db_query("SELECT nid FROM {node} WHERE type='%s'",$node_type);
while ($row = db_fetch_object($result)){
node_delete($row->nid);
$deleted_count+=1;
}
//simple debug message so we can see what had been deleted.
drupal_set_message("$deleted_count nodes have been deleted");
It's not entirely clear what you want to achieve. Do you simply want to execute that PHP code, once? Or whenever a node of a certain type is created?
If you just want to execute the PHP code once, you can install the devel module (http://drupal.org/project/devel) and paste your code in <your_site_url>/devel/php
--EDIT
Another option would be to create a php page that bootstraps Drupal and runs your code:
http://www.avenuewebmedia.com/drupalbootstrap-connect-drupal-external-php-script
OK, I managed myself how to do this: I had to enable the "PHP filter" module first (in Drupal core, disabled by default). In admin > Configuration > Content authoring > Text formats > Add text format, in "Enabled filters" mark "PHP evaluator", in Roles select 'admin', save configuration.
Then I created a new node (article), set the input format to PHP, pasted the code into the node body, added a title and clicked submit. Code has been executed. Sure, we need to delete the node when done.

Reading node field values in module code using Drupal 6

I have created a custom module and am using hook_block to programmatically create some blocks.
My question is how can I access field values including CCK fields for the current node within my module?
I basically want to get a value from a CCK field and use the value when building my block for that page.
Getting at the current node is an awkward pain in the posterior. Standard practice is to do something like this:
if (arg(0) == 'node' && is_numeric(arg(1)) && arg(2) == '') {
$node = node_load(arg(1));
// Collect output.
}
arg() pulls elements out of the Drupal path. Since all nodes (regardless of what a path alias might show you) appears at node/#, by checking for 'node' and that the second element is a number, you are fairly well guaranteed to have your hands on a node. Checking the third path element allows you to avoid processing on the node edit form and other pages that hang off a specific node.
CCK Values are loaded into the node, and usually look something like this:
// Text field. Structure also works for number fields.
$text = $node->field_my_text_field[0]['value']
// Node Reference field.
$nref = $node->field_my_nref_field[0]['nid']
// User Reference field.
$uref = $node->field_my_uref_field[0]['uid']
The "0" array element specifies the delta of the field. Any given field can actually process multiple values, and the array structure in CCK assumes this possibility even if you restrict the field to a single value.
In Drupal 6 there is a built-in Drupal function to get the node object.
if ($node = menu_get_object()) {
…
}
Read more here http://api.drupal.org/api/function/menu_get_item/6.

Difference between hook_node_type() and hook_nodeapi()

I'm trying to understand the difference between hook_node_type and hook_nodeapi
I've tried to use hook_node_type with the story node and a simple dsm but got nothing.
function mymod_node_story($op, $info){
dsm($info);
}
hook_node_type is made to hook into when a node type is changed. Fx if you want to allow comments on node type story etc.
hook_nodeapi is used to be able to hook into the different processes that can happen to an actual node, like when a node is saved, when it's being viewed etc.
There's not a hook for specific nodes, but instead you usually do something like this.
function module_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) {
if ($node->type == 'story') {
switch ($op) {
case 'load':
...
}
}
}
hook_node_type() is invoked each time a content type is deleted, or renamed. The purpose of the hook is to rename the Drupal variables used for the content type (which is automatically done for any form field included in the content type edit form, from node_type_form_submit()), or to delete the Drupal variables containing values for the content type that has been deleted.
hook_nodeapi() is invoked for each node when it's loaded from the database, the node edit form is shown, the node is visualized, when the node is being indexed from the search module, when a RSS feed, or the node is saved. A module should implement hook_nodeapi() to alter nodes for content types implemented by other modules.

Drupal - How to update a CCK NodeReference field programmatically?

I'm trying to create a node (B type) & assign it to a A type node's CCK nodereference field using node_save() method.
$node_type_A = node_load($some_nid);
$node_type_A->field_type_B_node_ref[]['nid'] = $node_type_B_nid;
$node_type_A = node_submit($node_type_A);
node_save($node_type_A);
As the result, a new B type node will be created, but no reference will be assigned to the A type node. any help would be appreciated.
GApple is right, the format is correct, but there are couple of things that you might want to care about.
Delta Value
First you need to know the delta value of the latest node reference attached to $node_type_A, the delta is actually a partial index, when combined with vid field of the $node_type_A, they become the index for node reference table in the database. In other words, its a count for $node_type_B which are referenced in $node_type_A, ok?
GApple is right again, you have to exactly say where to add the new reference. When you got that delta value you can exactly say where to append (delta+1) the new reference. Here it is:
function get_current_delta($node_vid){
return db_result(db_query("SELECT delta FROM {content_field_type_A_node_ref}
WHERE vid = '%d'
ORDER BY delta DESC
LIMIT 1", $node_vid));
}
Adding the new reference
We got delta! so we can attach the new $node_type_B node to our $node_type_A node:
// Loading type_A node.
$node_type_A = node_load($some_nid);
// Getting current delta value.
$current_delta = get_current_delta($node_type_A->vid);
// "Appending" a node reference based on delta.
$node_type_A->field_type_B_node_ref += array($current_delta + 1 => array('nid' => $node_type_B_nid));
Resaving the updated node
Optionally call node_submit() to populate some essential fields in the node object and save it by utilizing node_save(). After all, you need to call content_insert() to make the node completely saved asidelong with its CCK fields:
// Resaving the updated node.
$node_type_A = node_submit($node_type_A);
node_save($node_type_A);
content_insert($node_type_A);
Flushing the content cache
Probably the most important part, this was killin' me for couple of days. CCK has a cache table in the database called cache_content (take a look at its structure), after resaving the updated node, you will notice that nothing has changed in the $node_type_A theme output even though that the tables are updated. We have to remove a record from that content cache table, this will force Drupal to show the latest snapshot of the data. You can define the following as a function:
db_query("DELETE FROM {cache_content} WHERE cid = '%s'", 'content:' . $node_type_A->nid . ':' . $node_type_A->vid);
Hope it helps ;)
I just checked one of my own modules that does something similar for the object format, and $node_type_A->field_type_B_node_ref[]['nid'] should be correct.
One thing to check for is that when you load the node, CCK may pre-populate the node reference array with an empty value. If you have configured the field to only allow one value, by using the array append operator (field_type_B_node_ref[]) it will create a second entry that will be ignored (field_type_B_node_ref[1]), instead of overwriting the existing value (field_type_B_node_ref[0]). Try explicitly specifying the array key if possible.
Great post, but one correction: don't flush cache entries by manually querying the DB. In the event someone is using memcache or any other external cache it's going to fail.
cache_clear_all() is your friend for clearing.
Suggested code, direct from the CCK module:
cache_clear_all('content:'. $node_type_A->nid .':'. $node_type_A->vid, content_cache_tablename());
I show CCK storing node references as $node->field_node_reference[0]['items'][0]['nid'], not $node->field_node_reference[0]['nid']. Have you tried mimicking that?
"Flushing the content cache" This works for me, especially if you get a data from node_load()

Categories