Wordpress - How to get the information of a widget instance - php

I wanted to know how to get the information of a widget instance, to be able to get all its information from another widget. Try the Get Widget ID plugin but it returns "temp" as a result and I also tried with this code block:
https://wordpress.stackexchange.com/questions/240327/how-to-access-widget-data-from-outside-widget
But I still get the same result.
My idea is the following:
I am modifying a Wordpress widget so that it selects a static post in order to fulfill the function of a featured post in a digital newspaper ... The widget has already been modified and is already working. That same widget is repeated in several places on my website, that is, I use it several times (each with a different selected post).
My idea is to show the featured posts with that widget (those selected by the editor) and modify another widget, that shows me all the posts except the ones that are selected in those widgets. For that I want to know how to get the instance of said widgets that select the featured post, to be able to get the ID of the selected post in each widget and show all the posts except those that are already as featured posts.
In summary ... I just want to see no news that is selected as featured again.
Clarification: This is not a widget written by me, it is a template that I bought and since it did not have this functionality, I am trying to create it.
I leave the code of my widget, in case it is of any use:
<?php
if ( ! defined( 'ABSPATH' ) ) exit;
add_action('widgets_init', 'seleccion_subtitulo');
function seleccion_subtitulo() {
register_widget('seleccion_subtitulo');
}
class seleccion_subtitulo extends WP_Widget {
/*-----------------------------------------------------------------------------------*/
/* Widget Setup
/*-----------------------------------------------------------------------------------*/
public function __construct() {
$widget_ops = array(
'classname' => 'seleccion_subtitulo',
'description' => esc_html__('Seleccionar noticia con titulo y subtitulo', 'disto')
);
parent::__construct('seleccion_subtitulo', esc_html__('Noticias: Noticia titulo + subtitulo [Estilo 1]', 'disto'), $widget_ops);
}
/*-----------------------------------------------------------------------------------*/
/* Display Widget
/*-----------------------------------------------------------------------------------*/
function widget($args, $instance) {
extract($args);
$featured_post = isset($instance["featured_post"]) ? $instance["featured_post"] : '';
$posts = null;
$args = array(
'p' => $featured_post,
'posts_per_page' => 1,
'orderby' => 'date',
'order' => 'DESC',
'post_type' => 'post',
'post_status' => 'publish',
'ignore_sticky_posts' => true
);
$posts_query = new WP_Query;
$posts = $posts_query->query($args);
$unique_block_id = rand(10000, 900000);
echo '<div class="jl_large_builder jl_nonav_margin jelly_homepage_builder jl-post-block-'.esc_html($unique_block_id).'">';
if (!empty($instance['titles'])) {?>
<div class="homepage_builder_title">
<h2 class="builder_title_home_page">
<?php echo esc_attr($instance["titles"]);?>
</h2>
</div>
<?php }?>
<?php
while ($posts_query->have_posts()) {
$post_id = get_the_ID();
$posts_query->the_post();
$categories = get_the_category(get_the_ID());
?>
<div class="jl_post_title_top jl_large_format">
<h3 class="image-post-title"><a href="<?php the_permalink(); ?>">
<?php the_title()?></a></h3>
</div>
<div class="post-entry-content">
<div class="post-entry-content-wrapper">
<div class="large_post_content">
<p>
<?php echo wp_trim_words( get_the_content(), 34, '...' );?>
</p>
<!-- <div class="jl_large_sw">
<?php echo esc_html__('Read More', 'disto')?>
<?php if(function_exists('disto_share_footer_link')){echo disto_share_footer_link(get_the_ID());}?>
</div> -->
</div>
</div>
</div>
<div class="box jl_grid_layout1 blog_large_post_style">
<?php if ( has_post_thumbnail()) {?>
<div class="jl_front_l_w">
<?php $slider_large_thumb_id = get_post_thumbnail_id();
$slider_large_image_header = wp_get_attachment_image_src( $slider_large_thumb_id, 'disto_slider_grid_large', true ); ?>
<?php if($slider_large_thumb_id){?>
<span class="image_grid_header_absolute" style="background-image: url('<?php echo esc_url($slider_large_image_header[0]); ?>')"></span>
<?php }else{?>
<span class="image_grid_header_absolute"></span>
<?php }?>
<?php if(get_theme_mod('disable_post_category') !=1){
$categories = get_the_category(get_the_ID());
if ($categories) {
echo '<span class="meta-category-small">';
foreach( $categories as $tag) {
$tag_link = get_category_link($tag->term_id);
$title_bg_Color = get_term_meta($tag->term_id, "category_color_options", true);
$title_reactions = get_term_meta($tag->term_id, "disto_cat_reactions", true);
if($title_reactions){}else{echo '<a class="post-category-color-text" style="background:'.$title_bg_Color.'" href="'.esc_url($tag_link).'">'.$tag->name.'</a>';}
}echo "</span>";}}?>
<?php echo disto_post_type();?>
</div>
<?php }?>
<div class="jl_post_title_top jl_large_format">
<?php echo disto_single_post_meta(get_the_ID()); ?>
</div>
</div>
<?php }
if($post_loadmore == 1){echo '<div class="jl-loadmore-btn-w">'.esc_html__('Load more', 'disto').'</div>';
wp_add_inline_script( 'disto-custom', "(function($){ $(document).ready(function() {'use strict'; var current_page_".esc_js($unique_block_id)." = 1; $('.jl-post-block-".esc_js($unique_block_id)." .jl_btn_load').click(function(e){ e.preventDefault(); e.stopPropagation(); var button = $(this), data = {'action': 'jl_post_more','query': ".json_encode( $posts_query->query_vars , true).",'page' : current_page_".esc_js($unique_block_id).",'cat' : '".esc_js($cats)."','jl_layout' : 'postslarge'}; var button_default_text = button.text(); $.ajax({ url : '".esc_url(site_url())."/wp-admin/admin-ajax.php', data : data, type : 'POST', beforeSend : function ( xhr ) {button.text('');button.addClass('btn-loading'); }, success : function( data ){ if( data ) { button.text( button_default_text ); button.removeClass('btn-loading'); $('.jl-post-block-".esc_js($unique_block_id)." .jl-loadmore-btn-w').before(data); current_page_".esc_js($unique_block_id)."++; if ( current_page_".esc_js($unique_block_id)." == ".esc_js($posts_query->max_num_pages)." ) button.remove(); }else {button.remove();}}});});});})(jQuery);");
}
wp_reset_postdata();
?>
</div>
<?php }
/*-----------------------------------------------------------------------------------*/
/* Update Widget
/*-----------------------------------------------------------------------------------*/
function update( $new_instance, $old_instance ) {
$instance = $old_instance;
$instance['featured_post'] = $new_instance['featured_post'];
return $instance;
}
/*-----------------------------------------------------------------------------------*/
/* Widget Settings (Displays the widget settings controls on the widget panel)
/*-----------------------------------------------------------------------------------*/
function form( $instance ) {?>
<h2>Elige una de las ultimas 20 noticias para establecerla como portada secundaria.</h2>
<div class="container">
<p>
<label>
<strong> <?php esc_html_e('Seleccionar noticia destacada:', 'disto');?></strong>
</label>
</p>
<p>
<select id="<?php echo esc_attr( $this->get_field_id( 'featured_post' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'featured_post' ) ); ?>">
<?php
$posts_args = array('posts_per_page' => 20,
'orderby' => 'date',
'order' => 'DESC',
'post_type' => 'post',
'post_status' => 'publish',
'ignore_sticky_posts' => true);
$last_entries = get_posts($posts_args);
foreach ($last_entries as $entry) {
?>
<option value="<?php echo $entry->ID; ?>" <?php if($instance['featured_post']==$entry->ID){ echo 'selected="selected"'; } ?> ><?php echo $entry->post_title; ?></option>
<?php
}
?>
</select>
</p>
</div>
<?php
}
}
?>
If I do var_dump ($instance) it shows me the following:
array(3) { ["featured_post"]=> string(4) "2970" ["so_sidebar_emulator_id"]=> string(29) "seleccion_subtitulo-421210000" ["option_name"]=> string(26) "widget_seleccion_subtitulo" }
I estimate that the following value tells me the ID of my widget instance:
["so_sidebar_emulator_id"] => string (29) "seleccion_subtitulo-421210000"
but I don't know how to invoke it from another widget, to get the information from it.
When obtaining that information, I try the following code to see what I get (I saw this code in the link that happens first):
$widget_name = 'seleccion_subtitulo';
$widget_instance = '421210000';
$widget_instances = get_option('widget_' . $widget_name);
$data = $widget_instances[$widget_instance];
var_dump($widget_instances);
If I do var_dump($data); I get NULL
If I do var_dump($widget_instances); I get:
array(1) { ["_multiwidget"]=> int(1) }

