I am extending an existing plugin. The author of said plugin provided an action hook in the main class of their plugin:
public static function instance() {
if ( ! isset( self::$instance ) && ! (self::$instance instanceof self) ) {
self::$instance = new self();
self::$instance->setup_constants();
self::$instance->actions = array();
self::$instance->filters = array();
add_action( 'plugins_loaded', array( self::$instance, 'load_textdomain' ) );
add_action( 'bp_loaded', array( self::$instance, 'bp_include' ) );
global $ap_classes;
$ap_classes = array();
self::$instance->includes();
self::$instance->ajax_hooks();
self::$instance->site_include();
self::$instance->anspress_forms = new AnsPress_Process_Form();
self::$instance->anspress_query_filter = new AnsPress_Query_Filter();
self::$instance->anspress_cpt = new AnsPress_PostTypes();
self::$instance->anspress_reputation = new AP_Reputation();
/*
* ACTION: anspress_loaded
* Hooks for extension to load their codes after AnsPress is leaded
*/
do_action( 'anspress_loaded' );
self::$instance->setup_hooks();
}
return self::$instance;
}
I am trying to use this hook to run my code, but it isn't working. I'm using has_action() to try and see if it is running of this action hook, but it's not.
if(has_action('anspress_loaded', 'find_do_for_anspress')){
echo 'fd is hooked';
} else {
echo 'NOT WORKING CORRECTLY';
}
The code above is at the bottom of the main plugin's php file, outside of any classes. Any idea how to troubleshoot this??
Related
I want to speed up the loading of my wordpress website. I write a simple plugin that will add the defer attribute to some scripts that are used by the custom theme I've installed. I'm facing the issue that the site is locked to the preloader screen and no error is present in the chrome dev console nor xdebug error are showed. Maybe I'm doing something wrong, I don't know, is possible that the main javascript file that is responsable to load the theme are not loaded also if isn't present in the array of the scripts that are processed to add the defer attribute?
All the scripts are dependencies of the theme and are using jQuery that is not part of the list.
Any help will be appreciated.
class WP_scriptDefer {
private $scripts = [
'bootstrap.min.js',
'lazyload.min.js',
'viewportchecker.min.js',
'universal-parallax.min.js',
];
public function __construct()
{
$this->init();
}
public function init()
{
add_filter( 'script_loader_tag', [$this, 'deferScripts'], 10 );
}
public function deferScripts()
{
foreach( $this->scripts as $script ){
if( true == strpos($tag, $script) ){
return str_replace('src', 'defer="defer" src', $tag);
}
}
}
}
new WP_scriptDefer;
I edit your class, check it please:
class WP_scriptDefer
{
private $scripts = [
'bootstrap.min.js',
'lazyload.min.js',
'viewportchecker.min.js',
'universal-parallax.min.js',
];
public function __construct()
{
$this->init();
}
public function init()
{
add_filter('script_loader_tag', [ $this, 'deferScripts'], 10, 3);
}
public function deferScripts( $tag, $handle, $src )
{
foreach( $this->scripts as $script ){
if( true === strpos($tag, $script) ){
return str_replace('src', 'defer="defer" src', $tag);
}
}
return $tag;
}
}
new WP_scriptDefer;
After a day and also thanks to the suggestion of Dmitry I've found the correct way to let the plugin work. The array scripts needs to contain the names assigned inside the wp_enqueue_script() of each script and not the file name. This isn't very clear over the web because usually this filter is applied directly inside the function.php of a theme.
Here is the full working code:
<?php
class WP_deferScripts {
private $defer_scripts = [
'bootstrap',
'lazyload',
'swiper',
];
public function __construct()
{
add_filter( 'script_loader_tag', [$this, 'deferScripts'], 10, 2);
}
public function deferScripts( string $tag, string $handle ) : string
{
#var_dump($handle, $tag);
foreach( $this->defet_scripts as $script ){
if( $script === $handle ){
return str_replace('src', 'defer="defer" src', $tag);
}
}
return $tag;
}
}
?>
i'm trying to make a plugin for WordPress, which is has got an admin section for some basic settings, and also registers some shortcode to display some HTML, which is basically a form.
Here is my main plugin file, plugins/my-plugin/my-plugin.php:
/**
* Plugin Name: Pathway
* Plugin URI: http://www.martynleeball.com/
* Description: Pathway integration.
* Version: 1.0
* Author: Martyn Lee Ball
* Author URI: https://www.martynleeball.com/
**/
define('PATHWAY_VERSION', '0.0.8');
define('PATHWAY_AUTHOR', 'Martyn Lee Ball');
define('PATHWAY__MINIMUM_WP_VERSION', '4.*');
define('PATHWAY_CONTACT', 'martynleeball#gmail.com');
add_action(
'plugins_loaded',
array ( Pathway::get_instance(), 'plugin_setup' )
);
class Pathway
{
protected static $instance = NULL;
public $plugin_url = '';
private $cpt = 'post'; # Adjust the CPT
public function __construct() {}
public static function get_instance()
{
NULL === self::$instance and self::$instance = new self;
return self::$instance;
}
public function plugin_setup()
{
$this->plugin_url = '';
add_action( 'wp_enqueue_scripts', array( $this, 'enqueue' ) );
// if (is_admin()) {
//
// require_once( $this->plugin_url . 'admin/index.php' );
//
// register_activation_hook( __FILE__, 'install' );
//
// return;
// }
add_shortcode( 'pathway', array($this, 'shortcode'));
add_action( 'wp_ajax_ajax_login', array( $this, 'ajax_login' ) );
add_action( 'wp_ajax_nopriv_ajax_login', array( $this, 'ajax_login' ) );
add_action( 'wp_ajax_ajax_register', array( $this, 'ajax_register' ) );
add_action( 'wp_ajax_nopriv_ajax_register', array( $this, 'ajax_register' ) );
}
public function enqueue()
{
wp_enqueue_script( 'vuejs', 'https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js' );
wp_enqueue_script(
'ajax-handle-form',
"{$this->plugin_url}/wp-content/plugins/pathway/frontend/js/scripts.js"
);
wp_localize_script(
'ajax-handle-form',
'wp_ajax',
array(
'ajaxurl' => admin_url( 'admin-ajax.php' ),
'ajaxnonce' => wp_create_nonce( 'ajax_post_validation' )
)
);
}
public function ajax_login()
{
echo 'login';exit;
}
public function ajax_register()
{
echo 'register';exit;
}
public function shortcode()
{
if (!isset($_SESSION['pathway_login'])) {
self::view('forms/login');
}
}
public static function view( $name, array $args = array() ) {
foreach ( $args AS $key => $val ) {
$$key = $val;
}
// $file = $this->plugin_url . 'views/'. $name . '.php';
$file = 'views/'. $name . '.php';
include( $file );
}
}
Please correct me if i'm going wrong somewhere, there's so many mixed guides online showing different ways. Within this file i'm basically:
Adding my scripts and assigning the PHP values.
I would be then starting the admin section however has to comment this out for the AJAX call, this is my issue.
Registering my shortcode.
Adding the actions for the AJAX form submit.
Obviously my issue is that when I hit the is_admin from the AJAX call it is returning true, when it should be false as an public visitor can submit this form. The wp_ajax_nopriv action doesn't appear to work which would solve the issue, this is probably due to me being logged into WordPress.
I have tried logging out of WordPress but the is_admin still returns true!
Can someone advise?
is_admin will return true on all ajax calls.
It is not actually a useful function to check the user as it checks the uri rather than the user details, i.e. if on a admin page = true, if not false.
Now I was a little confused about your question here, it appears you want the is_admin to return false if its actually an ajax call?
if ( is_admin() && ! wp_doing_ajax() ) {}
It will return false on ajax calls.
If you are checking there is an "admin" logged in, as in can edit posts, see the other capabilities here
if ( current_user_can( 'edit_post' ) ) {}
The no_priv hook will not work when logged in, its not called.
I've used this plugin for adding specific templates for page.
class PageTemplater {
protected $plugin_slug;
private static $instance;
protected $templates;
public static function get_instance() {
if( null == self::$instance ) {
self::$instance = new PageTemplater();
}
return self::$instance;
}
private function __construct() {
$this->templates = array();
add_filter('page_attributes_dropdown_pages_args', array($this, 'register_project_templates'));
// add_filter('wp_insert_post_data', array($this, 'register_project_templates'));
add_filter('template_include', array($this, 'view_project_template'));
$this->templates = array(
'page-json.php' => 'JSON list',
);
}
public function register_project_templates( $atts ) {
// Create the key used for the themes cache
$cache_key = 'page_templates-' . md5( get_theme_root_uri() . '/' . get_stylesheet() );
// Retrieve the cache list.
// If it doesn't exist, or it's empty prepare an array
$templates = wp_get_theme()->get_page_templates();
if ( empty( $templates ) ) {
$templates = array();
}
// New cache, therefore remove the old one
wp_cache_delete( $cache_key , 'themes');
// Now add our template to the list of templates by merging our templates
// with the existing templates array from the cache.
$templates = array_merge( $templates, $this->templates );
// Add the modified cache to allow WordPress to pick it up for listing
// available templates
wp_cache_add( $cache_key, $templates, 'themes', 1800 );
return $atts;
}
/**
* Checks if the template is assigned to the page
*/
public function view_project_template( $template ) {
global $post;
if (!isset($this->templates[get_post_meta( $post->ID, '_wp_page_template', true)])) {
}
$file = plugin_dir_path(__FILE__) . get_post_meta($post->ID, '_wp_page_template', true);
// Just to be safe, we check if the file exists first
if (file_exists($file)) {
return $file;
} else {
echo $file;
}
return $template;
}
}
add_action( 'plugins_loaded', array( 'PageTemplater', 'get_instance' ) );
But when I've have updated a WordPress to 4.7 page template options had stopped to show. Maybe I use some deprecated functions?
Please help.
Fixed code:
// Add a filter to the attributes metabox to inject template into the cache.
if ( version_compare( floatval( get_bloginfo( 'version' ) ), '4.7', '<' ) ) {
// 4.6 and older
add_filter(
'page_attributes_dropdown_pages_args',
array( $this, 'register_project_templates' )
);
} else {
// Add a filter to the wp 4.7 version attributes metabox
add_filter(
'theme_page_templates', array( $this, 'add_new_template' )
);
}
/**
* Adds our template to the page dropdown for v4.7+
*
*/
public function add_new_template( $posts_templates ) {
$posts_templates = array_merge( $posts_templates, $this->templates );
return $posts_templates;
}
source: http://www.wpexplorer.com/wordpress-page-templates-plugin/
I am extending someone else's plugin. He has an action hook in the function he uses to initialize the plugin. It doesn't matter if I put echo nl2br("this is located OVER the do action anspress loaded. \n"); BELOW or ABOVE the line do_action('anspress_loaded'); - the line always get's echo'd out ABOVE another line I have being echo'd inside the other code loaded on that hook. Why is this? It's probably not TREMENDOUSLY important but I'm just curious....(noob here). Any idea?
this initializes the plugin
/**
* Initializes the plugin by setting localization, hooks, filters, and administrative functions.
*
* #return instance
*/
public static function instance() {
if ( ! isset( self::$instance ) && ! (self::$instance instanceof self) ) {
self::$instance = new self();
self::$instance->setup_constants();
self::$instance->actions = array();
self::$instance->filters = array();
add_action( 'plugins_loaded', array( self::$instance, 'load_textdomain' ) );
add_action( 'bp_loaded', array( self::$instance, 'bp_include' ) );
global $ap_classes;
$ap_classes = array();
self::$instance->includes();
self::$instance->ajax_hooks();
self::$instance->site_include();
self::$instance->anspress_forms = new AnsPress_Process_Form();
self::$instance->anspress_query_filter = new AnsPress_Query_Filter();
self::$instance->anspress_cpt = new AnsPress_PostTypes();
self::$instance->anspress_reputation = new AP_Reputation();
/*
* ACTION: anspress_loaded
* Hooks for extension to load their codes after AnsPress is leaded
*/
echo nl2br("this is located OVER the do action anspress loaded. \n");
do_action('anspress_loaded');
self::$instance->setup_hooks();
}
return self::$instance;
}
this might be important:
/**
* Register the filters and actions with WordPress.
*/
private function setup_hooks() {
foreach ( $this->filters as $hook ) {
add_filter( $hook['hook'], array( $hook['component'], $hook['callback'] ), $hook['priority'], $hook['accepted_args'] );
}
foreach ( $this->actions as $hook ) {
add_action( $hook['hook'], array( $hook['component'], $hook['callback'] ), $hook['priority'], $hook['accepted_args'] );
}
}
I tried to declare a new time interval for a WP_CRON.
When I do it in a PHP file it works.
When I do it in a PHP Class it doesn't.
Can someone see what I'm doing wrong ?
I'm using the plugin cron view to check if the declaration is working or not.
If I solve this problem I think it will also solve my problem to know why my cron job is not triggered in the class but works properly when not in a class.
=> File myplugin.php
function set_up_option_page() {
add_options_page( [...]);
}
add_action( 'admin_menu', 'set_up_option_page' );
function do_some_rock() {
$instance = My_Plugin_Class::instance();
if ( isset($_POST['action']) && 'do-magic' == $_POST['action'] ) {
$instance->do_stuff();
}else{
// Display the form.
<?
}
}
=> File My_Plugin_Class.php
<?php
if ( ! defined( 'ABSPATH' ) ) exit;
class My_Plugin_Class {
private static $_instance = null;
public function __construct () {
[...]
add_filter( 'cron_schedules', array($this,'cron_time_intervals'));
}
public function cron_time_intervals( $schedules ) {
echo "——— cron time intervals —— ";
$schedules['minutes_1'] = array(
'interval' => 10*60,
'display' => 'Once 10 minutes'
);
return $schedules;
}
public static function instance () {
if ( is_null( self::$_instance ) ) {
self::$_instance = new self();
}
return self::$_instance;
} // End instance ()
Best regards.
I am almost sure that do_some_rock() is not called every time - only when someone goes to that page. You can move add_filter( 'cron_schedules', array($this,'cron_time_intervals')); from your class constructor to main plugin file myplugin.php and do more or less something like this
add_action( 'admin_menu', 'set_up_option_page' );
$instance = My_Plugin_Class::instance();
add_filter( 'cron_schedules', array($instance ,'cron_time_intervals'));
One extra question. Does My_Plugin_Class constructor contain any code you would like to prevent being executed during each request?
I think the proper way to do this, is to have a specific class for my Cron.
This class is instanciated on each request this is why the code shouldn't be in a class with a static instance as I did before.
Also I think it's better to have the Cron outside the plugin class for logic and cleaner code purpose. Thanks to Lukas Pawlik for the help.
if (!defined('ABSPATH')) exit;
new My_Cron();
class My_Cron {
public function __construct() {
add_filter('cron_schedules', array($this, 'cron_time_intervals'));
add_action( 'wp', array($this, 'cron_scheduler'));
add_action( 'cast_my_spell', array( $this, 'auto_spell_cast' ) );
}
public function cron_time_intervals($schedules)
{
$schedules['minutes_10'] = array(
'interval' => 10 * 60,
'display' => 'Once 10 minutes'
);
return $schedules;
}
function cron_scheduler() {
if ( ! wp_next_scheduled( 'cast_my_spell' ) ) {
wp_schedule_event( time(), 'minutes_10', 'cast_my_spell');
}
}
function auto_spell_cast(){
My_Plugin_Class::instance()->launch_spell();
}
}
I am not Sure But Try this.
add_filter( 'cron_schedules', array($this,'cron_time_intervals'),1);
And Check cron_time_intervals() Function is Call or Not.