Wordpress - make variables available for all theme files (without Globals) - php

I'm developing a Wordpress theme and I'm trying to store some of my variables in a function to re-use it among my theme files, without writing the same variables hundreds of time and without make them global. I've read that's a bad practice.
For now I'm using add_action but without results. Having in my functions.php
add_action( 'run_pms_variables', 'pms_variables_function' );
function pms_variables_function ($uid ) {
$the_group_uid = isset($_COOKIE["v_group_id"]) && !empty($_COOKIE["v_group_id"]) ? trim(strip_tags($_COOKIE["v_group_id"])) : "";
$session_detail = vpb_get_the_user_detail($uid);
$session_username = strlen($session_detail[0]) > 40 ? ucfirst(substr($session_detail[0],0,40)) : ucfirst($session_detail[0]);
$session_uid = $session_detail[1];
$session_email = $session_detail[2];
$session_photo = $session_detail[3];
$session_country = $session_detail[4];
//$session_usernames = explode(' ', $session_detail[0]);
$session_firstname = get_user_meta($uid,'first_name', true );
$session_lastname = get_user_meta($uid,'last_name', true );
}
and using eventually in my files like:
do_action('run_pms_variables', $uid );
I mean, can you address me to the right method? Thanks.

Write a class, declare a global object of that class, save all your variables as attribute/property of that class.
Now from anywhere just get the global object.
You have all variables stored inside that.

Uuuuhmm you are mixing apples with peaches. The WordPress Hooks, Actions and Filters are ment to modify the WordPress core the way you want, it is not build to store any data somewhere in your template.
One way to do it would be to simply store the values in the database of your WordPress installation. To do that you need to get familiar with the "Nonce" function, which is security mechanism for storing stuff in the database of WP.
There are hundrets and thousands of tutorials out there which show how to do it.
If you want only to store some numeric values or short strings, you could use the HTML data-* object to store some data, when php spits it back.