Lets rephrase your question into 2 parts:
"How to get a widgets settings"
"How to get the list of featured posts as used by that widget for purpose of excluding them from another list of posts"
1. Widget settings:
Widget settings are stored in the database in the wp_options table. If you do a search in phpmyadmin using widget% wildcard in the option name field you will see all widgets and their serialised data arrays.
You may note that they all have a subarray called "_multiwidget" which will contain the instances and their settings. In your example above you dumped this ["_multiwidget"]=> int(1)
This shows that nothing has yet been stored for that widget. The widget is not in a sidebar and/or no featured posts have been defined for that widget.
If the widget had been saved to a sidebar with some settings we would be seeing more details here.
Setup some widget instances so you can see the saved data structures. Then you will be able to see the widget details (either via phpmyadmin or by dumping as before)
2. Get list of featured posts out of a set of widget instances in order to exclude them from a query (in another widget)
For the widget you looking at we would probably see an array of settings one of which would be called "featured_post".
Once the widget has been dragged to some sidebars and has some featured posts defined in a few instances, you can then in your new widget do something like (pseudo code):
$widget_name = 'seleccion_subtitulo'; //if that's the widget name in the db.
$widget_settings = get_option('widget_' . $widget_name);
$featured_posts = array();
if (!empty($widget_settings)) {
if (!empty($widget_settings["_multiwidget"])) {
$instances = $widget_settings["_multiwidget"];
foreach ( $instances as $wid => $instance) {
$featured_posts[] = $instance['featured_post']; // if that is how it is stored in the widget details
}
}
}
You can then use https://developer.wordpress.org/reference/functions/get_posts/ and pass the array $featured_posts
in the argument array as
'exclude' => $featured_posts
Note that It is not necessary to know the 'instance' or the 'widget id' for what you say to want to achieve, one simply has to loop through all the instances for that widget.

