Updating line items through code in WooCommerce - php

I'm trying to make an interface where I can edit some of the metadata attached to a lineitem. I've tried using update_post_meta() on the line item itself, however that returns bool(false). How can I update the line item meta data manually?
Thanks!

so I managed to figure it out. I wrote a small function that's below. So, all you need to do is load up the order using the API, parse through each line item and you can call wc_update_order_item_meta. The only thing is, you need to know the variation ID of the item being sold if you only want to update a specific item.
function update_order_item_meta($orderID, $variationID, $metaID, $metaValue) {
$order = returnWC_API()->get_order($orderID)->{'order'};
if(!$order) {
return false;
}
if($variationID == "all") {
foreach ($order->{'line_items'} as $line_item) {
if(!wc_update_order_item_meta($line_item->{'id'}, $metaID, $metaValue)) {
return false;
}
}
return true;
}
foreach ($order->{'line_items'} as $line_item) {
if($line_item->{'product_id'} == $variationID) {
return wc_update_order_item_meta($line_item->{'id'}, $metaID, $metaValue);
}
}
}

Related

WooCommerce: Old deleted item comes back when trying to change the quantity of other item in cart

I have created a custom popup cart using WooCommerce. It has functionalities like
Decrease a product
Increase a product
Remove a product
When I remove the product from the top it goes away. I am using this logic to do that using AJAX.
public function remove_item($key)
{
$this->refresh();
$remove = $this->woocommerce->cart->remove_cart_item($key);
$this->woocommerce->cart->calculate_totals();
if ($remove) {
$this->refresh();
return true;
} else {
return false;
}
}
Now I decrease the remaining item, from quantity 2 to 1. What I get back is the already deleted comes back with 1 quantity and the present item is set to 1.
public function set_item_quantity($key, $quantity)
{
if (!is_numeric($quantity)) {
return;
}
$job = $this->woocommerce->cart->set_quantity($key, $quantity, true);
$this->woocommerce->cart->calculate_totals();
if ($job) {
$this->refresh();
return true;
} else {
return false;
}
}
This is what refresh method looks like.
public function refresh()
{
$woocommerce = \WC();
$this->cart = $woocommerce->cart;
$this->woocommerce = $woocommerce;
$this->woocommerce->cart->calculate_totals();
}
This isn't a cache issue, as I have removed my cache plugin and it still gives me issues. The same doesn't happen when the cart has just one product.
Any help is appreciated. Thanks!

Laravel Nova Actions Multiple messages

I could find a proper solution in the forum for my problem.
In my Laravel nova I have some Course Categories and if the user wants to delete some of them I
create an action to delete the data but before that I
check if these course categories have some courses in it.
This works everything fine. I'll go trough a foreach loop for every checked
Categorie but if some are deletable and some not the foreach breaks out and stops.
I think its because the return statements. But how can i get this return
`Action::message('Deleted!');`
OR
Action::danger('The Course Category "'.$model->name.'" could not be deleted, it may contains some Courses!');
done without breaking out of the loop and continue ?
Set a variable before the loop - let's call it "alldeleted".
$alldeleted = true;
And also set a blank array for categories that cannot be deleted :
$undeletedcategories = array();
If, during the loop, one of the categories cannot be deleted, note that by setting alldeleted to be false, adding the category name to the array, and using continue to go to the next element in the loop :
$alldeleted = false;
$undeletedcategories[] = $model->name;
continue;
Then, at the end of the process, look at whether $alldeleted is true or not and compose your response accordingly :
if($alldeleted) {
// return your "all deleted alright" status message here.
} else {
// Return the "these categories weren't deleted" status message here.
}
Thanks for the fast help Giles, I was able to solve my issue. I added another foreach to fill all the Category names in the Message.
$alldeleted = true;
$undeletedcategories = [];
$categorie = [];
foreach ($models AS $model)
{
$course = Course::where('category_id', $model->id)->count();
if($course === 0)
{
$model->delete();
}
else {
$alldeleted = false;
$undeletedcategories[] = $model->name;
}
}
if($alldeleted === true) {
return Action::message('Deleted all selected Courses successfully!');
} else {
foreach($undeletedcategories AS $cat)
{
$categorie[] = $cat;
}
return Action::danger('The following Course Category "'.implode(", ",$categorie).' " could not be deleted, it may contains some Courses!');
}

How to use a PHP function for multiple calls within the same PHP page?

