Woocommerce - add new attribute values to variable product - php

First things first:
This is my first question posted on stackoverflow. Put another way, this is the first problem I could not solve by myself with your help (huge thanks to all of you, you make the world go round!).
My question is related to an answer given by #LoictheAztec to another question (I originally planned to post my question in the comments of that post but being the lurker that I am/was, I lack the reputation to do so): https://stackoverflow.com/a/47766413/13263330
I have created a variable product and would like to add new attribute values to this product programmatically.
I copied and slightly modified the code from the link above but when I tried to execute it, I received the following errors:
Notice: wc_get_product was called incorrectly. wc_get_product should not be called before the woocommerce_init, woocommerce_after_register_taxonomy and woocommerce_after_register_post_type actions have finished. Backtrace: require_once('wp-load.php'), require_once('wp-config.php'), require_once('wp-settings.php'), do_action('plugins_loaded'), WP_Hook->do_action, WP_Hook->apply_filters, execute_active_snippets, execute_snippet, eval, create_product_variation, wc_get_product, wc_doing_it_wrong
Fatal error: Uncaught Error: Call to a member function get_name() on boolean
The problem mainly seems to be about the following line of code in the link posted above:
'post_title' => $product->get_name()
Just as a reminder and for convenience reasons, the product variable is defined as follows:
$product = wc_get_product($product_id)
The attribute values are correctly added to the variable product, so the code does what I expected and intended it to do but the site still crashes.
As far as I understand the situation, problems (and their causes) occuring could be related to:
The modifications I made in the code (already checked with default code and example given by #LoictheAztec within his post, same problem)
As always, compatibility issues with plugins and/or theme (already checked, deactivated all other plugins and changed to default theme; also tried code with fresh WP installation)
According to an answer given to someone having a similar problem (https://github.com/woocommerce/woocommerce/issues/23160), the issue can also be caused by the $product variable not being correctly "associated with a valid product" (not sure about this one but I think the "parent" variable product already created is fine) or "the product no longer existing" (can definitely rule this one out).
Any help whatsoever is highly appreciated.

If you are using Code Snippets plugins, Please try following code. (Run example code within woocommerce hook)
add_action('woocommerce_after_register_post_type', 'test_create_product_variation');
function test_create_product_variation(){
$parent_id = 746; // Or get the variable product id dynamically
// The variation data
$variation_data = array(
'attributes' => array(
'size' => 'M',
'color' => 'Green',
),
'sku' => '',
'regular_price' => '22.00',
'sale_price' => '',
'stock_qty' => 10,
);
// The function to be run
create_product_variation( $parent_id, $variation_data );
}

Related

How can I fire a custom function just once in Woocommerce

I need to add variations to my Woocommerce products programmatically and I borrowed the code from this answer thread:
Create programmatically a WooCommerce product variation with new attribute values
It works, but gives me two variations when I pass this data array:
$variation_data = array(
'attributes' => array(
'kidssize' => '2'
),
'sku' => '',
'regular_price' => '120',
'sale_price' => '',
'stock_qty' => '',
);
My guess is that funcntion fires two times.
Since i am a noob in php and backend in general all I know how to call a function is from some template file and visiting the page.
And to prevent other visitors from triggering it I use
if(isset($_GET['**parameter Only I know**']))
… wrap and call it going to the page with set parameter;
I understand that this is a really bad way for doing that, but how do I do it otherwise if I need to call function once and never use it again?
And is even firing twice a problem here or is it something wrong with my array?
EDIT:
Here's a detailed process of what i do:
i put the function from the link above in functions.php,
then put the call in footer.php of my theme with above mentioned wrap (the parameter is irrelevant - it could be anything, because it's just used as a trigger)
and go to the page with said parameter to trigger the call,
load the page only once and look for the result in admin panel.
And it has 2 variations always, even if i add more attributes to an array it will return 2 variatons of the last attributes array item;

How to edit mySQL wp_posts table from plugin php in WordPress?

I have a need to change a plugin that creates/edits entries to the wp_posts table. Currently, it is lacking in that it cannot target some specific fields. I am endeavoring to edit the plugin so I can change these fields as well with the plugin. Specifics below.
How would I generally target this table then create/edit entries?
I have in mind something like this, which was copied from here.:
$my_post = array(
'post_title' => '#Enter the title#',
'post_content' => '#Enter the Content#',
'post_status' => 'publish',
'post_author' => 1
);
wp_insert_post( $my_post );
I assume this is possible because the plugin I'm hoping to change already makes changes to the wp_posts table. How do I do this? I have programming experience in C#, but my PHP and WP knowledge is severely lacking. I assume there's a few WordPress key functions that I'm looking for, but I simply don't know what they are or how to find them (I might be searching for the wrong terms). wp_insert_post() looks very promising, but the documentation seems to imply that it won't work for my specific needs.
Specifics
I'm using a great plugin called Really Simple CSV importer (RSC), which allows you to create/update posts with a csv. It seems to be able to target nearly every field (e.g. post_title, post_id, post_parent, post_content, _wp_page_template, etc.). This is quite a boon if you have to create hundreds of pages regularly (which I do).
The problem is that it won't target two specific fields, which are titled group_access and tag_list. I put those fields as columns in my csv, but they are not added to the mySQL database, and thus are not changed on the site. I believe these fields are specific to a plugin called iMember360, which is a plugin that ties into an InfusionSoft account.
Naturally, I've tried contacting RSC support, but have received no replies at all. I've spoken to iMember360 support at length, and the best they can give me without doing the work themselves is that they use the action hook import_end to make changes to the table, so if RSC is not using it, then it won't affect those fields. They also say that iMember360 has an import/export function, but it is only for the plugin's specific features, and ties in with the WordPress XML import/export feature. Clearly, this RSC plugin does not do that.
Regardless of these limitations, it seems to me like if the field exists in the table, then you should be able to edit it, so I tend to think that the RSC plugin is simply lacking in this functionality, probably only targeting WP default fields only.
What I've tried:
I have tried editing the plugin PHP directly, with the assumption that the plugin simply does not have an entry for the group_access and tag_list fields.
One of the PHP files contained:
// (string, comma separated) name of post tags
$post_tags = $h->get_data($this,$data,'post_tags');
if ($post_tags) {
$post['post_tags'] = $post_tags;
}
I simply copied and pasted it right above it and changed post_tags to group_access. It didn't work.
I also found, and added to:
$attachment = array(
'post_mime_type' => $mime_type ,
'post_parent' => $this->postid ,
'post_author' => $this->post->post_author ,
'post_title' => $title ,
'post_content' => $content ,
'post_excerpt' => $excerpt ,
'post_status' => 'inherit',
'menu_order' => $this->media_count + 1,
////////// added
'group_access' => $group_access ,
'tag_list' => $tag_list ,
//////
);
That didn't do anything either.
There are two ways to edit the wp_posts table that I know of. The first is with the wp_update_post() and wp_insert_post() functions. These are typical WP functions that are used like any others. You just have to pass the correct parameters. For example:
$my_post = array(
'ID' => $updatePostID, // User defined variable; the post id you want to update.
'post_title' => 'Update Title',
'post_content' => 'Update Content',
);
// Update the post into the database
$post_id = wp_update_post( $my_post, true ); // Returns 0 if no error; returns post id if there was an error.
// Check if table was updated without error. For debugging. Remove from your code if it all works, before publishing.
if (is_wp_error($post_id)) {
$errors = $post_id->get_error_messages();
foreach ($errors as $error) {
echo $error;
}
}
Simply pass an array with the predefined field names to the functions and they will then run correctly. The update function is for updates, naturally, and the insert function creates new table entries (rows). There is a limitation, however. These two functions will only operate on the WP predefined fields. So, if your table contains some custom fields, then you will have to use the $wpdb class.
The other way to update your mySQL tables from WordPress is to use the $wpdb class directly. This class is far more expansive than the wp_update_post() and wp_insert_post() functions. The first difference is that it can edit many other mySQL tables, not just the wp_posts table. It can also edit non-WP fields. For example:
global $wpdb; // This calls the use of the class. I actually do not think this is necessary, but I do it anyway.
$dbresult = $wpdb->update($wpdb->posts, // Returns 0 if no errors. Post ID if errors occurred.
// Notice posts instead of wp-posts. Prefixes are not necessary with this class.
['post_title' => 'Update Title',
'post_content' => 'Update Content',
'custom_field' => $customField, ], // User defined table column and variable.
['ID' => $updatePostID, ]); // User defined variable; the post id.
if (false === $dbresult) {
echo 'An error occurred while updating...';
$errors = $post_id->get_error_messages();
}
I'm not very familiar with either of these options, but there seems to a massive difference in the width of functionality, so there may be considerations you should take before using one over the other. I've asked a question to that end: https://wordpress.stackexchange.com/q/259043/38365 One reply says:
Downsides of $wpdb are that you do need to know SQL and you need to be conscious of normal data sanitization and when to use prepare() and what functions already prepare your statement which are hardly downsides at all. The $wpdb Class is by nature more powerful than any of the default WordPress functions because you have access to all the data, custom or not, assuming you know the proper SQL to get, modify, or remove it.
TL;DR $wpdb is more powerful but less friendly and forgiving.
That makes sense to me. Basically, don't fiddle with $wpdb unless you know what you are doing or absolutely have to.

How to show custom module direct in catalog tpl file in oc2

I have read all the related questions in SO and Opencart Forum but couldn't find solution.
So I have copy featured module and edited some of code, not too much and Now i want to show this new module direct in front on only success page. So i have put this code in catalog/controller/checkout/success.php
$data['successpage'] = $this->load->controller('module/successpage');
and in ***catalog/view/theme/default/template/common/success.tpl
<?php echo $successpage; ?>
Now i getting
error Undefined index: limit in controller\module\successpage.php on line 20
* I think its b'coz some variables values need to send in module controller file
And i have try all the answer for this but can't get solution.
Thanks If you know and help me to sort out.
You might get an error as there is not any settings (data) is passed in index method of your class ControllerModuleSuccesspage. You are directly calling $data['successpage'] = $this->load->controller('module/successpage');
Try to display your successpage module by setting from admin side. (From layout). If you want to call it directly then first check for condition if ($setting['any index']) { ..... } else {... }.
If you want to pass any parameter without setting up from admin side than do this.
$parameters = array(
'name' => 'Your module name',
'product' => array(43,40,42,30), // product id
'limit' => 4,
'width' => 200 ,
'height' => 200,
'status' => 1
);
$data['successpage'] = $this->load->controller('module/successpage',$parameters);
You will get all details of $parameters in index method of your successpage controller file.
That's it. :)
Try this url " [yourhost]/index.php?route=module/successpage" to see if this module is working perfectly. There is no error in loading this module to parent controller. I think issue is present in this module itself. Maybe some value dependency.

How to modify data for a SugarCRM SubPanel using PHP?

Is there anyway to modify the content shown in a SugarCRM Subpanel without relying on Action Hooks?
Right now to edit content for a Subpanel field I have to use the hooks like this...
$hook_array['process_record']
And in the Class method that I assign the Hook to call I can then change a field in the Subpanel like this...
$bean->name = '<a href="/index.php?action=ajaxui#ajaxUILoc=index.php%3Fmodule%3Dproje_Web_Project_Tasks%26action%3DDetailView%26record%3D'
.$bean->id.'" rel="popover" data-content="'
.$bean->description.'" data-original-title="">'.$bean->name.'</a>';
The main and major problem we have with this method is it works great until you do either of these actions....
Add an item using the Quick Create form
Change a page using the Subpanel paging buttons
In either case, it reloads the Subpanel data without running this hook code on the data, so the result is pretty major as the Subpanel fields that you have edited are no longer edited and show up as normal.
Here is a basic example...this shows 2-3 fields that have been edited using the Hook method above...
Now after paging or quick-creating a new record in the Subpanel, it reloads the Subpanel data and does not apply the Hooked code so you can see the result looks like this...
I know that ListView has a much more reliable and flexible method for editing it's content using the get_list_view_data() method I am able to apply the same edits and have them work all the time!
So I am hoping there is a similar method to edit Subpanel data and have it always apply the edits to that data? From what I have seen in my research so far, the only solution that will work as expected all the time, is to make a completely new Custom Field Type!
I am really hoping that is not the ONLY way as that is a major pain to do that for each type of field that I need to edit in the Subpanels and just doesn't feel right when there are easy ways to edit everything else except SubPanel data.
Does anyone have any ideas, suggestions, tips, help, please do share with me on this matter as it is the main problem I have had since I started developing with SugarCRM in the past few months?
You can change the data by writing a custom query to get data for your subpanel.
So inside your bean (this case Contacts) do a functions:
function get_project_list() {
$query = "SELECT project, info, matching, column, names FROM projects WHERE contact_id = '" . $this->id . "' AND deleted = 0"
return $query;
}
and then in subpanel definition set the data source like this:
$layout_defs["Contacts"]["subpanel_setup"]['projects'] = array(
'order' => 10,
'sort_order' => 'desc',
'sort_by' => 'name',
'title_key' => 'LBL_PROJECTS_TITLE',
'subpanel_name' => 'contact_projects',
'module'=>'projects',
'get_subpanel_data' => 'function:get_project_list',
'function_parameters'=>array('type'=>'urgent'), // this is optional if you decide to sent parameters to the function if do this dont forget to define your function with function get_project_list($params)
'top_buttons' => array (... buttons that you need go here..),
);
Since sql is quite powerful you can modify your subpanel data any way you like, well more or less :)

wordpress multisite wp_update_nav_menu_item returns $menu_item_db_id but does not show in menu

I have a strange problem when using the wp_update_nav_menu_item function in a multisite installation.
It normally works when I execute this from within wp-admin. However, now I've been tasked with writing a handler script to auto-create a site, add a number of default pages, add a menu and populate the menu with those pages.
Here is the code in question:
$miid = wp_update_nav_menu_item($menu_id, 0, array(
'menu-item-title' => $post['post_title'],
'menu-item-object' => 'page',
'menu-item-object-id' => $pid,
'menu-item-type' => 'post_type',
'menu-item-status' => 'publish',
'menu-item-parent-id' => $navParentID,
'menu-item-position' => $post['menu_order']));
I've ensured that all of the values passed in to the function are correct and match with those which would be passed in when I call this function from within wp-admin dashboard.
The blog gets created successfully, as do the default pages, and the menu. When this executes it does return a $menu_item_db_id value indicating it worked successfully but nothing has actually been added to the menu and calling something like print_r(wp_get_nav_menu_object($menu_id)); returns nothing.
When I call the same exact function with the same exact inputs from a page within wp-admin everything works fine.
I've considered that perhaps the current blog context was not set correctly and have used this snippet to validate that I'm in the correct blog:
//Ensure we're updating the correct blog
$blogid = get_current_blog_id();
switch_to_blog($blogid);
echo get_current_blog_id()."<br/>";
Has anyone else encountered this issue?
I've had exactly the same problem..
The solution was to create item and menu relationship for each item :
wp_set_object_terms($item_id, $menu_id, 'nav_menu');
For some reason it was not created in wp_update_nav_menu_item

Categories