How do I access a variable inside of preg_replace_callback? - php

I'm trying to replace {{key}} items in my $text with values from a passed array. but when I tried adding the print_r to see what was going on I got a Undefined variable: kvPairs error. How can I access my variable form within the preg_replace_callback?
public function replaceValues($kvPairs, $text) {
$text = preg_replace_callback(
'/(\{{)(.*?)(\}})/',
function ($match) {
$attr = trim($match[2]);
print_r($kvPairs[strtolower($attr)]);
if (isset($kvPairs[strtolower($attr)])) {
return "<span class='attr'>" . $kvPairs[strtolower($attr)] . "</span>";
} else {
return "<span class='attrUnknown'>" . $attr . "</span>";
}
},
$text
);
return $text;
}
Update:
I've tried the global scope thing, but it doesn't work either. I've added 2 print statements to see whats doing on, one inside and one outside the preg_replace_callback.
public function replaceValues($kvPairs, $text) {
$attrTest = 'date';
print_r("--" . strtolower($attrTest) . "--" . $kvPairs[strtolower($attrTest)] . "--\n");
$text = preg_replace_callback(
'/(\{{)(.*?)(\}})/',
function ($match) {
global $kvPairs;
$attr = trim($match[2]);
print_r("==" . strtolower($attr) . "==" . $kvPairs[strtolower($attr)] . "==\n");
if (isset($kvPairs[strtolower($attr)])) {
return "<span class='attr'>" . $kvPairs[strtolower($attr)] . "</span>";
} else {
return "<span class='attrUnknown'>" . $attr . "</span>";
}
},
$text
);
return $text;
}
The output I get is:
--date--1977-05-20--
==date====

As your callback function is a closure, you can pass extra arguments via use
function ($match) use ($kvPairs) {
...
}
better than polluting the global space

Related

Cannot redeclare two functions

How can I solve the following issue with the code attached? Seems that somehow Wordpress (or some kind of plugin) is calling the function twice.
function my_wpcf7_form_elements($html) {
function ov3rfly_replace_include_blank($name, $text, &$html) {
$matches = false;
preg_match('/<select name="' . $name . '"[^>]*>(.*)<\/select>/iU', $html, $matches);
if ($matches) {
$select = str_replace('<option value="">---</option>', '<option value="">' . $text . '</option>', $matches[0]);
$html = preg_replace('/<select name="' . $name . '"[^>]*>(.*)<\/select>/iU', $select, $html);
}
}
ov3rfly_replace_include_blank('countrylist', 'España', $html);
return $html;
}
add_filter('wpcf7_form_elements', 'my_wpcf7_form_elements');
Fatal error: Cannot redeclare ov3rfly_replace_include_blank() (previously declared in /Applications/XAMPP/xamppfiles/htdocs/w/wp-content/themes/bulwark_child/functions.php:21) in /Applications/XAMPP/xamppfiles/htdocs/w/wp-content/themes/bulwark_child/functions.php on line 21
Dont nest the functions - your current code declares the inner function every time the outer function is called, thereby causing the error the second time:
function ov3rfly_replace_include_blank($name, $text, &$html) {
$matches = false;
preg_match('/<select name="' . $name . '"[^>]*>(.*)<\/select>/iU', $html, $matches);
if ($matches) {
$select = str_replace('<option value="">---</option>', '<option value="">' . $text . '</option>', $matches[0]);
$html = preg_replace('/<select name="' . $name . '"[^>]*>(.*)<\/select>/iU', $select, $html);
}
}
function my_wpcf7_form_elements($html) {
ov3rfly_replace_include_blank('countrylist', 'España', $html);
return $html;
}
add_filter('wpcf7_form_elements', 'my_wpcf7_form_elements');
Check this file for re declare function as error message suggested
/Applications/XAMPP/xamppfiles/htdocs/w/wp-content/themes/bulwark_child/functions.php:21
rename one function and see whether it working or not
Write a separate function,multiple function calling in nested function:
function my_wpcf7_form_elements($html) {
ov3rfly_replace_include_blank('countrylist', 'España', $html);
return $html;
}
function ov3rfly_replace_include_blank($name, $text, &$html) {
$matches = false;
preg_match('/<select name="' . $name . '"[^>]*>(.*)<\/select>/iU', $html, $matches);
if ($matches) {
$select = str_replace('<option value="">---</option>', '<option value="">' . $text . '</option>', $matches[0]);
$html = preg_replace('/<select name="' . $name . '"[^>]*>(.*)<\/select>/iU', $select, $html);
}
}
add_filter('wpcf7_form_elements', 'my_wpcf7_form_elements');

how to limit numwords article in codeigniter?

