20 replies [Last post]
johngflower's picture
Offline
Joined: 01/04/2009
Juice: 88
Was this information Helpful?

How do insert a link into the Option text for an attribute?

I had this working, but after upgrading to ubercart-6.x-2.0-rc3 my links are broken. See http://localhost/drupal/product/cup-5.

Regards,

John

johngflower's picture
Offline
Joined: 01/04/2009
Juice: 88
Wrong link

My mistake. The attribute example is below:-

Artwork:
[ ] Text only
[ ] Reuse artwork that we have supplied in the past
[*] <a href="/drupal/node/add/artwork" target="_blank">Upload Artwork</a>. We will email you a quote for setting up the artwork.

johngflower's picture
Offline
Joined: 01/04/2009
Juice: 88
Re: Wrong link

*bump*

artatac's picture
Offline
Joined: 06/11/2009
Juice: 79
Re: Re: Wrong link

try temporarily putting in the full url http://...

johngflower's picture
Offline
Joined: 01/04/2009
Juice: 88
Re: Re: Re: Wrong link

No joy. Still get the code in plain text.

artatac's picture
Offline
Joined: 06/11/2009
Juice: 79
Re: Re: Re: Re: Wrong link

How about - input format - full html...

Lyle's picture
Offline
AdministratoreLiTe!
Joined: 08/07/2007
Juice: 6846
Re: Re: Re: Re: Re: Wrong link

There isn't an option to use an input format on option names.

How about putting a link to the upload instructions directly in the product description? If you don't want to type it in for all of your products, you can add a CCK Text field as a checkbox and have it display your message when it is checked on the edit screen.

jefkin's picture
Offline
Joined: 06/23/2009
Juice: 22
Hi John It maybe simpler to

Hi John

It maybe simpler to write a hook_form_alter and fix it that way, I've done that before with success in different but similar situation.

For example, the UC has different lifetime limits (and settings) for the shopping cart between anonymous and registered users. For my most recent site, we have no anonymous users, but the cart's minimum lifespan for registered users was 1 hour. I wanted it to be 10 minutes for testing. Additionally, The client wanted 65 minute lifespans on carts ... (meh clients Laughing out loud)

here is my code:

<?php
function mymodule_form_alter(&$form, &$form_state, $form_id)
{
 
/*
  ** For debugging, add the 10 minute timeout capability to authenticated
  ** accounts, or more importantly 65 minutes for production.
  */
 
if ($form_id == 'uc_cart_cart_settings_form')
  {
   
$form['authenticated']['uc_cart_auth_duration']['#options']['65']  = 65;
   
$form['authenticated']['uc_cart_auth_unit']['#options']['minutes'] = "Minute(s)";
  }
}
?>

So for your work, you should identify the form, and you might be able to work a similar trick.

HTH

Jeff

johngflower's picture
Offline
Joined: 01/04/2009
Juice: 88
Re: Hi John It maybe simpler to

Thank you for your suggestions.

I'm inclined to go through the Ubercart code. I had a brief look through the UC attribute module code and found

}
$form_attributes[$attribute->aid] = array(
'#type' => $attribute->display == 1 ? 'select' : 'radios',
'#title' => $attribute->name,
'#description' => check_plain($attribute->description),
'#default_value' => $attribute->default_option,
'#options' => $options,
'#required' => $attribute->required,
);
}

And noticed that in the new version check_plain had been changed to check_markup. I tried switching it back but didn't see any change, should I? I may not have flushed browser and drupal caches.

I could revert to the old version. But I chose to upgrade because Joel Stein @ http://www.ubercart.org/issue/8356/attribute_textarea#comment-40210 kindly created a patch which solved another of my problems. Maybe I'm better off trying to apply the patch to the old version?

Regards,

John

jefkin's picture
Offline
Joined: 06/23/2009
Juice: 22
Re: Re: Hi John It maybe simpler to

I tend to agree with Lyle, that putting this in a paragraph is superior to trying to dodge the check_plain or check_markup.

