WooCommerce shipping methods not working for logged-in users? - woocommerce

I have developed a custom build on woocommerce.
All is fine except for the checkout page.
The site ships to UK only, and i have Flat Rate shipping enabled.
However, on the checkout page there are two issues. The first is an invalid argument in a foreach loop:
Warning: Invalid argument supplied for foreach() in /home/****/public_html/wp-content/plugins/woocommerce/includes/class-wc-shipping.php on line 291
And the second problem is:
There doesn‘t seem to be any available shipping methods. Please double check your address, or contact us if you need any help.
I am bashing my head against a wall here. I have a shipping method enabled, so why is it continuing to tell me there is no method available?
All i want it to do there is simply list all the shipping methods i have enabled so the user can select one.
I also noticed that the shipping methods display when user is not logged in, but when they are logged in it shows Flat Rate - then a random price that isn't entered anywhere in admin.
To elaborate a little. This problem does not occur if i add a variable product to the art using the ?add-to-cart url, but as soon as i use the add_to_cart function it causes those errors.
woocommerce->cart->add_to_cart(522,1, 523,array("attribute_colour" => "colour","attribute_size" => "a3", "attribute_invoice-numbering" => "yes", "attribute_quantity-column" => "yes", "attribute_cc-type" => "duplicate"));
The above code works fine if it is used in a URL, but i want to call it via ajax with the function.

Go to woo commerce settings and add a shipping zone. See here.
On existing products and when adding new products always ensure u set the shipping location. See here

I had a similar problem, I got that message even if Shipping Zones and Shipping Methods were configured correctly. I expected just one flat rate, no choices available.
Doing more tests the bug disappeared when there were 2 or more methods available, it was weird. I found the issue in the theme template, the first control was a wrong:
if ( 1 < count( $available_methods ) ) :
instead of
if ( $available_methods ) :
Perhaps you have a bug in the theme template too. You can do a diff/compare between the original template (/wp-content/plugins/woocommerce/templates/cart/cart-shipping.php) and the custom file (/wp-content/themes/YOURTHEME/woocommerce/cart/cart-shipping.php)

Related

Woocommerce Stripe - hide shipping methods in google and apple pay

