WooCommerce Undefined Property stdClass::$url - woocommerce

When i am installing woocommerce and logged out from my site then on home page woocommerce causes this problem.My wp-config.php is turned true , that is why its showing this error. but i need to know what is happening
Notice: Undefined property: stdClass::$url in /home/......./wp-content/plugins/woocommerce/includes/wc-page-functions.php on line 123

Line 123 of that file is within the following piece of code:
function wc_nav_menu_items( $items ) {
if ( ! is_user_logged_in() ) {
$customer_logout = get_option( 'woocommerce_logout_endpoint', 'customer-logout' );
if ( ! empty( $customer_logout ) ) {
foreach ( $items as $key => $item ) {
$path = parse_url( $item->url, PHP_URL_PATH );
$query = parse_url( $item->url, PHP_URL_QUERY );
if ( strstr( $path, $customer_logout ) || strstr( $query, $customer_logout ) ) {
unset( $items[ $key ] );
}
}
}
}
return $items;
}
add_filter( 'wp_nav_menu_objects', 'wc_nav_menu_items', 10 );
Notice on the last line there is a filter hook for wp_nav_menu_objects. So this function is used to filter the nav menu, and specifically looks like it is there solely so that WooCommerce can hide a logout menu object when the user is not logged in.
Now to the reason why the error is being thrown. I believe it stems back to the wordpress hook wp_nav_menu_objects. When looking at the function again it looks like the argument getting filtered named $items is expected to be a keyed array of stdClass instances, however on line 123 PHP is discovering that the url property is not available. This leads me to believe that another filter that occurs before this one is incorrectly modifying the $items array so that this filter can not correctly read the property.
Looking further in the file wc-page-functions.php on line 185 there is another hook for this filter:
add_filter( 'wp_nav_menu_objects', 'wc_nav_menu_item_classes', 2 );
However checking wc_nav_menu_item_classes reveals that it does not do anything special either. So here are my suggestions based on what has been presented:
Make sure that WordPress is up to date, the version of WooCommerce you are running maybe incompatible.
If you have code that filters wp_nav_menu_objects, make sure that you have not introduced a bug that changes the $items array to no longer contain instances of stdClass.
Try disabling/enabling 3rd party plugins that are not WooCommerce, you may find that one of these if out of date or just bugged.
Best of luck!
Koda

Related

how to change edit url with "Id" to edit url with "Slug" in Wordpress

I have this is WordPress Post editing Url:
https://example.com/wp-admin/post.php?post=ID&action=edit
and I want to change it to Slug Not the ID Like This:
https://example.com/wp-admin/post.php?post=Slug&action=edit
I was trying to edit the post with this Url but is not working:
https://example.com/wp-admin/post.php?post=MyPostSlug&action=edit
In order to change the edit post link structure, you can use the get_edit_post_link filter like so:
add_filter( 'get_edit_post_link', 'so_73914075_get_edit_post_link', 10, 3);
function so_73914075_get_edit_post_link($link, $post_id, $context) {
$post = get_post( $post_id );
if ( ! in_array( $post->post_type, array( 'post', 'page' ) ) ) {
return $link;
}
$post_type_object = get_post_type_object( $post->post_type );
if ( 'revision' === $post->post_type ) {
$action = '';
} elseif ( 'display' === $context ) {
$action = '&action=edit';
} else {
$action = '&action=edit';
}
if ( 'display' === $context ) {
$post_type = '&post-type=' . $post->post_type;
} else {
$post_type = '&post-type=' . $post->post_type;
}
$custom_edit_link = str_replace( '?post=%d', '?post-name=%s', $post_type_object->_edit_link );
return admin_url( sprintf( $custom_edit_link . $action . $post_type, $post->post_name ) );
}
This will change the edit links for regular posts and pages to something like this:
https://example.com/wp-admin/post.php?post-name=the-post-slug&action=edit&post-type=post
WARNING: make sure you limit this to only the post types you need to change the URL for. Making this change global will almost surely
have unintended effects over other plugins
However, making the admin panel actually load the edit screen is not that easy.
Looking at the source code of the wp-admin/post.php file, you will see that there is no way to hook into the flow and populate the $post_id variable with the post id matching the slug you are sending through.
That means you have 2 options:
RECOMMENDED Update the edit link to whatever format you want and then create an admin redirect function that pulls the slug from the initial URL and redirects to the actual edit page with the ?post=%d in it.
NOT RECOMMENDED Create a new admin edit page that will understand your URL structure and include the wp-admin/post.php after the code that pulls the $post_id based on the slug.
The 2nd method might come with lots of extra code you need to write to cover all the cases and all the instances a post reaches the post.php in the admin panel

Output certain product page on homepage / WooCommerce shortcode not working properly

