I'm trying to develop my first Wordpress plugin and I got staled in the very first stage. I'm trying to setup some options and database tables when the plugin is activated, but no luck. No matter what I do, the plugin activates, but the database is untouched and the options are not stored in DB. I tried echoing inside the constructor, but it seems that it never reaches it. I have debug activated in WP, but no error is being reported. The function is not being hooked. Does someone can spot what's wrong with my code?
Thanks for any help in advance.
class Myplugin {
private static $instance;
public static function get_instance() {
if ( ! self::$instance ) {
self::$instance = new self();
}
return self::$instance;
}
private function __construct() {
register_activation_hook( __FILE__, array( &$this, 'plugin_activate' ) );
}
public function plugin_activate() {
if ( version_compare( get_bloginfo( 'version' ), '3.8.2', ' < ' ) ) {
deactivate_plugins( basename( __FILE__ ) );
} else {
$rlm_rsvplus_options = array(
'db_version' => '1.0',
'event_name' => '',
'end_date' => '',
);
update_option( 'rlm_myplugin_options', $rlm_myplugin_options );
require_once( "includes/rlm_myplugin_db_setup.php" );//It never reaches this file.
}
}
}
$myplugin = Myplugin::get_instance();
Back to the WordPress documentation.
<?php register_activation_hook( $file, $function ); ?>
Parameters
$file
(string) (required) Path to the main plugin file inside the wp-content/plugins directory. A full path will work.
Default: None
$function
(callback) (required) The function to be run when the plugin is activated. Any of PHP's callback pseudo-types will work.
Default: None
Possible issue
If calling a function from a file that is outside of main plugin file, then the hook will not work as it is not pointing to the right file. FILE will point to the file where the code is written. So if you happen to include this part of code from elsewhere (another file - not the main plugin file) it's not supposed to work unless you point the right path.
Solution
A solution could be declaring a constant in the main plugin file.
your_main_plugin_file.php
define(PLUGIN_FILE_URL, __FILE__);
and then use it in your included file like so.
includes/some_file.php
<?php register_activation_hook( PLUGIN_FILE_URL, ['your_class_name_here', 'your_class_method_name_here']); ?>
or if you use functions instead of classes then do
<?php register_activation_hook( PLUGIN_FILE_URL, 'your_function_name_here'); ?>
The register_activation_hook call needs to be outside of the class itself.
Something like:
class Myplugin {
private static $instance;
public static function get_instance() {
if ( ! self::$instance ) {
self::$instance = new self();
}
return self::$instance;
}
private function __construct() {
// do other stuff here
}
public function plugin_activate() {
if ( version_compare( get_bloginfo( 'version' ), '3.8.2', ' < ' ) ) {
deactivate_plugins( basename( __FILE__ ) );
} else {
$rlm_rsvplus_options = array(
'db_version' => '1.0',
'event_name' => '',
'end_date' => '',
);
update_option( 'rlm_myplugin_options', $rlm_myplugin_options );
require_once( "includes/rlm_myplugin_db_setup.php" );
}
}
register_activation_hook( __FILE__, array( 'Myplugin', 'plugin_activate' ) );
You can read more on the following tutorial by Francis Yaconiello about How to write WordPress plugin.
In order to work register_activation_hook OR register_deactivation_hook the functions should be in index file OR we need to specify the full path to the file argument.
Replace this:
register_activation_hook( FILE, array( &$this, 'plugin_activate' ) );
With:
register_activation_hook( FILE . 'plugin-main-file.php', array( &$this, 'plugin_activate' ) );
Here the point is register_activation_hook( $file, $function );
Here $file means Path to the main plugin file
Reference: https://codex.wordpress.org/Function_Reference/register_activation_hook
Thanks,
- Adi
Related
I'm trying to create a plugin for shortcodes. But my activation hook is not working. Plugin is activated in my wp-admin/plugins page but nothing works which is in my code like:
My enqueue & shortcode functions are not working. I've tried plugin_dir_path(__FILE__) & plugin_dir_url(__FILE__) b ut nothing works.
Here is my code:
if (!class_exists( 'DiliviBlocks' )) {
class DiliviBlocks {
public function __construct() {
$this->setup_actions();
$this->plugin_dir = plugin_dir_path(__FILE__);
}
/**
* Setting up Hooks
*/
public function setup_actions() {
register_activation_hook( plugin_dir_path(__FILE__), array( $this, 'activate_plugin' ) );
}
/**
* Activate callback
*/
public function activate_plugin() {
add_action( 'wp_enqueue_scripts', array($this, 'dilivi_blocks_scripts') );
add_shortcode( 'vans_search_form', array($this, 'vans_search_form_shortcode') );
}
public function dilivi_blocks_scripts() {
wp_enqueue_style( 'dilivi-blocks-plugin-css', plugin_dir_path(__FILE__) . '/assets/css/styles.css');
wp_enqueue_script( 'dilivi-blocks-plugin-jquery', plugin_dir_path(__FILE__) . '/assets/js/jquery.js' );
wp_enqueue_script( 'dilivi-blocks-plugin-js', plugin_dir_path(__FILE__) . '/assets/js/scripts.js' );
}
public function vans_search_form_shortcode($atts) {
return 'Hello World';
}
}
$diliviBlocks = new DiliviBlocks();
}
Please help me. I'm stuck
The documentation states that you only need the plugin directory name, and the name of the initial file. You should not include the whole path to it.
If your plugin contains only the file, than just __FILE__ would suffice.
In your case, it will probably be something like dilivi-blocks/divili-blocks.php.
Also, be aware that functions will only be executed once -- when your plugin is activated. If it is already active, the functions will not execute.
You should know that enqueueing stylesheets and the like will have to be done every time a page loads, so binding them to a single-use hook will not work. The wp_enqueue_scripts hook should be used for that.
I am trying to add custom endpoints (custom endpoint” mean an arbitrary URL not recognized by WP as a standard URL, like a permalink or so.) I use WordPress plugin boilerplate "https://github.com/DevinVinson/WordPress-Plugin-Boilerplate".
I want to send an API request on a custom endpoint. I create a new class file to register endpoints and include this class file in the plugin activate method and call add_action hook but it's not working.
Create a new class-rigal-custom-Endpoint.php file in the includes folder.
<?php
class Rigal_custom_Endpoint {
private static $initiated = false;
public static function init() {
if ( ! self::$initiated ) {
self::init_hooks();
}
}
public static function init_hooks() {
self::$initiated = true;
add_action('init', 'add_endpoint');
}
/**
*
* #description Create a independent endpoint
*/
public static function endpoint() {
global $wp;
$endpoint_vars = $wp->query_vars;
// if endpoint
if ($wp->request == 'exercise/test') {
// Your own function to process endpoint
exit;
}
}
}
After I Include this class file in the plugin activate method. (class-rigal-plugin-activator.php)
public static function activate() {
require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-rigal-custom-endpoint.php';
add_action( 'init', array( 'Rigal_custom_Endpoint', 'init' ) );
add_action( 'parse_request', array( 'Rigal_custom_Endpoint', 'endpoint' ) , 0);
}
When I activate the plugin and add "exercise/test" In URL but it's not working. Would you please suggest a solution to fix the above issue?
Environment
PHP: 7.4
Wordpress: 5.4
OS: Mac: 10.15.1
Browser: Chrome:Version 81.0.4044.122
Thanks
Because the activation method is only executed during the plugin activation. Once the plugin is active, this method will no longer be executed.
In class-plugin-name.php on load_dependencies method, add your class, for example:
require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-rigal-custom-endpoint.php';
in define_public_hooks add your action
$this->loader->add_action( 'parse_request', 'Rigal_custom_Endpoint', 'endpoint' );
This will work, but take in consideration that you don't register your endpoint api in the standard way. You should take a look at the WP REST API documentation:
https://developer.wordpress.org/rest-api/extending-the-rest-api/adding-custom-endpoints/
This is an example of minimal plugin using register_rest_route
<?php
/*
Plugin Name: Add WP Custom endpoint
Author: Robin Ferrari
Version: 1.0
*/
class MYPLUGIN_Api_Endpoint{
public function init(){
add_action( 'rest_api_init', array($this, 'register_rest_routes'));
}
public function register_rest_routes(){
register_rest_route( 'myplugin/v1', '/exercise/test', array(
'methods' => 'GET',
'callback' => array($this, 'exercise_test'),
));
}
/**
* Your custom route callback
*/
public function exercise_test(){
$error = false;
// do what you whant
if($error){
return new WP_Error(500, "KO");
}
return new WP_Rest_Response(array(
'status' => 200,
'message' => "OK",
));
}
}
$api = new MYPLUGIN_Api_Endpoint();
$api->init();
And then your endpoint is accessible here:
https://example.com/wp-json/myplugin/v1/exercise/test
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.
This question already has answers here:
The plugin generated X characters of unexpected output during activation (WordPress)
(25 answers)
Closed 4 years ago.
I want to create a wordpress plugin by just following the example listed here based on a class OOP architecture with an external setup object, and adapting the source code on my own way like this:
main plugin file:
<?php
/*
Plugin Name: My Plugin
Description: My Plugin
Version: 1.0
Author: drwhite
Author URL: drwhite-site
Plugin URL: drwhite-site/video-ad-overlay
*/
register_activation_hook(__FILE__, array( 'VAO_Setup_File_Inc', 'on_activation'));
register_deactivation_hook(__FILE__, array( 'VAO_Setup_File_Inc', 'on_deactivation'));
register_uninstall_hook(__FILE__, array( 'VAO_Setup_File_Inc', 'on_uninstall'));
add_action('plugins_loaded', array( 'VAO_Setup_File', 'init'));
class VAO_Setup_File{
protected static $instance;
public static function init()
{
is_null( self::$instance ) AND self::$instance = new self;
return self::$instance;
}
public function __construct()
{
add_action( current_filter(), array( $this, 'load_files' ));
}
public function load_files()
{
foreach ( glob( plugin_dir_path( __FILE__ ).'includes/*.php' ) as $file ){
include_once $file;
}
}
}
In my plugin root directory i have created a subdirectory called includes within i put the setup file to be loaded on plugin load called setup.class.php:
<?php
class VAO_Setup_File_Inc
{
public static function on_activation()
{
if ( ! current_user_can( 'activate_plugins' ) )
return;
$plugin = isset( $_REQUEST['plugin'] ) ? $_REQUEST['plugin'] : '';
check_admin_referer( "activate-plugin_{$plugin}" );
}
public static function on_deactivation()
{
if ( ! current_user_can( 'activate_plugins' ) )
return;
$plugin = isset( $_REQUEST['plugin'] ) ? $_REQUEST['plugin'] : '';
check_admin_referer( "deactivate-plugin_{$plugin}" );
}
public static function on_uninstall()
{
if ( ! current_user_can( 'activate_plugins' ) )
return;
check_admin_referer( 'bulk-plugins' );
// Important: Check if the file is the one
// that was registered during the uninstall hook.
if ( __FILE__ != WP_UNINSTALL_PLUGIN )
return;
}
}
When i activate the plugin i got an error like the following:
I have read several questions posted by other users here and this may be duplicated question, but any of suggested answer worked for me including:
Remove space from start of tags and even remove the php end tag: nothing changed
in wp_config.php file i set wp_DEBUG to true , but it doesn't show errors
I have converted the file to UTF8 (without BOM) nothing changed
Have you put the eye in the issue ?
You are getting this error because your plugin is generating a PHP error that is being outputted to the page and causing the headers sent error you see... The problem with your code is that your function
public function load_files()
{
foreach ( glob( plugin_dir_path( __FILE__ ).'includes/*.php' ) as $file ){
include_once $file;
}
}
is not being called in time, so
register_activation_hook(__FILE__, array( 'VAO_Setup_File_Inc', 'on_activation'));
is looking for a function that doesn't exist, inside a class that doesn't exist. Move your
foreach ( glob( plugin_dir_path( __FILE__ ).'includes/*.php' ) as $file ){
include_once $file;
}
outside the class altogether, and it'll load just fine. It may require you to rethink your use of
add_action('plugins_loaded', array( 'VAO_Setup_File', 'init'));
and the way your plugin is being created, but it's a step in the right direction. If you copy and paste the code from the link you got this code from, his code displays the same problem...
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.