Jump to content

bsandall

Member
  • Posts

    222
  • Joined

  • Last visited

  • Days Won

    11

Everything posted by bsandall

  1. There is a bug in the foundation skin that prevents the 'More' button from being hidden - see this PR for how to fix it. 'hide-for-small-up' means that the element will be hidden for all window sizes of small or larger. However, as you noted, this means it will not display for mobile, which defeats the purpose - you should indeed change it to 'hide-for-medium-up' or your mobile users will not have any way to paginate. One other thing - this line: <div class="hide-for-medium-up" id="ccScrollCat">{$category.cat_id} The {$category.cat_id} should be removed or you will have a seemingly random (to the customer) number show up just above the 'More' button. Removing this does not appear to have any effect on the button's functionality.
  2. This is the answer. Put the PDFs in the /files/public/ folder. Edit your product description to include a link to the appropriate PDF, e.g. http://yourstore/files/public/example.pdf. If you want to get fancier than including a link in the description, then you may need to wait for e.g. Noodleman's plugin and see what sorts of capabilities it offers.
  3. It controls all of that stuff, yes, so you are faced with an unfortunate choice: either stop tracking stock while waiting for this issue to be sorted or you have the possibility of weird order emails showing up. The first choice is fixable via SQL, though due to some issues where stock level does not go back up (which you have noticed in another thread), your stock levels are probably wrong anyway. Stock warning levels are responsible for the messages you see in the admin panel when you are running low on stock of an item. If you go with the first choice, make a note of the last order prior to updating your products' use_stock_level setting. Once the issue gets sorted and you re-enable it (run the same query but change the 0 to 1, assuming all of your products use stock levels), you can run a query to find out how many of each product was sold between now and then and another to adjust the stock levels. If it comes to that, I can post the SQL for such queries here.
  4. Easy with a simple SQL query - run either via PHPMyAdmin or via CubeCart's admin panel under Maintenance->Query Database: UPDATE CubeCart_inventory SET use_stock_level=0; There shouldn't be any need to change the stock warning level as the use_stock_level setting controls all of that at a higher level.
  5. There is an open bug report on GitHub about this. For now, do not use traditional pagination.
  6. I don't sell downloadable products but I was under the impression they remained downloadable forever. I'll take a look at the code later and see if I find anything.
  7. Viewing my database, that does seem to be the case - all customers have their language set as en_GB. Since I'm in the US, I simply deleted that file so the only language file available to the site is en_US, but obviously that won't work for you. I'll create an issue on GitHub for this and see if we can get it fixed.
  8. An easy way to test would be to visit your store page in another browser and/or private window - being logged in as an admin in the same browser that you are viewing the store page will have some settings carry over.
  9. I had the same issue initially which seems to have been caused by the page being cached and thus not including the CSRF token. The token is added via JavaScript so you have to force the page to redownload the latest JS. To do so, clear your browser cache and force-reload the page via Ctrl-F5 (if you are on a Windows machine). Hope that works for you as it did for me.
  10. There isn't currently a hook that would work, but it seems you are comfortable enough poking around in the code so why not simply edit it to do what you want? One thing I would be wary of, not having tested it, is what is the behavior of the addressbook's edit page if the customer doesn't have any addresses? It might be necessary to check what getAddresses returns before deciding to send the customer to 'add' or 'edit'. Or 'edit' might always work. Only one way to find out!
  11. Assuming you are talking about the file in setup/db/install AND you are doing a fresh install, then yes. You would then need to import your data from your previous CubeCart database, taking care not to overwrite the table structure. If you are talking about any of the files in setup/db/upgrade, it will work so long as each of those lines is an ALTER TABLE query which, judging by the syntax, I assume they are. At any rate, changing the 18 to 30 won't hurt anything even if it doesn't work as intended, but it seems like it will.
  12. Also, if you are in the process of upgrading an older store, you can manually edit the upgrade scripts before running them to set the varchar limit to whatever you want on those columns. Likewise, if you are doing a fresh install, you can edit the database install script prior to installing.
  13. I believe it is caused by the skin changes in the most recent version; I had the same issue, but after hard-refreshing my browser (Ctrl-F5) I was able to log in. If that doesn't work, clear your browser cache and/or restart your browser and you should be able to log in. If that also doesn't work, I suggest rolling back to the previous version for now and perhaps requesting help via the support plan, but I suspect the issue will be resolved by the above.
  14. Open PHPMyAdmin, select your CubeCart database and open the direct SQL query tab. Type: ``` SELECT table_name FROM information_schema.columns WHERE column_name='cart_order_id'; ``` That will show you all of the tables that have this column. You could also find this by selecting the information_schema 'database' and clicking the 'columns' table. Next, for each of those tables, you need to run the following query: ``` ALTER TABLE table_name CHANGE COLUMN cart_order_id cart_order_id VARCHAR(30) NOT NULL; ``` You could also change them from within PHPMyAdmin under the `Structure` tab, if you are more comfortable doing it that way.
  15. Perhaps also checked against a whitelisted set of allowed URLs? Since, you know, CSRF is exactly that - an attack by a remote server. EDIT: And by whitelisted URLs, I mean internal (CubeCart) ones that are allowed to be called remotely without a CSRF token.
  16. That would explain then why they don't suffer from this issue! Never did get around to looking at the code for it, so thanks for that tip.
  17. The recaptcha challenge works for me in Chrome except for when checking out as a guest. It does not work for me at all in FireFox.
  18. My IPN history also all show as successful, despite orders being stuck in Pending until manually resolved. Using PayPal_Pro 1.1.7. Orders paid for by credit card seem less prone to this error than those paid for by PayPal Express Checkout, though I can't confirm at this time whether the former never has this problem. Of note is that I have had this problem intermittently for at least the last few months, so for me it is not isolated to CC 6.1.7.
  19. Do any of your product options have price adjustments? Are any set to absolute price? The admin JavaScript does not handle absolute option prices well, but if you don't have any of those, it should have worked fine. If you could post a screenshot of your product's options tab, that would be helpful.
  20. At least you're getting the challenge - for me, I don't even get a chance to prove I'm human, it just fails automatically.
  21. Same here. I deal with manually deleting the obvious bot/would-be-hacker customer registrations so that paying customers don't have to be inconvenienced so much that they'll probably decide it's not worth placing an order.
  22. Heh, yeah my JS isn't too hot either - lots of trial and error. Just to note that my store I have added length, width and height to the products and product options. I also dynamically modify the product specification data displayed on the product page so that the product code and dimensions update based on the selected options. In other words, some portions of the above code may be completely irrelevant to your store, but it will at least hopefully get you started.
  23. I checked my (unedited) PayPal gateway class and it already had the bare ampersand - using PayPal Pro v1.1.7.
  24. You speak English well enough, mejor que hablo EspaƱol CubeCart makes an AJAX call via JavaScript (in `\skins\foundation\js\2.cubecart.js`) to format the price on the product page when options are selected. I modified that to instead query the database for the product data, including modifications from the options matrix. There were quite a few changes involved, including to the database, but here is my code for sending and handling the AJAX call. You will of course need to modify it to match your database and code needs. // in /skins/foundation/js/2.cubecart.js // change any calls to the `price_inc_options` function to use this function instead function specification_inc_options() { var options = []; $("[name^=productOptions]").each(function (index, element) { if (!$(this).val() || ($(this).is('input:radio') && $("input[name='" + element.name + "']:checked").length < 1)) { } else if ($(this).is('input:radio')) { // Prevent empty radio selections from adding multiple entries if (!$(this).is('input:radio') || $.inArray(element.name + '=0', options) === -1) { options.push(element.name + '=0'); } if ($(this).is(':checked')) { options.push(element.name + '=' + $(this).val()); } } else if ($(this).is('select')) { options.push(element.name + '=' + ($(this).find("option:selected").val())); } else if (($(this).is('textarea') || $(this).is('input:text')) && $(this).val() !== '') { // TODO options.push(element.name + '=' + $(this).val()); } else { // include other product options, e.g. those with only 1 option options.push(element.name + '=' + $(this).val()); } }); if (options.length > 0) { var product_id = document.getElementById('product_id'); if (product_id && product_id.tagName === 'INPUT') { options.push('product_id=' + product_id.value); } var action = $('form.add_to_basket').attr('action'); var parts = action.split("?"); action += (parts.length > 1 ? '&' : '?') + '_g=ajax_update_product_data&'; options = options.join('&'); $.ajax({ url: action + options, cache: true, complete: function(returned) { var data = $.parseJSON(returned.responseText); for (var key in data) { switch (key) { case 'price': $('#fbp').html(data[key]); break; case 'sale_price': $('#ptp').html(data[key]); break; case 'use_stock_level': var rows = $('table#product_spec_table tr'); if (data[key] == 1) { rows.filter('#stock_level_row').show(); rows.filter('.hidden_row').remove(); } else { rows.filter('#stock_level_row').hide(); if (rows.filter('.hidden_row').length == 0) { rows.filter('#stock_level_row').after('<tr class="hide hidden_row"><td></td><td></td></tr>'); } } break; case 'CTRL_SETTINGS': if (data[key]['CTRL_ALLOW_PURCHASE'] && !data[key]['CATALOGUE_MODE']) { if (data['set_enabled'] == 1) { $('#allow_purchase').show(); $('#lead_time').show(); } else { $('#allow_purchase').hide(); $('#lead_time').hide(); } $('#login_to_view').hide(); } else { $('#allow_purchase').hide(); $('#lead_time').hide(); if (data['set_enabled'] == 1 && data[key]['CTRL_HIDE_PRICES']) { $('#login_to_view').show(); } else { $('#login_to_view').hide(); } } break; default: // update product specifications var id = '#spec_' + key; if (data.hasOwnProperty(key) && $(id).length) { $(id).html(data[key]); } } } if (data['set_enabled'] == 1 && !data['CTRL_SETTINGS']['CTRL_HIDE_PRICES'] && data['CTRL_SETTINGS']['CTRL_OUT_OF_STOCK']) { $('#out_of_stock').show(); } else { $('#out_of_stock').hide(); } // Handle after loop so elements are properly displayed / hidden if (data['set_enabled'] == 1) { $('#ptp').show(); if (data['ctrl_sale']) { if ($('#fbp').length > 0) { $('#fbp').show(); $('#ptp').addClass('sale_price'); } } else { $('#fbp').hide(); $('#ptp').removeClass('sale_price'); } $('#combination_unavailable').hide(); } else { $('#fbp').hide(); $('#ptp').hide(); $('#combination_unavailable').show(); } } }); } } And then the processing of that AJAX request: // in `cubecart.class.php` after `case 'ajax_price_format':` in the `loadPage` function case 'ajax_update_product_data': $GLOBALS['debug']->supress(); $product_id = filter_var($_GET['product_id'], FILTER_VALIDATE_INT); if (!is_int($product_id)) { die(json_encode(false)); } $options = (isset($_GET['productOptions']) && is_array($_GET['productOptions']) ? $_GET['productOptions'] : false); $product = $GLOBALS['catalogue']->getProductData($product_id, 1, false, 10, 1, false, null); if ($product && $options) { // running totals of price modifiers for dealing with multiple absolute pricing options $product['price_total_modifier'] = 0.00; $product['option_price_ignoring_tax_modifier'] = 0.00; $product['price_optional_modifier'] = 0.00; // total price modifier of all non-matrix options // Modify product specifications based on each option $product['set_enabled'] = true; // default product, i.e. no options selected, should not show 'unavailable' message foreach ($options as $option_id => $option_data) { if (is_array($option_data)) { // Text option foreach ($option_data as $trash => $option_value) { if (($assign_id = $GLOBALS['db']->select('CubeCart_option_assign', false, array('product' => $product_id, 'option_id' => $option_id))) !== false) { $assign_id = $assign_id[0]['assign_id']; } else { $assign_id = 0; } $value = $GLOBALS['catalogue']->getOptionData((int)$option_id, $assign_id); if ($value) { Cart::updateProductDataWithOption($product, $value); } } } elseif (is_numeric($option_data)) { if (($value = $GLOBALS['catalogue']->getOptionData((int)$option_id, (int)$option_data)) !== false) { Cart::updateProductDataWithOption($product, $value); } } } // Apply option matrix modifiers, if any $options_identifier_string = $GLOBALS['catalogue']->defineOptionsIdentifier($options); $result = $GLOBALS['db']->select('CubeCart_option_matrix', 'product_id, set_enabled, price, sale_price, use_stock as use_stock_level, stock_level, product_code, upc, ean, jan, isbn', array('product_id' => $product_id, 'status' => 1, 'options_identifier' => $options_identifier_string)); if ($result) { Cart::applyProductMatrix($product, $result[0]); } } // Finally, format product values for display if (is_array($product)) { if ($product['sale_price'] == 0 || $product['price'] < $product['sale_price']) { $product['sale_price'] = $product['price']; } $product['ctrl_sale'] = ($product['sale_price'] > 0 && $product['sale_price'] < $product['price'] ? true : false); $product['price'] = $GLOBALS['tax']->priceFormat($product['price']); $product['sale_price'] = $GLOBALS['tax']->priceFormat($product['sale_price']); // Format the following entries to 3-decimal precision $thousands = array('product_weight','product_length','product_height','product_width'); foreach ($thousands as $key) { $product[$key] = sprintf('%.3F', $product[$key]); } // Add settings to determine which GUI elements to display / hide (replicates variables / logic in Catalogue#displayProduct) $product['CTRL_SETTINGS'] = array( 'CATALOGUE_MODE' => ($GLOBALS['config']->get('config', 'catalogue_mode') ? true : false), 'CTRL_ALLOW_PURCHASE' => true, 'CTRL_OUT_OF_STOCK' => false, 'CTRL_HIDE_PRICES' => false ); if ((bool)$product['use_stock_level']) { if ((int)$product['stock_level'] < 1) { $product['CTRL_SETTINGS']['CTRL_ALLOW_PURCHASE'] = (bool)$GLOBALS['config']->get('config', 'basket_out_of_stock_purchase'); $product['CTRL_SETTINGS']['CTRL_OUT_OF_STOCK'] = true; } } if ($GLOBALS['session']->get('hide_prices')) { $product['CTRL_SETTINGS']['CTRL_ALLOW_PURCHASE'] = false; $product['CTRL_SETTINGS']['CTRL_HIDE_PRICES'] = true; } } die(json_encode($product)); break;
  25. @havenswift-hosting Thanks for that info - had the same issue with some customers' orders getting stuck in pending and it turns out PayPal had turned off our IPN as well. :\
×
×
  • Create New...