Drupal: Fivestar Block with voting axis - drupal

I'm using fivestar 1.19 with voting axis. I believe the default fivestar block/fivestar function uses only the default 'vote' tag.
fivestar_widget_form($node)
I need to pass my custom fivestar tag to the function.
Attempting to follow the answer below:
For me $object is $node.
<?php
function custom_fivestar_widget ($object) {
global $user;
$star_display = variable_get('fivestar_style_'. $object->type, 'average');
$text_display = variable_get('fivestar_text_'. $object->type, 'dual');
if ($star_display == 'average' && ($text_display == 'average' || $text_display == 'none')) {
// Save a query and don't retrieve the user vote unnecessarily.
$votes = fivestar_get_votes($object->type, $object->nid, 'score', 0);
}
else {
$votes = fivestar_get_votes($object->type, $object->nid);
}
$values = array(
'user' => isset($votes['user']['value']) ? $votes['user']['value'] : 0,
'average' => isset($votes['average']['value']) ? $votes['average']['value'] : 0,
'count' => isset($votes['count']['value']) ? $votes['count']['value'] : 0,
);
$settings = array(
'stars' => variable_get('fivestar_stars_'. $object->type, 10),
'allow_clear' => variable_get('fivestar_unvote_'. $object->type, FALSE),
'style' => $star_display,
'text' => $text_display,
'content_type' => $object->type,
'content_id' => $object->nid,
'tag' => 'score',
'autosubmit' => TRUE,
'title' => variable_get('fivestar_title_'. $object->type, 1) ? NULL : FALSE,
'feedback_enable' => variable_get('fivestar_feedback_'. $object->type, 1),
'labels_enable' => variable_get('fivestar_labels_enable_'. $object->type, 1),
'labels' => variable_get('fivestar_labels_'. $object->type, array()),
);
return fivestar_custom_widget($form_state, $values, $settings);
}
print drupal_get_form('custom_fivestar_widget', $object);
?>
This prints me the widget, I believe using my score. However the text display is all wrong, as is the average score. And it gives everything a permanent 10 stars. :(

You can reproduce fivestar_form function in fivestar.module. See there $settings variable.
So just copy inner of this function, remove some variables checking and set manually some variables. In $settings array set to 'tag' value as you want.

Related

Why is the invoice page different for another user?

When I go to admin/store/orders/50457/invoice as the administrator, I see the following:
Notice how it has a payment method of "Free order" and the total at the bottom is $0.00.
When I go to the same page as a non-administrator, I see the following:
Notice how Payment Method is empty and the total for the order is $8.21.
The correct one is what the administrator sees, so what is going on that makes the two behave differently?
EDIT: It turns out in a module I created (a long time ago) called tf_store_credit.module, I have the following:
function tf_store_credit_line_item(){
global $user;
$total_credit= uc_store_credit_f_get_user_credit($user->uid);
if ($total_credit>0){
$items[] = array
(
'id' => 'store-credit', // You will use this ID in the javascript
'title' => t('Store Credit'), // This is the text that will be displayed on the line item in the subtotal
'callback' => 'tf_store_credit_line_item_callback', // This is the callback function
'stored' => TRUE,
'default' => FALSE,
'calculated' => TRUE,
'display_only' => FALSE,
'weight' => 15,
);
}
return $items;
}
The problem is that it is getting the currently logged in user's store credit instead of the user who placed the order. So how would I go about getting the correct user?
In tf_store_credit.module, I modified it like this:
function tf_store_credit_line_item(){
global $user;
$total_credit= uc_store_credit_f_get_user_credit($user->uid);
if ($total_credit>0 || in_array("view_orders", $user->roles)){
$items[] = array
(
'id' => 'store-credit', // You will use this ID in the javascript
'title' => t('Store Credit'), // This is the text that will be displayed on the line item in the subtotal
'callback' => 'tf_store_credit_line_item_callback', // This is the callback function
'stored' => TRUE,
'default' => FALSE,
'calculated' => TRUE,
'display_only' => FALSE,
'weight' => 15,
);
}
return $items;
}
In uc_free_order.module, I did a similar thing so that "Payment method" showed up:
function uc_free_order_payment_method() {
global $user;
if ($user->name=='blah' || $user->name=='blah2' || in_array("view_orders", $user->roles)){
$methods[] = array(
'id' => 'free_order',
'name' => t('Free order'),
'title' => t('Free order - payment not necessary.'),
'desc' => t('Allow customers with $0 order totals to checkout without paying.'),
'callback' => 'uc_payment_method_free_order',
'checkout' => TRUE,
'no_gateway' => TRUE,
'weight' => 10,
);
return $methods;
}
}

Style WordPress tables?

This is my WordPress table. I created an array so that I could try it out, but I need to add classes and IDs so I can use CSS to style it like the top level plugin page.
How can I add classes to the table elements?
<?php
if(!class_exists('WP_List_Table')){
require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
}
class TT_Example_List_Table extends WP_List_Table {
var $example_data = array(
array(
'ID' => 1,
'title' => '300',
'rating' => 'R',
'director' => 'Zach Snyder'
),
array(
'ID' => 2,
'title' => 'Eyes Wide Shut',
'rating' => 'R',
'director' => 'Stanley Kubrick'
),
array(
'ID' => 3,
'title' => 'Moulin Rouge!',
'rating' => 'PG-13',
'director' => 'Baz Luhrman'
),
array(
'ID' => 4,
'title' => 'Snow White',
'rating' => 'G',
'director' => 'Walt Disney'
),
array(
'ID' => 5,
'title' => 'Super 8',
'rating' => 'PG-13',
'director' => 'JJ Abrams'
),
array(
'ID' => 6,
'title' => 'The Fountain',
'rating' => 'PG-13',
'director' => 'Darren Aronofsky'
),
array(
'ID' => 7,
'title' => 'Watchmen',
'rating' => 'R',
'director' => 'Zach Snyder'
)
);
function __construct(){
global $status, $page;
//Set parent defaults
parent::__construct( array(
'singular' => 'movie', //singular name of the listed records
'plural' => 'movies', //plural name of the listed records
'ajax' => false //does this table support ajax?
) );
}
function column_default($item, $column_name){
switch($column_name){
case 'rating':
case 'director':
return $item[$column_name] . 'hi';
default:
return print_r($item,true) . ' hi'; //Show the whole array for troubleshooting purposes
}
}
function column_title($item){
//Build row actions
$actions = array(
'edit' => sprintf('Edit',$_REQUEST['page'],'edit',$item['ID']),
'delete' => sprintf('Delete',$_REQUEST['page'],'delete',$item['ID']),
);
//Return the title contents
return sprintf('%1$s <span style="color:silver">(id:%2$s)</span>%3$s',
/*$1%s*/ $item['title'],
/*$2%s*/ $item['ID'],
/*$3%s*/ $this->row_actions($actions)
);
}
function column_cb($item){
return sprintf(
'<input type="checkbox" name="%1$s[]" value="%2$s" />',
/*$1%s*/ $this->_args['singular'], //Let's simply repurpose the table's singular label ("movie")
/*$2%s*/ $item['ID'] //The value of the checkbox should be the record's id
);
}
function get_columns(){
$columns = array(
'cb' => '<input type="checkbox" />', //Render a checkbox instead of text
'title' => 'Title',
'rating' => 'Rating',
'director' => 'Director'
);
return $columns;
}
function get_sortable_columns() {
$sortable_columns = array(
'title' => array('title',true), //true means its already sorted
'rating' => array('rating',false),
'director' => array('director',false)
);
return $sortable_columns;
}
function get_bulk_actions() {
$actions = array(
'delete' => 'Delete'
);
return $actions;
}
function process_bulk_action() {
//Detect when a bulk action is being triggered...
if( 'delete'===$this->current_action() ) {
wp_die('Items deleted (or they would be if we had items to delete)!');
}
}
function prepare_items() {
$per_page = 5;
$columns = $this->get_columns();
$hidden = array();
$sortable = $this->get_sortable_columns();
$this->_column_headers = array($columns, $hidden, $sortable);
$this->process_bulk_action();
$data = $this->example_data;
function usort_reorder($a,$b){
$orderby = (!empty($_REQUEST['orderby'])) ? $_REQUEST['orderby'] : 'title'; //If no sort, default to title
$order = (!empty($_REQUEST['order'])) ? $_REQUEST['order'] : 'asc'; //If no order, default to asc
$result = strcmp($a[$orderby], $b[$orderby]); //Determine sort order
return ($order==='asc') ? $result : -$result; //Send final sort direction to usort
}
usort($data, 'usort_reorder');
$current_page = $this->get_pagenum();
$total_items = count($data);
$data = array_slice($data,(($current_page-1)*$per_page),$per_page);
$this->items = $data;
$this->set_pagination_args( array(
'total_items' => $total_items, //WE have to calculate the total number of items
'per_page' => $per_page, //WE have to determine how many items to show on a page
'total_pages' => ceil($total_items/$per_page) //WE have to calculate the total number of pages
) );
}
}
function tt_add_menu_items(){
add_menu_page('Example Plugin List Table', 'List Table Example', 'activate_plugins', 'tt_list_test', 'tt_render_list_page');
} add_action('admin_menu', 'tt_add_menu_items');
function tt_render_list_page(){
$testListTable = new TT_Example_List_Table();
$testListTable->prepare_items();
?>
<div class="wrap">
<div id="icon-users" class="icon32"><br/></div>
<h2>List Table Test</h2>
<form id="movies-filter" method="get">
<input type="hidden" name="page" value="<?php echo $_REQUEST['page'] ?>" />
<?php $testListTable->display() ?>
</form>
</div>
<?php
}
The only way to do this is by overriding some of the methods of the WP_List_Table class.
I went ahead and modified your class to support conditional HTML classes for each tr/td in the table. You weren't clear enough about to which elements you want classes applied, nor how exactly you want to specify that, so excuse me if it's not what you wanted(and please specify further details).
You can see the full code(only the TT_Example_List_Table class is there - the rest is the same) here.
Basically you define a class property called $cond_classes. This property is a multidimensional array of conditions. In there you have two top-level keys which are reserved - "odd" and "even". As you can guess they will be accessed for each row that is either odd or even.
The rest of the top-level keys can be column id's or item ID's.
Each top-level key can hold either an array or a string
If the top-level key holds a string, then when this condition is met, that class is added
If the top-level key holds an array, then it's looped through.
The second-level array can have string values and key=>value pairs, where the key is the class and the value
is an array of conditions.
I guess that's quite confusing, but the example bellow should give you an idea of how this works.
var $cond_classes = array(
'odd' => array(
'odd-class', // This class will always be given to odd rows and their columns
'special-odd-class' => array( // This class will only be given to odd rows and their columns if the rows is for an item with ID 1, 4 or 7
'ID' => array( 1, 4, 7 )
)
),
'even' => array(
'even-class'
),
'title' => array(
'custom_title_class',
'special_title_class' => array(
'ID' => array( 3, 7 ), // This will only be given to the "title" column for an item with ID 3 or 7
'title' => 'The Fountain', // This will only be given to the "title" column for an item with title "The Fountain"
),
),
7 => 'id_7_class', // This will be given to a row and it's columns for item with ID 7
);
And you can see the applied classes in the resulting table:
Hope that helps! If you have any questions - go ahead :)