I need to output a certain product page on the homepage. add_rewrite_rule doesn't work for homepage for any reason (
there are actually no rewrite rules for the homepage in the database, WordPress seems to use some other functions to
query the homepage):
//works fine
add_rewrite_rule( 'certainproductpage/?$',
'index.php?post_type=product&name=certainproduct',
'top'
);
//does not work
add_rewrite_rule( '', //tried everything like "/", "/?$" etc
'index.php?post_type=product&name=certainproduct',
'top'
);
After spending way too much time looking through wp / wc core code and stackoverflow I came across an alternative. I can
simply add a shortcode in the content of the page I need to be the homepage and a product page at the same
time: [product_page id=815]. Indeed it works great, but only if the shortcode is added in the admin editor or is
stored in the database (post_content). If I try to call the shortcode manually on the page template (
page-certainproductpage.php) then it outputs the product page without some necessary stuff (PayPal, PhotoSwipe and
Gallery js). Weirdly enough, if I keep the shortcode in the content (via Gutenberg / Code Editor) but don't
call the_content and only echo the shortcode then everything works fine:
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
get_header( 'shop' );
//works fine only if the same shortcode is within the certainproductpage's content
echo do_shortcode("[product_page id='815']");
//the_content();
get_footer( 'shop' );
Also when I try to add the shortcode via the_content filter hook before the do_shortcode function is applied in core's
default-filters.php ($priority < 11), then I get only the error:
NOTICE: PHP message: PHP Fatal error: Maximum execution time of 30 seconds exceeded in /var/www/html/wp-includes/functions.php on line 5106
Unfortunately there is no stack trace logged. And the function around line 5107 is wp_ob_end_flush_all which is called on shutdown from default-filters.php
echo do_shortcode(apply_filters('the_content', "[product_page id=815]")); did not help either (same incomplete output as
with echo do_shortcode("[product_page id=815]");)
Also totally weird:
When I compare the string of the content from the editor and the string of the shortcode added programmatically it is
equal!:
add_filter( "the_content", function ( $content ){
$wtf = "<!-- wp:paragraph -->
<p>[product_page id=815]</p>
<!-- /wp:paragraph -->";
$result = $wtf === $content;
?><pre><?php var_dump($result)?></pre><?php
return $content;
}, 1 );
But if I replace return $content with return $wtf - I get the maximimum exucution time exceeded error.
So how can I properly output a product page on the homepage ("/") or how can I get the same result with the shortcode
when applied within the the_content filter as when just adding the shortcode in the (Gutenberg) editor?
Update
Tested it with a simple custom shortcode outputting only a heading tag and it works fine with the_content filter. Also tried it on an absolutely clean site with only WooCommerce and PayPal installed - with the same results. Seems to be a bug on the WooCommerce side. Gonna run it through xDebug some day this week.
Ok, found a bit of a hacky solution. I just check on every page load whether the homepage is currently queried or not. Then I get the page content and check if it already contains the shortcode. If not then the page content gets updated in the database with the shortcode appended.
//it has to be a hook which loads everything needed for the wp_update_post function
//but at the same time has not global $post set yet
//if global $post is already set, the "certainproductpage" will load content not modified by the following code
add_action( "wp_loaded", function () {
//check if homepage
//there seems to be no other simple method to check which page is currently queried at this point
if ( $_SERVER["REQUEST_URI"] === "/" ) {
$page = get_post(get_option('page_on_front'));
$product = get_page_by_path( "certainproduct", OBJECT, "product" );
if ( $page && $product ) {
$page_content = $page->post_content;
$product_id = $product->ID;
$shortcode = "[product_page id=$product_id]";
//add shortcode to the database's post_content if not already done
$contains_shortcode = strpos( $page_content, $shortcode ) > - 1;
if ( ! $contains_shortcode ) {
$shortcode_block = <<<EOT
<!-- wp:shortcode -->
{$shortcode}
<!-- /wp:shortcode -->
EOT;
$new_content = $page_content . $shortcode_block;
wp_update_post( array(
'ID' => $page->ID,
'post_content' => $new_content,
'post_status' => "publish"
) );
}
}
}
} );
I'd recommend one step at a time. First of all, does this work?
add_filter( "the_content", function ( $content ) {
$content .= do_shortcode( '[product_page id=815]' );
return $content;
}, 1 );
This should append a product page to every WordPress page/post.
If it works, then you need to limit it to the homepage only, by using is_front_page() conditional in case it's a static page:
add_filter( "the_content", function ( $content ) {
if ( is_front_page() ) {
$content .= do_shortcode( '[product_page id=815]' );
}
return $content;
}, 1 );
If this works too, then we'll see how to return a Gutenberg paragraph block, but not sure why you'd need that, so maybe give us more context

Undefined index when setting WordPress custom options variables?