First, to make things simple, edit your 3rd attribute and remove the current link text (which isn't working and won't work as it can't pass through either check_plain or check_markup without denaturing the html). Set the attribute text to something simple like; 'We will email you a quote for setting up the artwork'.

Hacking core, or even major modules like UC is generally bad. Especially when you can accomplish what you need using hooks.

Ok found your code example in the file "uc_attribute.module", in the function _uc_attribute_alter_form, a helper function for uc_attributes's own hook_form_alter(): uc_attribute_form_alter().

Using that as a guideline, I propose you roll your own quick module along the lines of this:

module artwork_attribute

file: artwork_attribute.module

<?php
/*
** hook_form_alter -> catch all forms with attributes, and add our link text to them.
**
** we select the forms we will alter in the same manner that is used by module 'uc_attribute'
*/
function artwork_attribute_form_alter(&$form, &$form_state, $form_id)
{
 
// form id selection lifted from uc_attribute_form_alter
 
if (strpos($form_id, 'add_to_cart_form') || strpos($form_id, 'add_product_form'))
  {
   
$found = false;

   

// If the node has a product list, add attributes to them
   
if (isset($form['products']) && count(element_children($form['products'])))
    {
      foreach (
element_children($form['products']) as $key)
      {
       
$found = $found || array_key_exists('attributes', $form['products'][$key]);
      }
    }
    elseif (isset(
$form['attributes']))
    {
     
$found = true;
    }
    if (
$found)
    {
     
$form['artwork'] = array ( '#prefix' =>'<div>'
                            
,   '#value'  =>'Text here about uploads for art work'
                                          
. l('Upload Artwork', '/node/add/artwork',
                                               array (
'attributes'=>array ( 'target'=>'_blank' ))
                             ,  
'#suffix' =>'</div>'
                          
# ,   '#weight' =>0 // you'll have to play with this for display.
                            
, );
    }
  }
}
?>

Caveat Emptor, I wrote this on the forum, it is not tested. The point is you can do this with your own simple module. Not that you SHOULD do it that way. If you're totally unfamiliar with module building ask someone to do it for you here, maybe with a small bounty since I wrote some base code.

Jeff

johngflower's picture
Offline
Joined: 01/04/2009
Juice: 88
Re: Re: Re: Hi John It maybe simpler to

I acknowledge that hacking the core is a big NoNo. I have hacked the core in the past because I'm a complete numpty, and that was the easiest way to get the result I wanted given my state of ignorance. I've got a great dirty text file full of notes about my hacks!

Thank you for the headstart in building a module. Whilst totally unfamiliar with module building, I shall give it a bash. I'll do some research about building, test on a dev site, and report back my results.

Regards,
John

johngflower's picture
Offline
Joined: 01/04/2009
Juice: 88
Re: Re: Re: Re: Hi John It maybe simpler to

I followed the tutorial on creating a module at. I've got the module installed but I'm getting an error:-

Fatal error: Cannot use string offset as an array in /var/www/html/drupal/includes/form.inc on line 979

This error only displays on products with the Artwork attribute. The section of code the error relates to is:-

<?php
 
if (!empty($form['#disabled'])) {
   
$form['#attributes']['disabled'] = 'disabled';
  }
?>

This is how I've implemented Jeff's code from above:-

uc_attribute.info

; $Id$
name = Attribute Link
description = Insert a link to create an Artwork node in ubercart attribute descriptions
dependencies[] = uc_attribute
package = "Ubercart - extra"
core = 6.x
php = 5.0

uc_attribute.module

<?php
// $Id$

/**
* @file
* Ubercart Attribute Link module.
*
* This module makes it possible to have html links in an attribute option description.
*
*/

/******************************************************************************
* Drupal Hooks                                                               *
******************************************************************************/

/**
* Implementation of hook_help().
*/

function uc_attribute_link_help($path, $arg) {
 
$output = ''//declare your output variable
 
switch ($path) {
    case
"admin/help#uc_attribute_link":
     
$output = '<p>'t("This module makes it possible to have html links in an attribute option description.") .'</p>';
      break;
  }
  return
$output;
}

/*
** hook_form_alter -> catch all forms with attributes, and add our link text to them.
**
** we select the forms we will alter in the same manner that is used by module 'uc_attribute'
*/
function uc_attribute_link_form_alter(&$form, &$form_state, $form_id)
{
 
// form id selection lifted from uc_attribute_form_alter
 
if (strpos($form_id, 'add_to_cart_form') || strpos($form_id, 'add_product_form'))
  {
   
$found = false;

  

// If the node has a product list, add attributes to them
   
if (isset($form['products']) && count(element_children($form['products'])))
    {
      foreach (
element_children($form['products']) as $key)
      {
       
$found = $found || array_key_exists('attributes', $form['products'][$key]);
      }
    }
    elseif (isset(
$form['attributes']))
    {
     
$found = true;
    }
    if (
$found)
    {
     
$form['artwork'] = array ( '#prefix' =>'<div>',
                               
'#value'  =>'Text here about uploads for art work',
                                           
l('Upload Artwork', '/node/add/artwork',
                                               array (
'attributes'=>array ( 'target'=>'_blank' ))),
                               
'#suffix' =>'</div>',
                               
#'#weight' =>0, // you'll have to play with this for display.
                             
);
    }
  }
}
?>

Any ideas on what I need to change?

johngflower's picture
Offline
Joined: 01/04/2009
Juice: 88
Re: Re: Re: Re: Re: Hi John It maybe simpler to

Html in attributes isn't enough. I've been following the order process and discovered some new things. I want it through the whole order process. I have Text Areas as an option type. In plain text mode carriage returns aren't acknowledged. In Rich Text mode, using Tiny TinyMCE, the markup is exposed in the cart and the admin email. This requires a module/change of code at a higher level.

I'm going to start by looking for a place where the Ubercart module does allow html tags and then try and paste that code into the modules that are outputting plain text. I think this is the easist path. Unless the Ubercart Dev team might consider patching the Ubercart modules to allow html?

Any suggestions on this course of action, recommended things to look at?

johngflower's picture
Offline
Joined: 01/04/2009
Juice: 88
Re: Re: Re: Re: Re: Re: Hi John It maybe simpler to

Warning: Implementing these changes does not follow good Drupal coding practice. Any changes made will be broken if the module is updated.

I'm making some headway, hacking at the core:-

uc_cart.module
680 Shopping Cart block

$output .= ''. check_markup($item['desc'], $format = FILTER_FORMAT_DEFAULT, $check = TRUE) .'';

This change puts the carriage returns in. Still working through the rest of the code.

tembenite's picture
Offline
Joined: 08/15/2010
Juice: 64
Re: Wrong link

I ran into an issue like your original issue where I could not put links within the Product Attributes because it was escaped.

I traced the code down and discovered that the escaping of the attributes is happening from the returned output from uc_product_get_description. That function actually calls two hooks, hook_product_description and hook_product_description_alter which happen before the problem is introduced.

The actual escaping of the output happens when drupal_render is called, right before the results of uc_product_get_description are returned.

In taking a look at the drupal_render code, I noticed that it supports a post_render function if you store it within the element as $item[#post_render].

As a result I added a hook_product_description_alter hook which added the post_render tag to call one of my functions after drupal render is done with the output. As a result if I add my links at this stage of the game it will on longer be filtered Smiling.

Hopefully this might end up helping someone.

johngflower's picture
Offline
Joined: 01/04/2009
Juice: 88
Re: Want HTML links in Attribute Option text

Warning: Implementing these changes does not follow good Drupal coding practice. Any changes made will be broken if the module is updated.

Further changes:-

uc_cart.module
884 Shopping Cart
$form['items'][$i]['desc']['#value'] = check_markup($description, $format = FILTER_FORMAT_DEFAULT, $check = TRUE);

uc_cart_checkout_pane.inc
607 cart-checkout-item
array('data' => check_markup($description, $format = FILTER_FORMAT_DEFAULT, $check = TRUE), 'class' => 'products'),

And that completes the changes needed for uc_cart.module to display carriage returns. There are still some issues. Such as if the line is too long, and the cart block is on a side bar, the text may extend beyond the bar. Also, it'd be tidyier if the attribute has multiple lines of text, that the first line starts below the attribute title.

johngflower's picture
Offline
Joined: 01/04/2009
Juice: 88
Re: Re: Want HTML links in Attribute Option text

Warning: Implementing these changes does not follow good Drupal coding practice. Any changes made will be broken if the module is updated.

Also:-

uc_attribute.module
638
$options[$option->oid] = $options[$option->oid];
669
$form_attributes[$attribute->aid]['#title'] = $name;

djg_tram's picture
Offline
Joined: 06/26/2011
Juice: 26
Without patching

There is no need to patch core. Use the solution already hinted at here, but not to modify the function you add the descriptions in, just to post-process it.

Provide whatever description you need in hook_product_description_alter(). Also add a line:

$description['#post_render'][] = "_module_restore_links";

And post-process it with the function:

function _module_restore_links($html) {
  return str_replace(array('&lt;a href=&quot;', '&quot;&gt;', '&lt;/a&gt;'), array('<a href="', '">', '</a>'), $html);
}
klausson's picture
Offline
Joined: 05/05/2010
Juice: 31
Re: Without patching

@djg_tram: Thanks, this worked great for me in cases where we display a product and need to link the attribute name to some explanation (we're using lightbox2 for this). I put similar code into the _form_alter section of my module and it works. However, I'm trying to get the same links activated when users create a new entry. It seems that there must be yet another place to insert the post_render or some equivalent hook. Any idea which hook to use in this case?

klausson's picture
Offline
Joined: 05/05/2010
Juice: 31
Re: Re: Without patching

Oops, never mind: I had two separate blocks in my form_alter - one for a form with the id "node-form" the other for a product that's ready to order. I only added the post_render section to the latter. Duh :-/

klausson's picture
Offline
Joined: 05/05/2010
Juice: 31
Re: Re: Re: Without patching

One more question though: Now that I have my links working in the attribute option text, the links show up unconverted in the order form and shopping carts. I suspect there is an ubercart hook somewhere that will allow me to override them there as well and clean the links the same way. Does anybody know what the right hook is?