PHP - override an output, multiple config - php

I have an echo:
echo 'Hello world';
and there are two places where I can mange if this echo will visible or not, I can check them using:
global_option('show_echo');
and
post_option('show_echo');
Pleae tell how to override global_option from post_option, Like:
In global_option('show_echo') echo was set to hidden, and visible in post_option('show_echo'); then output the echo.
How to do I make a else if which give priority to post_option, mean post_option can override global_option.
Suggest me a simplest way to achieve this

It sounds like you need a function which implements the order of priority:
function check_config( $key) {
// Your question is unclear as to the exact logic necessary here
$post = post_option( $key);
if( isset( $post)) return $post;
$global = global_option( $key);
if( isset( $global)) return $global;
return false;
}
Then just call it with:
if( check_config( 'show_echo')) {
}

Related

The best way to use variables on all WordPress pages

I'm building a custom theme that has a lot of variables that I wish to use throughout.
Example:
$tv = $options['tv'];
$movies = $options['movies'];
$print = $options['print'];
//....and about 50 more.
For this purpose I have been simply placing them all in a file called vars.php and then in header.php of the theme I include it...
require_once('vars.php');
While this does work, it doesn't feel like the best way. I've read on numerous occasions that use global variables (presumably in functions.php) isn't a good idea, but is this true?
But if it's fine to use global variables in functions.php (even lots of them) is this the right way to go about it?:
global $tv;
$tv = $options['tv'];
global $movies
$movies = $options['movies'];
global $print
$print = $options['print'];
The best way for this is to define all the variables explicitly in functions.php or in main plugin file for plugin. I have verified this is the way most popular plugins including akismet use. Specifically you need to do this.
define( MYVAR_TV, $options['tv'] );
define( MYVAR_MOVIES, $options['movies'] );
define( MYVAR_PRINT, $options['print'] );
After these you can just use them whereever you want like
echo MYVAR_TV;
Hope it helps.
It's fine to use global, but it's not encouraged (you can read more here Are global variables in PHP considered bad practice? If so, why?). You may consider Singleton implementation:
<?php
class GlobalVariable {
/**
* #var array
*/
public static $option = [];
}
// You can set the variable using this way
GlobalVariable::$option['movies'] = 1;
// And get the variables using that array
print_r(GlobalVariable::$option);
Hope this can help you.
What about creating a function in functions.php that returns an array of your variables?
Example: $options = get_my_custom_vars();
I'm assuming that you would like global variables, where it makes an array with all your variables. To use it:
$GLOBALS['your-varriable']
Source:
PHP Documentation
I personally like using Acf Options Addon. Altering these and having them translatable via the wpml plugin is useful, too.
These Options will be addable/editable within a "Options Page" in the Backend or as programmed as described in the link.
After initializing the addon via the functions.php
if( function_exists('acf_add_options_page') ) {
acf_add_options_page();
}
simply call these in the template via
<?php the_field('header_title', 'option'); ?>
These examples were taken from the Acf Options Page documentation.
Keep in mind https://www.advancedcustomfields.com/ has to be installed for this to work.
You can implement a custom stream wrapper, too. This way you could access and store data using functions like file_get_contents, file_put_contents, fread, fwrite, etc. Just like reading and writing from a file, or getting info from a remote URL.
Actually there is an example in the PHP manual, using global variables like you ask. But lets pull it from there in order of completeness and adapting it to your use case in WP and examples of use.
<?php
// variable-stream-class.php just this is pulled from the PHP manual
class VariableStream {
var $position;
var $varname;
function stream_open($path, $mode, $options, &$opened_path)
{
$url = parse_url($path);
$this->varname = $url["host"];
$this->position = 0;
return true;
}
function stream_read($count)
{
$ret = substr($GLOBALS[$this->varname], $this->position, $count);
$this->position += strlen($ret);
return $ret;
}
function stream_write($data)
{
$left = substr($GLOBALS[$this->varname], 0, $this->position);
$right = substr($GLOBALS[$this->varname], $this->position + strlen($data));
$GLOBALS[$this->varname] = $left . $data . $right;
$this->position += strlen($data);
return strlen($data);
}
function stream_tell()
{
return $this->position;
}
function stream_eof()
{
return $this->position >= strlen($GLOBALS[$this->varname]);
}
function stream_seek($offset, $whence)
{
switch ($whence) {
case SEEK_SET:
if ($offset < strlen($GLOBALS[$this->varname]) && $offset >= 0) {
$this->position = $offset;
return true;
} else {
return false;
}
break;
case SEEK_CUR:
if ($offset >= 0) {
$this->position += $offset;
return true;
} else {
return false;
}
break;
case SEEK_END:
if (strlen($GLOBALS[$this->varname]) + $offset >= 0) {
$this->position = strlen($GLOBALS[$this->varname]) + $offset;
return true;
} else {
return false;
}
break;
default:
return false;
}
}
function stream_metadata($path, $option, $var)
{
if($option == STREAM_META_TOUCH) {
$url = parse_url($path);
$varname = $url["host"];
if(!isset($GLOBALS[$varname])) {
$GLOBALS[$varname] = '';
}
return true;
}
return false;
}
}
Let's suppose you have a plugin to isolate your functions, being able to deactivate it for debugging and not losing it if you change the active theme. I'd recommend putting something like this in your plugin entrypoint:
<?php
/**
* Plugin Name: Stream Wrapper for global variables
* Plugin URI: https://stackoverflow.com/q/46248656/
* Description: Utility class and functions to enable global data sharing in WordPress
* Author: Jesús E. Franco Martínez and the PHP Documentation Group
* Contributors: tzkmx
* Version: 0.1
* Author URI: https://tzkmx.wordpress.com
*/
require 'variable-stream-class.php';
stream_wrapper_register("var", "VariableStream")
or wp_die("Failed to register protocol", null, ['back_link' => true]);
Then, in your templates or other site plugins you can use the above mentioned functions, or use custom aliases. Let's expand on your request:
// functions.php in your theme or better, in the same plugin.php above
// Using a hook just for frontend in order to get populated
// our variables without require calls in the theme.
add_action('wp_head', 'populate_my_awesome_plugin_options');
function populate_my_awesome_plugin_options() {
// Let's say you get your data from a single get_option call
$options = get_option( 'my_awesome_plugin_options' );
foreach( $options as $key => $value ) {
file_put_contents( 'var://' . $key, $value );
}
}
function pop_get_var( $var_name ) {
return file_get_contents( 'var://' . $var_name );
}
Finally, in the header.php or whatever template file you are going to consume your data, the call is just like this:
<p>TV favorite show: <strong><?= pop_get_var( 'tv' ) ?></strong></p>
<p>Movies I like: <strong><?= pop_get_var( 'movies' ) ?></strong></p>
<p>Impressum: <em><?= pop_get_var( 'print' ) ?></em></p>
I know it may look like a lot of boilerplate at first, but because of separation of concerns, you are not limited only to scalar values like using constants, also your stream wrapper could be an adapter to whatever data store you like and not only in memory or stored in WordPress options table. And using a custom function eases you the hassle of writing such long calls to a singleton class, or calling global wherever you want to access your custom data.
Actually if you read the examples in the PHP manual, you'll find an example of using the wrapper to store an entire text, that you could call with include. There is nothing stopping you from using even serialized data, in example with json_encode/json_decode, and stored with your wrapper, even directly in the database with little effort. There is another example to write/read data from a database with PDO, but is easily ported to use WordPress $wpdb object.

