This question already has answers here:
The plugin generated X characters of unexpected output during activation (WordPress)
(25 answers)
Closed 4 years ago.
I am trying to develop a plugin. When I activate the plugin it's showing me following error message:
The plugin generated 2651 characters of unexpected output during
activation. If you notice “headers already sent” messages, problems
with syndication feeds or other issues, try deactivating or removing
this plugin.
I can not understand why it's showing this error. I can see there is no white space to show this error!
Here is my code:
<?php
/*
Plugin Name: Forum Roles
Plugin URI: http://www.creativeartbd.com
Description: Generate a google map
Version: 1.0
Author: Shibbir
Author URI: http://creativeartbd.com/bio/
License: GPL2
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Text Domain: gmape
Domain Path: /languages/
*/
// custom forum roles and capabilites class
class BOJ_Forum_Roles {
function __construct() {
// register plugin activation hook
register_activation_hook( __FILE__, 'activation' );
// register plgin deactivation hook
register_deactivation_hook( __FILE__, 'deactivation' );
}
// plugin activation method
function activation () {
// get the default administrator tole
$role =& get_role('administrator');
// add forum capabilities to the administrator role
if( !empty($role) ) {
$role->add_cap('publish_forum_topics');
$role->add_cap('edit_others_forum_topics');
$role->add_cap('delete_forum_topics');
$role->add_cap('read_forum_topics');
}
// create the forum administator tole
add_role( 'forum_administrator', 'Forum Administrator', array(
'publish_forum_topics', 'edit_others_forum_topics', 'delete_forum_topics', 'read_forum_topics'
) );
// create the moderator role
add_role('forum_moderator', 'Forum Moderator', array(
'publish_forum_topics', 'edit_others_forum_topics','read_forum_topics'
));
// create the forum member role
add_role('forum_member', 'Forum Member', array(
'publish_forum_topics', 'read_forum_topics'
));
// create the forum suspended role
add_role( 'forum_suspended', 'Forum Suspeded', array(
'read_forum_topics'
) );
}
// plugin deactivation method
function deactivation () {
// get the default administrator role
$role =& get_role('administrator');
//remove forum capabilites to the administrator role
if(!empty($role)) {
$role->remove_cap('publish_forum_topics');
$role->remove_cap('edit_others_forum_topics');
$role->remove_cap('delete_forum_topics');
$role->remove_cap('read_forum_topics');
}
// set up an array of roles to delete
$roles_to_delete = array(
'forum_administrator',
'forum_moderator',
'forum_member',
'forum_suspended'
);
// loop through each role, deleting the role if necessary
foreach ($roles_to_delete as $role) {
// get the users of the role
$users = get_users(array(
'role' => $role
));
// check if there are no users for the role
if( count($users) <= 0 ) {
//remove the role from the site
remove_role( $role );
}
}
}
}
$forum_roles = new BOJ_Forum_Roles();
Can you tell me how can I solve it?
For this error
Warning: call_user_func_array() expects parameter 1 to be a valid callback, function 'activation' not found or invalid function name ..
You'll wan't to call the method of your object (class). To do that you can pass an array to the callback, the first element is the class name (in static calls) or an instance of the object, the second element is the method name such as:
class BOJ_Forum_Roles {
public function __construct() {
register_activation_hook( __FILE__, [$this,'activation'] );
register_deactivation_hook( __FILE__, [$this,'deactivation'] );
}
public function activation(){...}
public function deactivation(){...}
}
In core PHP call_user_func_array() is called like this
call_user_func_array([$this,'activation'], $args);
http://php.net/manual/en/function.call-user-func-array.php
It's possible output from this error is giving you the original error you were seeing.
Static Calls
Just for completeness if you had
public static function activation(){...}
You would call it this way (static)
class BOJ_Forum_Roles {
public function __construct() {
register_activation_hook( __FILE__, [__CLASS__,'activation'] );
register_deactivation_hook( __FILE__, [__CLASS__,'deactivation'] );
}
public static function activation(){...}
public static function deactivation(){...}
}
Using the __CLASS__ constant is preferable to putting in the class name, in PHP5.5+ you can also do it this way self::class, although I believe the constant is a bit faster. I think the same holds true for static::class which would be late static binding. And of course you can always do this (in 5.5+) BOJ_Forum_Roles::class which in this example makes little sense, but it can be useful with namespaces.
UPDATE
showing...Notice: Only variables should be assigned by reference in
$role =& get_role('administrator');
Remove the Amp, as you are assigning the results of a function by reference. I am not certain, but if it's an object it's passed by reference anyway. It dosn't matter because you probably shouldn't be modifying it in your function and in fact this just caught my attention (in deactivation):
$role =& get_role('administrator');
...
foreach ($roles_to_delete as $role) {
...
}
You are re-assigning the $role variable in the loop. This may or may not cause issues (I can't tell for sure without testing it), but overwriting it is probably a simple over site on your part. It's generally bad practice to overwrite a variable this way (as the assignment of a loop) if it's been previously declared as often this would not be an intentional thing.
Cheers!
Related
So In my main plugin file I have this
class RegistrationHooks
{
/**
* #var string
*/
protected string $plugin_dir;
public function __construct()
{
$this->plugin_dir = WP_PLUGIN_DIR . '/invoices';
}
function active_invoices()
{
require_once $this->plugin_dir . '/includes/class-invoices.php';
new Invoices();
}
}
$hooksInstance = new RegistrationHooks();
register_activation_hook(__FILE__, array($hooksInstance, 'active_invoices'));
And inside My Invoices class I have this:
class Invoices
{
public function __construct()
{
$this->load_dependencies();
$this->define_admin_hooks();
}
private function load_dependencies()
{
$path = WP_PLUGIN_DIR . '/invoices';
if ($path) {
require_once $path . '/admin/class-admin.php';
}
}
private function define_admin_hooks()
{
$plugin_admin = new Admin();
add_action('admin_menu', array($plugin_admin, 'add_plugin_admin_menu'));
}
}
And Inside my Admin class I have simple method to add item to menu
class Admin {
public function add_plugin_admin_menu()
{
add_menu_page(
'Page Title',
'Menu Title',
'edit_posts',
'menu_slug',
);
}
}
But when I activate Plugin item doesnt get added to admin menu. When I Place my Invoices class inside my main Plugin class it works.
You're misusing register_activation_hook(). That hook only runs when you Activate your plugin (immediately after installing it, usually). It's used for things like creating plugin-specific tables and prepopulating options. Immediately after activation, WordPress does a redirect and starts a new page view, so anything non-persistent you do (like adding other actions) in the activation hook vanishes immediately.
Your code only requires your class-invoices.php file from within your registration hook. So it doesn't run in ordinary page views or dashboard views.
You can do this, in your toplevel plugin file, to require your admin code, and construct it, on dashboard views.
function invoices_admin_init () {
require_once( plugin_dir_path( __FILE__ ) . '/includes/class-invoices.php' );
new Invoices();
}
add_action( 'admin_init', invoices_admin_init );
It's good practice to require code only when it's needed (in this example, only on dashboard pageviews) to reduce the overhead your plugin causes.
Be aware that the action function you declare pollutes WordPress's global name space, so give it a distinct name no other plugin writer is likely to use.
I apologise if this question is a bit long winded, but it's quite a large chunk of code and I cannot get it to work for the life of me...
I am building a form inside a Wordpress plugin that should gather some data (either through form inputs, API, or a combination of both - such as calling different API endpoints depending on form values). I want to then use these variables (or properties, as they seem to be referred to within classes) in different methods.
Firstly, I have my class and then a method to register my plugin on the Wordpress menu bar:
class EnigmaDMU {
private $enigma_dmu_screen_name;
private static $instance;
static function GetInstance()
{
if (!isset(self::$instance))
{
self::$instance = new self();
}
return self::$instance;
}
// This loads the WP menu page and plugin page
public function PluginMenu() {
$this->enigma_dmu_screen_name = add_menu_page(
'Enigma DMU Post',
'Enigma DMU Post',
'manage_options',
__FILE__,
array($this, 'RenderPage'),
plugins_url('enigma-daily-update/assets/enigma-cube-white.svg',__DIR__)
);
}
I then have another method called 'RenderPage' which contains my form and the HTML elements for my plugin page inside the WP admin:
public function RenderPage(){
?>
<div class='wrap'>
<div class="header-bar">
<h1>Daily Market Update</h1>
....... continued here
At the very bottom of my code, I have a method to initiate the plugin which adds the AJAX handlers (my methods) for certain AJAX actions which are called in my AJAX requests:
public function InitPlugin() {
add_action('admin_menu', array($this, 'PluginMenu'));
add_action('admin_enqueue_scripts', array($this, 'dmu_load_scripts'));
add_action('admin_enqueue_styles', array($this, 'dmu_load_scripts'));
add_action('wp_ajax_btc_data', array($this, 'getBTCData'));
add_action('wp_ajax_test_func', array($this, 'testFunc'));
}
} //this is the closing tag for the Class.
Underneath this, I have some class-related definitions, which admittedly I am unsure what they do - this was part of a larger tutorial I followed to set up this plugin:
$EnigmaDMUpost = EnigmaDMU::GetInstance();
$EnigmaDMUpost->InitPlugin();
?>
Almost there... I also have my handlers (I have included a test handler to simplify this explanation):
public function getBTCData() {
require __DIR__."/vendor/autoload.php";
$client = new GuzzleHttp\Client();
$btc_curl = $client->get('https://api.alternative.me/v1/ticker/bitcoin/',);
$btc_curl_body = $btc_curl->getBody();
$btc_curl_body_json = json_decode($btc_curl_body);
foreach($btc_curl_body_json as $result){
$btc_price_ur = $result->price_usd;
$btc_change_ur = $result->percent_change_24h;
}
$btc_price = round($btc_price_ur, 2);
$btc_change = round($btc_change_ur, 2);
$this->row3b = $btc_change . '%';
echo 'inside: ' . $this->row3b;
die();
}
I am able to echo this value here (row3b) inside my plugin successfully - this works as expected.
However, when I try and call the property from my testFunc, I get nothing:
public function testFunc() {
$test_item = $this->row3b;
echo 'btc dominance = ' . $test_item . '%.';
}
Finally, the relevant areas of my AJAX script are as follows:
jQuery(document).ready(function($) {
$('#dmu_submit').click(function() {
$('#dmu-loader').show();
$('#dmu_submit').attr('disabled', true);
btc_data = {
action: 'btc_data',
dmu_nonce: dmu_vars.dmu_nonce
};
$.post(ajaxurl, btc_data, function(response) {
$('#dmu-results').html(response);
$('#dmu-loader').hide();
$('#dmu_submit').attr('disabled', false);
});
$('#dmu_test_func').click(function() {
$('#dmu-loader').show();
$('#dmu_submit').attr('disabled', true);
test_data = {
action: 'test_func',
dmu_nonce: dmu_vars.dmu_nonce
};
$.post(ajaxurl, test_data, function(response) {
$('#dmu-results-test').html(response);
$('#dmu-loader').hide();
$('#dmu_submit').attr('disabled', false);
});
return false;
});
Any help would be massively appreciated - I know it's a long post, but I feel as if the answer is actually really simple, I just cannot figure it out. It feels as if I'm doing everything right. Thank you!!
It's not completely clear from your code examples which class your testfunc() is in. But $this in php refers to the instance of the class that it resides within, and the ->row3b refers to a property called row3b (a property is a variable that belongs to the class which is usually defined at the top of the class code). If you're calling $this->row3b within the class itself it will work, but if you need to refer to it from outside the class you will need to instantiate a new instance of the class, and then refer to it with the variable name you assign. E.g.
$myInstance = new theclassname(); $myInstance->row3b;
If the row3b is a static property its slightly different again, you can refer to this outside of the class as theclassname::$row3b
Edit: also ensure that the testfunc resides in the same class that the add_actions are in. The $this in the add_action tells wordpress that it should look for your handler in 'this' class.
Edit2: I think you may also need the die() at the end of your testfunc. Wordpress ajax is funny about this.
I'm using awesome support plugin for creating a ticket system in my project.
The problem I have is that support plugin will add some fields into Users Admin page which I don't want them.
I searched inside plugin code and I've found the action that is used to put the fields in users page and I want to remove that action.
I tried removing its action by using this code:
remove_action('wpas_all_user_profile_fields', array( WPAS_User::get_instance() , 'profile_phone_fields'), 10)
and it is working and the fields doesn't show on users page but I'm getting a fatal error inside my debug.log which says:
PHP Fatal error: Uncaught Error: Class 'WPAS_User' not found in ...
the plugin class that is something like this
class WPAS_User {
public function __construct() {
add_action( 'wpas_all_user_profile_fields', array( $this, 'profile_phone_fields' ), 10, 1 );
}
public static function get_instance() {
// If the single instance hasn't been set, set it now.
if ( null == self::$instance ) {
self::$instance = new self;
}
return self::$instance;
}
.
.
.
}
Do you include in your php the name of the file ?
<?php include('yourfile.php') ?>
I'm building a Wordpress Plugin (structured as a Singleton) that, when activated, inserts three new WooCommerce Endpoints (each endpoint is stored in a separate file containing the Endpoint Class). Finally, a mandatory flush_rewrite_rules() is called. The flush must happen after the three endpoints have been inserted or the endpoints will 404 when visited.
I want to avoid having to activate 4 separate plugins (my plugin + 3 endpoints plugins). Just one plugin activation if possible would be preferred.
So far :
My plugin activates OK and the endpoints 'visually appear' OK in the navigation but will 404 when visited. and need a manual flush.
The key problems are:
Where is best to include the three Endpoint class files inside my Singleton plugin? Top of Plugin? Inside the __construct? Or after the plugin?
Where is best to call the Classes after including them?
How to ensure flush_rewrite_rules is called after the three new endpoints have been inserted. Calling a flush_rewrite_rules() inside the register_activation_hook() doesn't seem to fix the 404ing endpoints.
Here is my abstracted code:
/* Include endpoint files here? */
include_once( plugin_dir_path( __FILE__ ) . 'classes/endpoint1.php');
include_once( plugin_dir_path( __FILE__ ) . 'classes/endpoint2.php');
include_once( plugin_dir_path( __FILE__ ) . 'classes/endpoint3.php');
class My_Plugin {
private $endpoint1 = null;
private $endpoint2 = null;
private $endpoint3 = null;
private static $instance;
public static function getInstance() {
if (self::$instance == NULL) {
self::$instance = new self();
}
return self::$instance;
}
private function __construct() {
/*Call the endpoint classes here? */
$this->$endpoint1 = new Endpoint1();
$this->$endpoint1 = new Endpoint2();
$this->$endpoint1 = new Endpoint3();
}
public static function install() {
flush_rewrite_rules();
}
} /*End Class*/
My_Class::getInstance();
/*Flush rewrite rules here? */
register_activation_hook( __FILE__, array( 'My_Plugin', 'install' ) );
Any help appreciated <3
I'm building a way to extend a WordPress plugin I'm developing using the following filter for grabbing the html content from a different plugin:
$content = apply_filters('satl_render_view', array($view, $slides));
With just one plugin this works perfectly, but once I activate a second plugin utilizing this same filter it stops working, $content is null for either plugin:
I'm adding the filters on the plugins in the __construct() method:
add_filter('satl_render_view', array('SatellitePortraitPlugin','addRender'));
and
add_filter('satl_render_view', array('SatelliteAwesomePlugin', 'addRender'));
Anyone run into this before?
In case it helps, this is the addRender method as it currently stands:
public static function addRender($params)
{
list($view, $slides) = $params;
$plugin = new SatelliteAwesomePlugin();
return $plugin->render($view, array('slides' => $slides, 'frompost' => 'false'), false);
}
For the record, I've tried remove_filter() if there is no content to return, but that didn't solve the problem.
Params get passed to callback function, in this case addRender() and contain all the HTML of what is wanted to display to the second plugin using that same filter. To utilize this bit of information one must change the method:
public static function addRender($params)
{
if (is_array($params)) {
list($view, $slides) = $params;
$plugin = new SatelliteAwesomePlugin();
return $plugin->render($view, array('slides' => $slides, 'frompost' => 'false'), false);
} else {
return $params;
}
}
You also need to make sure to update how the render() method passed the proper information back to the apply_filters method so the next plugin would have the proper array to run the addRender()
} else {
return array($file,$params['slides']);
}
Main Learning: WordPress apply_filters is much dumber than you'd think. You can't assume it merges everything for you, it just passes the information along and your code needs to make sense of it.