i have cms blog with codeigniter. but when i limit content in article is not working. i am newbie in codeigntier can you tell me what am i to do.
this is cms_helper.php
function get_excerpt($article, $numwords = 20){
$string = '';
$url = article_link($article);
$string .= '<h2>' . anchor($url, e($article->judul_berita)) . '</h2>';
$string .= '<p class="pubdate">' . e($article->tanggal) . '</p>';
$string .= '<p>' . e(limit_to_numwords(strip_tags($article->content), $numwords)) . '</p>';// content is not show
$string .= '<p>' . anchor($url, 'Read more', array('judul_berita' => e($article->judul_berita))) . '</p>';
return $string;
}
function limit_to_numwords($string, $numwords){
$excerpt = explode(' ', $string, $numwords + 1);
if (count($excerpt) >= $numwords) {
array_pop($excerpt);
}
$excerpt = implode(' ', $excerpt);
return $excerpt;
}
function e($string){
return htmlentities($string);
}
in controller
private function _homepage()
{
$this->load->model('mberita');
$this->db->limit(6);
$this->data['articles'] = $this->mberita->get_berita();
//var_dump($this->data['articles']);
}
please help me what to do. thank you.
You should use Codeigniter text helper:
$this->load->helper('text'); // add this to the the function or to the constructor
$string .= '<p>' . e(word_limiter(strip_tags($article->content), $numwords)) . '</p>';
In this article you can find many useful codeigniter text functions
Try the below sample. this will surely work.
function limit_to_numwords($text,$no_words){
$next=substr($text,$no_words,strlen($text));
$spacepos=strpos($next," ");
$desc=substr($text,0,$no_words+$spacepos)."...";
return $desc;
}
From this, you can get exact full word text from the nearest space character. hope this will help your requirement.
Also, try to call the function as "$this->limit_to_numwords"

Variable data behaving strangely inside a function

I am working on a CodeIgniter application.
A part of the nav menu for my application is generated from using session data. Since, I have to print the same thing at a number of places, I wrote a function to do the printing. The file which creates the menu is given below. The function print_roles_assigned() is used a number of times in this file.
$roles_assigned = $this->session->userdata('roles_assigned');
function print_roles_assigned() {
$output = '';
if ($roles_assigned)
{
foreach ($roles_assigned as $role) {
$output .= '<li>' . anchor('main/home/'.$role->role_name, $role->rol
e_name) . '</li>';
}
}
else
{
$output .= '<li>No roles have been assigned.</li>';
}
return $output;
}
The code given above didn't work. Out of any options, I resorted to using a $GLOBAL. An issue like this has never happened with me before and I am not sure if the use of $GLOBAL is appropriate. The new code is given below:
$GLOBALS['roles_assigned'] = $this->session->userdata('roles_assigned'); // Change made here
function print_roles_assigned() {
$output = '';
$roles_assigned = $GLOBALS['roles_assigned']; // Using the global variable inside function
if ($roles_assigned)
{
foreach ($roles_assigned as $role) {
$output .= '<li>' . anchor('main/home/'.$role->role_name, $role->rol
e_name) . '</li>';
}
}
else
{
$output .= '<li>No roles have been assigned.</li>';
}
return $output;
}
I would like to know:
Why my initial code failed to work?
Is the use of $GLOBAL appropriate?
What can be an alternate method to fix this issue?
The initial code failed because your $roles_assigned in not injected. Parameterise the function to "function print_roles_assigned($roles_assigned) { .. } " to access the $roles_assigned variable.
Why my initial code failed to work?
Each function has what is called variable scope. Variables declared outside of the function are not accessible from within the function unless they are passed in as parameters, are members of a class that the function is a member of, or are explicitly declared to be global.
There are three different ways to do this, take your pick.
The easiest way to do this is to just pass the function in as a parameter I.E.
$roles_assigned = $this->session->userdata('roles_assigned');
function print_roles_assigned($roles_assigned) {
$output = '';
if ($roles_assigned)
{
foreach ($roles_assigned as $role) {
$output .= '<li>' . anchor('main/home/'.$role->role_name, $role->rol
e_name) . '</li>';
}
}
else
{
$output .= '<li>No roles have been assigned.</li>';
}
return $output;
}
Another option is to make $roles_assigned a member of the class, I.E.
$this->roles_assigned = $this->session->userdata('roles_assigned');
function print_roles_assigned() {
$output = '';
if ($this->roles_assigned)
{
foreach ($this->roles_assigned as $role) {
$output .= '<li>' . anchor('main/home/'.$role->role_name, $role->rol
e_name) . '</li>';
}
}
else
{
$output .= '<li>No roles have been assigned.</li>';
}
return $output;
}
The other option (not recommended) is to use the global keyword I.E.
$roles_assigned = $this->session->userdata('roles_assigned');
function print_roles_assigned() {
global $roles_assigned;
$output = '';
if ($roles_assigned)
{
foreach ($roles_assigned as $role) {
$output .= '<li>' . anchor('main/home/'.$role->role_name, $role->rol
e_name) . '</li>';
}
}
else
{
$output .= '<li>No roles have been assigned.</li>';
}
return $output;
}
This sounds like a scope issue. Try using $this->roles_assigned for your reference to that array.
IMO, it's not good-practise to use GLOBAL in this way.