add_action( 'run_pms_variables', 'pms_variables_function' );
function pms_variables_function ($uid ) {
class GlobalVariables{
function __construct ($uid){
$this->the_group_uid = isset($_COOKIE["v_group_id"]) && !empty($_COOKIE["v_group_id"]) ? trim(strip_tags($_COOKIE["v_group_id"])) : "";
$this->session_detail = vpb_get_the_user_detail($uid);
$this->session_username = strlen($session_detail[0]) > 40 ? ucfirst(substr($session_detail[0],0,40)) : ucfirst($session_detail[0]);
$this->session_uid = $session_detail[1];
$this->session_email = $session_detail[2];
$this->session_photo = $session_detail[3];
$this->session_country = $session_detail[4];
//$session_usernames = explode(' ', $session_detail[0]);
$this->session_firstname = get_user_meta($uid,'first_name', true );
$this->session_lastname = get_user_meta($uid,'last_name', true );
}
}
return GlobalVariables($uid);
}
//and to access:
$global_variables = do_action('run_pms_variables', $uid );
echo $global_variables->the_group_uid;
As a side note, be definition global variables are variables that can be accessed anywhere, other options include setting variables in the $_SESSION super global (as most of you're variables look session specific) inside the pms_variables_function instead of setting class attributes.

Related

PHP Custom CMS - How to handle settings

I'm currently trying to find a way to handle settings on my custom CMS (just a playground to learn PHP). I have database table that stores all settings. My temporary solution is a function that returns one dimensional array with query results.
// Get settings from db.
function getPanelOptions( $pdo ) {
$options = [];
$getOptions = $pdo->query( 'SELECT option_name, option_value FROM bp_options' );
while( $result = $getOptions->fetch() ) {
$options[ $result['option_name'] ] = $result['option_value'];
}
return $options;
}
$bpOptions = getPanelOptions( $pdo ); // Get settings to arr.
// Example use
if( $bpOptions['post_max_lenght'] === 400 ) ...
I've read a lot that global variables are not best way to do this, so I call function in file that is included on every page. I don't have problem with using hard coded variable, because I won't change it (even so I can replace all occurrences in sublime). My biggest problem is that I can't find a way to use settings to create a 'wrapper' functions like in WordPress, for example 'getHtmlLang()'. In JS it would be easy, but in PHP I need to pass setting to this function, at it gets to lengthy.
// Now i use
<html lang="<?php echo $bpOptions['panel_lang']; ?>">
// I'd like some wrapper function.
<html <?php getHtmlLang() ?>>
I'm not familiar with OOP in PHP so maybe this is way to achieve this, or should I simply use global because it's justified?

Using a URL query string variable in a Wordpress page or post

I want to access and use a variable passed in the URL within a WordPress page (not a template file, but the page itself).
Here's what I'm trying to accomplish. I want to create a single page that will display different WP content by using text passed in the URL in shortcodes and elsewhere on the page. So, if the URL was specified as:
www.greenneedham.org/blog/topicpage/?topic=solar
I will be able to use the passed text ('solar') in shortcodes and other places in the page, like this:
[documents category_name="solar" numberposts="-1" orderby="title" order="ASC"]
Ideally, I'd like to be able to create a variable or field that I can simply use within the page text. I just don't know how to accomplish that.
Here's what I've considered/tried:
1) There are plugins that access the passed variables (e.g. URL params), but that would seem to require nested shortcodes:
[documents category_name="[urlparam param="topic" default="home-energy-savings"/]" numberposts="-1" orderby="title" order="ASC"]
That doesn't work, and I'm not aware of any way to accomplish that.
Added: The Shortcode API documentation at http://codex.wordpress.org/Shortcode_API#Square_Brackets explains that the shortcode parser cannot handle square brackets within an attribute. Unfortunately, that's exactly what I'm trying to do.
If that won't work, The question is now - Is there some way within the page content of presenting a shortcode string that has been modified based on a query variable?
EndAdded
2) Using a filter to add the variable allows me to access the variable within a page template (e.g. page.php), but I want to use the value within the page itself.
3) Plugins to allow PHP snippets within a page or post. This seems to be generally discouraged. It's also complex, and the page itself (which may be used by non-coders) would get hard to use.
Any help or guidance would be much appreciated. Thanks!
add_shortcode('cat', 'get_name');
function get_name() {
return '[category_name='.$_GET['topic'].' numberposts="-1" orderby="title" order="ASC"]';
}
or echo do_shortcode('[category_name='.$_GET['topic'].' numberposts="-1" orderby="title" order="ASC"]'); // instead of return.
Should work as snippet function. then use it as [cat] shortcode
In addition, remember to sanitize your $_GET variable. Here's an example in the context of a simple shortcode to display a query variable within the page text, with reference to where I took the sanitizing code from:
//[query_string label="" class="" var=""] shortcode
function query_string_shortcode( $atts, $content = null ) {
//Create an array of default values for attributes. These don't have to be blank. If specified as attributes in the shortcode, those values will be used instead.
$a = shortcode_atts( array(
'label' => '',
'class' => '',
'var' => '',
), $atts );
//Create variables from atts/defaults
$label = $a['label'];
$class = $a['class'];
/*
* 1. Check if the variable is set
* 2. If so, sanitize the input for security (https://wordpress.stackexchange.com/questions/351292/sanitize-get-query-var-url-parameters)
* 3. Set the variable
*/
$var = ( isset( $_GET[$a['var']] ) ) ? sanitize_text_field( $_GET[$a['var']] ) : '';
if(!empty($label)) {
$label = "<b>$label</b>";
}
if(!empty($var)) {
$html = '<span class="pt-query ' . $class . '">' . $label . $var . '</span>';
return $html;
}
return;
}
add_shortcode( 'query_string', 'query_string_shortcode' );

Wordpress functions variable, cannot access from another file

I have a wordpress functions file in the themes directory running some code in order to apply custom fields to the Job Manager plugin.
The code runs fine, and everything works in order for example it allows you to enter the data and the data will then be displayed on the front end, however not where I want it to display.
I have tried including this functions file, into another php file where I am designing the look on the front end. However, when including the file the variables are not accessible and even though I am echoing the variable name out, nothing appears?
I have tried using a SESSION but even this doesn't work?
function display_job_salary_data() {
global $post;
$salary = get_post_meta( $post->ID, '_job_salary', true );
$salary = number_format($salary);
if ( $salary ) {
echo esc_html($salary);
}
}
Salary is the variable that I need to access in another php file
When a variable is created inside in a function, it's only accessible within the scope of that function.
If you want to use the value in any other way, the function needs to return the value.
Since your function name starts with display_, it wouldn't be very intuitive if it returned something, so I would break it up into two different functions.
First function gets and returns the salary data:
function get_job_salary_data() {
global $post;
$salary = get_post_meta( $post->ID, '_job_salary', true );
$salary = number_format($salary);
return $salary;
}
The second function outputs the salary data: (Just like it did before)
function display_job_salary_data() {
// Get the salary data from our previous function
$salary = get_job_salary_data();
if ( $salary ) {
echo esc_html($salary);
}
}
Now you can get the salary data where ever (as long as the file with the functions are included):
// Get the salary data
$salary = get_job_salary_data();
// ...or just output it, just like before
display_job_salary_data();
To read more about variable scopes, I recommend reading PHP's documentation about the subject here: http://php.net/manual/en/language.variables.scope.php

