Wordpress Woocommerce Variable Products - attributes

When setting up a variable type product in woocommerce based on product attributes, for the respective product, the front-end store provides a dropdown box where the user can pick the product attribute (ie lets say shirt size S, M or L).
At the moment that dropdown box is propagated by the attribute names, can someone please let me know where is the function located where I can make this dropdown be propagated by the names PLUS the particular attribute description?
So for instance, if the size attribute has name 'S' and description 'Small', I want the dropdown to say 'S [Small]', rather than just 'S', which is how it would be presented at the moment.

there's a filter available for this... but currently, version 2.5.2, you can only check for its name. Which for me, not so flexible. But at least we have this...
try pasting this code to your functions.php
add_filter('woocommerce_variation_option_name','rei_variation_option_name',10,1) ;
function rei_variation_option_name($name){
if ($name == 'S') {
$name = 'Small';
}
if ($name == 'M') {
$name = 'Medium';
}
if ($name == 'L') {
$name = 'Large';
}
return $name;
}
Please take note that this is just for displaying it. Database has not been change.

The solution I used, is this:
wc-template-functions.php, function wc_dropdown_variation_attribute_options
Modify:
$html .= '<option value="' . esc_attr( $term->slug ) . '" ' . selected( sanitize_title( $args['selected'] ), $term->slug, false ) . '>' . esc_html( apply_filters( 'woocommerce_variation_option_name', $term->name ) ) . '</option>';
to
$html .= '<option value="' . esc_attr( $term->slug ) . '" ' . selected( sanitize_title( $args['selected'] ), $term->slug, false ) . '>' . esc_html( apply_filters( 'woocommerce_variation_option_name', $term) ) . '</option>';
Then in functions.php, implement the following:
add_filter('woocommerce_variation_option_name','variation_option_name_description',10,1) ;
function variation_option_name_description($term){
return $term->name.' ['.$term->description.']';
}
Thanks to Reigel for steering me in the right direction.

Related

Display Dedicated IP into clientareainvoices.tpl list in WHMCS?

I'm using WHMCS 8.x and Smarty PHP is already enabled.
I hope to use some code or hook function to let the dedicated ip or hostname to display on the page clientareainvoices.tpl (/clientarea.php?action=invoices) list .
I hope anyone can help me with this .
Thanks alot .
I have search a lot of plan , but all not working . I don't know whether this can be done with hook .
Hope someone of genius can help me about this .
the function like this in the picture .
enter image description here
thanks thanks thanks.
I tried to use a hook file to do this . and tried to connect the database tables use left join . like :
the file is like :
select * from tblinvoices t1
left join tblinvoiceitems t2 on t1.id=t2.invoiceid
left join tblhosting t3 on t2.relid=t3.id
WHERE t3.dedicatedIP = value
And I add this into the hook file .
<?php
if (!defined("WHMCS")) {
die("This file cannot be accessed directly");
}
use WHMCS\Database\Capsule as DB;
add_hook('ClientAreaPageInvoices', 1, function($vars) {
$invoices = DB::table('tblinvoices')->where('invoicenum', $vars['invoicenum'])->get();
$fieldId = 'invoicenum';
$csVals = [];
foreach ($invoices as $invoice) {
$fieldVal = '';
$data = DB::table('tblinvoices AS t1')
->leftJoin('tblinvoiceitems AS t2', 't1.invoicenum', '=', 't2.invoiceid')
->leftJoin('tblhosting AS t3', 't2.relid', '=', 't3.id')
->select('t3.domain')
->where('t1.invoicenum', $fieldId)->where('t3.domain', $invoice['invoicenum'])
->first();
if (!is_null($data)) {
$fieldVal = $data->value;
}
$csVals[$invoice['invoicenum']] = $fieldVal;
}
return ['domain' => $csVals];
});
But all not working for this . it shows a result "Array" , hope anybody can hlep me . thanks in advance .
First you don't need to query invoices again, since the invoices are available in $vars['invoices'] variable.
$invoices = $vars['invoices'];
The code should work, you just need to edit the file clientareainvoices.tpl in your active template and replace:
<td>{$invoice.invoicenum}</td> with
<td>{$invoice.invoicenum} - {$domain[$invoice.invoicenum]}</td>

How do I do nested foralls in Drools?

