First I'll outline how I understand your set-up, along with my assumptions, because without seeing any code it is tricky to follow exactly:
I assume you are using an up-to-date Drupal 7, with the latest node reference and flag module. If you aren't up-to-date you should be, if you are using anything less than D7 this most likely won't work. With D8 you may be ok, but I haven't had a chance to test it.
You have a content type Applicant Profile
which the user can create, my assumption is that they can create multiple profiles?
You have your Apply Now
flag which is set to appear on your advertised jobs, assuming that Job
is a content type.
When a user clicks Apply Now
on a Job
they are taken to the flag confirmation form, which asks them to select their Applicant Profile
and fill out some text.
If all of the above are true then there isn't a way to accurately select the correct application profile automatically, because they can create more than one (and may wish to select one on an arbitrary choice), however you can make some educated guesses.
field settings
I'm not sure how you are displaying the Applicant Profiles
in the select box, you may just be relying on the content type checkbox in the field settings of your Applicant Name
node reference... if so, you should switch to using a view to select the items to display. This way you have greater control on how the list is generated... which includes being able to control the order of display. You'll find the following section at the bottom of the field settings form for a node reference field. Before you can use it however you need to create a references
view.

You should define this view so that it works with your profile content type and orders by most recent content at the top. Once editing the view add a references
display. Set this display to take a UID as a contextual argument, that gets its value from the logged in user if there is no argument passed. Then set your view up to display whatever text you want for each application profile and make sure you are filtering to only show those profiles owned by the UID.
bespoke code
It would be best for the next step if you were to create your own bespoke module that best describes (and keeps contained) the changes you are making. Usually developers either use the project name (for the core project module) or the name of the add-on you might be building. If you already have a bespoke module that may fit the bill you can merge the following code into that module. If the module already has a hook_form_alter
implemented, just copy the if ( $form_id === 'flag_confirm' ) { ... }
block into that hook. Remember you will have to replace HOOK_
with the name of your module. For example, my most recent module was called tate_microsites
so the hook would be tate_microsites_form_alter
.
NOTE: If you haven't created any bespoke modules before you can also copy this code into your site's theme template.php
(making sure you replace HOOK_
with your theme name i.e. bartik_form_alter
).
/**
* Implements hook_form_alter().
*
* Steps in, finds the flag confirmation form, and causes the
* 'Applicant Name' field to select its second most item.
*/
function HOOK_form_alter(&$form, &$form_state, $form_id) {
if ( $form_id === 'flag_confirm' ) {
/// make sure our form has the field we are looking for
if ( !empty($form['field_applicant_name']) ) {
$und = LANGUAGE_NONE;
/// grab out the possible options, rendered by our view
$options = &$form['field_applicant_name'][$und]['#options'];
/// shift on to avoid the _none option
next($options);
/// Set the default value to the second item, using its key.
$form['field_applicant_name'][$und]['#default_value'] = key($options);
}
}
}
Once this code is in your site remember to clear caches and then visit the form in question, you should see that the first real item in the list is selected. This makes the assumption that the user will want to select their most recently created profile, but seeing as the select box is still accessible they can choose another if they so wish.
troubleshooting
If you find the above doesn't work you will need to make certain that the $form_id
and field name are correct, and that you have replaced HOOK_
with the correct name for where you are placing the code. If you are using a specific language you may need to alter the use of LANGUAGE_NONE
to the language of your choice. If it still fails make sure that you have cleared caches and do not have any other caching systems that could be causing issues like varnish, memcache or APC.
workings
Just to explain how I arrived at this solution — as the pattern is generally the same for most simple Drupal modifications — first off you need to choose your hook. In this case, because we wish to modify the way a field is behaving, your first place to look is always either hook_form_alter
or hook_field_preprocess
. I went for the former this time because I knew I wanted the field items to be fully calculated, and by the time we are in form_alter
this is the case. If you aren't aware of what Drupal hooks are available you can normally search Google with the keywords "drupal hook" and whatever else you are attempting, to uncover a lot of information. However, there is also this list, which is by no means exhaustive, especially when you take into account contrib hooks from installed modules.
Anyway, once with the correct hook, I generally do the following initially:
function HOOK_form_alter(&$form, &$form_state, $form_id) {
watchdog(__FUNCTION__ . ':' . $form_id, '<xmp>' . print_r($form, TRUE) . '</xmp>');
}
NOTE: Obviously if you have any debug modules installed you can use their debug message handling instead, but this is generally a quick fallback.
With the above code live and caches cleared, you should perform the action that will trigger the debug message. In this instance we need to visit the form we are working on. After that our debug message should be available in watchdog (remember, this will only work if you have logging enabled).
With this output we should be able to find out two things, the form id we need to target — in this case it was flag_confirm
— and the construction of the field, who's output should look like the following:
[field_applicant_name] => Array
(
[#type] => container
[#attributes] => Array
(
[class] => Array
(
[0] => field-type-node-reference
[1] => field-name-field-applicant-name
[2] => field-widget-options-select
)
)
[#weight] => 1
[#tree] => 1
[#language] => und
[und] => Array
(
[#entity] => stdClass Object
(
[flagging_id] =>
[flag_name] => apply_now
[fid] => 2
[entity_type] => comment
[entity_id] => undefined
[uid] =>
[sid] =>
)
[#entity_type] => flagging
[#bundle] => apply_now
[#field_name] => field_applicant_name
[#language] => und
[#field_parents] => Array
(
)
[#columns] => Array
(
[0] => nid
)
[#title] => Applicant Name
[#description] =>
[#required] =>
[#delta] => 0
[#type] => select
[#default_value] => Array
(
)
[#multiple] =>
[#options] => Array
(
[_none] => - None -
[297541] => Pebbl Profile
[297543] => Another profile
)
[#value_key] => nid
[#element_validate] => Array
(
[0] => options_field_widget_validate
)
[#properties] => Array
(
[strip_tags] => 1
[optgroups] => 1
[empty_option] => option_none
[filter_xss] =>
)
[#after_build] => Array
(
[0] => field_form_element_after_build
)
)
[#access] => 1
)
From this output and cross referencing with Drupal Form API you should be able to see how the end result was calculated. The two key elements are #default_value
and #options
.
Update
Well, again, without seeing more of the views and other items you have in place; it is tricky to advise. However, as long as you have your field in the flag confirmation form, that is rendering the possible applications to select, you can still use the following form_alter
to modify that field.
If your field currently lists every possible profile, then as long as you have some way of identifying which profile is owned by the currently signed in user, you can scan through the options and pick the one that is required (just like my code does above, albeit for the first item in the list).
/**
* Implements hook_form_alter().
*
* Steps in, finds the flag confirmation form, and causes the
* 'Applicant Name' field to select its second most item.
*/
function HOOK_form_alter(&$form, &$form_state, $form_id) {
global $user; /// access to the $user object
if ( $form_id === 'flag_confirm' ) {
/// make sure our form has the field we are looking for
if ( !empty($form['field_applicant_name']) ) {
$und = LANGUAGE_NONE;
/// grab out the possible options, rendered by our view
$options = &$form['field_applicant_name'][$und]['#options'];
/// start with nothing selected
$selected = '';
/// here you could implement your search code
foreach ( $options as $application_nid => $option ) {
if ( ... ) {
$selected = $application_nid;
/// update the select box to only have one option
$form['field_applicant_name'][$und]['#options'] = array(
"$selected" => $option
);
break;
}
}
if ( $selected ) {
/// Set the default value to the correct application
$form['field_applicant_name'][$und]['#default_value'] = $selected;
/// Because this field has been auto selected, and only has one option
/// you might as well hide it from the user.
$form['field_applicant_name']['#access'] = 0;
}
}
}
}
Obviously in the above you would have to replace ...
with your logic for selecting the correct application. But this all depends on exactly how you have this relationship set up in your system. You do have access to the $user
object, but you may have to make some other kind of database look-up or load to get all the information you need to find the right application. It is fully possible to node_load
each $application_nid
and compare $user->uid
against the $application->uid
, however I wouldn't recommend this, especially if the list of applications could get large. Instead, if you need to load extra information for the comparison you should look to using EntityFieldQuery to locate the application itself and then compare that against the items in the options list.
The above is still not the most optimal way of doing things, as it would be far better to have either the options list being generated based on the current logged in user by default (meaning there will only ever be one item to select, which can be achieved using views and then have the selection automatic) or to rely on the flagging relationship and ignore having the application directly selected by the user. However, without at least seeing an example export & screenshot of your attempted view (one you mentioned in your comment about displaying both Application and Pitch) I can't really aid much further.