PHP Memcached delete function not working as expected

So the problem is that the keys I want to delete from memcached are actually not being removed. I get no errors. At this point I don't really have a clue what the problem could be. It also shows the correct key it wants to delete so there is nothing wrong with that.
Down below my Class for using memcached, does anybody have any clue on what the problem might be? So far I didn't find any clues on what the problem might be or how to fix the problem.
class MemCacher extends Memcached{
function __construct(){
parent::__construct();
parent::addServer(MEMCACHED_SERVER,11211,1);
}
function add($p_sKey,$p_oData,$p_iTime = 43200){
$t_sKey = CACHE_NAME.$p_sKey;
parent::set($t_sKey,$p_oData,$p_iTime);
}
function get($p_sKey){
$t_sKey = CACHE_NAME.$p_sKey;
return parent::get($t_sKey);
}
function remove($p_sKey){
$t_sKey = CACHE_NAME.$p_sKey;
parent::delete($t_sKey);
debug("Deleted:".$t_sKey);
}
function show_all(){
if( $l_aCacheInfo = parent::getAllKeys() ){
foreach($l_aCacheInfo as $key){
if( strpos($key, CACHE_NAME) !== FALSE ){
debug($key);
}
}
}
}
function clear_all(){
if( $l_aCacheInfo = parent::getAllKeys() ){
foreach($l_aCacheInfo as $key){
if( strpos($key, CACHE_NAME) !== FALSE ){
parent::delete($key);
debug("Deleted:".$key);
}
}
}
}
}
So apparently the delete method requires the expiration time to be 0 in order to remove it else it doesn't work.
doesn't work
parent::delete($t_sKey);
works
parent::delete($t_sKey,0);

