Wordpress plugin admin_notices not displaying - wordpress

I'm trying to create a Wordpress plugin and I'm unable to display error messages using the admin_notices feature.
function gbrew_notice_no_api_key() {
$url = admin_url('admin.php') . '?page=api-key';
?>
<div class="notice-info notice">
<p><?php _e("Please set up your client ID and client secret from the <a href='{$url}'>API Key</a> page first."); ?></p>
</div>
<?php
}
function gbrew_setup_menu() {
# Add the main menu option
add_menu_page('Spruce Beer Dashboard', 'Spruce Beer', 'manage_options', 'spruce-beer', 'gbrew_dashboard');
# Add the sub menu item to manage API keys
add_submenu_page('spruce-beer', 'API Key', 'API Key', 'manage_options', 'api-key', 'gbrew_manage_api_key');
}
function gbrew_dashboard() {
$client_id = get_option('untappd_client_id');
$client_secret = get_option('untappd_client_secret');
echo "<h1>Spruce Beer</h1>";
if(!empty($client_id) && !empty($client_secret)) {
var_dump($client_id);
var_dump($client_secret);
} else {
add_action('admin_notices', 'gbrew_notice_no_api_key');
}
}
# Add the plugin to the sidebar menu
add_action('admin_menu', 'gbrew_setup_menu');

already I think in your first function you can do better to return the HTML and maybe that will fix your problem
function gbrew_notice_no_api_key() {
$url = admin_url('admin.php') . '?page=api-key';
return <<<HTML
<div class="notice-info notice">
<p>Please set up your client ID and client secret from the <a href='$url'>API Key</a> page first.</p>
</div>
HTML;
}

Your calling notices too late, they fire before admin_menu; try this
function gbrew_notice_no_api_key()
{
$client_id = get_option('untappd_client_id');
$client_secret = get_option('untappd_client_secret');
if (empty($client_id) && empty($client_secret)) {
$url = admin_url('admin.php') . '?page=api-key';
?>
<div class="notice notice-success is-dismissible">
<p><?php
_e("Please set up your client ID and client secret from the <a href='{$url}'>API Key</a> page first."); ?></p>
</div>
<?php
}
}
function gbrew_setup_menu()
{
# Add the main menu option
add_menu_page('Spruce Beer Dashboard', 'Spruce Beer', 'manage_options', 'spruce-beer', 'gbrew_dashboard');
# Add the sub menu item to manage API keys
add_submenu_page('spruce-beer', 'API Key', 'API Key', 'manage_options', 'api-key', 'gbrew_manage_api_key');
}
function gbrew_dashboard()
{
$client_id = get_option('untappd_client_id');
$client_secret = get_option('untappd_client_secret');
echo "<h1>Spruce Beer</h1>";
if ( ! empty($client_id) && ! empty($client_secret)) {
var_dump($client_id);
var_dump($client_secret);
} else {
echo "<p>No Api Key Exists";
}
}
# Add the plugin to the sidebar menu
add_action('admin_menu', 'gbrew_setup_menu');
add_action('admin_notices', 'gbrew_notice_no_api_key');
If your also running multisite, might be worth adding: add_action('network_admin_notices', 'gbrew_notice_no_api_key'); as well

It seems to me that the problem is in the gbrew_dashboard function.
function gbrew_dashboard() {
$client_id = get_option('untappd_client_id');
$client_secret = get_option('untappd_client_secret');
echo "<h1>Spruce Beer</h1>";
if(!empty($client_id) && !empty($client_secret)) {
var_dump($client_id);
var_dump($client_secret);
} else {
add_action('admin_notices', 'gbrew_notice_no_api_key');
}
}
In the else statement you add gbrew_notice_no_api_key to admin_notices, but the action is never called. Read this answer about how do_action and add_action work in tandem. In summary,
The do_action() function executes any code that's been hooked with add_action().
I think the simplest solution looks like this:
function gbrew_dashboard() {
$client_id = get_option('untappd_client_id');
$client_secret = get_option('untappd_client_secret');
echo "<h1>Spruce Beer</h1>";
if(!empty($client_id) && !empty($client_secret)) {
var_dump($client_id);
var_dump($client_secret);
} else {
do_action('admin_notices');
}
}
add_action('admin_notices', 'gbrew_notice_no_api_key');
Add gbrew_notice_no_api_key to the action no matter what, then call it with do_action.
You could use a custom action (optional)
However, keep in mind that if you call do_action('admin_notices'), your plugin will call every function hooked to admin_notices, even if they belong to other plugins.
If you are not OK with that, then you could add a custom action instead. Taking gbrew as a prefix to uniquely identify your own hooks, you could add a custom action that will be called only by your plugin. In that case, your code would look like this:
function gbrew_dashboard() {
$client_id = get_option('untappd_client_id');
$client_secret = get_option('untappd_client_secret');
echo "<h1>Spruce Beer</h1>";
if(!empty($client_id) && !empty($client_secret)) {
var_dump($client_id);
var_dump($client_secret);
} else {
// calling your custom action here!!!
do_action('gbrew_admin_notices');
}
}
add_action('gbrew_admin_notices', 'gbrew_notice_no_api_key');

