i want to change or modify all taxonomy pages i write this piece of code in template.php in my bartik theme but some weird things happens.
the $term argument in second function "bartik_term_page" is null.
what is missing?
and it sometimes an error like this
it gives an error.
Warning: Parameter 1 to bartik_term_page() expected to be a reference, value given in menu_execute_active_handler() (line path\includes\menu.inc).
function bartik_menu_alter(&$menu) {
$menu['taxonomy/term/%']['page callback'] = 'bartik_term_page';
$menu['taxonomy/term/%']['access arguments'] = array('access content');
}
function bartik_term_page(&$term){
$voc = taxonomy_vocabulary_load($term->vid);
var_dump( $term ); die();
// here you generate the actual content of the page
// could be done e.g. with an entityfieldquery as follows
$query = new EntityFieldQuery();
$query->entityCondition('entity_type', 'node')
->fieldCondition('field_category', 'tid', $term->tid);
$result = $query->execute();
if (!empty($result['node'])) {
$build['content']['nodes'] = node_view_multiple(node_load_multiple(array_keys($result['node'])), 'teaser'); // output the node teasers. you can control the markup of the 'teaser' view mode with a template in the theme folder
} else {
$build['content']['status']['#markup'] = t('No results found for term ID !tid.', array('!tid' => $term->tid));
}
return $build;
}
You're actually introducing a new router item there instead of overriding the existing one.
The path for the taxonomy page is taxonomy/term/%taxonomy_term, so...
function bartik_menu_alter(&$menu) {
$menu['taxonomy/term/%taxonomy_term']['page callback'] = 'bartik_term_page';
$menu['taxonomy/term/%taxonomy_term']['access arguments'] = array('access content');
}
Clear caches and you should be good to go.
Add the following line after the 'page callback' line in your bartik_menu_alter() function:
$menu['taxonomy/term/%']['page arguments'] = array(3);
This tells Drupal where to find the parameter in your URL (it's the third component).
Related
I am creating a plugin. I want to pass parameters in URL or you can say I want multiple URLs for same page(But this will load same page Not a Redirect).
For example:
http://www.ijmsbr.boxysolutions.com/publications-of-ijmsbr/?data=2016-11
I want this URL in this structure
http://www.ijmsbr.boxysolutions.com/publications-of-ijmsbr/2016-11/
and these will be multiple links like
publications-of-ijmsbr/2016-11/
publications-of-ijmsbr/2016-12/
publications-of-ijmsbr/2017-01/
But all links should load this one page
publications-of-ijmsbr/
http://www.ijmsbr.boxysolutions.com/publications-of-ijmsbr/
this is my custom page. I want to get these parameters (/2016-11/, /2016-12/) on my page.
Resolved
First we'll add filter to set query variables. Remember you've to call flush_rewrite_rules() each time when you'll add new variable in array. Once you've run flush_rewrite_rule function after that you can comment or delete this line.
function themeslug_query_vars( $qvars ) {
$qvars[] = 'jm_volume';
$qvars[] = 'jm_art_id';
$qvars[] = 'jm_author';
//flush_rewrite_rules();
return $qvars;
}
add_filter( 'query_vars', 'themeslug_query_vars' , 10, 1 );
After registration of query variables we can add add_rewrite_rules and assign to our URL like this. Remember to call flush_rewrite_rules() function
function add_rewrite_rules($aRules) {
$aNewRules = array(
'publications-of-ijmsbr/article/(.*)?' => 'index.php?pagename=publications-of-ijmsbr&jm_art_id=$matches[1]',
'publications-of-ijmsbr/author/(.*)?' => 'index.php?pagename=publications-of-ijmsbr&jm_author=$matches[1]',
'publications-of-ijmsbr/(.*)?' => 'index.php?pagename=publications-of-ijmsbr&jm_volume=$matches[1]'
);
$aRules = $aNewRules + $aRules;
//flush_rewrite_rules();
return $aRules;
}
add_filter('rewrite_rules_array', 'add_rewrite_rules');
I have to add to my cart some line items with a custom amount.
The commerce product is saved with price = 0, and my module compute the price and add the line item to the cart/order, but i dont understand how to set programmatically the price.
I've read about using Rules, but I need my module to be able to set/alter the price, without invoking rules.
I've tryed with an entity wrapper, i tryed to alter the line item created with commerce_product_line_item_new(), but nothing, when the line item gets into the cart always has the original product price (in my case, 0).
How to alter a line item price programmatically?
My code so far looks like:
// For debugging, this function is called by hook_menu()
function mymodule_test($product_id)
{
global $user;
$user = user_load($user->uid);
$order = commerce_cart_order_load($user->uid);
$order_wrapper = entity_metadata_wrapper('commerce_order', $order);
$product = commerce_product_load($product_id);
$line_item = commerce_product_line_item_new(
$product,
1,
0,
array(
),
'cover'
);
$line_item_wrapper = entity_metadata_wrapper("commerce_line_item", $line_item);
$line_item_wrapper->commerce_unit_price->data = commerce_price_component_add(
$line_item_wrapper->commerce_unit_price->value(),
'base_price',
array(
'amount' => 1234,
'currency_code' => 'EUR',
'data' => array(),
),
TRUE
);
$insert_line_item = commerce_cart_product_add($user->uid, $line_item_wrapper->value(), FALSE);
return 'done';
}
The strange thing, is that I tryed to adapt the code of commerce_line_item_unit_price_amount() found in commerce/modules/line_item/commerce_line_item.rules.inc, but this test:
<?php
global $user;
$product = commerce_product_load(4); // my commerce product for test
$line_item = commerce_product_line_item_new(
$product,
1,
0,
array(
),
'cover' // I do have this line_items type
);
// manually set amount and component name
$amount = 1234;
$component_name = 'base_price'; // tryed with discount, nothing change
$wrapper = entity_metadata_wrapper('commerce_line_item', $line_item);
$unit_price = commerce_price_wrapper_value($wrapper, 'commerce_unit_price', TRUE);
// Calculate the updated amount and create a price array representing the
// difference between it and the current amount.
$current_amount = $unit_price['amount'];
$updated_amount = commerce_round(COMMERCE_ROUND_HALF_UP, $amount);
$difference = array(
'amount' => $updated_amount - $current_amount,
'currency_code' => $unit_price['currency_code'],
'data' => array(),
);
// Set the amount of the unit price and add the difference as a component.
$wrapper->commerce_unit_price->amount = $updated_amount;
$wrapper->commerce_unit_price->data = commerce_price_component_add(
$wrapper->commerce_unit_price->value(),
$component_name,
$difference,
TRUE
);
$insert_line_item = commerce_cart_product_add($user->uid, $line_item, FALSE);
?>
still fail, the line_item get into the cart but with the original price of the referenced product.
Any idea?
For those people who don't want to use rules and hope to alter the price directly. Here is my solution:
// Alter the price in list and single product page.
function my_module_commerce_product_calculate_sell_price_line_item_alter($line_item){
$price = 100; //1 dollar
$line_item->commerce_unit_price[LANGUAGE_NONE]['0']['amount'] = $price;
}
// Alter the price in cart & order.
function my_module_commerce_cart_line_item_refresh($line_item, $order_wrapper){
$price = 100; //1 dollar
$line_item->commerce_unit_price[LANGUAGE_NONE]['0']['amount'] = $price;
// Alter the base_price component.
$line_item->commerce_unit_price[LANGUAGE_NONE]['0']['data']['components']['0']['price']['amount'] = $price;
}
If you're looking to ignore whatever previous values have been saved to a line item and recalculate the total from your new amount the function you're looking for is commerce_line_item_rebase_unit_price.
Set the new amount value and then run your line item through there, save the line item and the order:
$line_item_wrapper->commerce_unit_price->amount = 13;
commerce_line_item_rebase_unit_price($line_item_wrapper->value());
commerce_line_item_save($line_item_wrapper->value());
I struggled through this issue all day today and final figured out the correct path to altering line items prices. The problem is that, even if you successfully change the line item price to a custom value, on the next page refresh the cart will reset the line items to match the original product price. Take a look at the commerce_cart_order_refresh() function for details. This function is executed every time an order/cart is loaded on the page and there is no way around it.
It turns out that the proper way to alter a line item price is to either use Rules or to implement the hook_commerce_cart_line_item_refresh() function. Either way, Drupal Commerce need to be able to apply the alteration logic each time the cart/order is loaded.
I ended up creating a custom field in the Line Item where I stored the custom price value I wanted. I then used a Pricing Rule to copy the custom price value to the product price value whenever the cart is refreshed.
The following blog post was very helpful in figuring this out. It shows you how to add a custom field to a line item type and how to setup a pricing rule to copy the custom amount to the unit price.
http://commerceguys.com/blog/using-custom-line-items-provide-donation-feature-drupal-commerce
Recently I had to implement a donation form in Commerce but the Commerce Express Checkout module doesn't handle custom line items. Since it was a donation and all (who is trying to screw the house?), I felt it appropriate to pass the donation amount as a 3rd parameter in URL the Express Checkout module provides. Here is how I went about hacking the module:
I added a new entry to the router:
$items['commerce-express-checkout/%/%/%'] = array(
'title' => 'Express Checkout w/ extra argument',
// 'page callback' => 'commerce_express_checkout_create_order',
'page callback' => 'commerce_express_checkout_create_order_extra',
'page arguments' => array(1, 2, 3),
'access arguments' => array('access checkout'),
'type' => MENU_CALLBACK,
);
I duplicated and tweaked the default callback and tacked '_extra' to it. Note that the "data" property seems to be a static variable store for occasions just such as this and persists the life of the line item.
function commerce_express_checkout_create_order_extra($product_id, $token, $amount) {
if (drupal_hmac_base64($product_id, drupal_get_private_key().drupal_get_hash_salt()) == $token && is_numeric($amount)) {
global $user;
$product = commerce_product_load($product_id);
$product->commerce_price['und'][0]['amount'] = (int)$amount;
$order = ($user->uid) ? commerce_order_new($user->uid, 'checkout_checkout') : commerce_cart_order_new();
commerce_order_save($order);
$price = array('amount' => commerce_round(COMMERCE_ROUND_HALF_UP, $amount), 'currency_code' => commerce_default_currency());
$line_item = commerce_product_line_item_new($product, 1, $order->order_id);
$line_item->data = array('und' => array('0' => $price));
commerce_line_item_save($line_item);
$order_wrapper = entity_metadata_wrapper('commerce_order', $order);
$order_wrapper->commerce_line_items[] = $line_item;
$order->data['type'] = 'commerce_express_checkout_order';
commerce_order_save($order);
drupal_goto('checkout/' . $order->order_id);
return "";
}
return "";
}
Here is the part that ended up being most tricky simply due to the learning curve and not knowing what the heck function to use:
/**
* Implements hook_commerce_cart_line_item_refresh().
*/
function commerce_express_checkout_commerce_cart_line_item_refresh($line_item, $order_wrapper) {
if ($line_item->commerce_product['und'][0]['line_item_label'] == 'DONATE' || $line_item->commerce_product['und'][0]['product_id'] == '11') {
$price = array('amount' => commerce_round(COMMERCE_ROUND_HALF_UP, $line_item->data['und'][0]['amount']), 'currency_code' => commerce_default_currency());
$line_item->commerce_unit_price = array('und' => array('0' => $price));
$line_item_wrapper = entity_metadata_wrapper('commerce_line_item', $line_item);
$line_item_wrapper->commerce_unit_price->data = commerce_price_component_add(
$line_item_wrapper->commerce_unit_price->value(), 'base_price', $price, TRUE
);
}
}
Every single time the cart is modified, it refreshes and attempts to set the products in the cart to their in-code prototype. It seems pretty inefficient to me too, but I could be missing something.
This post pointed me in the right direction for programmatically altering a drupal commerce line item by using hook_commerce_cart_line_item_refersh(). However, some of the answers here are either outright wrong, or very inefficient and sloppy.
This would be a correct working solution for altering the line item type in Drupal Commerce:
/*
* implements hook_commerce_cart_line_item_refresh()
*
*/
function MYMODULE_commerce_cart_line_item_refresh($line_item, $order_wrapper){
$line_wrapper = entity_metadata_wrapper('commerce_line_item', $line_item);
$new_price = 100; //I use a function to calculate the value of $new_price
if(!empty($new_price)){
$line_wrapper->commerce_unit_price->amount->set($new_price);
$line_wrapper->save();
}
}
I have a vocab category and four terms within it. what i want to do is if content is tagged with a termin in particular say "term1" to have the url generated as word1/[node:title] and for all the other tags just the standard url formatting.
If i wanted the term in the url obviously id use pattern replacement but i want another word to be used if a particular tag is used
I can't think of an easy plug-and-play way of achieving this. You may have to create your own token for the "Default path pattern" in Pathauto's URL alias settings:
/**
* Implementation of hook_token_info().
*/
function MODULE_token_info() {
$info['tokens']['node']['node-term-path'] = array(
'name' => t('Node path by term'),
'description' => t('The path to a node based on its taxonomy terms.'),
);
return $info;
}
/**
* Implementation of hook_tokens().
*/
function MODULE_tokens($type, $tokens, array $data = array(), array $options = array()) {
$replacements = array();
if ($type == 'node' && !empty($data['node'])) {
$node = $data['node'];
foreach ($tokens as $name => $original) {
switch ($name) {
case 'node-term-path':
$items = field_get_items('node', $node, 'TAXONOMY_FIELD_NAME');
foreach ($items as $item) {
$tids[] = $item['tid'];
}
if (in_array(TID_OF_TERM1, $tids)) {
// Path for nodes with term1
$replacements[$original] = 'word1/'. pathauto_cleanstring($node->title);
}
else {
// Path for other nodes
$replacements[$original] = 'content/'. pathauto_cleanstring($node->title);
}
break;
}
}
}
return $replacements;
}
Found a simple way actually to anyone who need a similar solution use the module Entity Reference.
http://drupal.org/project/entityreference
I just created a new field for the user account select entity reference then you can choose any entity within drupal to reference.
(ie so you can select a term/content/anything)
I'm trying to create a permalink pattern for a Custom Type, that includes one of its taxonomies. The taxonomy name is known from the start (so I'm not trying to add or mix all of its taxonomies, just a specific one), but the value will by dynamic, of course.
Normally, the Custom Type permalink is built using the rewrite arg with the slug param, but I don't see how I could add a dynamic variable in there.
http://codex.wordpress.org/Function_Reference/register_post_type
I'm guessing a custom solution is required, but I'm not sure what the best unintrusive approach would be.
Is there a known practice for this or has anyone built something similar recently? I'm using WP 3.2.1 btw.
After more searching I managed to create fairly elegant solution using the custom_post_link filter.
Let's say you have a project Custom Type with a client Taxonomy. Add this hook:
function custom_post_link($post_link, $id = 0)
{
$post = get_post($id);
if(!is_object($post) || $post->post_type != 'project')
{
return $post_link;
}
$client = 'misc';
if($terms = wp_get_object_terms($post->ID, 'client'))
{
$client = $terms[0]->slug;
//Replace the query var surrounded by % with the slug of
//the first taxonomy it belongs to.
return str_replace('%client%', $client, $post_link);
}
//If all else fails, just return the $post_link.
return $post_link;
}
add_filter('post_type_link', 'custom_post_link', 1, 3);
Then, when registering the Custom Type, set the rewrite arg like this:
'rewrite' => array('slug' => '%client%')
I guess I should have dug deeper before asking, but at least we have a complete solution now.
I have been going through the docs and source code looking for something without luck.
Is there a Drupal 6 hook that gets called after hook_search(), but before the $results gets handed off to the template system?
I need to do a fairly custom pruning and reordering of results that get returned. I could just reimplement hook_search(), but this seems like overkill.
Thanks.
There isn't; search_view() (which displays the results) calls search_data(), which invokes hook_search() then immediately themes the results. Re-implementing hook_search() is probably the most straightforward route.
With that said, you could instead implement hook_menu_alter() and have the search page call your custom function instead of calling search_view() (and subsequently calling search_data()). Something like:
function test_menu_alter(&$items) {
$items['search']['page callback'] = 'test_search_view';
foreach (module_implements('search') as $name) {
$items['search/' . $name . '/%menu_tail']['page callback'] = 'test_search_view';
}
}
// Note: identical to search_view except for --- CHANGED ---
function test_search_view($type = 'node') {
// Search form submits with POST but redirects to GET. This way we can keep
// the search query URL clean as a whistle:
// search/type/keyword+keyword
if (!isset($_POST['form_id'])) {
if ($type == '') {
// Note: search/node can not be a default tab because it would take on the
// path of its parent (search). It would prevent remembering keywords when
// switching tabs. This is why we drupal_goto to it from the parent instead.
drupal_goto('search/node');
}
$keys = search_get_keys();
// Only perform search if there is non-whitespace search term:
$results = '';
if (trim($keys)) {
// Log the search keys:
watchdog('search', '%keys (#type).', array('%keys' => $keys, '#type' => module_invoke($type, 'search', 'name')), WATCHDOG_NOTICE, l(t('results'), 'search/'. $type .'/'. $keys));
// Collect the search results:
// --- CHANGED ---
// $results = search_data($keys, $type);
// Instead of using search_data, use our own function
$results = test_search_data($keys, $type);
// --- END CHANGED ---
if ($results) {
$results = theme('box', t('Search results'), $results);
}
else {
$results = theme('box', t('Your search yielded no results'), search_help('search#noresults', drupal_help_arg()));
}
}
// Construct the search form.
$output = drupal_get_form('search_form', NULL, $keys, $type);
$output .= $results;
return $output;
}
return drupal_get_form('search_form', NULL, empty($keys) ? '' : $keys, $type);
}
// Note: identical to search_data() except for --- CHANGED ---
function test_search_data($keys = NULL, $type = 'node') {
if (isset($keys)) {
if (module_hook($type, 'search')) {
$results = module_invoke($type, 'search', 'search', $keys);
if (isset($results) && is_array($results) && count($results)) {
// --- CHANGED ---
// This dsm() is called immediately after hook_search() but before
// the results get themed. Put your code here.
dsm($results);
// --- END CHANGED ---
if (module_hook($type, 'search_page')) {
return module_invoke($type, 'search_page', $results);
}
else {
return theme('search_results', $results, $type);
}
}
}
}
}
You can use hook_search_page() to reorder or format the search result.
Hook search_execute allows you to modify the query in the way you needed. You can even fire new queries with custom sql, for example:
function mymodule_search_execute($keys = NULL, $conditions = NULL) {
// Do some query here.
$result = my_fancy_query();
// Results in a Drupal themed way for search.
$results[] = array(
'link' => (string) $result->U,
'title' => $title,
'snippet' => $snippet,
'keys' => check_plain($keys),
'extra' => array($extra),
'date' => NULL,
);