My problem is that my constants aren't being globally available to files included deeper within my plugin. Let me explain.
In my main wordpress plugin file, the very first line right after the necessary /* Plugin Name: blah blah etc... */ I include my constants like so
require_once( plugin_dir_path(__FILE__) . 'constants.php' );
Next, within my __construct() function I include another file which builds the menu items in the admin section of wordpress like so
require_once( TRADESHOW_DIR . 'structure/build_menu.php' );
The build_menu.php file works as a router with mor require_once calls to pages corresponding to each menu page, and submenu. Here's where I don't get it. within the build_menu.php I still have access to my constants, which I use to do wordpress database queries using them, but I don't have access to the constants within the files that are included right after. Here's the code:
//// build_menu.php
function tradeshow_all_forms() {// callback from a wordpress add_submenu_page() function
global $wpdb;
$TS = new Bio_Tradeshow_Request_Plugin();// store plugin class in variable
if( isset( $_GET['form_id'] ) && is_integer( intval( $_GET['form_id'] ) ) ) {
$form = $wpdb->get_results(
"
SELECT *
FROM " . TRADESHOW_FORMS . "
WHERE id = '" . $_GET['form_id'] . "'
"
);
$form = $form[0];
echo TRADESHOW_SUBMITTED . ' build_menu.php<br />';// echo's out the correct value
require_once( TRADESHOW_DIR . 'structure/fill_form.php' );
}
}
Here's the top part of the fill_form.php file
$user_id = $TS->user();
$user_id = $user_id['id'];
$form_aswers = $wpdb->get_row(// returns nothing because TRADESHOW_SUBMITTED doesn't work
"
SELECT answers
FROM " . TRADESHOW_SUBMITTED . "
WHERE user_id = '$user_id' AND form_id = '$form->id'
",
ARRAY_A
);
echo TRADSHOW_SUBMITTED;// echoes out TRADESHOW_SUBMITTED as a string and not a variable
So as you can see it's an include within an include within the main plugin.
Additionally if anyone could explain to me why the $this variable of the plugin isn't available within files included within the plugin. I have this at the top of my plugin
static $_o = null;
static public function init() {
if (self::$_o === null)
self::$_o = new self;
return self::$_o;
}
so that I can do $variable = new plugin_class; but I would like to understand if something gets lost when you include a file using require or require_once.
FROM " . self::TRADESHOW_SUBMITTED . "
When I'm writing a plugin, its always 100% inside class, so this always works for me. I define constants in __construct() and call them in child classes with self..
Related
Suppose I have a clean wordpress install, with a basic custom theme.
In that theme, I have a custom page template which is just an iframe, which is pointed at a webapp on a different domain.
So suppose my wordpress install can be reached at http://example.com, and my page with the iframe template is located at http://example.com/members/.
I now want to add dynamic routes, so that all requests to http://example.com/members/login, or http://example.com/members/event/1 (for example) all go to http://example.com/members/ but pass the second part of the route ('/login', or '/event/1') to the iframe inside.
What would be the best way to accomplish this, without having to hack into Wordpress' internals?
I found this plugin: https://wordpress.org/plugins/wp-on-routes/ but much to my dismay I discovered that when I tried using it it completely overwrites Wordpress' built in routing, which meant I would have to manually re-add each and every URL (as I understand it, I'm not that accomplished in PHP), which is a no go as my client still needs to be able to post without manually editing php files.
Thank you for reading.
You can add routing using the add_rewrite_rule hook like so:
function custom_rewrite_rule() {
add_rewrite_rule('members/([^/]+)/([^/]+)/?$',
'index.php?memberspage=$matches[1]&event_id=$matches[2]',
'top');
}
add_action('init', 'custom_rewrite_rule', 10, 0);
You may need to create several depending on the URLs you rewriting. You can then use the URL parameters in your template to load the appropriate page in your iframe.
I managed to find a solution for my problem, thanks to Fencer04's suggestion. I found this page: https://developer.wordpress.org/reference/functions/add_rewrite_rule/ where I found an example that was close enough to my problem to work.
So in functions.php:
function custom_rewrite_rule(){
$page_id = 318; // replace this ID with the page with the iFrame template
$page_data = get_post($page_id);
if(!is_object($page_data)){
return; // all other pages don't have to support custom deeplinks
}
// catches deeplinks 1 level deep, i.e.: /members/profile
add_rewrite_rule(
$page_data->post_name . '/([^/]+)/?$',
'index.php?pagename=' . $page_data->post_name . '&memberspage=$matches[1]',
'top'
);
// catches deeplinks 2 levels deep, i.e.: /members/profile/edit
add_rewrite_rule(
$page_data->post_name . '/([^/]+)/([^/]+)/?$',
'index.php?pagename=' . $page_data->post_name . '&memberspage=$matches[1]&members_param=$matches[2]',
'top'
);
// catches 3 levels deep, i.e. /members/profile/edit/confirm
add_rewrite_rule(
$page_data->post_name . '/([^/]+)/([^/]+)/([^/]+)/?$',
'index.php?pagename=' . $page_data->post_name . '&memberspage=$matches[1]&members_param=$matches[2]&members_param2=$matches[3]',
'top'
);
}
add_action('init', custom_rewrite_rule);
Next I added filters for the new query_vars:
add_filter('query_vars', function($vars) {
$vars[] = "memberspage";
$vars[] = "members_param";
$vars[] = "members_param2";
return $vars;
});
And then in my template-iframe.php, I can access these parameters like so:
<?php
// get query strings
global $wp_query;
$page = $wp_query->query_vars['memberspage'];
$params = $wp_query->query_vars['members_param'];
$params2 = $wp_query->query_vars['members_param2'];
$membersBaseURL = 'http://members.domain.com/';
$iframeURL = $membersBaseURL;
if(isset($page)){
$iframeURL = $iframeURL . $page . '/';
}
if(isset($params)){
$iframeURL = $iframeURL . $params . '/';
}
if(isset($params2)){
$iframeURL = $iframeURL . $params2 . '/';
}
?>
<iframe id="iframeLeden" src="<?php echo($iframeURL) ?>" frameborder="0"></iframe>
So now if I go to http://www.domain.com/members/login, it'll show me the correct static WP page, with inside an iframe that shows the page http://members.domain.com/login/ .
I use Yiiwheels. I want to change a combo box to select 2 widget, but the pertinent assets are not loaded yet. The ugly solution is creating a dummy select2 element in a hidden span, so assets are loaded automatically. but is there any better way to do that, I mean a function to load assets of a widget?
The function you are looking for is the registerClientScript() function in WhSelect2 widget class in Yiiwheels.
While creating an empty widget is the easiest way to register the script you can alternatively call it directly with something like this
<?php Yii::import('yiiwheels.widgets.select2.WhSelect2');
$w = new WhSelect2();
$w->registerClientScript();
?>
The registerClientScript() function is called in init()call during widget creation, the following is operations executed by this function See WhSelect2 on github for the full code
/**
* Registers required client script for bootstrap select2. It is not used through bootstrap->registerPlugin
* in order to attach events if any
*/
public function registerClientScript()
{
/* publish assets dir */
$path = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'assets';
$assetsUrl = $this->getAssetsUrl($path);
/* #var $cs CClientScript */
$cs = Yii::app()->getClientScript();
$cs->registerCssFile($assetsUrl . '/css/select2.css');
$cs->registerScriptFile($assetsUrl . '/js/select2.js');
if ($this->language) {
$cs->registerScriptFile(
$assetsUrl . '/js/locale/select2_locale_' . $this->language . '.js',
CClientScript::POS_END
);
}
/* initialize plugin */
$selector = '#' . TbArray::getValue('id', $this->htmlOptions, $this->getId());
$this->getApi()->registerPlugin('select2', $selector, $this->pluginOptions, CClientScript::POS_READY);
$this->getApi()->registerEvents($selector, $this->events, CClientScript::POS_READY);
}
I have a function log($text)
all this does is write $text to a database.
I would like to include __LINE__ and __FILE__, but don't want to include it as a parameter each time as I currently do:
function log($text,$file = null, $line = null){
// write $text to db using the three paramters
}
If I change $file = null to $file = __FILE__ it uses the file name that the function lives in, rather than where the function is being called.
Is there any way around this?
Although the question is identical, the answers seem to focus on some other topic: function name($param, $line = __LINE__, $file = __FILE__) {};
also, not using Zend framework: how to have php get the __LINE__ or __FILE__ value where a function is called
I'm building a script that got a static class used to load few things including files and views.
class load
{
public static function view($file_path, $area)
{
debug::log('getting view <b>' . $area . $file_path . '</b>.');
ob_start();
self::file($file_path, 'areas/' . $area . '/views');
debug::log('flushing view <b>' . $area . $file_path . '</b>.');
eturn ob_get_clean();
}
public static function file($file, $folder)
{
if(is_file($file_path = ROOT . '/' . $folder . '/' . $file))
{
if(require_once $file_path)
{
debug::log('file <b>' . $file_path . '</b> included.');
return true;
}
}
else
debug::kill('requested file <b>' . $file_path . '</b> does not exist.');
}
}
In the controller Im calling the view method to get a view:
$html = load::view('public', 'path/to/view/file.php');
Obviously, Im not able to access the variables from the controller at the view file using this practice, so I did a small modification on the view class to capture the vars:
public static function view($file_path, $area, $vars = array())
And added the following lines of codes to get the keys into vars:
while(list($n_list_var,$v_list_var)=each($vars))
$$n_list_var = $v_list_var;
But again I can't access the vars since Im using a method to load a file.
I have a method to load the files because I wanna test and log each file include attempt and not repeat the code every time I need include a file. And I have the loader view inside the loader class so I have all the methods of this kind together. Should I give up on using a class to load files? Should I use the loader view method on a extendable class from my controller?
Instead of going ahead and modify my entire script I would like to hear some opinions ... what would be the best practice to go? Or is there a way to solve my problem? Maybe using __set and __get magic methods?
Thanks,
Why not just pass a $vars argument to load::file() and extract( $vars ) (possibly moving the vars you use inside file() into class variables to prevent them from being overwritten)?
I'm suggesting using extract() instead of:
while(list($n_list_var,$v_list_var)=each($vars))
$$n_list_var = $v_list_var;
By the way, it would be a good idea to name your class Load.
I am working with a Drupal theme, and I see a lot of variables which look like were created with extract(). Is it possible to track back, and see where that array is?
I take you are referring to the variables passed to a template file, which effectively are extracted from an array.
The code that does that in Drupal 7 is in theme_render_template().
function theme_render_template($template_file, $variables) {
extract($variables, EXTR_SKIP); // Extract the variables to a local namespace
ob_start(); // Start output buffering
include DRUPAL_ROOT . '/' . $template_file; // Include the template file
return ob_get_clean(); // End buffering and return its contents
}
The function is called from theme(), which executes the following code.
// Render the output using the template file.
$template_file = $info['template'] . $extension;
if (isset($info['path'])) {
$template_file = $info['path'] . '/' . $template_file;
}
$output = $render_function($template_file, $variables);
$render_function by default is set to 'theme_render_template', but its value is set with the following code (in theme()).
// The theme engine may use a different extension and a different renderer.
global $theme_engine;
if (isset($theme_engine)) {
if ($info['type'] != 'module') {
if (function_exists($theme_engine . '_render_template')) {
$render_function = $theme_engine . '_render_template';
}
$extension_function = $theme_engine . '_extension';
if (function_exists($extension_function)) {
$extension = $extension_function();
}
}
}
Just echo the $GLOBALS variable and you might find where it came from if the array was not unset.
Im not familiar with Drupal so this is just a suggestion, but if drupal has a templating structure or if an array is passed from a controller or such then possible that extract is used,
You could use get_defined_vars within your view to get all vars and its possible that there is an array there that you can cross reference with variables you know of that are in the same array or such.
<?php
$vars = get_defined_vars();
print_r($vars);
//or maybe
print_r($this);
?>