Related

Allow contributors to upload images but not delete them

I enabled image uploads for contributors on my Wordpress site via the following code:
if ( current_user_can('contributor') && !current_user_can('upload_files') )
add_action('admin_init', 'allow_contributor_uploads');
function allow_contributor_uploads() {
$contributor = get_role('contributor');
$contributor->add_cap('upload_files');
}
It works great, but I also need to disallow them to delete the images they uploaded. Is there an easy way to do it? I know there's User Role Editor plugin, but I don't want to install it just for this.
You can use delete_attachment hook or pre_delete_attachment filter for that:
add_action('delete_attachment', 'wp66410923_prevent_delete_attachment', 11, 1);
function wp66410923_prevent_delete_attachment($postID)
{
if (current_user_can('contributor')) {
echo __('You can not delete attachments.');
die;
}
}
add_filter( 'pre_delete_attachment', 'wp66410923_filter_attachment_deletion', 10, 3 );
function wp66410923_filter_attachment_deletion( $delete, $post, $force_delete ){
if (current_user_can('contributor')) {
return false;
}
return true;
}

How to apply the "auto next post load" scroll on my website?

A newbie here...I am trying to apply a system that allows readers to "infinitely" scroll down to the next posts after finishing a single post so that they don't have to manually click them.
(Like this website does:
https://dancingastronaut.com/2020/12/maceo-plex-confronts-racism-and-diversity-in-latest-single-cinemax/)
I tried the “auto load next post” plugin, but it didn’t work on my theme :(.
I’m currently using the Amphibious theme developed by templatepocket.
https://wordpress.org/themes/amphibious/
This is the biggest part I’m having a struggle with, and I think my website is good to go once it’s applied. I hope someone can help me out here!
Thanks!
You would first need to edit your single post template, usually single.php, and add a trigger when a user scrolls past that point.
<?php $gpNextPost = get_next_post(); ?>
<div class="gp-infinite-scroll" style="display: none;"><?php echo $gpNextPost->ID; ?></div>
Then call an AJAX function to load next post's content and also replace the URL in the browser's address bar.
Here's a rough example:
function gp_infinite_scroll($pid){
if (is_single()) { ?>
<script type="text/javascript" >
jQuery(document).ready(function($) {
$(window).scroll(function() {
var footerPos = $('footer').last().position().top;
var pos = $(window).scrollTop();
if (pos+(screen.height*4) > footerPos) {
if ($(".gp-infinite-scroll").first().hasClass('working')) {
return false;
} else {
$(".gp-infinite-scroll").first().addClass('working');
}
var gpNextPostId = $(".gp-infinite-scroll").first().text();
var data = {
'action': 'gp_is',
'gpNextPostId': gpNextPostId
};
$.post(ajaxurl, data, function(response) {
$(".gp-infinite-scroll").first().replaceWith(response);
}, 'html');
}
// Update new URL
var currUrl = $(".gp-post-header").first().attr("url");
var currTitle = $(".gp-post-header").first().attr("title");
if ($(".gp-post-header").length > 1 && history.pushState) {
for (var i=0; i<$(".gp-post-header").length; i++) {
var trigger = $(".gp-post-header").eq(i).next().position().top;
if (pos+(screen.height/2) >= trigger) {
currUrl = $(".gp-post-header").eq(i).attr("url");
currTitle = $(".gp-post-header").eq(i).attr("title");
}
}
}
if (location.href != currUrl) {
history.pushState({}, currTitle, currUrl);
}
});
});
</script>
<?php }
}
add_action( 'wp_head', 'gp_infinite_scroll' );
function gp_infinite_scroll_callback() {
if (isset($_POST['gpNextPostId']) && $_POST['gpNextPostId']) {
$the_query = new WP_Query(array('p'=>$_POST['gpNextPostId']));
if ( $the_query->have_posts() ) {
while ( $the_query->have_posts() ) {
$the_query->the_post();
// Change to your own Single Post template file
get_template_part( 'template-parts/content', 'single' );
}
}
wp_reset_postdata();
}
wp_die();
}
add_action( 'wp_ajax_gp_is', 'gp_infinite_scroll_callback' );
add_action( 'wp_ajax_nopriv_gp_is', 'gp_infinite_scroll_callback' );
This code is untested but it should get you going. If the above seems too much for you then you migh try some of the related plugins.

Override wordpress routing / url rewriting?

I would like to serve different content based on the URL.
I started with a custom page setup via a custom template but I am open to something else.
The main goal is to have one PHP page that can serve different contents programmatically based on the URL.
For example:
https://some-url.com/my-plugin/ -> run my page
https://some-url.com/my-plugin/foo/ -> run my page
https://some-url.com/my-plugin/foo2/abc/ -> run my page
etc...
I have been looking at add_rewrite_rule, add_rewrite_tag, flush_rewrite_rules and WP_Rewrite API but I am getting confused about which one I should use?
I found an example here but I could not make it work, I get 404s, any idea why?:
/*
Plugin Name: Products Plugin
Plugin URI: http://clivern.com/
Description: Register URL rules for our products
Version: 1.0
Author: Clivern
Author URI: http://clivern.com
License: MIT
*/
function products_plugin_activate() {
products_plugin_rules();
flush_rewrite_rules();
}
function products_plugin_deactivate() {
flush_rewrite_rules();
}
function products_plugin_rules() {
add_rewrite_rule('products/?([^/]*)', 'index.php?pagename=products&product_id=$matches[1]', 'top');
}
function products_plugin_query_vars($vars) {
$vars[] = 'product_id';
return $vars;
}
function products_plugin_display() {
$products_page = get_query_var('pagename');
$product_id = get_query_var('product_id');
if ('products' == $products_page && '' == $product_id):
//show all products
exit;
elseif ('products' == $products_page && '' != $product_id):
//show product page
exit;
endif;
}
//register activation function
register_activation_hook(__FILE__, 'products_plugin_activate');
//register deactivation function
register_deactivation_hook(__FILE__, 'products_plugin_deactivate');
//add rewrite rules in case another plugin flushes rules
add_action('init', 'products_plugin_rules');
//add plugin query vars (product_id) to wordpress
add_filter('query_vars', 'products_plugin_query_vars');
//register plugin custom pages display
add_filter('template_redirect', 'products_plugin_display');
First of all, make sure your pretty permalinks are enabled, in this case the option "Plain" in Settings - Permalinks should be unselected:
Select one of these options to enable pretty permalinks
You can check whether pretty permalinks are enabled in the code like so:
function is_enabled_pretty_permalinks() {
return !empty( get_option( 'permalink_structure' ) );
}
if ( is_enabled_pretty_permalinks() ) {
echo 'Pretty permalinks enabled';
}
Next add a new rewrite rule:
function add_my_rewrite_rule() {
$page_slug = 'products'; // slug of the page you want to be shown to
$param = 'do'; // param name you want to handle on the page
add_rewrite_rule('my-plugin/?([^/]*)', 'index.php?pagename=' . $page_slug . '&' . $param . '=$matches[1]', 'top');
}
add_action('init', 'add_my_rewrite_rule');
Add your parameter to query vars so you will be able to handle it on the page:
function add_my_query_vars($vars) {
$vars[] = 'do'; // param name you want to handle on the page
return $vars;
}
add_filter('query_vars', 'add_my_query_vars');
Then you can access your query var do in the page template or in a shortcode, for example:
function my_plugin_shortcode_handler( $atts ){
$do = get_query_var( 'do' );
if ( $do === 'this' ) {
return 'do this';
} else {
return 'do that';
}
}
add_shortcode( 'myshortcode', 'my_plugin_shortcode_handler' );
Then place the shortcode to the content via Gutenberg.
Check out the links:
https://some-url.com/my-plugin/this/ - outputs "do this"
https://some-url.com/my-plugin/that/ - outputs "do that".
This can be solved by using query params. Like you mentioned you have set up custom page via a custom template. You can read the URL and check for the parameters and based on that you can send data from the PHP template page.
e.g,
function cleanTheInput($data) {
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data);
$data = htmlentities($data);
return $data;
}
if (isset($_GET['page_url'])) {
$theUrl = cleanTheInput($_GET['page_url']);
}
if($theUrl == 266)){
// data for https://some-url.com/?page_url=266
}
if($theUrl == 366)){
// data for https://some-url.com/?page_url=366
}