Problem returning excerpt with specified number of characters

I'm using the following code to grab a string and return a spesific number of characters
<div class="top_posts">
<ul>';
}
elseif($i>1 && $i<=$number_of_posts)
{
$retour.= "\n" . '<li>';
if($image_url) { $retour .= '<img src="' . get_bloginfo('template_directory') . '/js/timthumb.php?src=' . $image_url . '&h=120&w=180&zc=1" alt="" />'; }
$retour .= '<h6>' . the_title("","",false) . '</h6>';
$retour.= get_wpe_excerpt('wpe_popular_posts');
$retour.='</li>';
if($i%2==1)
$retour.= "\n" . '<li class="clear">&</li>';
}
$i++;
endforeach;
$retour.='</ul></div>';
return $retour;
}
add_shortcode('popular-posts', 'popular_posts_code');
The chunk at issue is this part
$retour.= get_wpe_excerpt('wpe_popular_posts');
which calls to
function wpe_popular_posts($length) {
return 55;
}
However I'm still getting the full text string untrimmed - any help appreciated.
//update
The get_wpe_excerpt function looks like this
function get_wpe_excerpt($length_callback='', $more_callback='') {
if(function_exists($length_callback)){
add_filter('excerpt_length', $length_callback);
}
if(function_exists($more_callback)){
add_filter('excerpt_more', $more_callback);
}
$output = get_the_excerpt();
$output = apply_filters('wptexturize', $output);
$output = apply_filters('convert_chars', $output);
$output = '<p>'.$output.'</p>';
return $output;
}
Now sure how the get_wpe_excerpt() function is done. You may want to try the simple code I used in several WordPress themes.
implode(' ', array_slice(explode(' ', get_the_content()), 0, 55));
You want to return the first 55 characters of the string?
Try substr($input, 0, 55);
However I really don't understand what's going on with that call to $retour.= get_wpe_excerpt('wpe_popular_posts');... so maybe I am misunderstanding what you are trying to achieve?

Simple templating with str_replace

I'm just experimenting first of all.
I just came up with an idea of making my own in a simple way here:
class Template
{
function parse($template_file, $braces)
{
if(file_exists($template_file))
{
$template = file_get_contents($template_file);
foreach($braces as $brace => $replacement)
{
$brace = trim(strtoupper($brace));
$build = str_replace('{' . $brace . '}', $replacement, $template);
}
echo $build;
}
else
{
trigger_error('Template file does not exist: ' . $template_file, E_ERROR);
}
}
}
This in order to work:
$template = new Template();
$template->parse('index_body.html', array('ONE' => 'one',
'TWO' => 'two',
'THREE' => 'three'));
index_body.html:
{ONE}
{TWO}
{THREE}
The problem is, that it only outputs:
{ONE} {TWO} three
It always replaces the last brace, how come not the whole array?
$build = str_replace('{' . $brace . '}', $replacement, $template);
^^^^^^^^^
You're always replacing against the original template, never against the updated one. Either keep assigning $template, or update $build
$template = file_get_contents($template_file);
$build = $template;
foreach($braces as $brace => $replacement)
{
$brace = trim(strtoupper($brace));
$build = str_replace('{' . $brace . '}', $replacement, $build);
}
It only replaces the last place because in each case, you're replacing the value in the original $template variable. It's not updating the variable each iteration.
You echo $build, which is being reassigned every foreach iteration.
You should've written this instead
$template = str_replace('{' . $brace . '}', $replacement, $template);
How about using like full php engine power (similar to smarty interface):
just for experimenting:
class Template {
private $_file;
private $_variables = array();
public function __construct($file = null) {
$this->_file = $file;
}
public function set($key, $value) {
$this->_variables[$key] = $value;
}
public function fetch($file = null) {
if (!$file) {
$file = $this->_file;
}
extract($this->_variables);
ob_start();
require($file);
$content = ob_get_contents();
ob_end_clean();
return $content;
}
public function display($file = null) {
if (!$file) {
$file = $this->_file;
}
$result = $this->fetch($file);
echo $result;
}
}
=============
$tpl = new Template('hello.tpl');
$tpl->set('world', 'earth');
$tpl->display();
=============
Template sample:hello.tpl
Hello <?=$world;?>
Your $build is overwritten in each iteration. This will solve the issue.
class Template
{
function parse($template_file, $braces)
{
if(file_exists($template_file))
{
$template = file_get_contents($template_file);
foreach($braces as $brace => $replacement)
{
$brace = trim(strtoupper($brace));
$temp = str_replace('{' . $brace . '}', $replacement, $template);//create a temporary array
$build = array_merge($build ,$temp);
}
echo $build;
}
else
{
trigger_error('Template file does not exist: ' . $template_file, E_ERROR);
}
}
}

Categories