uc_option_image.module in Ubercart Option Images 7
Same filename and directory in other branches
Allow store administrators to add images to attribute options.
@author Aaron Craig <aaron@evolving-design.com>
This module is a complete rewrite of the original UC Option Image module by Tj Holowaychuk <tj@vision-media.ca/>. The module has been rewritten to accomodate the many changes in the Drupal API for D7 and the Ubercart API for UC3
File
uc_option_image.moduleView source
<?php
/**
* @file
* Allow store administrators to add images to attribute options.
*
* @author
* Aaron Craig <aaron@evolving-design.com>
*
* This module is a complete rewrite of the original UC Option Image module by Tj Holowaychuk <tj@vision-media.ca/>.
* The module has been rewritten to accomodate the many changes in the Drupal API for D7 and the Ubercart API for UC3
*/
/**
* Implements hook_permission().
*/
function uc_option_image_permission() {
return array(
'view option images' => array(
'title' => t('view option images'),
'description' => t('Allow the user to view option images'),
),
'administer option images' => array(
'title' => t('administer option images'),
'description' => t('Allow the user to administer option images'),
),
);
}
/**
* Implements hook_theme().
*/
function uc_option_image_theme($existing, $type, $theme, $path) {
return array(
'uc_option_image_selected' => array(
'variables' => array(
'values' => NULL,
'aid' => NULL,
'pid' => NULL,
),
'file' => 'uc_option_image.theme.inc',
),
'uc_option_image_inline' => array(
'variables' => array(
'values' => NULL,
),
'file' => 'uc_option_image.theme.inc',
),
);
}
/**
* Implements hook_form_alter().
*/
function uc_option_image_form_alter(&$form, &$form_state, $form_id) {
// Before rendering the form, add the images
if (strstr($form_id, 'uc_product_add_to_cart_form')) {
$form['#pre_render'][] = 'uc_option_image_add_to_cart_prerender';
}
else {
if (strstr($form_id, 'uc_product_kit_add_to_cart_form')) {
$form['#pre_render'][] = 'uc_option_image_kit_add_to_cart_prerender';
}
}
// Change the AJAX handler for the add to cart form (and the add product form)
// TODO: some solution for uc_order_add_product_form
if (strpos($form_id, 'add_to_cart_form')) {
if (isset($form['attributes'])) {
foreach ($form['attributes'] as $key => $attribute) {
if (is_numeric($key) && isset($form['attributes'][$key]['#ajax'])) {
if ($form['attributes'][$key]['#ajax']['callback'] == 'uc_attribute_option_ajax') {
$form['attributes'][$key]['#ajax']['callback'] = 'uc_option_image_uc_attribute_option_ajax';
}
}
}
}
}
}
// Extended AJAX handler
function uc_option_image_uc_attribute_option_ajax($form, $form_state) {
$return = uc_attribute_option_ajax($form, $form_state);
// changes ajax_command_replace item
$parents = $form_state['triggering_element']['#array_parents'];
$wrapper = '#' . $form_state['triggering_element']['#ajax']['wrapper'];
while ($key = array_pop($parents)) {
if ($key == 'attributes') {
array_push($parents, $key);
$element = drupal_array_get_nested_value($form, $parents);
// _uc_option_image_modify_attributes($element);
foreach ($return['#commands'] as $key => $command) {
if ($command['command'] == 'insert' && $command['method'] == 'replaceWith' && $command['selector'] == $wrapper) {
$option = 0;
foreach ($element as $aid => $attribute) {
if (is_numeric($aid)) {
foreach ($attribute['#options'] as $oid => $text) {
$oldtitle = $wrapper . " #oldtitle_{$oid}";
$html = "<span class='oldtitle' id='oldtitle_{$oid}'>{$text}</span>";
if ($option == 0) {
// first replace action replaces the old one
$option++;
$return['#commands'][$key] = ajax_command_replace($oldtitle, $html);
}
else {
// subsequent replace actions are added at the end
$return['#commands'][] = ajax_command_replace($oldtitle, $html);
}
}
break;
}
}
break;
}
}
break;
}
}
return $return;
}
/**
* Add the image to each option element.
*/
function uc_option_image_add_to_cart_prerender($element) {
_uc_option_image_modify_attributes($element);
return $element;
}
function uc_option_image_kit_add_to_cart_prerender($element) {
foreach ($element['products'] as $key => $product) {
if (is_numeric($key)) {
_uc_option_image_modify_attributes($element['products'][$key]);
}
}
return $element;
}
function _uc_option_image_modify_attributes(&$element) {
$nid = $element['nid']['#value'];
foreach (element_children($element['attributes']) as $aid) {
$uc_attribute = $element['attributes'][$aid];
$oids = $uc_attribute['#type'] == 'select' ? array_keys($uc_attribute['#options']) : element_children($uc_attribute);
// add the images of each option as the element title
$values = NULL;
foreach ($oids as $oid) {
$values = uc_option_image_values('uc_product', array(
'aid' => $aid,
'oid' => $oid,
'pid' => $nid,
));
if (empty($values['fid']) || empty($values['fid']['value'])) {
continue;
}
if (in_array($uc_attribute['#type'], array(
'radios',
'checkboxes',
))) {
if ($values && isset($values['inline_active']) && $values['inline_active']['value']) {
$oldtitle = $element['attributes'][$aid][$oid]['#title'];
$extratitle = theme('uc_option_image_inline', array(
'values' => $values,
));
$newtitle = $extratitle . "<span id='oldtitle_{$oid}' class='oldtitle'>{$oldtitle}</span>";
$element['attributes'][$aid][$oid]['#title'] = $newtitle;
}
}
}
// add the image of the selected option as a prefix
if ($values && !empty($values['selected_active']) && $values['selected_active']['value']) {
$element['attributes'][$aid]['#prefix'] = theme('uc_option_image_selected', array(
'values' => $values,
'aid' => $aid,
'pid' => $nid,
));
}
}
}
/**
* Implements hook_uc_object_options_form_alter()
*
* Instead of adding the image upload field to the table rows on this form, as was done in the D6
* version, I'm adding a separate frameset.
*
* This avoids having to reimplement the entire theme function for the form.
*/
function uc_option_image_form_uc_object_options_form_alter(&$form, &$form_state) {
$type = isset($form['type']) && !empty($form['type']['#value']) ? 'uc_' . $form['type']['#value'] : NULL;
$nid = isset($form['id']) && !empty($form['id']['#value']) ? $form['id']['#value'] : NULL;
$attributes = uc_product_get_attributes($nid);
if (!$attributes) {
// no options
return;
}
$form['uc_option_image'] = array(
'#type' => 'fieldset',
'#title' => t("Option images"),
'#collapsible' => FALSE,
'#collapsed' => FALSE,
);
$id_key = uc_option_image_key($type);
foreach ($attributes as $aid => $uc_attribute) {
if (empty($uc_attribute->options)) {
continue;
}
$form['uc_option_image']['option_image_attribute-' . $aid] = array(
'#type' => 'fieldset',
'#title' => t("Option images for @attribute", array(
'@attribute' => $uc_attribute->name,
)),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
);
foreach ($uc_attribute->options as $oid => $uc_option) {
$object = uc_option_image_objects('uc_product', array(
'aid' => $aid,
$id_key => $nid,
'oid' => $oid,
));
$option_defaults = uc_option_image_values('uc_product', array(
'aid' => $aid,
$id_key => $nid,
'oid' => $oid,
));
$form['uc_option_image']['option_image_attribute-' . $aid]['option_image-fid-' . $oid] = uc_option_image_file_form($type, $object, $option_defaults);
$form['uc_option_image']['option_image_attribute-' . $aid]['option_image-fid-' . $oid]['#title'] = t("Image for !option", array(
'!option' => $uc_option->name,
));
}
$object = uc_option_image_objects('uc_product', array(
'aid' => $aid,
$id_key => $nid,
));
$defaults = uc_option_image_values('uc_product', array(
'aid' => $aid,
$id_key => $nid,
));
$form['uc_option_image']['option_image_attribute-' . $aid]['display_options'] = uc_option_image_display_form('uc_product', $object, $defaults, $aid);
}
$form['#submit'][] = 'uc_option_image_product_options_submit';
}
function uc_option_image_product_options_submit($form, $form_state) {
$values = $form_state['values'];
$type = 'uc_' . $values['type'];
$id_key = uc_option_image_key($type);
foreach ($values['attributes'] as $aid => $uc_attribute) {
foreach ($uc_attribute['options'] as $oid => $uc_option) {
if (!$uc_option['select']) {
continue;
}
$data['fid'] = !empty($values['option_image-fid-' . $oid]) ? $values['option_image-fid-' . $oid] : 0;
foreach (array(
'inline',
'selected',
) as $mode) {
$data[$mode . '_active'] = $values[$mode . '_active_' . $aid];
$data[$mode . '_style'] = $values[$mode . '_style_' . $aid];
}
uc_option_image_save_form_data($type, array(
'aid' => $aid,
'oid' => $oid,
$id_key => $values['id'],
), $data);
}
}
}
/**
* Implements hook_form_uc_attribute_form_alter()
*
* Add a form element to allow the admin to insert a default image which applies to
* all options, unless an option is overridden.
*/
function uc_option_image_form_uc_attribute_form_alter(&$form, &$form_state) {
uc_option_image_form($form, $form_state, 'uc_attribute');
}
function uc_option_image_form_uc_attribute_option_form_alter(&$form, &$form_state) {
uc_option_image_form($form, $form_state, 'uc_option');
}
/**
* Add a form element to allow the admin to insert a default image which applies to
* all options, unless an option is overridden.
*
* @param &$form
*
* @param &$form_state
*
* @param $type
* 'attribute' or 'option'
*/
function uc_option_image_form(&$form, &$form_state, $type) {
$aid = isset($form['aid']) ? $form['aid']['#value'] : NULL;
$oid = isset($form['oid']) ? $form['oid']['#value'] : NULL;
$object = uc_option_image_objects($type, array(
'aid' => $aid,
'oid' => $oid,
));
$values = uc_option_image_values($type, array(
'aid' => $aid,
'oid' => $oid,
));
$form['option_image'] = array(
'#type' => 'fieldset',
'#title' => t("Image"),
'#collapsible' => TRUE,
'uc_option_image_type' => array(
'#type' => 'hidden',
'#value' => $type,
),
'uc_option_image_aid' => array(
'#type' => 'hidden',
'#value' => $aid,
),
'uc_option_image_oid' => array(
'#type' => 'hidden',
'#value' => $oid,
),
'uc_option_image_fid' => uc_option_image_file_form($type, $object, $values),
uc_option_image_display_form($type, $object, $values),
);
if ($type != 'uc_attribute' && !empty($values['fid']) && $values['fid']['is_default']) {
$file = file_load($values['fid']['value']);
$form['option_image']['uc_option_image_fid']['#description'] .= " <strong>Currently using default image '" . $file->filename . "'</strong>";
}
$form['#submit'][] = 'uc_option_image_form_submit';
}
/**
* Generate a form element for the display / image style parameters
*
* @param $type = ''
* uc_attribute, uc_option, uc_product or uc_class
*
* @param $object
* The data for this instance
*
* @param $values
* The values for this instance, including default data
*
* @param $delta = ''
* Optionally pass a delta if there are more than one of these in the form.
*
* @return
* A form fieldset
*/
function uc_option_image_display_form($type, $object, $values, $delta = '') {
$form = array(
'#type' => 'fieldset',
'#title' => t("Image display options"),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
);
$image_styles = uc_option_image_styles($type);
foreach (uc_option_image_modes() as $mode) {
$active = $mode . '_active';
$style = $mode . '_style';
$active_key = $active;
$style_key = $style;
if ($delta !== '') {
$active_key .= '_' . $delta;
$style_key .= '_' . $delta;
}
if ($mode == 'inline') {
$description = t("Display an image inline next to each option title.");
}
else {
$description = t("Display an image showing the selected option(s).");
}
$form[$mode . '_wrapper'] = array(
'#type' => 'fieldset',
'#title' => t("!type display", array(
'!type' => ucwords($mode),
)),
'#collapsible' => FALSE,
'#collapsed' => FALSE,
$active_key => array(
'#type' => 'checkbox',
'#title' => $description,
'#default_value' => $object ? $object->{$active} : FALSE,
),
$style_key => array(
'#title' => t('Style'),
'#type' => 'select',
'#options' => $image_styles,
'#default_value' => $object ? $object->{$style} : 'none',
'#description' => t('Choose a style that will be used to display the image for this option, or leave blank to use the default style.'),
),
);
if ($type != 'uc_attribute' && !empty($values[$active]) && $values[$active]['is_default']) {
$form[$mode . '_wrapper'][$active_key]['#description'] = " <strong>Currently active due to the default setting.</strong>";
}
if ($type != 'uc_attribute') {
$form[$mode . '_wrapper'][$style]['#options']['none'] = t('use default');
if (!empty($values[$style]) && $values[$style]['is_default']) {
$form[$mode . '_wrapper'][$style_key]['#description'] .= " <strong>Currently using default style '" . $values[$style]['value'] . "'</strong>";
}
}
}
return $form;
}
/**
* Generate a file field for uploading an attribute image.
*
* @param $type = ''
* uc_attribute, uc_option, uc_product or uc_class
*
* @param $object
* The data for this instance
*
* @param $values
* The values for this instance, including default data
*
* @return
* A form file field
*/
function uc_option_image_file_form($type, $object, $values) {
$form = array(
'#title' => t('Image'),
'#type' => 'managed_file',
'#description' => t('Upload an image that will be displayed along with this option, or leave blank to use the default image.'),
'#default_value' => $object ? $object->fid : '',
'#upload_location' => 'public://uc_option_image/',
);
if ($type != 'uc_attribute' && !empty($values['fid']) && $values['fid']['is_default']) {
$file = file_load($values['fid']['value']);
if (!empty($file)) {
$form['#description'] .= " <strong>Currently using default image '" . $file->filename . "'</strong>";
}
}
return $form;
}
/**
* Submit handler for the attribute / option default settings forms
*/
function uc_option_image_form_submit($form, $form_state) {
$values = $form_state['values'];
$data['fid'] = $values['uc_option_image_fid'];
foreach (array(
'inline',
'selected',
) as $mode) {
$data[$mode . '_active'] = $values[$mode . '_active'];
$data[$mode . '_style'] = $values[$mode . '_style'];
}
$type = $values['uc_option_image_type'];
// if this is a new aid or oid, our value will be NULL but uc_attribute will have already
// saved the new object and stored the new id in $values
$aid = !empty($values['uc_option_image_aid']) ? $values['uc_option_image_aid'] : $values['aid'];
$oid = !empty($values['uc_option_image_oid']) ? $values['uc_option_image_oid'] : !empty($values['oid']) ? $values['oid'] : NULL;
uc_option_image_save_form_data($type, array(
'aid' => $aid,
'oid' => $oid,
), $data);
}
function uc_option_image_save_form_data($type, $ids, $values) {
$object = uc_option_image_objects($type, $ids);
if (!$object) {
$object = (object) array(
'type' => $type,
);
foreach ($ids as $key => $id) {
$object->{$key} = $id;
}
$object->fid = 0;
}
$id_key = uc_option_image_key($type);
// delete a file if it's been removed
if (isset($values['fid']) && $values['fid'] != $object->fid) {
if ($object->fid) {
$file = file_load($object->fid);
if ($file) {
file_usage_delete($file, 'uc_option_image', $type, $object->{$id_key});
file_delete($file);
}
}
if ($values['fid'] > 0) {
$file = file_load($values['fid']);
if ($file) {
$file->status = 1;
file_save($file);
file_usage_add($file, 'uc_option_image', $type, $object->{$id_key});
}
}
$object->fid = $values['fid'];
}
foreach (uc_option_image_modes() as $mode) {
$a = $mode . '_active';
$s = $mode . '_style';
// fixed: isset was '!empty', which prohibited unchecked checkboxes to be saved
if (isset($values[$a]) && !empty($values[$s])) {
$object->{$a} = $values[$a];
$object->{$s} = $values[$s] == 'none' ? '' : $values[$s];
}
}
uc_option_image_object_save($object);
}
/**
* Retrieve the image id for a given object
*
* @param $type = ''
* uc_attribute, uc_option, uc_product or uc_class
* If this is an empty string, all objects will be returned, keyed by type
*
* @param $ids = NULL
* The instance ids of the object, since each row contains multiple ids, according to the specificity of the data
* If this is NULL, all objects of the given type will be returned
*
* @return
* Depending on the parameters, an array, a keyed array, or an object
*
* $type and $ids are empty: a keyed array where the keys are type names and the values are arrays of objects
* only $ids is empty: an array of objects
* neither are empty: a single object
*
* In all cases, if no data is present, NULL will be returned
*/
function uc_option_image_objects($type = '', $ids = NULL) {
$query = db_select('uc_option_image', 'uoi');
$query
->fields('uoi');
if ($type) {
$query
->condition('type', $type);
}
if ($ids) {
$ids += array(
'aid' => NULL,
'oid' => NULL,
'pid' => NULL,
'cid' => NULL,
);
foreach ($ids as $field => $id) {
if ($id) {
$query
->condition($field, $id);
}
else {
$query
->condition($field, 0);
}
}
}
$result = $query
->execute();
$objects = array();
foreach ($result as $row) {
$objects[$row->type][] = $row;
}
if (!$objects) {
return NULL;
}
if ($type && $ids) {
return empty($objects[$type]) ? NULL : $objects[$type][0];
}
if ($type && !$ids) {
return empty($objects[$type]) ? NULL : $objects[$type];
}
return $objects;
}
/**
* Store one or more objects to the database
*
* Note that the object MUST have an id.
*
* @param $objects
* An array of objects, or a single object
*/
function uc_option_image_object_save($objects) {
if (is_object($objects)) {
$objects = array(
$objects,
);
}
foreach ($objects as $object) {
$d = db_delete('uc_option_image');
$d
->condition('type', $object->type);
foreach (array(
'aid',
'oid',
'pid',
'cid',
) as $field) {
if (!empty($object->{$field})) {
$d
->condition($field, $object->{$field});
}
else {
$object->{$field} = 0;
}
}
$d
->execute();
if (empty($object->fid) && empty($object->inline_style) && empty($object->inline_active) && empty($object->selected_style) && empty($object->selected_active)) {
continue;
}
drupal_write_record('uc_option_image', $object);
}
}
/**
* Get the value to use for this instance
*
* @param $type
* uc_attribute, uc_option, uc_product or uc_class
*
* @param $ids
* The instance ids of the object, since each row contains multiple ids, according to the specificity of the data
* If this is NULL, all objects of the given type will be returned
*
* @return
* An array containing keys corresponding to the requested values. Each key's value is itself an array, containing value and is_default.
*/
function uc_option_image_values($type, $ids) {
$query = db_select('uc_option_image', 'uoi');
$query
->fields('uoi');
foreach ($ids as $field => $id) {
if ($id) {
$or = db_or();
$or
->condition($field, $id);
$or
->condition($field, 0);
$query
->condition($or);
}
}
$result = $query
->execute();
$objects = array();
foreach ($result as $row) {
$objects[$row->type][] = $row;
}
$return = array();
foreach (array(
'fid',
'inline_active',
'inline_style',
'selected_active',
'selected_style',
) as $value) {
if (!empty($objects[$type]) && !empty($objects[$type][0]->{$value})) {
$return[$value] = array(
'value' => $objects[$type][0]->{$value},
'is_default' => FALSE,
);
}
else {
foreach (array(
'uc_product',
'uc_class',
'uc_option',
'uc_attribute',
) as $test_type) {
if (!empty($objects[$test_type]) && !empty($objects[$test_type][0]->{$value})) {
$return[$value] = array(
'value' => $objects[$test_type][0]->{$value},
'is_default' => TRUE,
);
break;
}
}
}
}
return $return;
}
/**
* Get the id key for a given type
*
* @param $type
* uc_attribute, uc_option, uc_product or uc_class
*
* @return
* A string corresponding to the name of the id field
*/
function uc_option_image_key($type) {
return substr($type, 3, 1) . 'id';
}
/**
* Get a list of image styles as options for a select element
*
* @param $type
* uc_attribute, uc_option, uc_product or uc_class
*
* @return
* A keyed array of image styles. The first option is a null value
*/
function uc_option_image_styles($type) {
$image_styles = image_styles();
$styles = array(
'none' => $type == 'uc_attribute' ? t("no style selected") : t('use default'),
);
foreach ($image_styles as $name => $settings) {
$styles[$name] = $name;
}
return $styles;
}
/**
* Get a list of display styles as options for a select element
*
* @return
* A keyed array of display methods. The first option is a null value
*/
function uc_option_image_displays() {
return array(
'default' => t("use default"),
'inline' => t('inline'),
'selected' => t('selected'),
);
}
/**
* Get an array of the available display modes.
*
* @return
* An array of strings.
*/
function uc_option_image_modes() {
return array(
'inline',
'selected',
);
}
Functions
Name![]() |
Description |
---|---|
uc_option_image_add_to_cart_prerender | Add the image to each option element. |
uc_option_image_displays | Get a list of display styles as options for a select element |
uc_option_image_display_form | Generate a form element for the display / image style parameters |
uc_option_image_file_form | Generate a file field for uploading an attribute image. |
uc_option_image_form | Add a form element to allow the admin to insert a default image which applies to all options, unless an option is overridden. |
uc_option_image_form_alter | Implements hook_form_alter(). |
uc_option_image_form_submit | Submit handler for the attribute / option default settings forms |
uc_option_image_form_uc_attribute_form_alter | Implements hook_form_uc_attribute_form_alter() |
uc_option_image_form_uc_attribute_option_form_alter | |
uc_option_image_form_uc_object_options_form_alter | Implements hook_uc_object_options_form_alter() |
uc_option_image_key | Get the id key for a given type |
uc_option_image_kit_add_to_cart_prerender | |
uc_option_image_modes | Get an array of the available display modes. |
uc_option_image_objects | Retrieve the image id for a given object |
uc_option_image_object_save | Store one or more objects to the database |
uc_option_image_permission | Implements hook_permission(). |
uc_option_image_product_options_submit | |
uc_option_image_save_form_data | |
uc_option_image_styles | Get a list of image styles as options for a select element |
uc_option_image_theme | Implements hook_theme(). |
uc_option_image_uc_attribute_option_ajax | |
uc_option_image_values | Get the value to use for this instance |
_uc_option_image_modify_attributes |