Add metabox if there is at least one post available - php

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>';
}
?>

Related

Display my block in a conditional-logic way

I use this plugin to filter my searches.
in this section they explain how to create my own custom block.
function prefix_register_block( $blocks ) {
// 'my_block' corresponds to the block slug.
$blocks['my_block'] = [
'name' => __( 'My Block', 'text-domain' ),
'render_callback' => 'prefix_my_block_render',
];
return $blocks;
}
add_filter( 'wp_grid_builder/blocks', 'prefix_register_block', 10, 1 );
// The render callback function allows to output content in cards.
function prefix_my_block_render() {
// Get current post, term, or user object.
$post = wpgb_get_post();
// Output the post title.
echo '<h3>' . esc_html( $post->post_title ) . '</h3>';
}
the code looks simple, so it's a matter of common sense and a php expert can figure it out quickly.
I would like to add a line to say
if slug or term "office" exist in the property-type taxnonomy
then Output the post title
(which I will of course edit to display custom fields)
but how to make conditional logic possible?
thank you for your patience, I do my best to understand the correct technique
I'm not a WP guru, but I think it should be this simple. Set up an array of slugs you want to affect in this way and then iterate through them in a foreach loop
function prefix_register_block( $blocks ) {
$slugs = ['office','somethingelse'];
foreach($slugs as $slug) {
$blocks[$slug] = [
'name' => __( ucwords($slug), 'text-domain' ),
'render_callback' => 'prefix_my_block_render',
];
}
return $blocks;
}
add_filter( 'wp_grid_builder/blocks', 'prefix_register_block', 10, 1 );
// The render callback function allows to output content in cards.
function prefix_my_block_render() {
// Get current post, term, or user object.
$post = wpgb_get_post();
// Output the post title.
echo '<h3>' . esc_html( $post->post_title ) . '</h3>';
}

"No block type exists" when trying to create ACF block for Gutenberg

I have a new block that I'm trying to init which is called hero. At the moment, I'm trying to assign an ACF field group to that block, but currently seeing this in the WordPress backend:
I have created the block and registered the block type, but unable to see where things are not working?
Here is my approach:
/acf-blocks/blocks.php
<?php
function register_acf_block_types() {
$hero = array(
'name' => 'hero',
'title' => __('Hero'),
'description' => __(''),
'render_callback' => 'block_render',
'category' => 'formatting',
'icon' => 'admin-comments',
'keywords' => array( 'hero' ),
);
}
$blocks = [
$hero
];
return $blocks;
// Check if function exists, and hook into setup
if( function_exists('acf_register_block_type') ) {
add_action('acf/init', 'register_acf_block_types');
}
?>
/acf-blocks/render.php
<?php
/**
* This is the callback that renders the block.
*/
function block_render( $block ) {
// convert name ("acf/testimonial") into path friendly slug ("testimonial")
$slug = str_replace('acf/', '', $block['name']);
// include a template part from within the "template-parts/block" folder
if( file_exists( get_theme_file_path("/template-parts/block/content-{$slug}.php") ) ) {
include( get_theme_file_path("/template-parts/block/content-{$slug}.php") );
}
}
?>
/acf-blocks/functions.php
<?php
function block_acf_init(){
$blocks = require(__DIR__.'/inc/acf-blocks/blocks.php');
foreach($blocks as $block) {
acf_register_block($block);
}
}
?>
/template-parts/block/hero.php
<?php
/*
* Block Name: hero
*/
?>
Here is my folder structure:
theme
inc
acf-blocks
blocks.php
functions.php
render.php
template-parts
blocks
hero.php
Change the ACF function in your foreach loop (in /acf-blocks/functions.php) to:
foreach($blocks as $block) {
acf_register_block_type($block);
}

Adding custom field through functions.php