php exit from an inner function

I have a function for creating post. Before save the new post, there is a hook for manipulating data before save:
function save(){
$data = apply_filters('data_before_save',array(....));
$post_id = wp_insert_post( $data );
return $post_id;
}
Now I am adding stuffs to the $data:
add_filter('data_before_save','conditional_save',10,1 );
function conditional_save( $data ){
//...some stuffs
if( $data['x']== $blabla ){
wp_safe_redirect( $link);
exit();
}else{
$data['x'] = $x;
}
return $data;
}
Will the function save be exited by the function conditional_save before the line save_post ?
I don't want return any data if condition meet. I tried my code, it seems works-- redirected and didn't create new post. But I want to make sure the function save is really stopped running.
exit() will abruptly halt all execution of the code.
Its not usually a good idea.
Make use of FLAGS instead.
EDIT :
FLAG is not a reserved keyword.
Just set a var to true/false on your conditional save, check for the flag on your save(). Depends on the result of the var you can restrict what to do and what not to.

Function to return true if current page has child pages

I'm trying to create a simple function to do a "status test". Goal is to test and see if the current page being viewed has any child pages or not. Using this to alter layout to accomodate child pages. The following code seems like it should work, but alas, no dice.
Anyone see what I'm missing? EDIT- Note that this is in WordPress.
function is_subpage() {
global $post; // load details about this page
if ( is_page() && $post->post_parent ) { // test to see if the page has a parent
return true; // return true, confirming there is a parent
} else { // there is no parent so ...
return false; // ... the answer to the question is false
}
}
Take a look here: http://wordpress.org/support/topic/using-query-posts-to-list-child-pages?replies=7
Since it seems a bit resources intensive to load all the child pages just to do a simple check, I thought of this early this morning:
function has_children($p = null) {
global $post, $wpdb;
$pid = ($p) ? $p : $post->post_parent;
if ($pid) :
$r = $wpdb->get_row("SELECT ID FROM $wpdb->posts WHERE post_parent = $pid LIMIT 1");
if ($r) : return true; endif;
else :
return false;
endif;
}
You can use it just as if (has_children()) or pass it the post parent if (has_children($post-post_parent)) — the latter is helpful if you're using get_posts/get_pages and not the global $post variable.

Simple template var replacement, but with a twist