Drupal global variables between module hook functions

Can anyone advice how best to set a temporary variable with scope to be used between hooks?
I have a custom module with the purpose of checking and warning if an attempted file upload matches an existing file on the system.
I am using hook_form_alter to identify the specific upload form and hook_file_validate to check if the file was previously uploaded.
My problem is those two hooks don't share a common parameter - I need to pass information from hook_form_alter back to hook_validate.
The information I want the functions to share is a simple boolean which should be destroyed immediately the file upload is done/dismissed, so using variable_set to persist it to the database is overkill. I don't believe a session or cookie approach is best either.
UPDATES:
Globals approach:
function duplicate_uploads_warning_init(){
$GLOBALS['processed'] = 'testing';
}
function duplicate_uploads_warning_file_validate($file){
drupal_set_message("PROCESSED[file-validate]: {$GLOBALS['processed']}", 'warning');
}
function duplicate_uploads_warning_form_alter(&$form, &$form_state, $form_id){
if( $form_id == 'file_entity_add_upload' ){
drupal_set_message("PROCESSED[form-alter]: {$GLOBALS['processed']}", 'error');
$GLOBALS['processed'] = 'tested';
$form['#validate'][] = 'duplication_validate';
}
}
The code above sets GLOBALS[processed] in the init hook and that value in immediately confirmed in the hook_form_alter.
However the attempt to reassign the value to tested fails. The reassigned value is what I hoped to see in hook_file_validate but I still get the initial value of testing.
Hook_form_alter validation approach:
I tried adding a custom validation function but the upload of the image still took place where I intend to stop it. My code is as follows:
function duplication_validate($form, &$form_state) {
$data = duplicates($form_state['complete form']['upload']['#file']->filename);
if( sizeof($data) > 0 ){
form_set_error('test', 'testing validation');
return false;
}
}
I can confirm my $data variable has content and the sizeof test returns greater than 0.
using variable_set to persist it to the database is overkill
I don't agree they are overkill (you can easily delete variables), and as #2pha have mentioned globals are not recommended. I think you could use variable_set($name, $value), variable_get($name), and variable_del($name) without worrying unless you need to super-optimise your sites database queries. If you really don't want to use the variable_* functions, then maybe cache_set() and cache_get() might work because you can give it a temporary status.
Edit, variables approach:
function duplicate_uploads_warning_init(){
$account = \Drupal::currentUser();
variable_set($account->id() . '_processed', 'testing');
}
function duplicate_uploads_warning_file_validate($file){
$account = \Drupal::currentUser();
$processed_var = variable_get($account->id() . '_processed');
drupal_set_message("PROCESSED[file-validate]: {$processed_var}", 'warning');
}
function duplicate_uploads_warning_form_alter(&$form, &$form_state, $form_id){
if( $form_id == 'file_entity_add_upload' ){
$account = \Drupal::currentUser();
$processed_var = variable_get($account->id() . '_processed');
drupal_set_message("PROCESSED[form-alter]: {$processed_var}", 'error');
variable_set($account->id() . '_processed', 'tested');
$form['#validate'][] = 'duplication_validate';
}
}
… and in a success or #submit callback function run variable_del($account->id() . '_processed') to delete the variable.
maybe $GLOBALS['processed'] was initialized with the static keyword elsewhere....?

Best practice to place meta tags, links and styles in zend framework?