I need to hide in google pay and apple pay certain delivery methods in plugin (https://wordpress.org/plugins/woocommerce-gateway-stripe/) Can I do it with a filter or something?
Some shipping methods i have can't use - they're unsupported with apple and google pay.
Support of WC Stripe plugin told me:"Google and Apple Pay uses whichever shipping method is available on the site for the Stripe payment gateway. There isn’t an inbuilt option to selectively hide certain shipping method from Google and Apple pay, and we’re not aware of a workaround as well. I recommend taking a lot at a similar discussion here (related to disabling shipping method based on the payment gateway)" but I don't know how I do that.
–
Thanks for help.
The answer of the above mentioned question is "Yes". We can hide the shipping methods only in Apple Pay Using Stripe. Currently, there is no settings both in Woo-commerce and Stripe to select the specific shipping methods. But you can achieve that functionality by adding custom code in the right file and function. Please follow all the steps:
Step1: The file url for Stripe is listed below:
woocommerce-gateway-stripe/includes/payment-methods/class-wc-stripe-payment-request.php
Step2: Look for the following function in the file
public function get_shipping_options( $shipping_address, $itemized_display_items = false )
Step3: Remember that "STRIPE" by default uses the first Shipping method by default. So you need to check in that particular function, where that thing is happening.
Step4: Right before that specific IF condition --
"if ( isset( $data['shipping_options'][0] ) )"
Step5: Insert the Following Code before that IF condition
foreach($data['shipping_options'] as $index => $myshipping){
if(strpos($myshipping['label'],'Select Future Date') !== false){
unset($data['shipping_options'][$index]);
$data['shipping_options']= array_values($data['shipping_options']);
}
}
Note: You can do by ID or any other element in an Array.
You just need to match the shipping method ID and then Unset that ID. Please don't forget to update the array by using array_values() function.

Use "Team Members" custom post type instead of Author for blog posts

For SEO purposes....a client would like to have author links point to the Team member's bio page instead of the default author page....for example:
There's a blog posts written by user A. The author link now points to:
/author/usera
but they would like it to point to
/our-team/user-a
"Our Team" is a custom post type, and User A is a post within it.
I've tried a few workaround solutions, but haven't found a good way to establish the relationship between the author and the team member. If I could just add the team member from that custom post type when choosing the Author...that would solve my problem, though I imagine that's fairly complicated - but hopefully gives an idea of what I'm trying to accomplish.
My workaround so far is to rewrite the author base to the slug of the custom post type, which takes care of half of it, but there's still no relationship between the author and team member, so I use the_author_meta(user_url) to get the "Website" field in the user profile, and I put in the url of the team member there.
It works, but doubles the work since you have to add the Team Member to Our Team, as well as add them as a user/author, and then requires the knowledge of the admin adding the user/author to add the bio url in the website field, otherwise...it won't work well, so I'd love a cleaner solution.
Let me know if that makes any sense or not and if there's a better way to do this...
Thanks!
Currently, I cannot see an automated mapping of user account → team member post happening. So, there are multiple ways to achieve this by manually mapping user accounts to a team member post.
Set the author's website to the URL of the team page
Advanced Custom Fields: creating a field group that is shown for all user accounts and includes a Post field (limited to Team posts), so you can select exactly one team post for each WP user manually
I will show you the first option.
Assume, each user account (Users) has the URL to the team member page set, e.g., in the user profile of usera you see:
Website: https://your-site/our-team/user-a
Then you can add a filter to modify the author link like so, adding this to your functions.php or own plugin:
add_filter( 'author_link', 'team_author_link', 10, 3 );
function team_author_link( $link, $author_id, $author_nicename ) {
$userinfo = get_userdata($author_id);
// if the user's Website field is not empty, replace the author link:
$link = empty($userinfo->data->user_url) ? $link : $userinfo->data->user_url;
return $link;
}
Now, you will have all your author's links linked to their "website", which hopefully has been set to the team member page.
This can also be done with Advanced Custom Fields a bit prettier where you could add a field group shown for User Roles -> All, with the field group having a "Post"-type field named "team_post", matching only the team custom post type. It would look similar to this: https://i.stack.imgur.com/LLgWv.png
(your post type most likely will not display as "Staff member", but most likely "Team").
Then, you can select a Team post in each author's user profile and change the filter function to this:
add_filter( 'author_link', 'team_author_link', 10, 3 );
function team_author_link( $link, $author_id, $author_nicename ) {
$team_post_id = get_field('team_post', $author_id);
// if the team post is set, get the permalink to the team post:
$team_link = get_permalink($team_post_id);
$link = ($team_link !== false) ? $team_link : $link;
return $link;
}
Keep in mind that in both cases, each user can tamper with their URL. Using Advanced Custom Fields, it would also be possible to create an admin-only options page where you can map user accounts to Team posts - but this is a bit more complex.

Custom post Types slug and permalinks issue - SEO and Structure

I see this issue has been brought up before but they don't seem to address my specific issue. I do feel my specific issue is a broad one though. That may seem paradoxical but hear me out.
For a site I'm working on in WordPress, I created some pages for the counties they serve. So far I have one for Bucks, Montgomery, and Delaware Counties, but there will be plenty more. From there we want people to be able to navigate to "Recent Jobs" based on the county that the client can add themselves. So it can be 1 to however many jobs the client wants to add. These pages will talk about a specific job in a specific town, then link to "Related Jobs" by job type, not county. So these go 3 levels deep, County Hub page > Specific job in specific town > Specific job type (ie: Bucks County, PA > Window Replacement Job in Newtown, PA > Window Replacement Job in Wherever).
Hope that makes sense. So what I did was create a Page for each County. Then I created a Custom Post type: County Jobs. I created custom taxonomies for each county to group them by county. I will probably need taxonomies to group them by job type also but I'm not there yet. I set up my template "single-county-job.php" and my Custom Fields to display only on this post type. The problem came when "/county-job/", the post type slug, displays in the URL. Adding that extra level is bad for SEO rankings. If you so a search for anything in Google you will see the first pages of results show sites that go only two levels deep: "URL.com/level1/level2" and anything with "/level3/" is at best on the third page (besides sites like Amazon or eBay). I ideally want the URL to be: "/bucks-county-pa/post-title" not "/county-job/bucks-county-pa/post-title". It also doesn't make sense for a user to go from the "/bucks-county/" page to "/county-job/bucks-county-pa/post-title".
So I found multiple ways to get the slug out of the URL but all result in a 404. Basically WordPress no longer recognizes the post as a post. There are some redirect rules I can add to get around the 404s but that is not good for SEO either. I also read it is bad practice, a hack, and shouldn't be done.
Have you set up similar pages/posts in the past and how did you handle it? That slug is a problem, but making a CPT for each county is not an option either because there are way too many and they would all be the same set up - it just doesn't make sense. Maybe this shouldn't be a CPT, but then how do I handle it? It doesn't seem like they should be pages, and how would I handle the Custom Fields?
I am stuck! Any help or insight you could provide would be a huge help.
Considering that the word county is static in your url, you can use it in order to make Wordpress recognize what you're trying to request. You can use generate_rewrite_rules filter in order to add your own rewrite rule:
add_filter('generate_rewrite_rules', 'my_rewrite', 9);
function my_rewrite($wp_rewrite)
{
$wp_rewrite->rules = array_merge(array(
'^([^-]*)-county-([^/]*)/([^/]*)/?$' => 'index.php?post_type=county-job&county=$matches[1]-county-$matches[2]&county-job‌​=$matches[3]'
), $wp_rewrite->rules);
}
The second important part is to tell Worpdress to not use anymore links with /county-job/ as prefix. You can do this with the post_type_link filter:
add_filter('post_type_link', 'my_post_link', 1, 3);
add_filter('post_link', 'my_post_link', 10, 3);
add_filter('page_link', 'my_post_link', 10, 3);
function my_post_link($post_link, $id = 0) {
$post = get_post($id);
if(is_object($post) && $post->post_type == 'job') {
return str_replace('county-job/', '', $post_link);
}
return $post_link;
}
Don't forget that you need to flush your rewrite rules in order to make this script working. You can do this by visiting the Permalinks section in WP back office.

Modifying Wordpress post status on Publish

I am attempting to validate fields on a custom post type in the admin panel Edit Post page.
When the user clicks "Publish" I want to validate fields in the POST data, and change the post_status to "pending" if the data does not pass the tests. When this occurs, I'd also like to add errors to the page in the admin notices area.
I've been trying this with an added hook to the "wp_insert_post" action which also saves our own data. I'm not certain of the order of operations, but I'm assuming that the wp_insert_post events happen first, and then my function gets called via the hook.
The problem is that it's the Wordpress function which is doing the post publish actions, so by the time I get to validate data, Wordpress has already saved the post with a status of "publish". What I need to do is either prevent that update, or change the status back to "pending", but I'm having little success in finding a way to do this within the API.
So, here's an order of operations I'd like to effect:
1. admin user edits post data and clicks "Publish"
2. via wp_insert_post, my data validation and post meta save routine is called
3. If data passes validation, post status is "published"
4. Otherwise, post status set to "pending" & message shown in admin notice area
Surely someone has done this, but extensive Googling just leads me to the same seemingly irrelevant pages. Can someone point me in the right direction here? Thanks in advance-
UPDATE:
So, RichardML was indeed correct, hooking to the wp_insert_post_data filter gave me the right place to validate admin post edit page fields. I'm updating this however to note what the rest of the solution is, specifically getting the reason reported in the admin notice area.
First off, you can't just output data or set a field because the admin page is the result of a redirect, and by the time you get to rendering the admin post page again, the admin_notices action is already gone. The trick was something I picked up from another forum, and it's hackish, but it works.
What you'll need to do is in your validation filter function, if you determine that you will need to display errors, is use set_option() to add a blog option with a unique name (I used 'publish_errors'). This should be HTML code in a div with a class of "error".
You will also need to add an action hook for 'admin_notices', pointing at a function which checks for the existence of the 'publish_errors' option, and if it finds it, prints it to the page and deletes it with delete_option().
You can use the wp_insert_post_data filter to inspect and modify post data before it's inserted into the database.
In response to your update I don't think it's necessary to temporarily add an option to the database. It should be possible to simply add a query string variable to the Wordpress redirect, something like this:
add_filter('wp_insert_post_data', 'my_post_data_validator', '99');
function my_post_data_validator($data) {
if ($data['post_type'] == 'post') {
// If post data is invalid then
$data['post_status'] = 'pending';
add_filter('redirect_post_location', 'my_post_redirect_filter', '99');
}
return $data;
}
function my_post_redirect_filter($location) {
remove_filter('redirect_post_location', __FILTER__, '99');
return add_query_arg('my_message', 1, $location);
}
add_action('admin_notices', 'my_post_admin_notices');
function my_post_admin_notices() {
if (!isset($_GET['my_message'])) return;
switch (absint($_GET['my_message'])) {
case 1:
$message = 'Invalid post data';
break;
default:
$message = 'Unexpected error';
}
echo '<div id="notice" class="error"><p>' . $message . '</p></div>';
}

Drupal module to control user post frequency?

We've been having a new type of spam-bot this week at PortableApps.com which posts at a rate of about 10 comments a minute and doesn't seem to stop - at least the first hour or so (we've always stopped it within that time so far). We've had them about a dozen times in the last week - sometimes stopping it at 50 or 60, sometimes up to 250 or 300. We're working to stop it and other spam bots as much as possible, but at the moment it's still a real pest.
I was wondering whether in the mean time whether there's any sort of module to control the frequency a user can post at to e.g. 50 an hour or something like 10 in an hour for new users. That at least would mean that instead of having to clear up 300 comments 50 at a time in admin/content/comment we'd have a smaller number to clear. (A module to add a page to delete all content by a user and block them would also be helpful!)
I believe that there's a plugin to do this available for WordPress, but can't find any such thing for Drupal.
For your second question, i would have a look at the code of the User Delete module (click).
The module also disables the user account and unpublished all nodes/comments from a certain user. By extending the code, you could easily create another possibility to unpublish + delete all nodes/comments from a certain user and blocking the account.
After the unpublish code in the module, you should just put delete code (in sql if the module is selecting by a sql-query or by using the drupal delete functions).
Another option would be so make a view (using the view module) only to be viewed by administrators, where you choose a certain user using the filters and then lists his/her posts. Then in the node-contenttype.tpl.php you place a button that calls a function which deletes all nodes/comments and the user.
First problem (post frequency)
I've been thinking about the comment post limit. If I remember correctly Drupal stores comments in a seperate table and has comment specific functions.
I'd create a new module and using the comment_nodeapi function i would check in the operation 'insert' how much comments the current user has already made within a certain timeframe.
To check this I would write a custom sql query on the database which takes the count of alle comments made by uid where the post_date is larger then NOW-1hour. If that count is larger then 10 or 15 or whatever post frequency you want then you give a message back to the user. You can retrieve the user id and name by using the global $user variable.
(example: print $user->name;)
You have to check on your own for the sql query but here's some code when you have the amount:
<?php
function comment_nodeapi(&$node, $op, $arg = 0) {
switch ($op) {
case 'insert':
//PLACE HERE THE SQL TO GET THE COUNT
if($count > 15){
$repeat = FALSE;
$type = 'status'
drupal_set_message("You have reached the comment limit for this time.", $type, $repeat);
break;
}else{
db_query('INSERT INTO {node_comment_statistics} (nid, last_comment_timestamp, last_comment_name, last_comment_uid, comment_count) VALUES (%d, %d, NULL, %d, 0)', $node->nid, $node->changed, $node->uid);
break;
}
}
}
?>
(this code has not been tested so no guarantees, but this should put you on the right track)
I would suggest something like Mollom (from the creator of Drupal). It scans the message for known spam pattern/keywords/... and if this scan fails, it displays a CAPTCHA to the user to make sure that it's a real human that wants to enter content that has the same properties like spam.
They offer a free service and some paid solutions. We are using it for some customers and it's worth the money. It also integrates very well in Drupal.
Comment Limit is probably what you need.
http://drupal.org/project/spam
http://drupal.org/project/antispam - with akismet support

Resources