OK, to point the right direction, here's how I do it:
1. hidden input
As you know, in catalog/view/theme/default/template/product/product.php there is an AJAX request to add a product to the cart:
$('#button-cart').bind('click', function() { $.ajax({ url: 'index.php?route=checkout/cart/add', type: 'post', data: $('.product-info input[type=\'text\'], .product-info input[type=\'hidden\'], .product-info input[type=\'radio\']:checked, .product-info input[type=\'checkbox\']:checked, .product-info select, .product-info textarea'), dataType: 'json',
If you look at the data parameter, you will see that all inputs, selections, text fields, etc. that are present in the .product-info div are filled and sent to PHP.
Therefore, I would provide hidden input with a custom price value in this .product-info div so that there is no need to modify the AJAX request at all. Let say that the name of this input will be custom_price .
2. checkout/cart/add
Open catalog/controller/checkout/cart.php and find the add method. Here all the magic must be done. After this piece of code:
if (isset($this->request->post['option'])) { $option = array_filter($this->request->post['option']); } else { $option = array(); }
I would add the following:
if(isset($this->request->post['custom_price']) && $this->isCustomPriceValid($this->request->post['custom_price'])) { $custom_price = $this->request->post['custom_price']; } else { $custom_price = false; }
Implement the isCustomPriceValid() method to meet your requirements ... and go to the last edit here - change this line:
$this->cart->add($this->request->post['product_id'], $quantity, $option);
in
$this->cart->add($this->request->post['product_id'], $quantity, $option, $custom_price);
3. Trolley
Now open this file: system/library/cart.php and find the add method again. You will need to change the method definition to this:
public function add($product_id, $qty = 1, $option = array(), $custom_price = false) {
Before the last line of code in this method, add another one:
(this code has been edited due to a comment from OP)
// ... if($custom_price) { if(!isset($this->session->data['cart']['custom_price'])) { $this->session->data['cart']['custom_price'] = array(); } $this->session->data['cart']['custom_price'][$key] = $custom_price; } $this->data = array(); // <- last line }
The last edit should be in the getProducts() method, since it loads all the data from the database and sends it to other controllers to display the goals.
Now I donβt know if your user price should overwrite the price of the price + price or only the price, so the option price will be added to it, so I stick to the second choice, because it is more descriptive, and the first choice could be easily extracted from my example .
String search
$price = $product_query->row['price'];
and immediately after adding
if(isset($this->session->data['cart']['custom_price'][$key])) { $price = $this->session->data['cart']['custom_price'][$key]; }
Now the price should be overwritten by the user. Check further that the price of the product is later set as:
$this->data[$key] = array( // ... 'price' => ($price + $option_price), // ... );
So, if you want to rewrite the entire price using a custom one, add this condition immediately after this array, like this (instead of $price = ...; ):
if(isset($this->session->data['cart']['custom_price'][$key])) { $this->data[$key]['price'] = $this->session->data['cart']['custom_price'][$key]; }
It should be. I have not tested the code; it may or may not work with minor changes. I worked with OC 1.5.5.1. This should only indicate the right direction (although assuming that the finish is not so far).
Enjoy it!