woocommerce: Show login / register form without account information

I want to show the woocommerce login and register page but without the options when an user is logged in.
In former versions you could use a shortcode but now you have to use [my_account]. When an user is logged in, he sees his account information.
Are there any hooks / functions to show the register and login forms?
Thanks
Maddin
i know, the question is a little bit older...
Try this:
add_shortcode('woo-login', 'my_login');
function my_login() {
if (is_user_logged_in()) {
// Do what you want...
} else {
ob_start();
echo '<div class="woocommerce">';
wc_get_template('myaccount/form-login.php');
echo '</div>';
return ob_get_clean();
}
}
Although Oliver's code works, it's now missing a couple Woocommerce styles and subsequent JS that WP uses to render the form correctly. Perhaps they added these since the answer was posted. This snippet adds relevent <body> classes if the woo-login shortcode is used.
/**
* Shortcode - Render Woocommerce login/register form
**/
add_shortcode('woo-login', function() {
if (is_user_logged_in()) {
} else {
ob_start();
echo '<div class="woocommerce">';
wc_get_template('myaccount/form-login.php');
echo '</div>';
return ob_get_clean();
}
});
/**
* Mitigate theme before render
**/
add_action('template_redirect', function() {
global $post;
if (has_shortcode($post->post_content, 'woo-login')) {
// Add Woocommerce body classes
add_filter('body_class', function($body_classes) {
$body_classes[] = 'woocommerce-account';
$body_classes[] = 'woocommerce-page';
return $body_classes;
});
}
});
Heres a link to the Gist: https://gist.github.com/dhaupin/7a5d429de5be0d623add58edad51b479