I'm trying to add a custom field just below the price in my Woocommerce theme. I was able to add simple html by using:
add_action( 'woocommerce_before_add_to_cart_form', 'SomeName' );
function SomeName() {
echo '<p>Some Text Here</p>';
}
But what I want to do is add a custom field key instead. I'm using this code for placing custom fields:
<?php
$naslov = get_post_meta($post->ID, 'Naslov', true);
if ($naslov) { ?>
<h2 class="single-naslov-kat"><? echo $naslov; ?></h2>
<?php
} else {
// do nothing;
}
?>
The code works great when I add it to content-single-product.php theme file. But I can't add it below the price through that file. And I have no idea how to incorporate it through functions.php.
If you have any other suggestions on how I might be able to add custom text below the price for each specific product that's ok too.
Any help would be greatly appreciated.
In your themes functions.php add the code,
//create custom field
function cfwc_create_custom_field() {
$args = array(
'id' => 'custom_field',
'label' => __( 'Custom Field', 'cfwc' ),
'class' => 'cfwc-custom-field',
'desc_tip' => true,
'description' => __( 'Enter Custom Field Description.', 'ctwc' ),
);
woocommerce_wp_text_input( $args );
}
add_action( 'woocommerce_product_options_general_product_data', 'cfwc_create_custom_field' );
// save custom field
function cfwc_save_custom_field( $post_id ) {
$link = wc_get_product( $post_id );
$title = isset( $_POST['custom_field'] ) ? $_POST['custom_field'] : '';
$link->update_meta_data( 'custom_field', sanitize_text_field( $title ) );
$link->save();
}
add_action( 'woocommerce_process_product_meta', 'cfwc_save_custom_field' );
// display custom field in single.php page
add_action('woocommerce_before_add_to_cart_form','cmk_additional_button');
function cmk_additional_button() {
global $product;
$custom_field = $product->get_meta('custom_field');
if(!empty($custom_field)) {
echo "<a href='$custom_field' target='_blank'><button type='button' class='button alt'>Custom Field</button></a>";
}
}

reset custom field when navigation menu is deleted in WordPress

I have a custom field associated with all posts and pages. It's a dropdown of all the navigation menus.
here is how I'm populating the custom field drop-down: (the field name is custom_menu...)
function acf_load_menu_field_choices( $field ) {
// reset choices
$field['choices'] = array();
$menus = get_terms( 'nav_menu', array( 'hide_empty' => true ) );
$blank_list = json_encode(array( "name" => "Select Menu", "slug" => ""));
$blank_list = json_decode($blank_list);
array_unshift($menus, $blank_list);
foreach ( $menus as $val ) {
$value = $val->slug;
$label = $val->name;
$field['choices'][ $value ] = $label;
}
// return the field
return $field;
}
add_filter('acf/load_field/name=custom_menu', 'acf_load_menu_field_choices');
Here is a common menu location that I'm using on each page:
function register_custom_menu() { //function to register new menu
register_nav_menu('custom-menu',__( 'Custom Menu' ));
}
add_action( 'init', 'register_custom_menu' );
And then I'm assigning a menu dynamically to the location custom-menu based on the custom field menu on each page.
and here is the function the fires on each page when it's loaded:
add_action("wp_ajax_load_custom_menu", "load_custom_menu");
add_action("wp_ajax_nopriv_load_custom_menu", "load_custom_menu");
function load_custom_menu(){
$post_id = $_POST['page_id'];
$page_custom_menu = get_field('custom_menu', $post_id);
if(empty($page_custom_menu) || $page_custom_menu == "primary") return;
$locations = get_theme_mod( 'nav_menu_locations' );
if(!empty($locations)) {
foreach($locations as $locationId => $menuValue) {
if($locationId == "custom-menu") $menu = get_term_by('slug', $page_custom_menu, 'nav_menu');
if(isset($menu)) { $locations[$locationId] = $menu->term_id; }
}
}
set_theme_mod('nav_menu_locations', $locations);
wp_nav_menu( array(
'theme_location' => 'custom-menu',
'menu_id' => 'primary-menu',
'menu_class' => 'main-nav underline-decoration l-to-r-line level-arrows-on outside-item-remove-margin',
'container' => false
)
);
wp_die();
}
This ajax function fires on ready event and recieves a POST value called page_id. This function checks the custom field value of the given page_id for custom-menu and assign that menu to the menu location called custom-menu.
Here's my JavaScript in case you need to have a look on it:
jQuery(document).ready( function($){
let customMenu;
let page_id = script_vars.postID;
$.post(dtLocal.ajaxurl, { action: "load_custom_menu", page_id: page_id }, resp => customMenu = resp);
$(window).scroll(() => {
if(customMenu !== "0"){
$("#phantom .main-nav").remove();
$("#phantom .menu-box").html(customMenu);
}
})
})
This is how my code is working, And everything works fine up to this point.
Now here is the problem
Whenever I delete a Navigation menu from Appearence>Menus>Delete Menu My custom Menu starts behaving unexpectedly because the custom field value is still pointing to the deleted Menu.
What I want to do here is, I want to Delete the Custom Field whenever a menu is deleted. First I want to get the slug of a deleted menu and then find the custom field value with that slug and then finally, delete or reset that custom field.
Menus in WordPress are just terms in a taxonomy. So you can use all of the term hooks.
In particular the pre_delete_term hook.
add_action( 'pre_delete_term', 'my_func' );
function my_func($term, $taxonomy){
// Check the taxonomy is really 'menu', then check term
}
You are looking for action wp_delete_nav_menu that will take one argument - menu id. The problem that at that point your nav menu will be deleted, so you won't be able to take it slug.
If it is possible that you can store nav menu ID instead of slug, that would simplify things greatly.
In acf_load_menu_field_choices replace:
foreach ( $menus as $val ) {
$value = $val->term_id;
$label = $val->name;
$field['choices'][ $value ] = $label;
}
And in load_custom_menu:
$page_custom_menu = get_field('custom_menu', $post_id);
if(empty($page_custom_menu) || $page_custom_menu == /* Should be your primary menu ID */) return;
$locations = get_theme_mod( 'nav_menu_locations' );
if(!empty($locations)) {
foreach($locations as $locationId => $menuValue) {
if($locationId == "custom-menu") $menu = get_term_by('id', $page_custom_menu, 'nav_menu');
if(isset($menu)) { $locations[$locationId] = $menu->term_id; }
}
}
After those changes you will need to rewrite custom_menu in all posts\pages.
After that, following function will remove all related fields when you delete menu. It has been tested only on typical ACF field (string) instead of custom, but should work just fine with your code as well.
add_action('wp_delete_nav_menu', 'delete_all_acf_fields_with_menu', 10, 1);
function delete_all_acf_fields_with_menu($term_id) {
$args = array(
'post_type' => array('post', 'page'),
'posts_per_page' => -1,
'meta_key' => 'custom_menu',
'meta_value' => $term_id,
);
$posts = get_posts($args);
if( $posts ) {
foreach( $posts as $p ) {
delete_field('custom_menu', $p->ID);
}
}
}