I have project-range meta tags that are need to be set.
I've put them in protected method _initMeta in Bootstrap class.
Are there any better options? What if I would like different set of this data for another languages?
protected function _initMeta(){
$this->bootstrap('view');
$view = $this->getResource('view');
$view->doctype('XHTML1_STRICT');
$view->headTitle()->headTitle('Foo title');
$view->headMeta()->appendName('keywords','foo');
$view->headMeta()->appendHttpEquiv('Content-Type', 'text/html; charset=UTF-8')
->appendHttpEquiv('Content-Language', 'any');
$view->headLink()->appendStylesheet('/foo.css')->headLink(array('rel' => 'favicon',
'href' => '/favicon.ico'),
'PREPEND');
}
I use config for basic (bootstrap) data as:
application.ini
resources.view.meta.name.Viewport = "width=device-width, initial-scale=1.0"
resources.view.meta.name.MobileOptimized = "width"
resources.view.meta.name.HandheldFriendly = "true"
resources.view.meta.name.Keywords = "basic,keywords"
...
; format resources.view.headStyle.{MEDIA}.nfile =
resources.view.headStyle.all.1.href = "/css/basic.css"
resources.view.headStyle.all.1.conditionalStylesheet =
resources.view.headStyle.all.1.extras.title = "Basic style"
resources.view.headStyle.all.1.extras.charset = "utf-8"
resources.view.headStyle.all.2.href = "/css/ie.css"
resources.view.headStyle.all.2.conditionalStylesheet = "IE"
resources.view.headStyle.all.2.extras.title = "Internet Explorer style"
resources.view.headStyle.all.2.extras.charset = "utf-8"
; print media example
resources.view.headStyle.print.1.href = "/css/print.css"
...
; format resources.view.headLink.{REL} =
resources.view.headLink.humans.href = "/humans.txt"
resources.view.headLink.humans.type = "text/plain"
; ___ will be replaced by space, __ by point (or set another nest separator)
resources.view.headLink.shortcut___icon.href = "/favicon.png"
resources.view.headLink.shortcut___icon.type = "image/png"
...
At this point, maybe you have some special data. For example in:
project1.ini
project.headLink.author.href = "https://plus.google.com/XXXXX?rel=author"
project.headLink.image_src.href = "/author.jpg"
project.headLink.image_src.type = "image/jpg"
And finally, you mix all in your
Bootstrap.php
(example for *_initHeadLink()*):
// $options = your app options (basic)
// $projectOptions = your project options (special)
// $assets_url = your assets url
if ( is_array($headStyle = $options['headStyle']) ) {
foreach ( $headStyle as $media => $value ) {
foreach ( $value as $style ) {
extract($style);
$this->view->headLink()->appendStylesheet($assets_url . $href, $media,
$conditionalStylesheet, $extras);
}
}
}
$headLinks = array();
if ( isset($options['headLink']) )
$headLinks = $options['headLink'];
if ( isset($projectOptions['headLink']) )
$headLinks = array_merge($headLinks, (array) $projectOptions['headLink']);
// *array key, is the value for rel
foreach ( $headLinks as $rel => $value ) {
$rel = str_replace(array('___', '__'), array(' ', '.'), $rel);
$this->view->headLink()->headLink(array_merge(array('rel' => $rel), (array) $value));
}
Then, you can override these data from your Controller: setName, set...
I hope it helps ;)
You have several ways of achieving this. First and foremost, make sure the moment you define the metadata you already know what language will be loaded for the current request. Sometimes this may not be easy to determine at bootstrap time.
Having said this, besides the bootstrap, you can set the metadata on a:
Front Controller Plugin class (using for example the dispatchLoopStartup() or predispatch() methods).
Action Helper class (using for example the init() or preDispatch() methods).
At those points of execution you probably already determined the language to use, and can set the metadata accordingly. You can always change the metadata afterwards in your action controllers for specific cases in your application, so you're never really stuck if you previously specified metadata.
In my own work, I have this setup:
Front Controller Plugin, dispatchLoopStartup() method: determine language to load, giving priority to a "lang" GET parameter in the request object, then browser language, then default site language. I also use this to determine if the request is a normal request or an ajax request; if it's the former case, I register an action helper, see next...
Action Helper, preDispatch() method: load metadata depending on language and other stuff, load Layout and widgets, etc.
Action controller, someAction() method: if necessary, change some of the previously set metadata, for example headTitle(), which can depend on the effectively loaded content.
This arrangement makes sense to me, maybe it can help your approach?
The bootstrap is way to early for my projects. I add them in my controller/actions
$keywords = 'php,zend,framework';
$this->view->headMeta($keywords,'keywords','name',array(),'SET');
... etc.
Actually very late almost at the end. At this point I would also know about language and other things.

Categories