Related

Wordpress custom admin page - Save Checkbox

I am trying to create a custom page in the administration panel to save some checkboxes somewhere in an array so that later I can show them in the wordpress theme. But the truth is I am limited, I do not know how to continue to save that information, nor do I know if it is better to use update_option () or update_post_meta () to save that configuration.
I have the following code in the theme's functions file:
function wpdocs_unsub_add_pages() {
add_menu_page(
__( 'Unsub List', 'textdomain' ),
__( 'Unsub Emails','textdomain' ),
'manage_options',
'categoriasrelacionadas',
'wpdocs_unsub_page_callback',
''
);
}
/**
* Display callback for the Unsub page.
*/
function wpdocs_unsub_page_callback() {
echo 'Unsubscribe Email List';
?>
<form method="post"
action="<?php echo esc_html('?page=categoriasrelacionadas'); ?>">
<?php $cat_argtos=array(
'orderby' => 'name',
'order' => 'ASC');
$categorias=get_categories($cat_argtos);
foreach($categorias as $categoria) {
$args=array(
'showposts' => -1,
'category__in' => array($categoria->term_id),
'caller_get_posts'=>1
);
$entradas=get_posts($args);
if ($entradas) {
echo '<p>' .$categoria->name.
'<input type="checkbox"
name="categorias"
value="'.$categoria->term_id.'">
</p>';
}
}
?>
<?php
wp_nonce_field( 'acme-settings-save', 'acme-custom-message' );
submit_button();
?>
</form>
<?php
...
}
What else could I do to save the information and show the selected boxes?