cannot get checkboxes value using drupal form api

i have form in drupal which uploads images and has got few checkboxes in it.
Here is the form:
$form['checklist_fieldset'] = array(
'#type' => 'fieldset',
'#title' => t('Check List'),
'#collapsible' => FALSE,
'#collapsed' => FALSE,
);
$form['checklist_fieldset']['heating'] = array(
'#type' => 'checkboxes',
'#title' => t('Heating options'),
'#options' => array(
'0' => t('Yes'),
'1' => t('No')
),
'#description' => t('Heating details.')
);
and here is my submit function where i am processing image upload and grabbing the checkboxes value as well. I am getting the success message and image is getting uploaded but not getting the value of check boxes.
function property_add_view_submit($form,&$form_state){
$validators = array();
if($file = file_save_upload('p_file1',$validators,file_direcotry_path)){
$heating = array_keys($form_state['values']['heating']);
drupal_set_message(t('Property Saved! '.$heating));
dpm( $form_state['values']['heating']);
}
When you use #options on a FAPI element the value passed to the $form_state is the array key, so you don't need to use array_keys().
I'm not sure why you're using checkboxes for a yes/no, usually one would use a simple checkbox element. However if that's really what you want to do:
Your #options can't contain on option with 0 as the array key, it will be automatically filtered out and you'll never know if that option has been checked.
You should use $heating_options_chosen = array_filter($form_state['values']['heating'] to get the selected checkbox options.
I honestly think your code should look like this though:
$form['checklist_fieldset']['heating'] = array(
'#type' => 'checkbox',
'#title' => t('Heating options'),
'#options' => array(
'1' => t('Yes'),
'0' => t('No')
),
'#description' => t('Heating details.')
);
$heating_checked = $form_state['values']['heating'] == 1;
If I have checkbox Friends and options are like
[ ] abc
[ ] def
[ ] ghi
[ ] jkl
And I want to know which options user have marked, then use below function.
if ($form_state->getValue('friends') != NULL) {
foreach ($form_state->getValue('friends') as $key => $value) {
if ($value != 0) {
$friends = $friends . ", " . $key;
$friends = substr_replace($friends, "", 0, 1);
}
}
}
If user has chosen abc and ghi then you will get 1,3 as result in $friends
If you wanted to know the value then use $friends = $friends.", ".$value;
it worked for me..hope it will help you as well :)

Drupal Block not showing on the page

$blocks['onemore'] = array(
'info' => t('onemore'),
'status' => TRUE,
'region' => 'content',
'weight' => 0,
'cache' => DRUPAL_NO_CACHE,
'visibility' => BLOCK_VISIBILITY_LISTED,
'pages' => 'admin/structure/nodequeue/1/view/1',
);
Problem - The above block shows up and works perfectly and as expected at 'admin/structure/nodequeue/1/view/1'
My problem is that I need to declare dynamic amounts of blocks based on the users inputs. So I wrote a db fetch and for each loop.
If I do this then the block shows up in 'admin/modules' but the it is not in 'content' region for the seven theme. As I want to show it there.
I have double checked the values and even the admin/structure/block/manage/xdmp/onemore/configure has the value but the region is not selected.
I am assuming there is some conflict in the for each loop or the db query. Please advice your thoughts on it.
function xdmp_block_info() {
$blocks = array();
// Here we are going to do a db query so that I can get a list of
// block ids to declare
$resultxdmp = db_query("
SELECT * FROM xdmp_container_list ");
foreach($resultxdmp as $resultRecords)
{
$xdmp_nodeque_id_to_display =(int)$resultRecords->xdmp_nodequeue_id;
$xdmp_nodeque_id_to_display = intval($xdmp_nodeque_id_to_display);
$xdmp_path_to_show_block = 'admin/structure/nodequeue/'.$xdmp_nodeque_id_to_display.'
/view/'.$xdmp_nodeque_id_to_display.'';
$xdmp_machinenameofblock=(string)$resultRecords->xdmp_container_machine_name;
$xdmp_nameofblock=(string)$resultRecords->xdmp_container_name;
$blocks[$xdmp_machinenameofblock] = array(
'info' => t($xdmp_nameofblock),
'status' => TRUE,
'region' => 'content',
'weight' => 0,
'cache' => DRUPAL_NO_CACHE,
'visibility' => BLOCK_VISIBILITY_LISTED,
'pages' => $xdmp_path_to_show_block,
);
} // end for for each
return $blocks;
}
cheers,
Vishal
Are you sure the 'content' region is valid? If it's not, it of course can't show up :)

Drupal: Parent-child draggable table

So I've been going at this one for a while now. I'm trying to create a draggable table that has a parent-child relationship, but where the children cannot be moved out of the parent group, and all of the parents are sortable among each other. I've modeled my form and theme off of the admin menu code, and I have it duplicating that functionality. The problem is that I can move the children to another parent, or let it become a parent. As an illustration:
Category 1
|
|--Item 1
|--Item 2
Category 2
|
|--Item 3
|--Item 4
|--Item 5
I would like to be able to sort Item 1 and Item 2 with each other, and Item 3, Item 4, and Item 5 with each other, but not move them between Category 1 and Category 2. I also need to be able to sort Category 1 and Category 2 with one another, taking the children with them. I've went through so many combinations of $action, $group, $subgroup settings mixed with $class settings for the categories and items that I've lost track. Nothing I have tried so far has produced the desired result. Here's the relevant bits of my code as it is currently:
In my form:
$form['#tree'] = true;
foreach($categories as $cat) {
if(!isset($form['categories'][$cat->cid])){
$form['categories'][$cat->cid] = array(
'weight' => array(
'#type' => 'weight',
'#delta' => 25,
'#attributes' => array('class' => array('item-weight', 'item-weight-' . $cat->cid)),
),
'cid' => array(
'#type' => 'hidden',
'#value' => $cat->cid,
'#attributes' => array('class' => array('cid')),
),
);
foreach($cats[$cat->cid] as $item) {
$form['categories'][$cat->cid]['items'][$item->id] = array(
'weight' => array(
'#type' => 'weight',
'#delta' => 25,
'#default_value'=> $item->weight,
'#attributes' => array('class' => array('item-weight', 'item-weight-' . $cat->cid)),
),
'cid' => array(
'#type' => 'hidden',
'#value' => $cat->cid,
'#attributes' => array('class' => array('cid')),
),
);
}
}
}
In my theme:
$children = element_children($form['categories']);
$rows = array();
if(count($children) > 0) {
foreach($children as $cid) {
$row = array(
drupal_render($form['categories'][$cid]['weight']) .
drupal_render($form['categories'][$cid]['cid']),
);
$rows[] = array(
'data' => $row,
'class' => array('draggable', 'tabledrag-root'),
);
foreach(element_children($form['categories'][$cid]['items']) as $id) {
$row = array(
theme('indentation', array('size' => 1)) . drupal_render($form['categories'][$cid]['items'][$id]['name']),
drupal_render($form['categories'][$cid]['items'][$id]['weight']) .
drupal_render($form['categories'][$cid]['items'][$id]['cid']),
);
$rows[] = array(
'data' => $row,
'class' => array('draggable', 'tabledrag-leaf'),
);
}
drupal_add_tabledrag('cat-table', 'order', 'sibling', 'item-weight', 'item-weight-' . $cid);
}
}
drupal_add_tabledrag('cat-table', 'match', 'parent', 'cid', 'cid', 'cid', true, 1);
$output = theme('table', array('header' => $headers, 'rows' => $rows, 'attributes' => array('id' => 'cat-table')));
$output .= drupal_render_children($form);
return $output;
I've read over the documentation for drupal_add_tabledrag(), looked at the code, looked at example code, and searched around drupal.org and Google, but haven't come up with anything.
My only solution so far is to copy and modify the tabledrag.js file to just eliminate those capabilities, but while stopping the indent problem with the items (meaning, not letting them be on the same as the categories), keeping them in the same category has been Not Fun.
I suppose the most important question is, using standard Drupal is this possible?
I know you've already done a lot of coding so you might not want to give it up at this point, but DraggableViews is great to accomplish this. You can set up a normal view and add this draggableviews filter, it adds a weight and optionally a parent reference. The view itself uses the same drag-n-drop system as the rest of Drupal's backend tables.
Alternatively you can use a term reference and tie taxonomy terms to nodes, and just use that drag-n-drop.
If I'm missing something in your needs, my apologies, just thought I'd offer this simpler solution as it has definitely served me well in the past. Best of luck either way.
Just finished adding this functionality to my module
https://github.com/player259/ajax_table
There is no help, demo is outdated, but I'm working on it from time to time
Sections support was achieved by overriding tabledrag.js functions
Use this snippet to insert table
$form['map'] = array(
'#type' => 'ajax_table',
'#header' => array(t('Element'), t('Settings'), t('Weight')),
'rows' => array(),
'#draggable' => array(
// drupal_add_tabledrag will be called in theme layer
// NULL first arg to apply to this table
array(NULL, 'match', 'parent', 'perfect-form-parent', 'perfect-form-parent', 'perfect-form-index'),
array(NULL, 'depth', 'group', 'perfect-form-depth', NULL, NULL, FALSE),
array(NULL, 'order', 'sibling', 'perfect-form-weight'),
),
'#draggable_groups' => array(),
);
foreach ($map as $i => $element) {
// ... some logic
$form['map']['rows'][$i] = array(
'data' => array(
'element' => array(),
'settings' => array(),
'tabledrag' => array(
'index' => array(
'#type' => 'hidden',
'#value' => $element['data']['tabledrag']['index'],
'#attributes' => array('class' => array('perfect-form-index')),
),
'parent' => array(
'#type' => 'hidden',
'#default_value' => $element['data']['tabledrag']['parent'],
'#attributes' => array('class' => array('perfect-form-parent')),
),
'depth' => array(
'#type' => 'hidden',
'#default_value' => $element['data']['tabledrag']['depth'],
'#attributes' => array('class' => array('perfect-form-depth')),
),
'weight' => array(
'#type' => 'weight',
'#delta' => $max_weight,
'#default_value' => $weight,
'#attributes' => array('class' => array('perfect-form-weight')),
),
),
),
'#attributes' => array('class' => array($row_class_current, $row_class_child)),
);
// This means that row with $row_class_child class could have as parent
// only row with $row_class_parent class
// NULL means root - there are no parents
$form['map']['#draggable_groups'][$row_class_child] =
$depth ? $row_class_parent : NULL;
}
I had a similar problem at work so posting here my solution since none i found worked correctly in all situation. It is done 100% in javascript, on the php side you just have to set tabledrag in match with parent on pid and sort with siblings on weight.
The current code work on the example module (tabledrag parent/child) to adapt it to your need, change the .example-item-pid by your class for the PID input field. You just need to add it to the example code to have it working and see if it corresponds to your need.
First function invalidate any attempt to drop elements that don't have the same parent (PID) than the target element.
Second Function bypass the dragRow function to drop the element in the correct place (= the last children of the target row) and at the right depth ( = same depth than the target row).
/**
* Invalidate swap check if the row target is not of the same parent
* So we can only sort elements under the same parent and not move them to another parent
*
* #override Drupal.tableDrag.row.isValidSwap
*/
// Keep the original implementation - we still need it.
Drupal.tableDrag.prototype.row.prototype._isValidSwap = Drupal.tableDrag.prototype.row.prototype.isValidSwap;
Drupal.tableDrag.prototype.row.prototype.isValidSwap = function(row) {
if (this.indentEnabled) {
if (row && $('.example-item-pid', this.element).val() !== $('.example-item-pid', row).val()) {
return false;
}
}
// Return the original result.
return this._isValidSwap(row);
}
/**
* Position the dragged element under the last children of the element target for swapping when moving down our dragged element.
* Removed the indentation, since we can not change parent.
* #override Drupal.tableDrag.row.dragRow
*/
Drupal.tableDrag.prototype.dragRow = function (event, self) {
if (self.dragObject) {
self.currentMouseCoords = self.mouseCoords(event);
var y = self.currentMouseCoords.y - self.dragObject.initMouseOffset.y;
var x = self.currentMouseCoords.x - self.dragObject.initMouseOffset.x;
// Check for row swapping and vertical scrolling.
if (y != self.oldY) {
self.rowObject.direction = y > self.oldY ? 'down' : 'up';
self.oldY = y; // Update the old value.
// Check if the window should be scrolled (and how fast).
var scrollAmount = self.checkScroll(self.currentMouseCoords.y);
// Stop any current scrolling.
clearInterval(self.scrollInterval);
// Continue scrolling if the mouse has moved in the scroll direction.
if (scrollAmount > 0 && self.rowObject.direction == 'down' || scrollAmount < 0 && self.rowObject.direction == 'up') {
self.setScroll(scrollAmount);
}
// If we have a valid target, perform the swap and restripe the table.
var currentRow = self.findDropTargetRow(x, y);
if (currentRow) {
if (self.rowObject.direction == 'down') {
/**
* When going down we want to position the element after the last children and not right under the currentRow
*/
// create a new row prototype with currentRow
var rowObject = new self.row(currentRow, 'mouse', self.indentEnabled, self.maxDepth, false);
// extract all children
var childrenRows = rowObject.findChildren();
// if we have children
if (childrenRows.length > 0) {
// we change the row to swap with the last children
currentRow = childrenRows[childrenRows.length - 1];
}
self.rowObject.swap('after', currentRow, self);
}
else {
self.rowObject.swap('before', currentRow, self);
}
self.restripeTable();
}
}
/**
* We have disabled the indentation changes since it is not possible to change parent.
*/
return false;
}
};

Resources