Handling $_POST in Wordpress

How can i handle $_POST in wordpress? I am creating a custom "send" button which displays in my plugin's admin panel. When pressing the "send" button, mails have to be send to the subscribers. But how can this be done? How can i handle the custom "send" $_POST button?
I have tried to do it with init, but with no succes:
add_action('manage_nieuwsbrief_posts_custom_column', 'nwsbrf_custom_nieuwsbrief_column', 10, 2);
function nwsbrf_custom_nieuwsbrief_column($column, $post_id) {
global $wpdb;
$getcategories = $wpdb->get_results( $wpdb->prepare("SELECT * FROM wp_nwsbrf_couple INNER JOIN wp_nwsbrf_categories WHERE wp_nwsbrf_couple.category_id = wp_nwsbrf_categories.category_id AND ID = %d", $post_id) );
foreach ($getcategories as $categorie) {
switch ($column) {
case 'cat':
echo $categorie->category_name;
break;
}
}
switch ($column){
case 'send';
echo '<input type="submit" class="button button-secondary button-small" name="send_post" value="Verzenden">';
break;
}
}
add_action('init', 'process_send_post');
function process_send_post(){
if($_POST['send_post']) {
echo 'Postelijk';
}
}
You are looking for the isset() function in PHP:
if(isset($_POST['send_post'])) {
// handle your form
}
In your code, try not to use a switch for single cases, use an if instead, makes your code more readable and compact.
Also you can get the category of a post using the built-in Wordpress function get_the_category($id). No need to execute a DB query yourself

Resources