Add metabox if there is at least one post available

So I am building a WordPress Dashboard widget which will showcase all posts & pages where a Gutenberg Block is active.
The below code does it's job and pulls in an array based on get_posts().
Here is what I'm attempting to do:
Is there a way that I can invoke the add_action and the pardot_dashboard_widget() function ONLY if there is at least one or more posts in get_posts()? If it's an empty array, don't even bother creating the metabox.
Here is the code:
/**
* Pardot Widget for Dashboard
*/
function pardot_dashboard_widget()
{
add_meta_box(
'pardot_dashboard_meta_box',
esc_html__( 'Pardot Form Locations', 'wporg' ),
'pardot_dashboard_stats',
'dashboard',
'side', 'high'
);
}
add_action('wp_dashboard_setup', 'pardot_dashboard_widget');
function pardot_dashboard_stats()
{
$args = [
's' => '<!-- wp:acf/pardot-form ',
'sentence' => 1,
'post_type' => [
'post',
'page'
],
];
$pardot_form_query = get_posts($args);
if (!$pardot_form_query) {
echo 'There are no active pardot forms available.';
}
}
You can try assigning the meta to a variable, and using that in the if statement.
For example:
<?php
$price_list = get_post_meta( $post->ID, 'price_list_category1', true );
?>
And then...
<?php
if ($price_list == '') {
echo ' ';
} else {
echo '<h2>' . add your meta box conditions here . '</h2>';
}
?>

Wordpress - custom page template will not assign to page

First time building a Wordpress plugin. I create a page and I want to assign it a page template from my plugin folder. My code shows the Template name in the selectable list in the page editor, but it is not attached to the page. Nor manually attaching does anything to the page. But the path for the file is correct.
My code to create a page:
$page_path = "this-is-a-campaign-landing-page";
$page_title = 'This is a Campaigns Page Title';
$page_content = 'THIS IS A CAMPAIGNS PAGE BODY';
$page_check = get_page_by_title( $page_path );
$page = array(
'post_type' => 'page',
'post_title' => $page_title,
'post_content' => $page_content,
'post_status' => 'publish',
'post_author' => $author->ID,
'post_slug' => $page_path
);
if (!isset($page_check->ID) && !get_page_by_path($page_path)) {
$page_id = wp_insert_post($page);
if ($page_id) {
$template = '/home/vagrant/src/wptest/wp-content/plugins/pm/campaign_page.php';
update_post_meta($page_id, '_wp_page_template', $template );
}
}
Separately I add the template with add_filters
function add_campaign_template ($templates) {
$templates['campaign_page.php'] = 'Campaign Page';
return $templates;
}
add_filter ('theme_page_templates', 'add_campaign_template');
function set_campaign_template ($template) {
if ('campaign_page.php' == basename ($template)) {
$template = '/home/vagrant/src/wptest/wp-content/plugins/pm/campaign_page.php';
}
return $template;
}
add_filter ('page_template', 'set_campaign_template');
The page creates with no errors. When I view or edit the page, Default template is selected and my template appears in the list. Selecting it manually has no effect. What did I miss?
My simple page template:
<?php
/**
* Template Name: Campaign Page
*
* #package PM
*/
// get_header();
?>
<div id="primary" class="content-area">
<main id="main" class="site-main">
<section class="outer-categories">
<div class="container-fluid">
<div class="row text-justify">
THIS IS THE RIGHT PAGE TEMPLATE
THIS IS THE RIGHT PAGE TEMPLATE
THIS IS THE RIGHT PAGE TEMPLATE
THIS IS THE RIGHT PAGE TEMPLATE
<div class="col-lg-12">
<?php
while ( have_posts() ) :
the_post();
get_template_part( 'template-parts/content', 'page' );
endwhile; // End of the loop.
?>
</div>
</div>
</div>
</section>
</main><!-- #main -->
</div><!-- #primary -->
<?php
// get_footer();
Why is it not adding the template? With debug on I get no error in debug.log
Wow, long day.
Change this:
function set_campaign_template ($template) {
if ('campaign_page.php' == basename ($template)) {
$template = '/home/vagrant/src/wptest/wp-content/plugins/pm/campaign_page.php';
}
return $template;
}
add_filter ('page_template', 'set_campaign_template');
to this:
function set_campaign_template ($template) {
if ('campaign_page.php' == basename ($template)) {
$template = 'campaign_page.php'; <---- FIX
}
return $template;
}
add_filter ('page_template', 'set_campaign_template');

