I'm building an Address Book view based on a simple CCK that I built.
I need to pass the initial letter as argument to the view in order to show only the elements starting with the received letter. How can I do it using Drupal Views? I've searched in arguments but cannot find a way to get substring support but only node/user references or CCK fields.
If you use this:
$view = views_get_view('masvisitados');
$view->execute();
print_r( $view->render() );
It will render with the markup, but If you just want the data (like me), you can try this:
$view = views_get_view('masvisitados');
$view->preview('Mas visitados', 4);
$view = $view->result;
print_r( $view );
It returns an array.
That's exactly what a "glossary view" does. Navigate to /admin/build/views on your site. If the default view called "glossary" is disabled, enable it. You can now edit/inspect/try it to see how it works. The key is in the 'Node: Title' argument, where the "glossary mode" checkbox is selected. For your address book, you can duplicate it and add a filter on the desired node type.
...
$view->set_exposed_input( array('field1' => data1, 'field2' => 'some data') );
...
Related
I have archive page of movies in which I am presenting all movies paginated. On side bar I have genres(taxonomy) for movies. When user clicks on one I want results on the page to be filtered according to which genre he clicked.
My way of thinking made me do this using query string in URL. So when user click on genre it requests same URL (archive for movies) but adds ?genre=SOMETHING. Then in pre_get_posts hook I have this if statement to modify main query:
if(
!is_admin() &&
$query->is_main_query() &&
is_post_type_archive('movie') &&
get_query_var('genre')
)
Then after that I have code like this to filter movies by genre user clicked on :
$taxonomyQuery = [
[
'taxonomy' => 'genre',
'field' => 'slug',
'terms' => get_query_var('genre'),
],
];
$query->set('tax_query', $taxonomyQuery);
Sidebar link are constructed like this :
<a href="<?php echo esc_url(add_query_arg('genre', $genre->slug)) ?>">
<?php echo $genre->name; ?>
</a>
Taxonomy is created with name genre so that name is automatically added to query_vars.
When I open archive page of movies /movies/ I get paginated results and everything works fine. But once I click on genre I get this path /movies/?genre=comedy.
pre_get_posts activates and filters movies according to the genre selected but pagination doesnt work. Even if I set $query->set('posts_per_page', 1); I still get more than one result returned from query. Problem only occurs when query string ?genre=SOMETHING gets added to URL and I cannot figure out why.
NOTE: I am relatively new to wordpress development and I do not actually know if this is the right way to do this kind of thing.
Any help is appreciated!
So after some testing with different things I got to this conclusion.
When I registered taxonomy with register_taxonomy I did not place 'query_var' property as I thought it is adding query string value like when you use :
add_filter('query_vars', 'demo_query_vars');
function demo_query_vars($queryVars) {
$queryVars[] = 'genre';
return $queryVars;
}
These two thing are not the same. First one enables you to load taxonomy using query_var. From the docs :
Sets the query var key for this taxonomy. Default `$taxonomy` key. If false, a taxonomy cannot be loaded at `?{query_var}={term_slug}`. If a string, the query `?{query_var}={term_slug}` will be valid.
Second one enables custom query_var and query string to be used, which is what i needed.
FIX: Just disable query_bar 'query_var' => false'
Then add code I posted above to allow query variable to be processed (add_filter function) and you will be able to use your query_var.
NOTE: This problem was caused for me because I my taxonomy is called genre therfore query_var in register_taxonomy function is automatically set to this value. And I also wanted to use the same name for my own custom query_var which made conflicts.
If your taxonomy name is different from your query_var (the query string you wich to use, example if I used ?g=SOMETHING instead of ?genre=SOMETHING) YOU WILL NOT run into this problem since there will be no conflicts between these two variables..
Another possible solution would be to make your custom query_var different than one specified in register_taxonomy if you are using query_var defined in register_taxonomy function. They just need to be different so there are no conflicts.
I am just at the beginning so this potentially could not be right but it for sure has something to do with these 2 variable names being the same.
What's the easiest way to edit the default success message when saving an item in GridField edit view?
The message seems to be in a variable in class GridFieldDetailForm within method doSave.
$message = _t(
'GridFieldDetailForm.Saved',
'Saved {name} {link}',
array(
'name' => $this->record->i18n_singular_name(),
'link' => $link
)
);
Since the message uses the _t() function it will attempt to fetch the value defined in the lang file corresponding to the current user's locale. The default string defined in the function is just a fallback for when no translation could be found within the lang files.
To change the message you can update your site's yml lang file located in mysite/lang/{LANGUAGE_CODE}.yml
For english this would be:
# mysite/lang/en.yml
# remember to flush after editing me :-)
en:
GridFieldDetailForm:
Saved: 'My custom message using {name} and here is a link to the object: {link}'
https://docs.silverstripe.org/en/3.4/developer_guides/i18n/
Something like this should work for specific implementations
$form = $gridField->getConfig()->getComponentByType('GridFieldDetailForm');
$form->setItemEditFormCallback(function($form, $itemRequest)
{
// Replace save action with custom method in here
});
For more general implementations, you'll likely want to extend GridFieldDetailForm and override doSave, then replace the GridFieldDetailForm component with your custom class.
I have some custom post type "video" and I added some custom ACF fields to it ("video_path", "author_name" and "audio_author"). I'm generating posts in that type programmatically like this:
$video_post_params = array(
'post_title' => wp_strip_all_tags($video_title),
'post_status' => 'publish',
'post_author' => 1,
'post_type' => 'video'
);
$video_id = wp_insert_post( $video_post_params );
update_field('video_path', $video_path, $video_id);
update_field('author_name', $video_author, $video_id);
update_field('audio_author', $audio_author, $video_id);
All values are inserted well - when I open the post in back-end everything is fine. However, when I try to use those values, I don't get anything?!?
I'm reading values from template files like this:
get_field('video_path', $video_id)
And if I open the post and just save it without any change everything starts working normally and I'm getting post ACF fields normally after that. Posts created manually, from back-end are working well all the time.
What I'm doing wrong? Do I need some extra step when generating posts from code?
The issue is reported here:
http://support.advancedcustomfields.com/forums/topic/programmatic-post-insertion-acf-fields-and-the-save_post-hook/
But that solution is obviously not working for me - my update_field() functions already are immediately after wp_insert_post().
Found it!
When inserting ACF field value field key must be used. If key name is used instead, as I did, everything is inserted well at first look, but value isn't available until post is saved manually. So it's like:
update_field('field_56e683ab6265f', $video_path, $video_id);
update_field('field_56e68415b5c4b', $video_author, $video_id);
update_field('field_56e6842d58740', $audio_author, $video_id);
What a mess....
If you want to use the field name instead of the field key, you can use add_post_meta
For example:
add_post_meta($video_id, 'video_path', $video_path, true);
add_post_meta($video_id, 'author_name', $video_author, true);
add_post_meta($video_id, 'audio_author', $audio_author, true);
With ACF5 you have to use not post id, but post object, lake that:
update_field('field_56e683ab6265f', $video_path, $video);
update_field('field_56e68415b5c4b', $video_author, $video);
update_field('field_56e6842d58740', $audio_author, $video);
I had the same problem, and I correct it with simply add do_action('acf/save_post', $postID); at the end of the script, and that's all…
Using the autocomplete field for a cck nodereference always displays the node id as a cryptic bracketed extension:
Page Title [nid:23]
I understand that this ensures that selections are unique in case nodes have the same title, but obviously this is a nasty thing to expose to the user.
Has anyone had any success in removing these brackets, or adding a different unique identifier?
Ultimately, you need to change the output of nodereference_autocomplete() in nodereference.module.
To do this properly, you want a custom module to cleanly override the function.
This function is defined as a menu callback, thus,
/**
* Implementation of hook_menu_alter().
*/
function custom_module_menu_alter(&$items) {
$items['nodereference/autocomplete']['page callback'] = 'custom_module_new_nodereference_autocomplete';
}
Then, copy the nodereference_autocomplete function into your custom module, changing it's name to match your callback. Then change this one line:
$matches[$row['title'] ." [nid:$id]"] = '<div class="reference-autocomplete">'. $row['rendered'] . '</div>';
Dropping the nid reference.
$matches[$row['title']] = '<div class="reference-autocomplete">'. $row['rendered'] . '</div>';
I believe the identifier is purely cosmetic at this point, which means you could also change the text however you like. If it is not purely cosmetic, well, I haven't tested to see what will happen in the wrong conditions.
I always meant to identify how to do this. Thank you for motivating me with your question.
What Grayside has posted will work... as long as you don't have two nodes with the same title. In other words, if you want to do as Grayside has proposed, you need to be aware that the nid is not entirely unimportant. The nodereference_autocomplete_validate() function does two things. It checks to see if there is a node that matches, and if so, it passes the nid on, setting it to the $form_state array. If it can't find a node, it will set an error. If the nid is present, it will be used to get the node, which also is faster, the code is here:
preg_match('/^(?:\s*|(.*) )?\[\s*nid\s*:\s*(\d+)\s*\]$/', $value, $matches);
if (!empty($matches)) {
// Explicit [nid:n].
list(, $title, $nid) = $matches;
if (!empty($title) && ($n = node_load($nid)) && $title != $n->title) {
form_error($element[$field_key], t('%name: title mismatch. Please check your selection.', array('%name' => t($field['widget']['label']))));
}
}
This just checks to see if there is a nid and checks if that node matches with the title, if so the nid is passed on.
The 2nd option is a bit slower, but it is here errors can happen. If you follow the execution, you will see, that if will try to find a node based on title alone, and will take the first node that matches. The result of this, is that if you have two nodes with the same title, one of them will always be used. This might not be a problem for you, but the thing is, that you will never find out if this happens. Everything will work just fine and the user will think that he selected the node he wanted to. This might be the case, but he might as well have chosen the wrong node.
So in short, you can get rid of the nid in the autocomplete callback, but it has 2 drawbacks:
performance (little)
uncertainty in selecting the correct node.
So you have to think about it, before going this route. Especially, since you most likely wont be able to find the problem of the selection of the wrong nodes, should it happen. Another thing to be aware of, is that the nid showing up, also brings some valuable info to the users, a quick way to lookup the node, should they be in doubt if it is the one they want, if several nodes have similar titles.
I got Grayside's answer to work, but I had to use MENU alter, instead of the FORM alter he posted. No biggy!
function custommodule_menu_alter(&$items) {
$items['nodereference/autocomplete']['page callback'] = 'fp_tweaks_nodereference_autocomplete';
}
I've found an alternative solution is to change your widget type to select list and then use the chosen module to convert your list to an autocomplete field.
This handles nodes with the same title, and actually I think the UI is better than the one provided by the autocomplete widget.
To anyone coming across this (rather old) topic by way of a google search - for Drupal 7 please consider using entityreference module and "Entity Reference" field type if possible.
You can acheive a lot more in configuration with an "Entity Reference" field. It doesn't have this problem with the nid in square brackets.
Here is the full Drupal 7 version (References 7.x-2.1) of Grayside's answer. This goes in your custom module:
/**
* Implementation of hook_menu_alter().
*/
function custom_menu_alter(&$items) {
$items['node_reference/autocomplete/%/%/%']['page callback'] = 'custom_new_node_reference_autocomplete';
}
/**
* Implementation of Menu callback for the autocomplete results.
*/
function custom_new_node_reference_autocomplete($entity_type, $bundle, $field_name, $string = '') {
$field = field_info_field($field_name);
$instance = field_info_instance($entity_type, $field_name, $bundle);
$options = array(
'string' => $string,
'match' => $instance['widget']['settings']['autocomplete_match'],
'limit' => 10,
);
$references = node_reference_potential_references($field, $options);
$matches = array();
foreach ($references as $id => $row) {
// Markup is fine in autocompletion results (might happen when rendered
// through Views) but we want to remove hyperlinks.
$suggestion = preg_replace('/<a href="([^<]*)">([^<]*)<\/a>/', '$2', $row['rendered']);
// Add a class wrapper for a few required CSS overrides.
$matches[$row['title']] = '<div class="reference-autocomplete">' . $suggestion . '</div>'; // this is the line that was modified to remove the "[nid:XX]" disambiguator
}
drupal_json_output($matches);
}
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!