Custom Post Type active link - Wordpress

I have a custom post type named 'schools' on my wordpress site. When you hover over the schools tab a list of schools are shown in the submenu. These are pages I created with different school names. Now when you click on one of the school pages I have a sidebar with all the schools so they can naviate through the different schools from the sidebar rather than using the menu.
I have the sidebar being populated using the following snippet.
while( $shools_loop->have_posts() ) : $schools_loop->the_post();
$content .= '<li class="schools-list">';
$content .= ''.get_the_title().'';
$content .= '</li>';
endwhile;
This works perfectly and I can navigate through all the schools without a problem from my sidebar. I'm trying to find a way to when I view a school via the sidebar or nav that when I'm on the active page I create some css styling to the li of the ACTIVE page. I've already figured out how to do this with the nav menu. But need help on the sidebar menu. Since the sidebar list menu is being populated I'm unsure how to check if the custom post type link is active and corresponds to the /schools/get-title page.
I found something like this online and I've tried editing it, but I'm not sure if this only works for nav menu
add_action( 'init', 'create_post_type' );
function create_post_type() {
register_post_type( 'services',
array(
'labels' => array(
'name' => __( 'Services' ),
'singular_name' => __( 'Services' )
),
'public' => true,
'has_archive' => true,
'rewrite' => array('slug' => 'services'),
)
);
}
// highlight active custom post page in nav
add_filter( 'nav_menu_css_class', 'namespace_menu_classes', 10, 2 );
function namespace_menu_classes( $classes , $item ){
if ( get_post_type() == 'services' ) {
// remove unwanted classes if found
$classes = str_replace( 'current_page_parent', '', $classes );
// find the url you want and add the class you want
if ( $item->url == 'services/physical-therapy-services/' ) {
$classes = str_replace( 'menu-item', 'menu-item current_page_parent', $classes );
}
}
return $classes;
}
Basically need to find a way to check whether the custom post type is active or not.
You can set a global variable in the main template page with the ID of the current post and then in your sidebar loop, you can retrieve that global variable and compare it with current post's ID by using get_the_ID() function and then perform the necessary actions.
Example:
single-cpt.php
// Inside the loop
global $post_id = get_the_ID();
sidebar-cpt.php
$post_id = isset($_GLOBALS['post_id']) ? $_GLOBALS['post_id'] : 0;
while( $shools_loop->have_posts() ) : $schools_loop->the_post();
if($post_id == get_the_ID()){
// This is the active link
$content .= '<li class="schools-list selected">';
} else {
$content .= '<li class="schools-list">';
}
$content .= ''.get_the_title().'';
$content .= '</li>';
endwhile;

Categories