Add `active` class to li of current single page wordpress

Looking for your help and advices.
I have a list of links to single in Wordpress. I need to place class active only to li of active page.
Should be like on this image
But it is:
My wp-code:
<ul class="inline-list medium-6 large-4 skill-items">
<?php
$id = get_the_ID();
// echo $id;
$class;
$skills = new WP_Query( array(
'post_type' => 'skills',
'order' => 'ASC'
));
if ($skills->have_posts()) : while ($skills->have_posts()) : $skills->the_post();
// echo $post->ID;
if( $id == $post->ID) {$class = 'active';} else {$class = '';}
?>
<li class="<?php echo $class; ?>"><?php the_title(); ?></li>
<?php endwhile; endif; wp_reset_query();
?>
</ul>
That's not the proper way to do a menu in Wordpress. You should use wp_nav_menu instead of doing a custom WP_Query.
First, in functions.php add the following to register a new menu:
add_action('after_setup_theme', 'register_my_menu');
function register_my_menu() {
register_nav_menu('skills_menu', __( 'Skills menu', 'your-theme-name' ));
}
Then log in your administration, you will see that new menu placement under Appearance > Menu. Create a new menu for that placement - you have the possibility to automatically add top level new pages to this menu.
Then in your template add the following in order to display the menu:
<?php wp_nav_menu(array('theme_location' => 'skills_menu')); ?>
Wordpress will automatically handle the active class by adding current-menu-item to the appropriate li. No need for any filter for that.
Found an answer for my question using Javascript/jQuery
jQuery(document).ready(function($){
var pgurl = window.location.href;
$("ul.skill-items li").each(function(){
if($(this).find('a').attr("href") == pgurl || $(this).find('a').attr("href") == '' )
$(this).addClass("active");
})
});
pgurl contains your current url. After that for each item we are looking for anchor and its link. Then we are comapring those links, and if their are equal, we add class active to li
You may try this:
function my_alter_classes_on_li( $classes, $item ){
global $post;
if( in_array( $post->post_type, $classes ) ) $classes[] = 'current-menu-item';
return $classes;
}
add_filter( 'nav_menu_css_class', 'my_alter_classes_on_li', 10, 2 );

$post is null while in the loop

