PHP: __call not working properly - php

I'm having a problem creating a class called API_Widgets in WordPress using the magic __call function. If I simple rename the file to derp.php and the class to API_Derp then it works without problems.
The following example has been stripped of everything unimportant to this issue (so if there is any error other than the specific fatal error specified in the third code block, ignore it).
Please keep in mind that I know the core.php or API class' __call works, as renaming the widgets.php or invoking another class works just fine.
core.php:
class API {
function __call( $method, $args ) {
$rmethod = "API_{$method}";
if ( !class_exists( $rmethod ) ) {
$lmethod = strtolower( $method );
require_once( "{$lmethod}.php" );
}
return new $rmethod( $args );
}
}
widgets.php:
class API_Widgets {
private $widgets = array();
function Add( $widgets ) {
if ( is_array( $widgets ) ) {
foreach ( $widgets as $widget ) {
if ( !in_array( $widget, $this->widgets ) )
$this->widgets[] = $widget;
}
} else
$this->widgets[] = $widgets;
}
}
api.php:
$api = new API();
$widgets = $api->Widgets(); // Fatal error: Class 'API_Widgets' not found in /home4/goldencr/public_html/wp-content/plugins/minecraft-api/api/core.php on line 25
//$widgets->Add( 'some_widget' );

Extending from comment:
Though not hinted at your question, it seems you may not actually included the widgets.php. Try to use absolute path to fix that:
require_once( __DIR__.DIRECTORY_SEPARATOR.$lmethod.".php" );

Related

Wordpress: Troubleshooting a hook not loading on an action

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??

The plugin generated N characters of unexpected output during activation [duplicate]

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...

plugin activation hook not working in wordpress

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

Unexpected T_Public on function.

I am trying to extend a background image control in the Wordpress theme customizer. I have been trying to get this code right and now that I think it should be working I am receiving an unexpected T_Public on this function:
public function tab_builtins() {
I have attempted to remove the public declaration before it, although that creates a new issue: Unexpected t_function
I have been looking at this code for a long time trying to change minor things but the issue remains. Can anyone help me out?
Here is the full code in question:
function WP_Customize_Background_Image_Control_Defaults($wp_customize) {
/* Substitute the default control for our new one */
$wp_customize->remove_control( 'background_image' );
$wp_customize->add_control( new WP_Customize_Background_Image_Control_Defaults( $wp_customize ) );
class WP_Customize_Background_Image_Control_Defaults extends WP_Customize_Background_Image_Control {
public function __construct( $manager ) {
$this->add_tab( 'builtins', __('Built-ins'), array( $this, 'tab_builtins' ) );
public function tab_builtins() {
$backgrounds = array(
'/wp-content/themes/newtheme/img/backgrounds/background1.jpg', '/wp-content/themes/newtheme/img/backgrounds/background2.jpg', '/wp-content/themes/newtheme/img/backgrounds/background3.jpg', '/wp-content/themes/newtheme/img/backgrounds/background4.jpg', '/wp-content/themes/newtheme/img/backgrounds/background5.jpg'
);
if ( empty( $backgrounds ) )
return;
foreach ( (array) $backgrounds as $background )
$this->print_tab_image( esc_url_raw( $background->guid ) );
}
}
}
}
add_action( 'customize_register', 'wp_customize_background_image_control_defaults', 11, 1 );
You have missed the closing curly brace right before public function tab_builtins()
Put it to close your __construct definition properly

How does array(__CLASS__, work in wordpress?

I'm trying to mod a wordpress plugin to take custom categories. So when the random_post_link is called, I can add the custom category by using random_post_link('Random Link',3). 3 being the category name.
How does the plugin below create a new object of class Random_Post_Link? I thought you created new objects by doing something like:
$a = new random_post_link;
But I don't see that in the plugin. I think it creates the new object in the init function by using a hook:
add_action('init', array(CLASS, 'jump'));
If that's the case, how can I add parameter to jump function?
I think I know how add_action works, the second parameter should be the function name, how does
" array(CLASS, 'jump')" work?
Here's the full code for the plugin:
function random_post_link($text = 'Random Post',$the_cat = 36) {
printf('%s', get_random_post_url(), $text);
$the_category = $the_cat;
}
function get_random_post_url() {
return trailingslashit(get_bloginfo('url')) . '?' . Random_Post_Link::query_var;
}
class Random_Post_Link {
const query_var = 'random';
const name = 'wp_random_posts';
public $the_category;
function init() {
add_action('init', array(__CLASS__, 'jump'));
// Fire just after post selection
add_action('wp', array(__CLASS__, 'manage_cookie'));
}
// Jump to a random post
function jump() {
if ( ! isset($_GET[self::query_var]) )
return;
$args = apply_filters('random_post_args', array(
'post__not_in' => self::read_cookie(),
));
$args = array_merge($args, array(
'orderby' => 'rand',
'cat' => $the_category,
'showposts' => 1,
));
$posts = get_posts($args);
if ( empty($posts) ) {
self::update_cookie(array());
unset($args['post__not_in']);
$posts = get_posts($args);
}
if ( empty($posts) )
wp_redirect(get_bloginfo('url'));
$id = $posts[0]->ID;
wp_redirect(get_permalink($id));
die;
}
// Collect post ids that the user has already seen
function manage_cookie() {
if ( ! is_single() )
return;
$ids = self::read_cookie();
$id = $GLOBALS['posts'][0]->ID;
if ( count($ids) > 200 )
$ids = array($id);
elseif ( ! in_array($id, $ids) )
$ids[] = $id;
self::update_cookie($ids);
}
private function read_cookie() {
return explode(' ', #$_COOKIE[self::name]);
}
private function update_cookie($ids) {
setcookie(self::name, trim(implode(' ', $ids)), 0, '/');
}
}
Random_Post_Link::init();
Some WordPress authors use the Class structure in PHP to basically reduce global vars. The class is meant as a 'singleton' of sorts, and so it isn't usually instantiated (that code calls Random_Post_Link::init(); at the bottom instead). The class functions are treated as Class members, not instance members, sort of like Math.max() in other languages, for example.
The __CLASS__ php keyword is simply a token for the current class, so when passed, the callable becomes Random_Post_Link::method() or array( 'Random_Post_Link', 'method' )
If you need to unhook, try remove_action( 'init', array( 'Random_Post_Link, 'jump' ) );
(Also note, that methods used that way should be declared static function jump() {...})
P.S. To further clarify:
http://php.net/manual/en/language.types.callable.php
The array('class', 'function') syntax is a PHP thing, while WordPress actions expect a callable which could be any of the PHP callable things.

Categories