Drupal 7 - How to retrieve Object/ID and use inside Hook Menu? - drupal

I'm using the Entity Registration Module and added a "Cancel" tab inside
function registration_menu() ...
$items['registration/%registration/view'] = array(
'title' => 'View',
'page callback' => 'registration_view',
'page arguments' => array(1),
'access callback' => 'entity_access',
'access arguments' => array('view', 'registration', 1),
'type' => MENU_DEFAULT_LOCAL_TASK,
);
$items['registration/%registration/cancel'] = array(
'title' => 'Cancel',
'page callback' => 'registration_view_cancel',
'page arguments' => array(1),
'access callback' => 'entity_access',
'access arguments' => array('view', 'registration', 1),
'type' => MENU_LOCAL_TASK,
);
which I want to hide based on the Registration State by placing that tab inside an if condition.
I couldn't figure out how to load the current "registration" object (ID is only in the URL) to read the state.
I take this works different than for node types, as this is an entity type "registration".
How best can I load that object to extract the "state" value?
See devel output below
.. (Object) Registration
entityType:protected (String, 12 characters ) registration
entityInfo:protected (Array, 25 elements)
idKey:protected (String, 15 characters ) registration_id
nameKey:protected (String, 15 characters ) registration_id
statusKey:protected (String, 6 characters ) status
defaultLabel:protected (Boolean) FALSE
registration_id (String, 3 characters ) 633
type (String, 9 characters ) classroom
entity_id (String, 4 characters ) 1426
entity_type (String, 4 characters ) node
anon_mail (NULL)
user_uid (String, 4 characters ) 1772
count (String, 1 characters ) 1
author_uid (String, 4 characters ) 1772
state (String, 8 characters ) complete
created (String, 10 characters ) 1591628269
updated (String, 10 characters ) 1591628269
UPDATE dpm($items);
admin/structure/registration (Array, 6 elements)
registration/%registration (Array, 6 elements)
test/registration2/%registration (Array, 6 elements)
test/registration2/%registration/view (Array, 6 elements)
registration/%registration/view (Array, 6 elements)
registration/%registration/edit (Array, 7 elements)
registration/%registration/delete (Array, 6 elements)
node/%entity_object/register (Array, 7 elements)
node/%entity_object/registrations (Array, 7 elements)
node/%entity_object/registrations/list (Array, 7 elements)
node/%entity_object/registrations/settings (Array, 8 elements)
node/%entity_object/registrations/broadcast (Array, 8 elements)
registration/%registration/devel (Array, 8 elements)
registration/%registration/devel/load (Array, 2 elements)
and the registration object (the page i'm on)
registration/%registration (Array, 6 elements)
title callback (String, 23 characters ) registration_page_title | (Callback) registration_page_title();
title arguments (Array, 1 element)
0 (Integer) 1
page callback (String, 17 characters ) registration_view | (Callback) registration_view();
page arguments (Array, 1 element)
0 (Integer) 1
access callback (String, 13 characters ) entity_access | (Callback) entity_access();
access arguments (Array, 3 elements)
0 (String, 4 characters ) view
1 (String, 12 characters ) registration
2 (Integer) 1

menu_alter will modify the menu based on the criteria set in the registration_cancel_visibility access callback. In this case, if the callback finds "complete" in $registration->state, it will return TRUE and the Cancel button will show, otherwise, it will remain hidden.
There is no need to add $items['registration/%registration/cancel'] under the registration_menu.
You'll likely want to change the page callback to direct the user to a cancel page/form.
Add this to your registration.module:
/**
* Implements hook_menu_alter.
*/
function registration_menu_alter(&$items) {
$items['registration/%registration/cancel'] = array(
'title' => 'Cancel',
'page callback' => 'drupal_get_form',
'page arguments' => array('registration_form', 1),
// access callback to a function to check if the menu item should be visible
'access callback' => 'registration_cancel_visibility',
'access arguments' => array('update', 1),
'weight' => 10,
'type' => MENU_LOCAL_TASK,
);
}
/**
*
* Check state of registration and apply visibility of cancel functionality accordingly
*/
function registration_cancel_visibility($action, $registration) {
// ternary operator to return TRUE or FALSE based on the value of $registration->state
return $registration->state === "complete" ? TRUE : FALSE;
}

Related

Override functionalities in Woocommerce Reports section

I need to customize the Reports in WooCommerce, so I have to edit the core file class-wc-report-sales-by-date.php, such file doesn't use any hook.
Check this in WC source code: includes/admin/reports/class-wc-report-sales-by-date.php
I have to edit the 393 line, this variable: $this->report_data->total_sales
I need to customize the Total Sales amount to add it another value.
How can I override WooCommerce this core file?
Never override core files… There is other ways made for that. If you look at line 411, you have woocommerce_admin_report_data filter hook to make changes, this way (example):
add_filter( 'woocommerce_admin_report_data', 'custom_admin_report_data', 10, 1 );
function custom_admin_report_data( $report_data ){
// HERE you make your calculations and changes
// New amout to set (example)
$new_calculated_amount = 100;
// Set the new amounts for "total_sales" key
$report_data->total_sales = $new_calculated_amount;
// Raw data output just for testing, to get the keys and the structure of the data
// to be removed
echo '<pre>'; print_r($report_data); echo '</pre>';
// Return the changed data object
return $report_data;
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
Tested and works.
I have included a line of code that outputs the raw data that you should remove… It's just to see the data structure and the changes made by the function on the "total_sales" value…
The Raw data output is something like this (that gives you the data structure to better make changes):
stdClass Object
(
[order_counts] => Array
(
[0] => stdClass Object
(
[count] => 1
[post_date] => 2017-11-21 16:45:43
)
)
[coupons] => Array
(
)
[order_items] => Array
(
[0] => stdClass Object
(
[order_item_count] => 1
[post_date] => 2017-11-21 16:45:43
)
)
[refunded_order_items] => 0
[orders] => Array
(
[0] => stdClass Object
(
[total_sales] => 48
[total_shipping] => 15
[total_tax] => 5
[total_shipping_tax] => 3
[post_date] => 2017-11-21 16:45:43
)
)
[full_refunds] => Array
(
)
[partial_refunds] => Array
(
)
[refund_lines] => Array
(
)
[total_tax_refunded] => 0
[total_shipping_refunded] => 0
[total_shipping_tax_refunded] => 0
[total_refunds] => 0
[total_tax] => 5.00
[total_shipping] => 15.00
[total_shipping_tax] => 3.00
[total_sales] => 48.00
[net_sales] => 25.00
[average_sales] => 3.57
[average_total_sales] => 6.86
[total_coupons] => 0.00
[total_refunded_orders] => 0
[total_orders] => 1
[total_items] => 1
)
So as you can see you also need to make changes on the "orders" object data as you also have the "total_sales" key…

Page Argument In Drupal

I have a block in that I have a search button, when clicks that button I pass this url (www.jksb.com/saleorderlist?field_month=4) to drupal menu. In page argument of menu I need to provide parameter (field_month).My page argument is like this: 'page argument' => array(1), but it doesn't work for me. I need somebody to help me out of this problem.
This is what I solve to this problem.
saleordermonthly.module
function sale_order_monthly_menu() {
$items = array();
$items["saleOrderMonthlyList"] = array(
'title' => 'Sale Order Monthly Report',
'description'=>'Sale Order Monthly',
'page callback' => 'sale_order_monthly_loadAllrecord',
//'page arguments' => array($para),
'access arguments' => array('access saleOrderMonthlyList'),
'type' => MENU_NORMAL_ITEM,
'file' => 'sale_order_monthly.admin.inc',
'access callback' => TRUE
);
return $items;
}
saleordermonthly.inc
enter code here
<?php
function sale_order_monthly_loadAllrecord()
{
$para='';
$query = drupal_get_query_parameters();
if(count($query) > 0){
$para= $query['field_month'];
};
}
?>
You are passing your argument in query string but if you use "page argument' => array(1)", it means you want the second segment/component of the path to be passed as the first parameter of your callback function. (you can still get the parameter inside your callback but you must use the "$_GET" variable in that case).
For instance :
$items['my-module/%/edit'] = array(
'page callback' => 'mymodule_abc_edit',
'page arguments' => array(1),
);
Here, "%" is a wildcard at position "1" ("my-module" is at position 0 and "edit" at position 2). This is the value that will be passed as the first parameter in the callback function ("mymodule_abc_edit")
In your case your path in "hook_menu" should look as follow:
'saleorderlist/%'
then if you call the path "saleorderlist/4", "4" will be passed as the first parameter of your callback function:
function my_callback($field_month) {
echo $field_month;//Will echo "4"
}
More info about hook_menu here ("Wildcards in Paths" section for your current question) : https://api.drupal.org/api/drupal/modules!system!system.api.php/function/hook_menu/7

Combining events that are on the same day into one in Calendar using Date Repeat API

Im using the Date Repeat API to set events that occur every week. However, date repeat only let's you set the event for one time(hour and minute). To solve this limitation I just created another repeat input in the content type.
It works great, but I want the node titles that show in my calendar for the two time slots to be displayed as one. So, if I have three timeslots on one day it will only appear as one.
I tried intercepting the View results by making a custom module but it only came back with the node's information without any info on the actual day it will be on.
[0] => stdClass Object
(
[nid] => 145
[node_title] => Repeat 1
[node_data_field_recurring_field_recurring_value] => 2011-05-19T20:00:00
[node_data_field_recurring_field_recurring_rrule] => RRULE:FREQ=WEEKLY;INTERVAL=1;BYDAY=TH,FR;UNTIL=20110722T235959Z;WKST=SU
[node_data_field_recurring_delta] => 0
[node_type] => test_event
[node_vid] => 145
[node_data_field_specific_date_field_specific_date_value] => 2011-06-15T16:00:00
[node_data_field_specific_date_delta] => 0
[node_data_field_recurring_2_field_recurring_2_value] => 2011-05-19T00:00:00
[node_data_field_recurring_2_field_recurring_2_rrule] => RRULE:FREQ=DAILY;INTERVAL=1;BYDAY=MO,FR;UNTIL=20110722T235959Z;WKST=SU
[node_data_field_recurring_2_delta] => 0
)
[1] => stdClass Object
(
[nid] => 145
[node_title] => Repeat 1
[node_data_field_recurring_field_recurring_value] => 2011-05-19T20:00:00
[node_data_field_recurring_field_recurring_rrule] => RRULE:FREQ=WEEKLY;INTERVAL=1;BYDAY=TH,FR;UNTIL=20110722T235959Z;WKST=SU
[node_data_field_recurring_delta] => 0
[node_type] => test_event
[node_vid] => 145
[node_data_field_specific_date_field_specific_date_value] => 2011-06-15T16:00:00
[node_data_field_specific_date_delta] => 0
[node_data_field_recurring_2_field_recurring_2_value] => 2011-05-20T00:00:00
[node_data_field_recurring_2_field_recurring_2_rrule] => RRULE:FREQ=DAILY;INTERVAL=1;BYDAY=MO,FR;UNTIL=20110722T235959Z;WKST=SU
[node_data_field_recurring_2_delta] => 1
)
[2] => stdClass Object
(
[nid] => 145
[node_title] => Repeat 1
[node_data_field_recurring_field_recurring_value] => 2011-05-19T20:00:00
[node_data_field_recurring_field_recurring_rrule] => RRULE:FREQ=WEEKLY;INTERVAL=1;BYDAY=TH,FR;UNTIL=20110722T235959Z;WKST=SU
[node_data_field_recurring_delta] => 0
[node_type] => test_event
[node_vid] => 145
[node_data_field_specific_date_field_specific_date_value] => 2011-06-15T16:00:00
[node_data_field_specific_date_delta] => 0
[node_data_field_recurring_2_field_recurring_2_value] => 2011-05-23T00:00:00
[node_data_field_recurring_2_field_recurring_2_rrule] => RRULE:FREQ=DAILY;INTERVAL=1;BYDAY=MO,FR;UNTIL=20110722T235959Z;WKST=SU
[node_data_field_recurring_2_delta] => 2
)
As you can see, it only returns the Repeat rule, so i'm thinking the Calendar module must do the calculations after. But where?
I'd take a different approach entirely. Create a node reference which creates a parent to child relationship between events. Then in your View just exclude events that have parent nodes.
You'd have to modify your event template to display the child events.
From a data entry standpoint this would take more work per event unless some other customization to make it efficient to input was done. Haven't used this but it seems like it could speed up multiple node creations, http://drupal.org/project/editview

Unpredictable CCK field name in returned View data

I'm using views_get_view_result to directly access the data in a view. I've stumbled upon this odd behavior where cck fields are prefixed with the first field name as a query optimization. Explained here.
What's bizarre though is that fields are named differently depending on whether I retrieve that data as Anonymous or as Admin. I'm pretty sure all my permissions are set up, and the view itself has no restrictions. What is going on here?
This is a big problem since I can't know how to retrieve a field. Here's a dump of the two view results. Notice that node_data_field_game_date_field_game_home_score_value != node_data_field_game_official_field_game_home_score_value.
// View as Admin
stdClass Object
(
[nid] => 3191
[node_data_field_game_date_field_game_date_value] => 2010-03-27T00:00:00
[node_type] => game
[node_vid] => 5039
[node_data_field_game_date_field_game_official_value] => 0
[node_node_data_field_game_home_team_title] => TeamA
[node_node_data_field_game_home_team_nid] => 3396
[node_data_field_game_date_field_game_home_score_value] => 68
[node_node_data_field_game_visitor_team_title] => TeamB
[node_node_data_field_game_visitor_team_nid] => 3442
[node_data_field_game_date_field_game_visitor_score_value] => 118
)
// View as Anonymous
stdClass Object
(
[nid] => 3191
[node_data_field_game_date_field_game_date_value] => 2010-03-27T00:00:00
[node_type] => game
[node_vid] => 5039
[node_data_field_game_official_field_game_official_value] => 0
[node_node_data_field_game_home_team_title] => TeamA
[node_node_data_field_game_home_team_nid] => 3396
[node_data_field_game_official_field_game_home_score_value] => 68
[node_node_data_field_game_visitor_team_title] => TeamB
[node_node_data_field_game_visitor_team_nid] => 3442
[node_data_field_game_official_field_game_visitor_score_value] => 118
)
Very weird behavior. Maybe it's a problem with content permission?

drupal hook_menu_alter() for adding tabs

I want to add some tabs in the "node/%/edit" page from my module called "cssswitch".
When I click "Rebuild Menus", the two new tabs are displayed, but they are displayed for ALL nodes when editing them, not just for the node "cssswitch". I want these new tabs to be displayed only when editing node of type "cssswitch".
The other problem is when I clear all cache, the tabs completely dissapear from all edit pages. Below is the code I wrote.
function cssswitch_menu_alter(&$items) {
$node = menu_get_object();
//print_r($node);
//echo $node->type; //exit();
if ($node->type == 'cssswitch') {
$items['node/%/edit/schedulenew'] = array(
'title' => 'Schedule1',
'access callback'=>'user_access',
'access arguments'=>array('view cssswitch'),
'page callback' => 'cssswitch_schedule',
'page arguments' => array(1),
'type' => MENU_LOCAL_TASK,
'weight'=>4,
);
$items['node/%/edit/schedulenew2'] = array(
'title' => 'Schedule2',
'access callback'=>'user_access',
'access arguments'=>array('view cssswitch'),
'page callback' => 'cssswitch_test2',
'page arguments' => array(1),
'type' => MENU_LOCAL_TASK,
'weight'=>3,
);
}
}
function cssswitch_test(){
return 'test';
}
function cssswitch_test2(){
return 'test2';
}
Thanks for any help.
hook_menu_alter() is only called during the menu building process, so you can't do dynamic node type checks within that function.
However, to achieve what you want, you can do this with a custom access callback as follows:
// Note, I replaced the '%' in your original code with '%node'. See hook_menu() for details on this.
$items['node/%node/edit/schedulenew2'] = array(
...
'access callback'=>'cssswitch_schedulenew_access',
// This passes in the $node object as the argument.
'access arguments'=>array(1),
...
);
Then, in your new custom access callback:
function cssswitch_schedulenew_access($node) {
// Check that node is the proper type, and that the user has the proper permission.
return $node->type == 'cssswitch' && user_access('view cssswitch');
}
For other node types, this function will return false, thus denying access, and thus removing the tab.

Resources