Basic search API integration.
[sandbox/serialjaywalker/1195272.git] / modules / quantity_profile / commerce_pos_quantity_profile.module
1 <?php
2
3 /**
4 * Implements hook_enable().
5 */
6 function commerce_pos_quantity_profile_enable() {
7 $field_name = 'commerce_pos_quantity_profile';
8 $field = field_info_field($field_name);
9
10 if (empty($field)) {
11 $field = array(
12 'field_name' => $field_name,
13 'type' => 'list_text',
14 'settings' => array('allowed_values_function' => 'commerce_pos_quantity_profile_titles'));
15 field_create_field($field);
16 }
17
18 foreach (commerce_product_types() as $type => $info) {
19 commerce_pos_quantity_profile_configure_product_type($type);
20 }
21 }
22
23 /**
24 * Implements hook_modules_enabled().
25 */
26 function commerce_pos_quantity_profile_modules_enabled($modules) {
27 foreach ($modules as $module) {
28 if (module_implements('commerce_product_type_info', $module)) {
29 $types = module_invoke($module, 'commerce_product_type_info');
30 if ($types) {
31 foreach ($types as $type => $info) {
32 commerce_pos_quantity_profile_configure_product_type($type);
33 }
34 }
35 }
36 }
37 }
38
39 /**
40 * Creates a quantity profile instance on a product bundle.
41 * @param $type
42 * The machine readable name of the product type.
43 */
44 function commerce_pos_quantity_profile_configure_product_type($type) {
45 $field_name = 'commerce_pos_quantity_profile';
46
47 $instance = field_info_instance('commerce_product', $field_name, $type);
48
49 if (empty($instance)) {
50 $instance = array(
51 'field_name' => $field_name,
52 'label' => t('Quantity profile'),
53 'entity_type' => 'commerce_product',
54 'bundle' => $type,
55 );
56
57 field_create_instance($instance);
58 }
59 }
60
61 /**
62 * Gets all quantity profiles, or a specific one.
63 *
64 * @param $profile_name
65 * (Optional) The name of the quantity profile to return.
66 *
67 * @return
68 * An array of all quantity profiles if $profile_name is not provided,
69 * the one given by $quantity_profile if it exists, or FALSE otherwise.
70 */
71 function commerce_pos_quantity_profile_info($profile_name = NULL) {
72 $profiles = &drupal_static(__FUNCTION__);
73
74 if (empty($profiles)) {
75 foreach(module_implements('commerce_pos_quantity_profile_info') as $module) {
76 $function = $module . '_commerce_pos_quantity_profile_info';
77 $new_profiles = $function();
78
79 foreach($new_profiles as $name => $profile) {
80 $profile += array(
81 'name' => $name,
82 'increment' => 1,
83 'weight' => 0,
84 );
85
86 $profiles[$name] = $profile;
87 }
88 uasort($profiles, 'drupal_sort_weight');
89 drupal_alter('commerce_pos_quantity_profile_info', $profiles);
90 }
91 }
92
93 if (empty($profile_name)) {
94 return $profiles;
95 }
96
97 if (!empty($profiles[$profile_name])) {
98 return $profiles[$profile_name];
99 }
100
101 return FALSE;
102 }
103
104 /**
105 * Returns an array of quantity profile titles, keyed by machine name.
106 */
107 function commerce_pos_quantity_profile_titles($field) {
108 $titles = &drupal_static(__FUNCTION__);
109
110 if (empty($titles)) {
111 $titles = array();
112 $profiles = commerce_pos_quantity_profile_info();
113 foreach ($profiles as $profile) {
114 $titles[$profile['name']] = $profile['title'];
115 }
116 }
117
118 return $titles;
119 }
120
121 /**
122 * Implements hook_commerce_pos_quantity_profile_info().
123 */
124 function commerce_pos_quantity_profile_commerce_pos_quantity_profile_info() {
125 return array(
126 'individual' => array(
127 'increment' => 1,
128 'title' => t('Individual (counted)'),
129 'rules component' => TRUE,
130 'weight' => 10,
131 'error' => t('The quantity should be an integer.'),
132 ),
133 'weight_pound' => array(
134 'increment' => 0.01,
135 'title' => t('Weight (pounds)'),
136 'unit name' => t('pound'),
137 'unit plural' => t('pounds'),
138 'unit abbreviation' => t('lb'),
139 'rules component' => TRUE,
140 'error' => t('Please enter the weight with no more than two decimal places.'),
141 'weight' => 1,
142 ),
143 );
144 }
145
146 /**
147 * Determines the quantity profile associated with a particular product.
148 *
149 * @param $product
150 * A fully loaded Commerce Product object.
151 * @param $nocache
152 * (optional) TRUE if the profile should not be loaded from the Cache.
153 *
154 * @return The machine name of the corresponding profile.
155 */
156 function commerce_pos_quantity_profile_get_product_profile($product, $nocache = FALSE) {
157 $profile_names = &drupal_static(__FUNCTION__);
158
159 if (!empty($product->commerce_pos_quantity_profile)) {
160 $wrapper = entity_metadata_wrapper('commerce_product', $product);
161 $value = $wrapper->commerce_pos_quantity_profile->value();
162
163 if (!empty($value))
164 return $value;
165 }
166
167 if (!empty($profile_names[$product->product_id]) && !$nocache) {
168 return $profile;
169 }
170
171 $components = rules_get_components(FALSE, 'action');
172
173 // Loop over each quantity profile in search of matching components.
174 foreach (commerce_pos_quantity_profile_info() as $name => $profile) {
175
176 $component_name = 'commerce_pos_quantity_profile_' . $name;
177
178 // If we can load the current profile's component...
179 if (!empty($components[$component_name])) {
180 // Invoke it with the product.
181 rules_invoke_component($component_name, $product);
182 }
183 if (!empty($product->quantity_profile)) {
184 $profile_names[$product->product_id] = $product->quantity_profile;
185 return $product->quantity_profile;
186 }
187 }
188 }
189
190 /**
191 * Implements hook_commerce_pos_action_info_alter().
192 */
193 function commerce_pos_quantity_profile_commerce_pos_action_info_alter(&$info) {
194 foreach ($info['commerce_pos_product']['callbacks']['validate'] as $key => $function) {
195 if ($function == 'commerce_pos_line_item_require_integer_quantity') {
196 $info['commerce_pos_product']['callbacks']['validate'][$key] = 'commerce_pos_quantity_profile_validate';
197 return;
198 }
199 }
200 }
201
202 /**
203 * Quantity validator for quantity profiles.
204 */
205 function commerce_pos_quantity_profile_validate($variables) {
206 if (!empty($variables['line_item'])) {
207 $line_item = $variables['line_item'];
208
209 if (!empty($line_item->commerce_product)) {
210 $wrapper = entity_metadata_wrapper('commerce_line_item', $line_item);
211 $product = $wrapper->commerce_product->value();
212 $profile_name = commerce_pos_quantity_profile_get_product_profile($product);
213
214 if (!empty($profile_name)) {
215 $profile = commerce_pos_quantity_profile_info($profile_name);
216 //Make sure that the quantity is an integer multiple of the increment.
217 $quantity = $line_item->quantity;
218 if (!is_numeric($quantity)) {
219 return array(t('The quantity should be a number'));
220 }
221 $increment = $profile['increment'];
222 $num_increments = $quantity / $increment;
223
224 if ((string)$num_increments - round($num_increments) != 0) {
225 $error = empty($profile['error']) ? t('Invalid quantity.') : $profile['error'];
226 return array($error);
227 }
228 }
229 }
230 }
231 }
232
233 /**
234 * Make necessary changes to product buttons.
235 */
236 function commerce_pos_quantity_profile_commerce_product_view($product, $view_mode) {
237 if ($view_mode == 'commerce_pos_product_search_result') {
238 $profile_name = commerce_pos_quantity_profile_get_product_profile($product);
239 $profile = commerce_pos_quantity_profile_info($profile_name);
240 $render = &$product->content;
241 if (!empty($profile['unit abbreviation']) && !empty($render['commerce_price'])) {
242 $render['commerce_price'][0]['#markup'] .= '/' . $profile['unit abbreviation'];
243 }
244
245 $render['#quantity_profile'] = $profile_name;
246 }
247 }
248
249 /**
250 * Preprocess function for entity theme hook.
251 */
252 function commerce_pos_quantity_profile_preprocess_entity(&$variables) {
253 $elements = &$variables['elements'];
254 if ($elements['#entity_type'] == 'commerce_product' && $elements['#view_mode'] == 'commerce_pos_product_search_result') {
255 $profile_name = $elements['#quantity_profile'];
256 $class = 'commerce-pos-quantity-profile-' . commerce_pos_quantity_profile_machine_name_to_arg($profile_name);
257 if (empty($variables['classes_array'])) {
258 $variables['classes_array'] = array($class);
259 }
260 else {
261 $variables['classes_array'][] = $class;
262 }
263 }
264 }
265
266 /**
267 * Implements hook_commerce_pos_search_info_alter().
268 */
269 function commerce_pos_quantity_profile_commerce_pos_search_info_alter(&$search_info) {
270 //Add CSS and JS
271 $path = drupal_get_path('module', 'commerce_pos_quantity_profile');
272 $search_info['product']['attached']['css'][] = array(
273 'data' => $path . '/theme/commerce_pos_quantity_profile.css',
274 );
275 $search_info['product']['attached']['js'][] = array(
276 'data' => $path . '/commerce_pos_quantity_profile.js',
277 );
278 }
279
280 /**
281 * Converts a profiles machine name for use in a CSS class name
282 */
283 function commerce_pos_quantity_profile_machine_name_to_arg($machine_name) {
284 return strtr($machine_name, '_', '-');
285 }