Question
Considering these classes:
class BookCase { ArrayList<Book> books }
class Book { ArrayList<Page> pages }
class Page { String color }
And considering this natural language rule:
When all pages in a bookcase are black, do A
The trivial approach would be to nest forall clauses, but in Drools can't do that, because forall clauses only allow Patterns (not Conditional Elements, what a forall clause is) inside!
How do I express this in Drools then?
This is close, but not quite the right thing:
rule "all black pages"
when
BookCase( $books: books )
$book: Book( $pages: pages ) from $books
not Page( color != "black" ) from $pages
then
System.out.println( "doing A" );
end
The problem is that this will fire once for each book where all pages are black. To assess all pages in all books one could assemble a list of all pages and make sure they are all black:
rule "all black pages, take 2"
when
BookCase( $books: books )
$pages: ArrayList() from accumulate( Book( $ps: pages ) from $books,
init( ArrayList list = new ArrayList(); ),
action( list.addAll( $ps ); ),
result( list ) )
not Page( color != "black" ) from $pages
then
System.out.println( "doing A" );
end
You can actually nest multiple foralls if you don't use forall(p1 p2 p3...), but the equivalent not(p1 and not(and p2 p3...)). Then, to keep individual books and pages from firing the rule, chuck an exists in between there.
rule 'all pages in bookcase are black'
when
(and
$bookCase: BookCase()
(not (exists (and
$book: Book() from $bookCase.books
not( (and
not( (exists (and
$page: Page() from $book.pages
not( (and
// slightly different constraint than I used in question
eval($page.color == $book.color)
) )
) ) )
) )
) ) )
)
then
...
end
Unlike using accumulate to create a flat list of all pages, this will maintain the context of $page, that is, when a page is put in a constraint with its parent book as in the example above, in this solution Drools still 'knows' what the parent book is.
While I was writing the question, I think I found the answer myself:
BookCase($caseContents : books)
$bookWithOnlyBlackPages : ArrayList<Page>() from $caseContents
forall ( $page : Page(this memberOf $bookWithOnlyBlackPages)
Page(this == $page,
color == "black") )
forall ( $bookInCase : ArrayList<Page>(this memberOf $caseContents)
ArrayList<Page>(this == $bookInCase,
this == $bookWithOnlyBlackPages) )

Drupal 7 - Ubercart - Attributes in Views Fields

I have products that have attributes for 'color' & 'strength'. I'm trying to get those options listed under those attributes as fields for views, so that I can use them as filters. So for example sort by color & strength.
I've looked all around on google and can only find modules for Drupal 6. Anyone know of anything for 7?
Like said in the previous post I had 2 attributes 'color' & 'strength' which I needed to match for exact product matches but ubercart didn't have anything for that, so I wrote them into URL for get statements as variables 1 & 2, so for example a URL which had both attributes selected would look like:
www.website.com/node/68?1=96&2=7
Sometimes one variable would be set but not the other, so I had to make up for that also by using a % wildcard. Here's the code for that part
// Since PHP's serialize function sometimes serializes in the incorrect order,
// here we manually build the comparison key
// Additionally append the image links urls with provided strength/color data
if( isset( $_REQUEST['1'] ) ) {
$_1 = $_REQUEST['1'];
if( $_1 !== '%' ) $url[] = "1=$_1";
} else $_1 = '%';
if( isset( $_REQUEST['2'] ) ) {
$_2 = $_REQUEST['2'];
if( $_2 !== '%' ) $url[] = "2=$_2";
} else $_2 = '%';
$combination = "a:2:{i:1;s:";
$combination .= $_1 == '%' ? '%:"%";' : strlen($_1) . ':"' . $_1 . '";';
$combination .= "i:2;s:";
$combination .= $_2 == '%' ? '%:"%";' : strlen($_2) . ':"' . $_2 . '";';
$combination .= '}';
// if some products don't have a second attribute at all
$combination2 = "a:1:{i:1;s:";
$combination2 .= $_1 == '%' ? '%:"%"' : strlen($_1) . ':"' . $_1 . '";';
$combination2 .= ';}';
Underneath that I had to do some extra queries like if a taxonomy was set and check if some dynamic properties were set, thats why the WHERE is stored in a variable. Frankly they'll just confuse anyone so I left them out. But for your sake the next part you just need to query it.
$where = "WHERE (pa.combination LIKE :pattern1 OR pa.combination LIKE :pattern2) AND s.stock IS NOT NULL";
$comparison = array( ':pattern1' => $combination,
':pattern2' => $combination2 );
$filtered = db_query(
"
SELECT pa.nid, pa.model, pa.combination, n.title, p.sell_price, f.uri
FROM {uc_product_adjustments} pa
LEFT JOIN {node} n ON pa.nid = n.nid
LEFT JOIN {uc_products} p ON pa.nid = p.nid
LEFT JOIN {field_data_uc_product_image} i ON i.entity_type = 'node' AND i.entity_id = n.nid
LEFT JOIN {file_managed} f ON f.fid = i.uc_product_image_fid
LEFT JOIN {uc_product_stock} s ON pa.model = s.sku AND s.stock <> '0'
$where
",
$comparison
);
Lastly loop over the results and store them in a normal array
foreach( $filtered as $i => $record ) {
if( is_int( array_search( $record->nid, $nids ) ) ) continue;
else {
$nids[] = $record->nid;
$result[] = $record;
}
}
This code checks for any products that match any of the attribute values that are currently in stock
You may have a look at these sandbox projects : UC Views Attributes Work and UC attribute views.
I'm looking for a similar feature, as it seems not possible to get UC attributes into a view. I cannot test myself right now as I have a deadline this weekend for a project, but I'd be happy to have your feedback.

