drupal rules adding field data to referenced node without replacing existing data - drupal

My question is about: "adding field data to referenced node without replacing existing data".
For example, I have a project node with team members referencing the project. Each team member has on its node a location, ie, 'United Kingdom', 'United States', 'Australia'.
On the project node I have those exact same fields. I need to create a rule so that when a 'team member' node is created, its location is added to the project node without replacing existing content.
So for instance, a project node with a team member from the United Kingdom would also have on its location field, 'United Kingdom'. When a team member from 'United States' is added, the project's location field would have 'United Kingdom' and 'United States'. When a team member who's location is both Canada AND France is added, the project's location becomes United Kingdom, United States, Canada, and France.
Thanks!
Doing something like:
return array(
0 => array('value' => 'United Kingdom')
);
Just wouldn't work! It would replace the existing values. How do I make it so that it adds on to the existing values. Thanks!

Is it important to actually have the reference on the node or just to display the location.
If you are just worried about displaying the location then I think you can do this quite easily with a view.
There is a node reference reverse option I believe, but this would only display the team members and not the location.
If it is important to actually have the location information in the project node, then you will have to use hook_nodeapi op = save with code similar to Matts' answer.

Will something like this work? Basically we capture the current nodes cck location field (change the field names below to fit), load the reference node, and add the location data to it, and save it away. I've not added the code to check to see if the location already exists, but that's something for another day. - Hope it helps.
#some debug data below
#krumo ($node);
#print "<pre>". print_r($node,true) . "</pre>";
#$node is our current data set
# save the current $node nid into a variable
$nid = $node->nid;
#get the reference nid
$refnid = $node->field_refnid[0][nid];
#get the location
$currentlocation = $node->field_team_location[0][value];
# nowload the reference node
$refnode = node_load ($refnid);
# some debug data below
#krumo ($refnode);
#print "<pre>". print_r($refnode,true) . "</pre>";
$newlocation = array ("value"=>$currentlocation);
$refnode->field_loacations[] = $newlocation;
#now save the reference node
node_save ($refnode);
#drupal_goto ("node/$nid");

Have you tried:
return array(
array('value' => 'United Kingdom'),
array('value' => 'United States'),
);

Related

Symfony 2.7 findOneBy() Function Finds the Wrong Entity