So I'm setting up a system that has a lot of emails, and variable replacement within it, so I'm writing a class to manage some variable replacement for templates stored in the database.
Here's a brief example:
// template is stored in db, so that's how this would get loaded in
$template = "Hello, %customer_name%, thank you for contacting %website_name%";
// The array of replacements is built manually and passed to the class
// with actual values being called from db
$replacements = array('%customer_name%'=>'Bob', '%website_name%'=>'Acme');
$rendered = str_replace(array_keys($replacements), $replacements, $template);
Now, that works well and good for single var replacements, basic stuff. However, there are some places where there should be a for loop, and I'm lost how to implement it.
The idea is there'd be a template like this:
"hello, %customer_name%, thank you for
requesting information on {products}"
Where, {products} would be an array passed to the template, which the is looped over for products requested, with a format like:
Our product %product_name% has a cost
of %product_price%. Learn more at
%product_url%.
So an example rendered version of this would be:
"hello, bob, thank you for requesting
information on:
Our product WidgetA has a cost of $1.
Learn more at example/A
Our product WidgetB has a cost of $2.
Learn more at example/B
Our product WidgetC has a cost of $3.
Learn more at example/C.
What's the best way to accomplish this?
Well, I really dont see the point in a template engine that uses repalcements/regex
PHP Is already a template engine, when you write <?php echo $var?> its just like doing <{$var}> or {$var}
Think of it this way, PHP Already translates <?php echo '<b>hello</b>'?> into <b>hello</b> by its engine, so why make it do everything 2 times over.
The way i would implement a template engine is like so
Firstly create a template class
class Template
{
var $vars = array();
function __set($key,$val)
{
$this->vars[$key] = $val;
}
function __get($key)
{
return isset($this->vars[$key]) ? $this->vars[$key] : false;
}
function output($tpl = false)
{
if($tpl === false)
{
die('No template file selected in Template::output(...)');
}
if(!file_exists(($dir = 'templates/' . $tpl . '.php')))
{
die(sprintf('Tpl file does not exists (%s)',$dir));
}
new TemplateLoader($dir,$this->vars);
return true;
}
}
This is what you use in your login such as index.php, you will set data just like an stdClass just google it if your unsure. and when you run the output command it sends the data and tpl to the next class below.
And then create a standalone class to compile the tpl file within.
class TemplateLoader
{
private $vars = array();
private $_vars = array(); //hold vars set within the tpl file
function __construct($file,$variables)
{
$this->vars = $variables;
//Start the capture;
ob_start();
include $file;
$contents = ob_get_contents();
ob_end_clean(); //Clean it
//Return here if you wish
echo $contents;
}
function __get($key)
{
return isset($this->vars[$key]) ? $this->vars[$key] : (isset($this->_vars[$key]) ? $this->_vars[$key] : false) : false;
}
function __set($key,$val)
{
$this->_vars[$key] = $val;
return true;
}
function bold($key)
{
return '<strong>' . $this->$key . '</string>';
}
}
The reason we keep this seperate is so it has its own space to run in, you just load your tpl file as an include in your constructor so it only can be loaded once, then when the file is included it has access to all the data and methods within TemplateLoader.
Index.php
<?php
require_once 'includes/Template.php';
require_once 'includes/TemplateLoader.php';
$Template = new Template();
$Template->foo = 'somestring';
$Template->bar = array('some' => 'array');
$Template->zed = new stdClass(); // Showing Objects
$Template->output('index'); // loads templates/index.php
?>
Now here we dont really want to mix html with this page because by seperating the php and the view / templates you making sure all your php has completed because when you send html or use html it stops certain aspects of your script from running.
templates/index.php
header
<h1><?php $this->foo;?></h1>
<ul>
<?php foreach($this->bar as $this->_foo):?>
<li><?php echo $this->_foo; ?></li>
<?php endforeach; ?>
</ul>
<p>Testing Objects</p>
<?php $this->sidebar = $this->foo->show_sidebar ? $this->foo->show_sidebar : false;?>
<?php if($this->sidebar):?>
Showing my sidebar.
<?php endif;?>
footer
Now here we can see that were mixing html with php but this is ok because in ehre you should only use basic stuff such as Foreach,For etc. and Variables.
NOTE: IN the TemplateLoader Class you can add a function like..
function bold($key)
{
return '<strong>' . $this->$key . '</string>';
}
This will allow you to increase your actions in your templates so bold,italic,atuoloop,css_secure,stripslashs..
You still have all the normal tools such as stripslashes/htmlentites etc.
Heres a small example of the bold.
$this->bold('foo'); //Returns <strong>somestring</string>
You can add lots of tools into the TempalteLoader class such as inc() to load other tpl files, you can develop a helper system so you can go $this->helpers->jquery->googleSource
If you have any more questions feel free to ask me.
----------
An example of storing in your database.
<?php
if(false != ($data = mysql_query('SELECT * FROM tpl_catch where item_name = \'index\' AND item_save_time > '.time() - 3600 .' LIMIT 1 ORDER BY item_save_time DESC')))
{
if(myslq_num_rows($data) > 0)
{
$row = mysql_fetch_assc($data);
die($row[0]['item_content']);
}else
{
//Compile it with the sample code in first section (index.php)
//Followed by inserting it into the database
then print out the content.
}
}
?>
If you wish to store your tpl files including PHP then that's not a problem, within Template where you passing in the tpl file name just search db instead of the filesystem
$products = array('...');
function parse_products($matches)
{
global $products;
$str = '';
foreach($products as $product) {
$str .= str_replace('%product_name%', $product, $matches[1]); // $matches[1] is whatever is between {products} and {/products}
}
return $str;
}
$str = preg_replace_callback('#\{products}(.*)\{/products}#s', 'parse_products', $str);
The idea is to find string between {products} and {products}, pass it to some function, do whatever you need to do with it, iterating over $products array.
Whatever the function returns replaces whole "{products}[anything here]{/products}".
The input string would look like that:
Requested products: {products}%product_name%{/products}

Categories