According to WP documentation this can't be happening but it is:
http://codex.wordpress.org/The_Loop
You can display other information about each post using the
appropriate Template Tags or (for advanced users) by accessing the
$post variable, which is set with the current post's information while
The Loop is running.
All following code examples use $post to access the current post but I can't. Even though it goes in the loop $post is null:
$args = array('post_type' => 'carousel_bootstrap', 'posts_per_page' => 10);
$loop = new WP_Query($args);
while ($loop->have_posts()) : $loop->the_post();
var_dump($post->ID);//=NULL
$title=the_title(null,null,false);
var_dump($title);//string(4) "NOPE"
....
endwhile;
wp_reset_postdata();
So either $post should not be null or the var_dump should not execute in the loop. I need to access this current post's custom fields but can't do it if $post is null. To make it more confusing; in the next line the $title variable is set to the current post's title.
How would I go about solving this? Using word press 3.6.1
[UPDATE]
I made a custom post called carousel, thought I'd use it to contain the html code for a twitter bootstrap carousel. In header I'm calling a function that checks if a custom carousel post exist with a certain name (provided by a custom value from the page).
In the header $post is the page, in the function checking the custom post the $post is null and when exiting the function and continuing in the header $post is the custom post (no longer the page).
Seemed like a good idea to do it this way when I started but looks like it can't be done this way.
The right way to get the post id in a custom WP_QUERY is: $loop->post->ID
$args = array('post_type' => 'carousel_bootstrap', 'posts_per_page' => 10);
$loop = new WP_Query($args);
global $post;
while ($loop->have_posts()) : $loop->the_post();
$loop->post->ID; //This is how you get the id $post will not work unless you
setup_postdata( $loop->post->ID );
print_r($post->ID); //now works.
endwhile;
wp_reset_postdata();
Got it doing what it does but think the code could use some improvement:
(added on blankslate)
In /wp-content/themes/blankslate/functions.php
//only using single carousel per page now
$vars=array('carouselHtml'=>'<div style="h'.
'eight:100px"><h1>Working, no Carousel</h1></div>',
'css'=>[],
'js'=>[]
);
function getInits(){
global $vars;
return $vars;
}
function setInits() {
global $post;
global $vars;
//see if the page specified a carousel (if value it's the title)
$carousel = get_post_meta($post->ID, 'carousel', true);
//collect all custom fields named "js" usually to fix screen
//re sizing like hiding images or big sliders
$scriptItems = get_post_meta($post->ID, 'js', false);
if ($scriptItems) {
foreach ($scriptItems as $item) {
$vars["js"][]=$item;
}
}
//load all custom fields of the page named css
//can be used for specific styles for the page
$cssItems = get_post_meta($post->ID, 'css', false);
if ($cssItems) {
foreach ($cssItems as $item) {
$vars["css"][]=$item;
}
}
//page has a custom field value named carousel
//it contains the title of the custom post that
//should contain the html, css and js
if ($carousel) {
//nice and intuitive query, gotta love it
$args = array('post_type' =>
'carousel_bootstrap',
'title' => $carousel,
'posts_per_page' => 100);
$loop = new WP_Query($args);
while ($loop->have_posts()) : $loop->the_post();
$title=the_title(null,null,false);
if($title===$carousel){
//found the custom carousel post, load html
//and add css js not to the page because css
//goes in the top and js goes in the bottom
$tmp=get_post_meta($post->ID, 'js', true);
if($tmp){$vars["js"][]=$tmp;}
$tmp=get_post_meta($post->ID, 'css', true);
if($tmp){$vars["css"][]=$tmp;}
$vars["carouselHtml"]=$post->post_content;
break;
}
endwhile;
//$post was the page at the start of the function
//now it could be the carousel post, not sure
//if the following is needed but works either
//with or without it
wp_reset_postdata();
}
}
//creating custom post named carousel
add_action('init', 'create_carousel_post_type');
function create_carousel_post_type() {
register_post_type( 'carousel_bootstrap', array(
'labels' => array(
'name' => __('Carousels'),
'singular_name' => __('Carousel')
),
'public' => false,
'has_archive' => true,
'rewrite' => array('slug' => 'carousels'),
'show_ui' => true,
'menu_position' => 5,
'supports' => array('title','editor','author',
'thumbnail','custom-fields','revisions')
));
}
In /wp-content/themes/blankslate/page.php
setInits();
get_header();
....
<body <?php body_class(); ?> id="top">
<!-- Carousel
based on http://getbootstrap.com/2.3.2/examples/carousel.html
================================================== -->
<div id="myCarousel" class="carousel slide">
<div class="carousel-inner">
<?php
$vars=getInits();
echo $vars["carouselHtml"];
?>
In /wp-content/themes/blankslate/header.php
$vars=getInits();
//output collected css
foreach ($vars["css"] as $item) {
echo '<link rel="stylesheet" type="text/css" href="'.$item.'" />';
}
The footer has same sort of code but for JavaScripts.
$args = array('post_type' => 'carousel_bootstrap', 'posts_per_page' => 10);
$loop = new WP_Query($args);
if($loop->have_posts()): while($loop->have_posts()): $loop->the_post();
//echo the title
the_title();
the_content();
//get the ID
$postId = get_the_ID();
endwhile;
endif;

Categories