I've got a controller action that's supposed to be looking for semi-duplicate entries in a collection, and removing them from that Entity's list. New ones should not have an ID yet, and existing ones do, so I'm running findOneBy() with an array of parameters to match on (leaving out ID).
I am baffled and deeply troubled by the error I am getting, where it finds the wrong entity! I've got some relevant code below, I hope this is just a dream or a silly mistake, I can't reproduce the output on my own windows development environment, but my co-worker was testing on his mac, and was getting errors, so I went on his machine and did some quick echoing to see what was going on. See the code and the result below.
CODE
foreach($entity->getTechnicians() as $tech) {
//find new addtions, see if they exist
if (!$tech->getId()) {
echo "Technician " . $tech->getFirstName() . " has no ID, trying to find one that does<br/>";
$found = $em->getRepository('TechnicianBundle:Technician')->findOneBy(array(
'firstName' => $tech->getFirstName(),
'lastName' => $tech->getLastName(),
'email' => $tech->getEmail(),
'residentEngineer' => $tech->getResidentEngineer(),
'officeNumber' => $tech->getOfficeNumber()
));
//if one with an ID already exists
if ($found) {
echo "found technician " . $found->getFirstName() . " that already has id " . $found->getId() . "<br/>";
...
OUTPUT
Technician Four has no ID, trying to find one that does
found technician khjvuov that already has id 7
Probably it's not a findOneBy() issue.
If without add/remove calls it works, it may be caused by modified current pointer of ArrayCollection so when $tech->getFirstName() is called it actually points to another entry.
You may try to iterate your collection like this:
$iterator = $entity->getTechnicians()->getIterator();
while ($iterator->valid()) {
$tech = $iterator->current();
... $entity->addTechnician()/$entity->removeTechnician()
$iterator->next();
}
It will create new ArrayIterator object, so you can modify underlying object preserving ArrayCollection's internal pointer.
This may be obsolete if you are running PHP7 (reference - Note box)
Ultimately, the findOneBy() method uses the load() method of the Doctrine ORM.
In the doc, the parameter $criteria is described as such :
#param array $criteria The criteria by which to load the entity.
You should probably dig deeper into Doctrine API to make sure, but there is a big chance that in the array you are passing as an argument, only the first key => value pair is taken into account (in your example, 'firstName' => $tech->getFirstName()).
If this is the case, you'll probably need to add your own custom method in your entity repository, one that would allow you to query your database with more advanced statements (using OR/AND or LIKE() in SQL for instance).

Symfony2 Form - Complex "property" option

I have the following Entities, with the main attributes:
Location
id
name
address
type
Station
location_id
trigram
altitude
Institute
location_id
abreviation
departement
Station and Institute are "inheriting" from Location: any location_id of those 2 tables refers to an id in the Location table.
As you can guess, the idea is that the different types of locations share common characteristics (gathered in Location) but also have independant ones (gathered in the Station and Institute tables).
I also have a entity "Item", and an Item can be placed and move in a location, no matter if it is a Station or an Institute.
So in my "move Item" form, I need to display all the locations in a dropdown list to select the required one. For that, I use GenemuFormBundle - select2.
My problem: I would like to display:
"location.name - station.trigam" if location.type is Station
"location.name - intitute.abreviation" if location.type is Institute
I know that what is displayed in the "select" dropdown list is determined by the "property" option:
$builder->add('location', 'genemu_jqueryselect2_entity', array(
'class' => 'MyBundle:Location',
'property' => 'labelSelect2',
'query_builder' => function(LocationRepository $lr) {
return $lr->createQueryBuilder('l')
->orderBy('l.name', 'ASC');}
))
"labelSelect2" refers to the function getLabelSelect2() of my entity Location.
But unfortunately, even though I can know the location.type, I don't know how to access station.trigram or institute.abreviation from the function Location::getLabelSelect2().
Any idea how to do that?

drupal 7: how to access list-field's key instead of its label (field api)

I'm working on a custom theme and googled the whole day but can't find an answer to my question:
how to print out a cck list field's key instead of its label?
I think it's the right way to access fields via the field api, right?
so I try
$output = field_view_field('node', $node, 'field_list');
print render($output);
that seems to be the way to get the label value of the key|label pair. but even if i set the display options format to 'key' - it only prints the label value. what am I doing wrong?
I know there are other options to render the key but how is it possible using field api?
You can get the field value itself (which will be the allowed values array key) with field_get_items():
$items = field_get_items('node', $node, 'field_list');
$key = $items[0]['value'];
If you need to match those up again at any point you can get the full key/value list from the field metadata:
$info = field_info_field('field_list');
$values = $info['settings']['allowed_values'];
$label = $values[$key];
Here's a similar way. This example works for a Country list with ISO codes.
The idea is to render the Name of the Country that was selected because the dump returns only the key ( iso code in this case)
Format of the select list on the backend:
AR|Argentina
US|United States
Assuming you have selected United States on the backend and you want to print the country name on the node template:
$country_field = field_info_field('field_country_iso');
$country_iso = $node->field_country_iso[LANGUAGE_NONE][0]['value'];
$country_name = $country_field['settings']['allowed_values'][$country_iso];
then
print $country_name; // This will return United States, not US code
I hope this helps.

One to one relationship in Silverstripe

I'll try and put this as simply as possible but basically what I am trying to achieve is this.
There are two page types with a one to one relationship, car and owner. I want to be able te be able to select an owner through a dropdown on the car page. If an owner is already linked to another car I don't want it to appear in the dropdown.
I know that I'll need an if statement but I I'm finding it hard to puzzle out how it should go. I followed this tutorial to create the dropdown and it worked quite well.
Thanks in advance.
You can modify the function that gives you the dropdown values. Your DataObject::get() call
can have a filter for the second argument. Simply select all owners that have a CarID of 0.
So, from the tutorial you provided, you can use this modified code:
new DropdownField(
'OwnerID',
'Please choose an owner',
Dataobject::get("Owner","CarID='0'")->map("ID", "Title", "Please Select")
);
2 things to note:
This assumes your DataObjects are called Car and Owner (change as necessary, but keep the ID at the end of the name as it is written above)
This may not work depending how you set up the relationships with the $has_one assignments on your DataObjects. If there is no CarID field on the Owner table, then this code won't help you (you may have it set up vice-versa). In that case, you'll have to create a function that loops through all cars, and then removes the DataObjects from that DataObjectSet that have an OwnerID of 0. Add a comment if this isn't making sense.
Benjamin Smith' answer is perfectly valid for the dropdown you were asking for, just wanted to point to another approach: instead of taking care of the one-to-one relation yourself, there's the 'HasOneComplexTableField' handling this for you.
use the following code for your Car class:
class Car extends Page {
public static $has_one = array(
'Owner' => 'Owner'
);
function getCMSFields() {
$fields = parent::getCMSFields();
$tablefield = new HasOneComplexTableField(
$this,
'Owner',
'Owner',
array(
'Title' => 'Title'
)
);
$tablefield->setParentClass('Car');
$tablefield->setOneToOne();
$tablefield->setPermissions(array());
$fields->addFieldToTab('Root.Content.Owner', $tablefield);
return $fields;
}
}
note the 'setOneToOne()' call, telling the tablefield to only let you select Owners which aren't already selected on another car.
you'll find more information on this in the silverstripe tutorial: http://doc.silverstripe.org/framework/en/tutorials/5-dataobject-relationship-management

how to customise search results of apachesolr (drupal 6)

can somebody help me how to customize the search result of a apache solr search. i was only able to access these variables [comment_count] => [created] => [id] => [name] => [nid] => [title] => [type] => [uid] => [url] => [score] => [body].
how can i access other variable like status, vote .... from the index ( i don't want to access the database for retrieving these values, i want to get it from the index itself)
i need to display no of votes for that specific node in the result snippet
i need to understand
1. how to index votes field
2. how to show the vote, status... in result snippet.
Votes are a poor choice for indexing for a couple of reasons:
Votes can change quickly
When a vote is made, the node is not updated. As such, apachesolr won't know to re-index the node to pick up the change.
If by 'status' you mean the node->status value, then the answer is that it will always be 1. Unpublished nodes are never indexed.
Now, if you want to add something else to the index, you want hook_apachesolr_update_index(&$document, $node) - this hook gets called as each node is being indexed, and you can add fields to $document from $node to get the values into the solr index. However, you want to use the pre-defined field prefixes - look at schema.xml to find the list.
Below is example of code to add fields for sorting, and for output.
/**
* Implementation of hook_apachesolr_update_index()
* Here we're adding custom fields to index, so that they available for sorting. To make this work, it's required to re-index content.
*/
function somemodule_apachesolr_update_index(&$document, $node) {
if ($node->type == 'product') {
$document->addField('sm_default_qty', $node->default_qty);
$document->addField('sm_sell_price', $node->sell_price);
$document->addField('sm_model', $node->model);
foreach ($node->field_images AS $image) {
//$imagecached_filepath = imagecache_create_path('product', $image['filepath']);
$document->addField('sm_field_images', $image['filepath']);
}
}
}
/**
* Implementation of hook_apachesolr_modify_query()
* Here we point what additional fields we need to get from solr
*/
function somemodule_apachesolr_modify_query(&$query, &$params, $caller) {
$params['fl'] .= ',sm_default_qty,sm_field_images,sm_sell_price,sm_model';
}
If you want to totally customize output, you should do following:
1) Copy search-results.tpl.php and search-result.tpl.php from /modules/search to your theme's folder.
2) Use the $result object as needed within search-result.tpl.php
3) Don't forget to clear the theme registry by visiting admin/build/themes
Or as mentioned about, you can override using preprocessor hooks.
Regards, Slava
Another option is to create a view(s) of your liking with input argument nid, then create the following preprocess in your template.php file:
function MYTHEME_preprocess_search_result(&$vars) {
$vars['myView'] = views_embed_view('myView', 'default', $vars['result']['node']->nid);
}
Matching the view name 'myView' with the variable name makes sense to me. Then you can use the variable $myView in your search-results.tpl.php file.
Here's a video by the makers of the Solr Search Integration module with an overview on how to customise what nodes and fields are indexed, and what Solr spits out as a search result...
For Drupal 6:
http://sf2010.drupal.org/conference/sessions/apache-solr-search-mastery.html
And Drupal 7:
http://www.acquia.com/resources/acquia-tv/conference/apache-solr-search-mastery
It all looks very customisable!

Resources