Index: uc_restrict_qty.module
===================================================================
--- uc_restrict_qty.module (revision 4710)
+++ uc_restrict_qty.module (working copy)
@@ -281,6 +281,50 @@ function uc_restrict_qty_form_alter(&$fo
if ($form_id == 'uc_product_feature_settings_form') {
$form['#validate'][] = 'uc_restrict_qty_settings_validate';
}
+
+ if ($form_id == 'uc_product_class_form') {
+ $class = $form['#parameters'][2];
+
+ $form['uc_restrict_qty'] = array(
+ '#type' => 'fieldset',
+ '#title' => t('Restrict Qty'),
+ '#collapsible' => TRUE,
+ '#collapsed' => TRUE,
+ );
+
+ $form['uc_restrict_qty']['uc_restrict_qty_default_qty'] = array(
+ '#title' => t("Default maximum limit for a product of this class"),
+ '#type' => 'textfield',
+ '#size' => 5,
+ '#maxlength' => 5,
+ '#description' => t('The number of products of this class that can be added to a cart. Set to 0 for unlimited.'),
+ '#default_value' => $class->uc_restrict_qty_default_qty,
+ );
+ $form['uc_restrict_qty']['uc_restrict_qty_default_lifetime'] = array(
+ '#title' => t("Is restriction the user's lifetime limit"),
+ '#type' => 'checkbox',
+ '#description' => t("Useful when you want to prevent double ordering of a product."),
+ '#default_value' => $class->uc_restrict_qty_default_lifetime,
+ );
+
+ $options = array(
+ '' => t('Do nothing'),
+ 'batch_empty' => t('Update nodes with no current qty restriction'),
+ 'batch_all' => t('Update every single node with new defaults (old restrictions will be overwritten)')
+ );
+ $form['uc_restrict_qty']['uc_restrict_qty_default_batch_update'] = array(
+ '#title' => t("Batch update existing nodes"),
+ '#type' => 'radios',
+ '#description' => t("This can be useful if you are enabling this after some products have been created, of you want overwrite restrictions with new information. Use the last option carefully."),
+ '#default_value' => '',
+ '#options' => $options,
+ );
+
+
+ $form['#submit'][] = 'uc_restrict_qty_uc_product_class_form_submit';
+
+ $form['submit']['#weight'] = 10;
+ }
}
// Themes cart Qty. boxes so they can't be changed. (currently not in use)
@@ -306,12 +350,9 @@ function uc_restrict_qty_count($form_val
* ************************************************************************* */
/**
- * Delete all data associated with a given node.
- *
- * @param $nid
- * A Drupal node ID.
+ * Nodeapi 'delete' callback handler
*/
-function uc_restrict_qty_node_delete($nid) {
+function uc_restrict_qty_nodeapi_delete($nid) {
db_query("DELETE FROM {uc_restrict_qty_products} WHERE nid = %d", $nid);
}
@@ -324,3 +365,180 @@ function uc_restrict_qty_node_delete($ni
function uc_restrict_qty_feature_delete($pfid) {
db_query("DELETE FROM {uc_restrict_qty_products} WHERE pfid = %d", $pfid);
}
\ No newline at end of file
+
+/**
+ * Implementation of hook_schema_alter().
+ */
+function uc_restrict_qty_schema_alter(&$schema) {
+ // Add field to existing schema.
+ $schema['uc_product_classes']['fields']['uc_restrict_qty_default_qty'] = array(
+ 'type' => 'int',
+ 'not null' => TRUE,
+ 'default' => 0,
+ 'description' => 'The number of products of this class that can be added to a cart.',
+ );
+ $schema['uc_product_classes']['fields']['uc_restrict_qty_default_lifetime'] = array(
+ 'type' => 'int',
+ 'not null' => TRUE,
+ 'default' => 0,
+ 'description' => 'Is restriction the user\'s lifetime limit.',
+ );
+}
+
+/**
+ * Submit handler for uc_poroduct_class_form().
+ */
+function uc_restrict_qty_uc_product_class_form_submit($form, &$form_state) {
+ // @see uc_product_class_form_submit().
+ $is_new = $form['pcid']['#type'] == 'textfield';
+ $pcid = $form_state['values']['pcid'];
+ if ($is_new) {
+ // Convert whitespace to underscores, and remove other non-alphanumeric characters.
+ $pcid = preg_replace(array('/\s+/', '/\W/'), array('_', ''), strtolower($pcid));
+ }
+
+ // We assume it has to be there as the previous submit handler should have
+ // created it
+ db_query("UPDATE {uc_product_classes} SET uc_restrict_qty_default_qty = %d, uc_restrict_qty_default_lifetime = %d WHERE pcid = '%s'", $form_state['values']['uc_restrict_qty_default_qty'], $form_state['values']['uc_restrict_qty_default_lifetime'], $pcid);
+
+ if (!empty($form_state['values']['uc_restrict_qty_default_batch_update'])) {
+ $batch_parameters = array(
+ 'pcid' => $pcid,
+ 'batch_update' => $form_state['values']['uc_restrict_qty_default_batch_update'],
+ );
+ $batch = array(
+ 'operations' => array(
+ array('uc_restrict_qty_batch_process', array($batch_parameters)),
+ ),
+ 'finished' => 'uc_restrict_qty_batch_finished',
+ 'title' => t('Batch updating existing nodes'),
+ 'init_message' => t('Batch updating is starting.'),
+ 'progress_message' => t('Processing nodes.'),
+ 'error_message' => t('Batch updating has encountered an error.'),
+ // in case we want to move batch logic into a separate file
+ //'file' => drupal_get_path('module', 'uc_restrict_qty') . '/uc_restrict_qty.batch.inc',
+ );
+ batch_set($batch);
+ }
+}
+
+function uc_restrict_qty_batch_process($batch_parameters, &$context) {
+ if (!isset($context['sandbox']['progress'])) {
+ $context['sandbox']['progress'] = 0;
+ $context['sandbox']['current_node'] = 0;
+ if ($batch_parameters['batch_update'] == 'batch_all') {
+ $context['sandbox']['max'] = db_result(db_query("SELECT COUNT(DISTINCT n.nid) FROM {node} n WHERE n.type = '%s'", $batch_parameters['pcid']));
+ }
+ else {
+ $context['sandbox']['max'] = db_result(db_query("SELECT COUNT(DISTINCT n.nid) FROM {node} n LEFT JOIN {uc_product_features} pf ON n.nid = pf.nid AND pf.fid = 'restrict_qty' LEFT JOIN {uc_restrict_qty_products} rq ON n.nid = rq.nid WHERE n.type = '%s' AND rq.nid IS NULL AND pf.nid IS NULL", $batch_parameters['pcid']));
+ }
+ }
+
+ // Set the amount of nodes we will process on each batch page reload
+ $limit = 5;
+
+ // With each pass through the callback, retrieve the next group of nids.
+ if ($batch_parameters['batch_update'] == 'batch_all') {
+ $result = db_query_range("SELECT DISTINCT n.nid FROM {node} n WHERE n.nid > %d AND n.type = '%s' ORDER BY nid ASC", $context['sandbox']['current_node'], $batch_parameters['pcid'], 0, $limit);
+ }
+ else {
+ $result = db_query_range("SELECT DISTINCT n.nid FROM {node} n LEFT JOIN {uc_product_features} pf ON n.nid = pf.nid AND pf.fid = 'restrict_qty' LEFT JOIN {uc_restrict_qty_products} rq ON n.nid = rq.nid WHERE n.nid > %d AND n.type = '%s' AND rq.nid IS NULL AND pf.nid IS NULL ORDER BY nid ASC", $context['sandbox']['current_node'], $batch_parameters['pcid'], 0, $limit);
+ }
+
+ while ($row = db_fetch_array($result)) {
+
+ // Here we actually perform our processing on the current node.
+ $node = node_load($row['nid'], NULL, TRUE);
+
+ // delete node's features
+ db_query("DELETE FROM {uc_product_features} WHERE fid ='restrict_qty' AND nid = %d", $node->nid);
+ // delete node's internal data
+ uc_restrict_qty_nodeapi_delete($node->nid);
+
+ uc_restrict_qty_nodeapi_insert($node);
+
+ // Store some result for post-processing in the finished callback.
+ $context['results'][] = check_plain($node->title);
+
+ // Update our progress information.
+ $context['sandbox']['progress']++;
+ $context['sandbox']['current_node'] = $node->nid;
+ $context['message'] = t('Now processing %node (%progress/%max)', array('%node' => $node->title, '%progress' => $context['sandbox']['progress'], '%max' => $context['sandbox']['max']));
+ }
+
+ // Inform the batch engine that we are not finished,
+ // and provide an estimation of the completion level we reached.
+ if ($context['sandbox']['progress'] != $context['sandbox']['max']) {
+ $context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max'];
+ }
+}
+
+/**
+ * Batch 'finished' callback
+ */
+function uc_restrict_qty_batch_finished($success, $results, $operations) {
+ if ($success) {
+ // Here we do something meaningful with the results.
+ $message = count($results) .' processed.';
+ $message .= theme('item_list', $results);
+ }
+ else {
+ // An error occurred.
+ // $operations contains the operations that remained unprocessed.
+ $error_operation = reset($operations);
+ $message = t('An error occurred while processing %error_operation with arguments: @arguments', array('%error_operation' => $error_operation[0], '@arguments' => print_r($error_operation[1], TRUE)));
+ }
+ drupal_set_message($message);
+}
+
+/**
+ * Nodeapi 'insert' callback handler
+ */
+function uc_restrict_qty_nodeapi_insert($node) {
+ $class = uc_product_class_load($node->type);
+ $models = uc_product_get_models($node);
+ $product_qty = array(
+ 'nid' => $node->nid,
+ 'qty' => $class->uc_restrict_qty_default_qty,
+ 'lifetime' => $class->uc_restrict_qty_default_lifetime,
+ );
+
+ $description = ''. t('SKU') .': '. (empty($product_qty['model']) ? t('Any') : $product_qty['model']) .'
';
+ $description .= ''. t('Quantity restriction') .': '. $product_qty['qty'] .'
';
+ $description .= ''. t('Type') .': '. ($product_qty['lifetime'] ? t('Lifetime') : t('Cart max.')) .'
';
+
+ $data = array(
+ 'pfid' => $product_qty['pfid'],
+ 'nid' => $product_qty['nid'],
+ 'fid' => 'restrict_qty',
+ 'description' => $description,
+ );
+
+ uc_product_feature_save($data);
+
+ // Insert or update uc_file_product table
+ if (empty($product_qty['pfid'])) {
+ $product_qty['pfid'] = db_last_insert_id('uc_product_features', 'pfid');
+ }
+
+ drupal_write_record('uc_restrict_qty_products', $product_qty);
+}
+
+/**
+ * Implementation of hook_nodeapi().
+ */
+function uc_restrict_qty_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
+ $class = uc_product_class_load($node->type);
+
+ if ($class->uc_restrict_qty_default_qty) {
+ switch ($op) {
+ case 'insert':
+ uc_restrict_qty_nodeapi_insert($node);
+ break;
+
+ case 'delete':
+ uc_restrict_qty_nodeapi_delete($node->nid);
+ break;
+ }
+ }
+}
\ No newline at end of file
Index: uc_restrict_qty.install
===================================================================
--- uc_restrict_qty.install (revision 4710)
+++ uc_restrict_qty.install (working copy)
@@ -73,6 +73,22 @@ function uc_restrict_qty_schema() {
*/
function uc_restrict_qty_install() {
drupal_install_schema('uc_restrict_qty');
+
+ $ret = array();
+ $field = array(
+ 'type' => 'int',
+ 'not null' => TRUE,
+ 'default' => 0,
+ 'description' => 'The number of products of this class that can be added to a cart.',
+ );
+ db_add_field($ret,'uc_product_classes', 'uc_restrict_qty_default_qty', $field);
+ $field = array(
+ 'type' => 'int',
+ 'not null' => TRUE,
+ 'default' => 0,
+ 'description' => 'The number of products of this class that can be added to a cart.',
+ );
+ db_add_field($ret, 'uc_product_classes', 'uc_restrict_qty_default_lifetime', $field);
}
/**
@@ -83,6 +99,10 @@ function uc_restrict_qty_install() {
function uc_restrict_qty_uninstall() {
drupal_uninstall_schema('uc_restrict_qty');
db_query("DELETE FROM {variable} WHERE name LIKE 'uc_restrict_qty_%%'");
+
+ $ret = array();
+ db_drop_field($ret, 'uc_product_classes', 'uc_restrict_qty_default_qty');
+ db_drop_field($ret, 'uc_product_classes', 'uc_restrict_qty_default_lifetime');
}
/**
@@ -105,3 +125,25 @@ function uc_restrict_qty_update_6201() {
db_add_field($ret, 'uc_restrict_qty_products', 'lifetime', array('type' => 'int', 'size' => 'tiny', 'unsigned' => TRUE, 'not null' => TRUE, 'default' => 1));
return $ret;
}
+
+/**
+ * Add fields to the uc_product_classes schema
+ */
+function uc_restrict_qty_update_6202() {
+ $ret = array();
+ $field = array(
+ 'type' => 'int',
+ 'not null' => TRUE,
+ 'default' => 0,
+ 'description' => 'The number of products of this class that can be added to a cart.',
+ );
+ db_add_field($ret,'uc_product_classes', 'uc_restrict_qty_default_qty', $field);
+ $field = array(
+ 'type' => 'int',
+ 'not null' => TRUE,
+ 'default' => 0,
+ 'description' => 'The number of products of this class that can be added to a cart.',
+ );
+ db_add_field($ret, 'uc_product_classes', 'uc_restrict_qty_default_lifetime', $field);
+ return $ret;
+}
\ No newline at end of file