I am trying to use a php function to get the prices of a tola (11.664 grams) at an order status page. The function uses a php page 'priceApi4CurCtrl.php' that fetches the price data from a website using an external API. My function is as follows:
function tolaPrice($cur_pick) {
require('priceApi4CurCtrl.php');
if($cur_pick == 'pkr') {
$tola_price = $bitprice_pkr*10*11.664;
return $tola_price;
} elseif($cur_pick == 'usd') {
$tola_price = $bitprice_usd*10*11.64;
return $tola_price;
} elseif($cur_pick == 'aed') {
$tola_price = $bitprice_aed*10*11.64;
return $tola_price;
}
}
// Succeeds for the first call as under
$cur_pick = 'pkr';
echo tolaPrice($cur_pick);
// Fails for the second call as under
$cur_pick = 'aed';
echo tolaPrice($cur_pick);
The function works fine for the first call using echo tolaPrice($cur_pick). However, it fails all subsequent calls and hence I am unable to complete the order status of second and subsequent orders.
I am not sure how to work around this.
Instead of trying to wrap an if else loop in a function, I simply calculated the prices in a separate file named tola_price.php as follows:
include('priceApi4CurCtrl.php');
$tola_price_pkr = $bitprice_pkr*10*11.664;
$tola_price_usd = $bitprice_usd*10*11.64;
$tola_price_aed = $bitprice_aed*10*11.64;
And then called the tola_price.php within my script with if else loop as follows:
require_one('tola_price.php');
if($cur_pick == 'pkr') {
$tola_price = $tola_price_pkr;
} elseif($cur_pick == 'usd') {
$tola_price = $tola_price_usd;
} elseif($cur_pick == 'aed') {
$tola_price = $tola_price_aed;
}
And then used the prices to build further script.
Thanks to those who offered help

Cannot retrieve data from database using first() method

I have this routing:
Route::get('/item/{item_id?}',['uses'=>'ItemController#get_item_view']);
I want to redirect to the first item if no item ID is given.
public function get_item_view($id = null)
{
if($id == null)
{
#This doesnt work
$selected_item = Item::where('item_id',Auth::user()->item_id)->first();
}
else
{
#This works
$selected_item = Item::where('id',$id)
->where('item_id',Auth::user()->item_id)
->first();
}
if($selected_item === null)
{
return redirect('/');
}
return view('auth.forms.item')->with('item',$selected_item);
}
If I introduce an ID (www.myproject.com/item/2), the page works perfectly, but if I don't, and try to get just the first of the list just to generate the page. I expect www.myproject.com/item to give me the first item.
This is the error I get:
Trying to get property of non-object (View:
/var/www/myproject/resources/views/auth/forms/item.blade.php)
and when I use dd($selected_item) on both cases I get the same type of object. I have no idea why one is working and the other one isn't.
if you don't provide item id then it'll be null,
$selected_item = Item::where('item_id',null)->first();
if you want to list first item just do
if($id == null)
{
#This doesnt work
$selected_item = Item::all()->first();
}
Make sure Auth::user()->item_id has a value. the error seems to be generating from it.
you can do dd(Auth::user()->item_id) to check it

Magento's getAttributeText is inconsistent

I'm trying to write some custom logic for browsing and searching in a Magento store.
So I figured I'd overwrite getProductCollection for both Mage_Catalog_Model_Layer and Mage_CatalogSearch_Model_Layer.
I'm trying to make decisions based on what the value of certain Attributes are for some of the products in the collection, but I can't seem to get the text value of all attributes.
The function as I've overwritten is:
public function getProductCollection()
{
if (isset($this->_productCollections[$this->getCurrentCategory()->getId()])) {
$collection = $this->_productCollections[$this->getCurrentCategory()->getId()];
} else {
$collection = $this->getCurrentCategory()->getProductCollection();
$this->prepareProductCollection($collection);
$this->_productCollections[$this->getCurrentCategory()->getId()] = $collection;
}
//ben
$collection->addAttributeToSelect('parent_sku');
$collection->addAttributeToSelect('door_color');
foreach($collection as $product) {
echo "\nSKU: ".$product->getSku()."\n";
$product_data = $product->getData();
if(isset($product_data['parent_sku']) && ($product_data['parent_sku'] != '')) {
echo "GETDATA PARENT: ".$product_data['parent_sku']."\n";
}
if($product->getAttributeText('parent_sku') != '') {
echo "ATTR TEXT PARENT: ".$product->getAttributeText('parent_sku')."\n";
}
if($product->getAttributeText('door_color') != '') {
echo "ATTR TEXT COLOR: ".$product->getAttributeText('door_color')."\n";
}
}
//end ben
return $collection;
}
This produces output like:
SKU: TEST_SKU_1
GETDATA PARENT: TEST_SKU_2
ATTR TEXT COLOR: Black
Notice:
I add both 'parent_sku' and 'door_color' as attributes to select.
I can access door_color using $product->getAttributeText()
I cannot access parent_sku using $product->getAttributeText()
I can access parent_sku through $product->getData()
Any time I call $product->getAttributeText('parent_sku') it returns false.
I assumed that this was a caching problem, but I flushed the cache and that didn't seem to help.
Does anyone have a clue why I can't access the value of 'parent_sku' through getAttributeText()?
Is parent_sku implemented as a dropdown box? My understanding is that getAttributeText loaded dropdown options and mapped them from and ID to text for you.

Categories