-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathuc_restrict_qty.module
397 lines (353 loc) · 13.9 KB
/
uc_restrict_qty.module
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
<?php
/**
* @file
* Restrict the quantity on specified products so that only specified quantity
* may be purchased at a time.
*/
/**
* Implements hook_theme().
*/
function uc_restrict_qty_theme() {
return array(
'restrict_qty_field' => array(
'render element' => 'form',
),
);
}
/**
* Implements hook_uc_product_feature().
*/
function uc_restrict_qty_uc_product_feature() {
$features[] = array(
'id' => 'restrict_qty',
'title' => t('Restrict Qty'),
'callback' => 'uc_restrict_qty_feature_form',
'delete' => 'uc_restrict_qty_feature_delete',
'settings' => 'uc_restrict_qty_settings',
);
return $features;
}
/**
* Implements hook_config_info().
*/
function uc_restrict_qty_config_info() {
$prefixes['uc_restrict_qty.settings'] = array(
'label' => t('UC Restrict Qty settings'),
'group' => t('Configuration'),
);
return $prefixes;
}
/**
* Adds settings to the product features form for UC Restrict Qty.
*/
function uc_restrict_qty_settings($form, &$form_state) {
$config = config('uc_restrict_qty.settings');
$form['#description'] = t('This feature is limited in scope to preventing a user from adding different products to the cart. This does not restrict the quantity of products in the cart if updated after being added, so this feature is best used on sites where all products have a restrict quantity feature on them.');
$form['uc_restrict_qty_global'] = array(
'#title' => t('Global limit'),
'#type' => 'textfield',
'#size' => 5,
'#maxlength' => 5,
'#description' => t('The number of different products that can be added to a cart. Set to 0 for unlimited.'),
'#default_value' => $config->get('uc_restrict_qty_global'),
);
$form['uc_restrict_qty_global_replace'] = array(
'#title' => t('Replace Contents'),
'#type' => 'checkbox',
'#description' => t('Enabling this feature will cause the users cart to be emptied if they add more items than the Global Limit set above. This is best used when you offer mutually exclusive content (such as subscription services) where purchasing more then one product is not a valid option.'),
'#default_value' => $config->get('uc_restrict_qty_global_replace'),
);
$form['defaults'] = array(
'#title' => t('Defaults'),
'#type' => 'fieldset',
'#description' => t('These options will take action, only if product has the "Restrict quantity" feature activated.'),
);
$form['defaults']['uc_restrict_qty_default_qty'] = array(
'#title' => t("Default maximum limit for a product"),
'#type' => 'textfield',
'#size' => 5,
'#maxlength' => 5,
'#description' => t('The number of products of single type that can be added to a cart. Set to 0 for unlimited.'),
'#default_value' => $config->get('uc_restrict_qty_default_qty'),
);
$form['defaults']['uc_restrict_qty_default_lifetime'] = array(
'#title' => t("Is restriction is the user's lifetime limit"),
'#type' => 'checkbox',
'#description' => t("Useful when you want to prevent double ordering of a product."),
'#default_value' => $config->get('uc_restrict_qty_default_lifetime'),
);
return $form;
}
/**
* Validates the textfield on the product features settings form.
*/
function uc_restrict_qty_settings_validate($form, &$form_state) {
if (!is_numeric($form_state['values']['uc_restrict_qty_global']) || $form_state['values']['uc_restrict_qty_global'] < 0) {
form_set_error('uc_restrict_qty_global', t('You must enter 0 or a positive number value.'));
}
if (!is_numeric($form_state['values']['uc_restrict_qty_default_qty']) || $form_state['values']['uc_restrict_qty_default_qty'] < 0) {
form_set_error('uc_restrict_qty_default_qty', t('You must enter 0 or a positive number value.'));
}
}
/**
* Submit handler.
*
* Saves all settings.
*/
function uc_restrict_qty_settings_submit($form, $form_state) {
$config = config('uc_restrict_qty.settings');
$restrict_qty_settings_keys = array(
'uc_restrict_qty_global',
'uc_restrict_qty_global_replace',
'uc_restrict_qty_default_qty',
'uc_restrict_qty_default_lifetime',
);
foreach ($restrict_qty_settings_keys as $key) {
$config->set($key, $form_state['values'][$key]);
}
$config->save();
}
/**
* Builds the form to display for adding or editing a the restricted quantity feature.
*/
function uc_restrict_qty_feature_form($form, &$form_state, $node, $feature) {
$config = config('uc_restrict_qty.settings');
$models = uc_product_get_models($node->nid, FALSE);
if (!empty($feature)) {
$product_qty = db_query("SELECT * FROM {uc_restrict_qty_products} WHERE pfid = :pfid", array(':pfid' => $feature['pfid']))->fetchObject();
$default_qty = $product_qty->qty;
$default_model = $product_qty->model;
$default_lifetime = $product_qty->lifetime;
$form['pfid'] = array(
'#type' => 'value',
'#value' => $feature['pfid'],
);
$form['rqpid'] = array(
'#type' => 'value',
'#value' => $product_qty->rqpid,
);
}
$form['nid'] = array(
'#type' => 'value',
'#value' => $node->nid,
);
$form['model'] = array(
'#type' => 'select',
'#title' => t('SKU'),
'#default_value' => isset($default_model) ? $default_model : 0,
'#description' => t('This is the SKU of the product that will be restricted to this quantity.'),
'#options' => $models,
);
$form['quantity'] = array(
'#title' => t('Quantity limit'),
'#type' => 'textfield',
'#size' => 5,
'#maxlength' => 5,
'#description' => t('The number of times this product can be added to a cart. Set to 0 for unlimited.'),
'#default_value' => isset($default_qty) ? $default_qty : $config->get('uc_restrict_qty_default_qty'),
);
$form['lifetime'] = array(
'#title' => t('Is it a lifetime restriction?'),
'#type' => 'checkbox',
'#description' => t("If checked, user's ordering history will be taken into account too. Useful when you want to prevent double ordering of a product."),
'#default_value' => isset($default_lifetime) ? $default_lifetime : $config->get('uc_restrict_qty_default_lifetime'),
);
return uc_product_feature_form($form, $form_state, $node, $feature);
}
/**
* Validates the textfield on the product node feature settings form.
*/
function uc_restrict_qty_feature_form_validate($form, &$form_state) {
// Check for invalid quantity.
if (!is_numeric($form_state['values']['quantity']) || $form_state['values']['quantity'] < 0) {
form_set_error('uc_restrict_qty_product_qty', t('You must enter 0 or a positive integer value.'));
}
// Check if this feature is already set on this SKU.
$product_roles = db_query("SELECT * FROM {uc_restrict_qty_products} WHERE nid = :nid AND model = :model", array(
':nid' => $form_state['values']['nid'],
':model' => $form_state['values']['model'],
))->fetchObject();
if ($product_roles && $form_state['values']['pfid'] == 0) {
form_set_error('uc_roles_model', t('A quantity restriction has already been set up for this SKU'));
}
}
/**
* Form submit handler for the roles feature form.
*/
function uc_restrict_qty_feature_form_submit($form, &$form_state) {
$product_qty = array(
'rqpid' => isset($form_state['values']['rqpid']) ? $form_state['values']['rqpid'] : NULL,
'pfid' => isset($form_state['values']['pfid']) ? $form_state['values']['pfid'] : NULL,
'nid' => $form_state['values']['nid'],
'model' => $form_state['values']['model'],
'qty' => $form_state['values']['quantity'],
'lifetime' => $form_state['values']['lifetime'],
);
$description = '<strong>' . t('SKU') . ':</strong>' . (empty($product_qty['model'])?t('Any') : $product_qty['model']) . '<br/>';
$description .= '<strong>' . t('Quantity restriction') . ':</strong>' . $product_qty['qty'] . '<br/>';
$description .= '<strong>' . t('Type') . ':</strong>' . ($product_qty['lifetime']?t('Lifetime') : t('Cart max.')) . '<br/>';
$data = array(
'nid' => $product_qty['nid'],
'fid' => 'restrict_qty',
'description' => $description,
);
if (isset($product_qty['pfid'])) {
$data['pfid'] = $product_qty['pfid'];
}
$form_state['redirect'] = uc_product_feature_save($data);
$key = array();
if ($product_qty['rqpid']) {
$key[] = 'rqpid';
}
// Insert or update uc_file_product table
if (empty($product_qty['pfid'])) {
$product_qty['pfid'] = $data['pfid'];
}
backdrop_write_record('uc_restrict_qty_products', $product_qty, $key);
}
/**
* Implements hook_uc_add_to_cart().
*/
function uc_restrict_qty_uc_add_to_cart($nid, $qty, $data) {
$config = config('uc_restrict_qty.settings');
$limit = $config->get('uc_restrict_qty_global');
$replacecart = $config->get('uc_restrict_qty_global_replace');
$result = NULL; // added by Jeff
// If a global restriction on the number of items has been made.
if ($limit > 0) {
if (count(uc_cart_get_contents()) >= $limit) {
if ($replacecart) {
db_query("DELETE FROM {uc_cart_products} WHERE cart_id = :cart", array(':cart' => uc_cart_get_id()));
$result[] = array('success' => TRUE);
}
else {
$message = format_plural($limit, 'Sorry, you may only have 1 item in your cart. You must checkout or remove the item in your cart before adding a different item.',
'Sorry, you may only have a total of @count items in your cart. You must checkout or remove items from your cart before adding others.');
$result[] = array(
'success' => FALSE,
'message' => $message,
);
}
}
}
// Check lifetime product-level limit.
if (!empty($data['restrict_qty']['lifetime'])) {
if (!$data['restrict_qty']['rest']) {
$message = t('Sorry, you have reached the quantity limit for this product. You can not order more items of this product.');
$result[] = array(
'success' => FALSE,
'message' => $message,
);
}
}
return $result;
}
/**
* Implements hook_add_to_cart_data().
* @param $form_values
* The values submitted to the Add to Cart form.
*
* @return
* An array of data to be merged into the item added to the cart.
*/
function uc_restrict_qty_uc_add_to_cart_data($form_values) {
return array('restrict_qty' => uc_restrict_qty_count($form_values));
}
/**
* Implements hook_uc_cart_item_update().
*/
function uc_restrict_qty_uc_cart_item_update($item) {
// Check if this item has a quantity restriction on it.
if (isset($item->data['restrict_qty']['qty']) && $item->data['restrict_qty']['qty'] > 0) {
$is_lifetime = isset($item->data['restrict_qty']['lifetime']) && $item->data['restrict_qty']['lifetime'];
$restrict_qty = $is_lifetime ? $item->data['restrict_qty']['rest'] : $item->data['restrict_qty']['qty'];
if ($item->qty > $restrict_qty) {
// Reduce the quantity to 1 if necessary.
$item->qty = $restrict_qty;
db_update('uc_cart_products')
->fields(array('qty' => $restrict_qty, 'changed' => time()))
->condition('cart_id', uc_cart_get_id())
->condition('nid', $item->nid)
->condition('data', serialize($item->data))
->execute();
backdrop_set_message(format_plural($restrict_qty, 'You may only add 1 !item to your cart. Quantity has been restricted.', 'You may only add @count !item to your cart. Quantity has been restricted.', array('!item' => $item->title)), 'warning');
}
}
}
/**
* Implements hook_form_alter().
*/
function uc_restrict_qty_form_alter(&$form, &$form_state, $form_id) {
// Disable the appropriate Qty. fields on the cart view form.
if ($form_id == 'uc_cart_view_form') {
for ($i = 0, $j = count(uc_cart_get_contents()); $i < $j; $i++) {
$data = unserialize($form['items'][$i]['data']['#value']);
// If this item has a quantity restriction on it.
if (!empty($data['restrict_qty'])) {
$is_lifetime = isset($data['restrict_qty']['lifetime']) && $data['restrict_qty']['lifetime'];
$restrict_qty = $is_lifetime ? $data['restrict_qty']['rest'] : $data['restrict_qty']['qty'];
if ($restrict_qty == 1) {
$form['items'][$i]['qty']['#type'] = 'value';
$form['items'][$i]['qty']['#theme'] = 'restrict_qty_field';
}
}
}
}
if ($form_id == 'uc_product_feature_settings_form') {
$form['#validate'][] = 'uc_restrict_qty_settings_validate';
}
}
/**
* Themes cart Qty. boxes so they can't be changed. (currently not in use)
*/
function theme_restrict_qty_field($variables) {
return check_plain($variables['form']['#value']);
}
/**
* Returns the number of restrict_qty features on a product node.
*/
function uc_restrict_qty_count($form_values) {
global $user;
$data = db_query("SELECT qty, lifetime FROM {uc_restrict_qty_products} WHERE nid = :nid", array(':nid' => $form_values['nid']))->fetchAssoc();
if ($data !== FALSE && $data['lifetime']) {
$bought_qty = db_query('SELECT SUM(uop.qty) FROM {uc_orders} uo LEFT JOIN {uc_order_products} uop ON uo.order_id = uop.order_id WHERE uo.order_status = :completed AND uo.uid = :uid AND uop.nid = :nid ORDER BY uop.nid', array(
':completed' => 'completed',
':uid' => $user->uid,
':nid' => $form_values['nid'],
))->fetchField();
$data['rest'] = $data['qty'] - $bought_qty;
}
return $data;
}
/* ************************************************************************* *
* Actions *
* ************************************************************************* */
/**
* Delete all data associated with a given node.
*
* @param Node $node
* A Backdrop node object.
*/
function uc_restrict_qty_node_delete($node) {
db_delete('uc_restrict_qty_products')
->condition('nid', $node->nid)
->execute();
}
/**
* Delete all data associated with a given product feature.
*
* @param $feature
* An Ubercart product feature array.
*/
function uc_restrict_qty_feature_delete($pfid) {
db_delete('uc_restrict_qty_products')
->condition('pfid', $pfid)
->execute();
}
/**
* Implements hook_autoload_info().
*/
function uc_restrict_qty_autoload_info() {
return array(
);
}