I have my custom options set like this...
function my_options_init(){
register_setting(
'myoptions',
'myoptions',
'myoptions_validate'
);
}
add_action( 'admin_init', 'my_options_init' );
...and I'm used to setting variables on my custom settings page in this manner...
$myoptions = get_option( 'myoptions' );
$foo = $myoptions['foo'];
But when debugging is enabled I get an error:
Notice: Undefined index: foo
The solution as I understand it is to do this...
if(isset($myoptions['foo'])) {
$foo = $myoptions['foo'];
}
..which makes the error go away.
The problem is that I have many variables I want to use in my plugin, and it seems like a lot of unnecessary work to do this every time I need to use a variable.
Then I stumbled on this in another topic:
"...to avoid having to include this check everytime you are getting a
setting from $myoptions - would be to review your
myoptions() function and make sure it returns an
array that includes every setting, including default values for those
settings that are not saved in the database yet."
My question is, how would I go about doing that?
You can setup a function for default values. Then when you fetch plugin option, you can fetch options with defaults. After that even if there is no options in the database, function will get value from default. So no PHP notice. Please check following example.
function wpso_get_default_options() {
// Default plugin options.
$default = array(
'foo' => 1,
'bar' => 'left',
);
return $default;
}
function wpso_get_plugin_option( $key ) {
$defaults = wpso_get_default_options();
$plugin_options = get_option( 'myoptions' );
$plugin_options = wp_parse_args( $plugin_options, $defaults );
$value = null;
if ( isset( $plugin_options[ $key ] ) ) {
$value = $plugin_options[ $key ];
}
return $value;
}

How to set homepage based on device with Wordpress?

I need to set a default homepage based on the visitor device (mobile/desktop), I tried the following code in plugin, but did not work.
if ( wp_is_mobile() ) {
$homepage = get_page_by_title( 'mobile' );
}else{
$homepage = get_page_by_title( 'home1' );
}
if ( $homepage ){
update_option( 'page_on_front', $homepage->ID );
update_option( 'show_on_front', 'page' );
}
it keeps loading the home1, which is selected from theme options.
Thanks,
Your current functionality wouldn't work, even if it "worked". You're attempting to set a site-wide option in the database based on the most recent visitor's device.
Using update_option() isn't in your best interest here. What you should be doing is programmatically changing the template that's loaded at run-time based on the user's device, using the template_include filter - that way you're not storing a (semi) permanent change in your database, which would get constantly overwritten countless times by any user and affect all other users.
This would end up looking something like this:
add_filter( 'template_include', 'so_52745088_homepage_template', 99 );
function so_52745088_homepage_template( $template ){
// Only execute on the front page, not pages/posts/cpts
if( is_front_page() ){
// Determine if mobile
if( wp_is_mobile() ){
// Make sure mobile homepage template is found
if( $home_template = locate_template( array( 'homepage-mobile.php' ) ) ){
return $new_template;
}
}
}
return $template;
}
If you don't have a separate page template for mobile, and it's just a regular ol' separate page, then you can look at using wp_safe_redirect() on any number of hooks, a common one being template_redirect, which would end up looking like this:
add_action( 'template_redirect', 'so_52745088_homepage_redirect' );
function so_52745088_homepage_redirect( $template ){
// Only execute on the front page, not pages/posts/cpts
if( is_front_page() ){
// Determine if mobile
if( wp_is_mobile() ){
wp_safe_redirect( 'mobile' );
exit;
}
}
}

Relocate wordpress plugin output thats hooked into the content

I am trying to relocate the position of the output generated by a review plugin for wordpress. The plugin hooks into the end of "the_content". I have found the filter which works to remove the output:
remove_filter('the_content', array( EDD_Reviews::get_instance(), 'load_frontend'));
Now I am going crazy trying to relocate the output to a new location. I have created a custom hook in my theme file:
function reviews() {
do_action('reviews');
}
The above hook outputs just fine to custom location in the theme files when passed a simple function. However the tricky part is getting the reviews and review form to display. I tried adding it back with this:
add_action('reviews', array( EDD_Reviews::get_instance(), 'load_frontend'));
This did not work. The full function I am trying to call is below. Any body have any ideas how I may call this via my new hook? I am rather stuck.
public function load_frontend( $content ) {
global $post;
if ( $post && $post->post_type == 'download' && is_singular( 'download' ) && is_main_query() && ! post_password_required() ) {
ob_start();
edd_get_template_part( 'reviews' );
if ( get_option( 'thread_comments' ) ) {
edd_get_template_part( 'reviews-reply' );
}
$content .= ob_get_contents();
ob_end_clean();
}
return $content;
}
Many thanks in advance.
Ok mostly figured this out after studying classes. If anyone else is looking to do this then remove the hook as below:
remove_filter('the_content', array( EDD_Reviews::get_instance(), 'load_frontend'));
The following line will then render the reviews and form anywhere you like:
<?php echo EDD_Reviews()->load_frontend( '' ); ?>

Resources