Propel Nested Set in combination with Pagination

$root = AnimeCommentQuery::create()->findRoot(2);
$html = "<ul>{$root->getComment()}";
foreach ($root->getDescendants() as $post)
{
$html .= '<li style="padding-left: '.$post->getLevel().' em;">';
$html .= $post->getComment();
$html .= ' by '.$post->getIbfMembersRelatedByInsertBy()->getName();
$html .= "</li>";
}
$html .= "</ul>";
echo $html;
I want to paginate the posts but I am not able to do this by:
$root = AnimeCommentQuery::create()->findRoot(2)->paginate(2, 1);
OR
$root = AnimeCommentQuery::create()->paginate(2, 1)->findRoot(2);
Can it be done with standard Pagination from propel? And how?
Don't know if this is too late....
First off, you can't use the paginate and find in the same query, they're both termination methods.
I think what you need is something like this:
$comments = AnimeCommentQuery::create()->inTree(2)->orderByBranch()->paginate(2,1);
Then foreach your way through that Collection.
Now you'll have to be a bit clever with when to close and open lists, checking current Level etc. And top and bottom of page 2+ will take a bit of consideration too. Good Luck!
The Nested Set API is worth studying further http://www.propelorm.org/behaviors/nested-set.html#complete_api, got a fair bit in.
Also consider using a ->joinWith() to get your getIbfMembersRelatedByInsertBy() prepopulated in the main query.

Drupal 6 - Passing variable between functions specifically - Passing menu name to phptemplate_menu_item

I'm quite new to Drupal 6 and theming it. My theme required the main menu to pump out quite extensive html/css for my reasonably involved styling. To achieve this I pieced together this code 'function phptemplate_menu_item' (see bottom) which sits in my template.php and produces different html depending on the whether the menu item has children or not and uses the contents of the link to generate a css class.
My problem is that this code is also being applied to my other menus. I would like make the menu_item generate different html depending on whether it is in the primary-menu or not. I would have thought that the easiest way to do this is with an if statement in the function phptemplate_menu_item, for example:
function phptemplate_menu_item (...){
if ($menu_name == 'primary-links')
{DO ABC}
else
{DO XYZ}
}
However I believe I need to know how to pass the menu name to the phptemplate_menu_item function. Any help with this would be really appreciated as I have been banging my head against the wall trying to solve this for some time now.
Thanks!
function phptemplate_menu_item($link, $has_children, $menu = '', $in_active_trail = FALSE, $extra_class = NULL) {
$class = ($menu ? 'no_wrap' : ($has_children ? 'collapsed' : 'li_wrap'));
if (!empty($extra_class)) {
$class .= ' '. $extra_class;
}
if ($in_active_trail) {
$class .= ' active-trail';
}
if (!empty($link)) {
/* The following section gives the list items unique classes based on their link text - note how spaces and sepcial chars are removed */
// remove all HTML tags and make everything lowercase
$css_id = strtolower(strip_tags($link));
// remove colons and anything past colons
if (strpos($css_id, ':')) $css_id = substr ($css_id, 0, strpos($css_id, ':'));
// Preserve alphanumerics, everything else goes away
$pattern = '/[^a-z]+/ ';
$css_id = preg_replace($pattern, '', $css_id);
$class .= ' '. $css_id;
}
// the following code returns the menu item formatted in a different fashion depending on the class of the item. The first one is for items with a class of none - ie the space li at end of menu
if (strstr($class, 'none')) {
return '<li class="'. $class . ' main"></span></span></li>';
}
if (strstr($class, 'li_wrap')) {
return '<li class="'. $class .' main"><span class="wrapped">'. $link . $menu ."<span class='indicator'></span></li>\n";
}
if (strstr($class, 'no_wrap')) {
return '<li class="'. $class . ' main">'. $link ."<span class='indicator'></span><span class='menu_box'><span class='menu_box_inner'>". $menu ."</span></span></li>\n";
}
}
Well I think the solution found here it's the best so I'm not going to take credit for it. Instead of overwriting theme_menu_item you should define your custom function theme_primary_links starting from theme_links.You can choose whatever name you think it's best for your custom theme (but make sure that it's not already used).
Bottom line: sometimes it's easier to define your custom theme than overwriting the default ones. That way you know that you can strictly apply the custom theme according to your needs (e.g. applied only to the primary menu links). Overwriting is best used when you want your changes to be global (e.g. applied to all menu links).

Resources