Replacing preg_replace by preg_replace_callback is giving me a warning - php

This is my code.
private function _checkMatch($modFilePath, $checkFilePath) {
$modFilePath = str_replace('\\', '/', $modFilePath);
$checkFilePath = str_replace('\\', '/', $checkFilePath);
$modFilePath = preg_replace('/([^*]+)/e', 'preg_quote("$1", "~")', $modFilePath);
$modFilePath = str_replace('*', '[^/]*', $modFilePath);
$return = (bool) preg_match('~^' . $modFilePath . '$~', $checkFilePath);
return $return;
}
I changed preg_replace to preg_replace_callback but it is giving me the following error.
Warning: preg_replace_callback(): Requires argument 2, 'preg_quote("$1", "~")', to be a valid callback
I'm currently using opencart version 1.x.x
Any one can help me out?

http://php.net/manual/en/function.preg-replace-callback.php
You need to use the valid callback as the second argument. You can use function or it name as string:
$modFilePath = preg_replace_callback('/[^*]+/', function ($matches){
return preg_quote($matches[0], "~");
}, $modFilePath);
I have deleted unsecured e modifier and replaced it to a valid callback for preg_replace_callback function.
Also with Old version of PHP you need to add function statement below your code
function myCallback($matches){
return preg_quote($matches[0], "~");
}
And then use preg_replace_callback('/[^*]+/', 'myCallback', $modFilePath);

Related

Solution for create optional Route parameter PHP

I created Route class for my PHP application. Everything ok, this's my function dispatch:
public function dispatch()
{
//some code...
$search = array();
$regex = preg_replace_callback(
'#{([\w]+)?(:([^/\(\)]*))?}#',
function($m) use (&$search) {
$search[$m[1]] = null;
if (isset($m[3])) {
return '(?P<'.$m[1].'>'.$m[3].')';
}
return '(?P<'.$m[1].'>[^/\?]+)';
},
str_replace(array(')','/+'), array(')?','(/?|/.*?)'), $pattern)
);
$regex .= ($last === '/') ? '?' : '/?';
$regex = '#^'.$regex.'$#i';
if (preg_match($regex, $url, $matches)) {
// some code...
}
// some code...
}
Now, i can use Route look like this:
$router = new Router();
$router->add('/', function() {
echo 'Homepage';
});
$router->add('/user/{id}', function($id) {
echo 'User ID: ' . $id;
});
Optional Route:
$router->add('/user(/{id})', function($id) {
echo 'User ID: ' . $id;
});
It working, but i want change syntax from '/user(/{id})' to '/user/{id?}', how can i do that? I think maybe change regex '#{([\w]+)?(:([^/()]*))?}#' to something, but i can't. Somebody help me?
You can use this to match either: \/\{(\w+)(\?)?\}.
This will match any /{param} or /{param?}. You would check if the '?' was captured to check whether it's optional or not.
That expression will match parameters containing only letters, you could easily expand it to take whatever characters you would want by doing something like this: \/\{([a-zA-Z0-9\-\_])(\?)?\}

Making anonymous functions from PHP 5.3 work with PHP 5.2

I have an anonymous functions that I now need to update to be compatible with PHP 5.2. The function (below) takes text and uppercases the first letter of every sentence.
function clean_text($input) {
$output = $input;
$output = preg_replace_callback('/([.!?])\s*(\w)/', function ($matches) {
return strtoupper($matches[1] . ' ' . $matches[2]);
}, ucfirst(strtolower($input)));
return $output;
}
I tried pulling the function out, but I'm receiving an error stating that argument 2 in the callback is now missing. Any ideas on how to resolve this?
function clean_text($input) {
function upper_case($input) {
return strtoupper($input[1] . ' ' . $input[2]);
}
$output = preg_replace_callback('/([.!?])\s*(\w)/', upper_case($input), ucfirst(strtolower($input)));
return $output;
}
Error notice: Warning: preg_replace_callback()
[function.preg-replace-callback]: Requires argument 2, 'U S', to be a
valid callback
preg_replace_callback() as a second argument requires a callable, that is a function itself, not a returned value from a function.
So just replace, upper_case($input) with upper_case, so it would look like this
preg_replace_callback('/([.!?])\s*(\w)/', 'upper_case', ucfirst(strtolower($input)));

How php read local variable in temp function?

I noticed that PHP now can use temp function definition (like js and other scripts language), but how can I get local variable in the temp function ?
ex:
function my_func($text, $prefix){
$regex = '/xxxx/';
return preg_replace_callback($regex, function($matches){
// how to read $prefix here?
}, $text);
}
The use will do the job..
function my_func($text, $prefix){
$regex = '/xxxx/';
return preg_replace_callback($regex, function($matches) use(&$prefix){
//^^^^^^^^^^^^^
}, $text);
}
I find it ..
http://www.php.net/manual/en/functions.anonymous.php
function my_func($text, $prefix){
$regex = '/xxxx/';
return preg_replace_callback($regex, function($matches) use ($prefix){
// how to read $prefix here?
}, $text);
}

How to call a function in an preg_replace?

How can I call a function within preg_replace()?
$template = '<div> [BILD="123"][BILD="246"] </div>';
$pat = '/\[BILD="(.*?)"\]\[BILD ="(.*?)"\]/';
$ret = getImageArea($id, $config, '$1', '$2');
return preg_replace($pat, $rep, $template);
It fails opening the function and doesn't sends 123 or 246.
It just sends $1 and $2.
As I (and many others) told in comments, you have to use preg_replace_callback in this case. One possible approach:
$template = '<div> [BILD="123"][BILD="246"] </div>';
$pat = '/\[BILD="(.*?)"\]\[BILD="(.*?)"\]/';
return preg_replace_callback($pat, function($matches) use($id, $config) {
return getImageArea($id, $config, $matches[1], $matches[2]);
}, $template);
Demo. As you see, it's quite straight-forward; the only catch is making $id and $config variables available inside the callback (which is done with use op).

Symfony 1.4 using deprecated functions in php 5.5

I recently upgraded PHP from version 5.3.27 to 5.5.0.
Everything is working fine in my Symfony 2.3.2 project, and I can enjoy the latest PHP functionalities.
Now when I am going back to my other Symfony 1.4.16 project, I get a PHP error about preg_replace being deprecated with the /e modifier.
I can find no reference about this error in the forums: Has anyone had this problem before ? Is there any kind of patch that I could apply out of the box ? Is an upgrade to Symfony 1.4.20 going to fix this issue ?
The error message goes like this:
Deprecated: preg_replace(): The /e modifier is deprecated, use preg_replace_callback instead in /myproject/lib/vendor/symfony/lib/response/sfWebResponse.class.php on line 409
One way to go may be to modify the code as recommended in the message, and in the manual.
How can I change my preg_replace expression to a preg_replace_callback call ?
Any help / hint will be very welcome.
EDIT:
To this date, there is no patch for this (and Symfony 1.4.20 does not address the issue). The solution is to replace failing calls to preg_replace with corresponding call to preg_replace_callback in the sourche, which is easily done in the sfWebResponse class (thanks for the hint Jon). Now next failing occurrence is slightly more complex, unfortunately... And on the other hand, we probably would have to grep for preg_replace uses with /e option in order to find out where Symfony is likely to break. Which gives quite a few results :o
So... My conclusion would be that Symfony 1.4 users would better not upgrade PHP to version 5.5 until some serious patch comes out. What do you think ? Any alternative ?
The errors do not show up in prod unless you have enabled debug in index.php. It' s also possible to remove them in dev by unsetting the E_DEPRECATED flag in settings.yml :
dev:
.settings:
error_reporting: <?php echo ((E_ALL | E_STRICT) ^ E_DEPRECATED)."\n" ?>
Basically what you have to do is take the replacement argument from the preg_replace call and factor it out into a proper PHP expression, then make that expression the body of a function that will be used as the callback to the equivalent preg_replace_callback call.
In your case the relevant code is
return preg_replace('/\-(.)/e', "'-'.strtoupper('\\1')", /* input */)
So you would do that as
$callback = function($matches) {
return '-'.strtoupper($matches[1]);
};
return preg_replace_callback('/\-(.)/', $callback, /* input */)
As you can see the callback code is the same as the original replace expression, the only difference being that references such as \\1 are replaced with array accesses like $matches[1].
All in all, the best solution is to avoid upgrading PHP to version 5.5, as it is no more compatible with Symfony 1.4
If you have both Symfony 2 and 1.4 versions in a development environment, you may want to be able to switch your PHP version, as nicely described here.
If you really need to, it is possible to setup two different versions of PHP running on the same Apache server at the same time: this will need some more configuration, the above link explains that too.
Alternative HOT FIX:
With a couple of updates in the Symfony code, I can get most of my webpages running in dev. Of course, it would be dangerous to apply this in production, as the "deprecated" error may turn up again at any time, arising from another Symfony library.
In myproject/lib/vendor/symfony/lib/response/sfWebResponse.class.php on line 409, I have now (commented code is original Symfony code):
protected function normalizeHeaderName($name)
{
// return preg_replace('/\-(.)/e', "'-'.strtoupper('\\1')", strtr(ucfirst(strtolower($name)), '_', '-'));
return preg_replace_callback(
'/\-(.)/',
function ($matches) {
return '-'.strtoupper($matches[1]);
},
strtr(ucfirst(strtolower($name)), '_', '-')
);
}
And in myproject/lib/vendor/symfony/lib/util/sfToolkit.class.php on line 362 we get:
public static function pregtr($search, $replacePairs)
{
// return preg_replace(array_keys($replacePairs), array_values($replacePairs), $search);
foreach($replacePairs as $pattern => $replacement)
$search = preg_replace_callback(
$pattern,
function ($matches) use ($replacement){
if(array_key_exists(1, $matches)){ $replacement = str_replace("\\1", $matches[1], $replacement);}
if(array_key_exists(2, $matches)){ $replacement = str_replace("\\2", $matches[2], $replacement);}
return $replacement;
},
$search
);
return $search;
}
Use at your own risks :)
FIX for normalizeHeaderName method in /lib/vendor/symfony/lib/response/sfWebResponse.class.php on line 407
protected function normalizeHeaderName($name)
{
//return preg_replace('/\-(.)/e', "'-'.strtoupper('\\1')",
strtr(ucfirst(strtolower($name)), '_', '-');
return str_replace(array('\'$1$3\'','\'$2$4\'','\'$1\'', '\'$2\'', '$1', '$2'),array('$matches[1].$matches[3]','$matches[2].$matches[4]','$matches[1]','$matches[2]','$matches[1]','$matches[2]'),
$name);
}
FIX for pregtr method in /lib/vendor/symfony/lib/util/sfToolkit.class.php on line 360
public static function pregtr($search, $replacePairs){
// return preg_replace(array_keys($replacePairs), array_values($replacePairs), $search);
foreach($replacePairs as $pattern => $replacement)
{
if (preg_match('/(.*)e$/', $pattern, $matches))
{
$pattern = $matches[1];
$search = preg_replace_callback($pattern, function ($matches) use ($replacement) {
preg_match("/('::'\.)?([a-z]*)\('\\\\([0-9]{1})'\)/", $replacement, $match);
return ($match[1]==''?'':'::').call_user_func($match[2], $matches[$match[3]]);
}, $search);
}
else
{
$search = preg_replace($pattern, $replacement, $search);
}
}
return $search;
}
There is a community version of Symfony that maintains and patches the older code:
https://github.com/LExpress/symfony1
Alternative FIX for pregtr method in /lib/vendor/symfony/lib/util/sfToolkit.class.php on line 360
public static function pregtr($search, $replacePairs)
{
// return preg_replace(array_keys($replacePairs), array_values($replacePairs), $search);
foreach($replacePairs as $pattern => $replacement)
{
if (preg_match('/(.*)e$/', $pattern, $matches))
{
$pattern = $matches[1];
$search = preg_replace_callback($pattern, function ($matches) use ($replacement) {
preg_match("/('::'\.)?([a-z]*)\('\\\\([0-9]{1})'\)/", $replacement, $match);
return ($match[1]==''?'':'::').call_user_func($match[2], $matches[$match[3]]);
}, $search);
}
else
{
$search = preg_replace($pattern, $replacement, $search);
}
}
return $search;
}
Deprecated: preg_replace(): The /e modifier is deprecated, use preg_replace_callback instead in lib/vendor/symfony/…This changelog will solve the problem for all symfony 1.4.x. Tested on Symfony 1.4.20
---
lib/vendor/symfony/lib/command/sfCommandManager.class.php | 4 +++-
lib/vendor/symfony/lib/form/addon/sfFormObject.class.php | 2 +-
lib/vendor/symfony/plugins/sfDoctrinePlugin/lib/form/sfFormFilterDoctrine.class.php | 2 +-
lib/vendor/symfony/plugins/sfPropelPlugin/lib/form/sfFormFilterPropel.class.php | 2 +-
lib/vendor/symfony/lib/response/sfWebResponse.class.php | 2 +-
lib/vendor/symfony/lib/util/sfInflector.class.php | 5 +----
lib/vendor/symfony/lib/util/sfToolkit.class.php | 11 +++++++++++
7 files changed, 19 insertions(+), 9 deletions(-)
lib/vendor/symfony/lib/command/sfCommandManager.class.php
## -108,7 +108,9 ## class sfCommandManager
else if (!is_array($arguments))
{
// hack to split arguments with spaces : --test="with some spaces"
- $arguments = preg_replace('/(\'|")(.+?)\\1/e', "str_replace(' ', '=PLACEHOLDER=', '\\2')", $arguments);
+ $arguments = preg_replace_callback('/(\'|")(.+?)\\1/', function($matches) {
+ return str_replace(' ', '=PLACEHOLDER=', $matches[2]);
+ }, $arguments);
$arguments = preg_split('/\s+/', $arguments);
$arguments = str_replace('=PLACEHOLDER=', ' ', $arguments);
}
lib/vendor/symfony/lib/form/addon/sfFormObject.class.php
## -278,6 +278,6 ## abstract class sfFormObject extends BaseForm
protected function camelize($text)
{
- return preg_replace(array('#/(.?)#e', '/(^|_|-)+(.)/e'), array("'::'.strtoupper('\\1')", "strtoupper('\\2')"), $text);
+ return sfToolkit::camelize($text);
}
}
lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/form/sfFormFilterDoctrine.class.php
## -323,7 +323,7 ## abstract class sfFormFilterDoctrine extends sfFormFilter
protected function camelize($text)
{
- return sfToolkit::pregtr($text, array('#/(.?)#e' => "'::'.strtoupper('\\1')", '/(^|_|-)+(.)/e' => "strtoupper('\\2')"));
+ return sfToolkit::camelize($text);
}
protected function getTable()
lib/vendor/symfony/lib/plugins/sfPropelPlugin/lib/form/sfFormFilterPropel.class.php
## -263,6 +263,6 ## abstract class sfFormFilterPropel extends sfFormFilter
protected function camelize($text)
{
- return sfToolkit::pregtr($text, array('#/(.?)#e' => "'::'.strtoupper('\\1')", '/(^|_|-)+(.)/e' => "strtoupper('\\2')"));
+ return sfToolkit::camelize($text);
}
}
lib/vendor/symfony/lib/response/sfWebResponse.class.php
## -406,7 +406,7 ## class sfWebResponse extends sfResponse
*/
protected function normalizeHeaderName($name)
{
- return preg_replace('/\-(.)/e', "'-'.strtoupper('\\1')", strtr(ucfirst(strtolower($name)), '_', '-'));
+ return preg_replace_callback('/\-(.)/', function ($matches) { return '-'.strtoupper($matches[1]); }, strtr(ucfirst(strtolower($name)), '_', '-'));
}
/**
lib/vendor/symfony/lib/util/sfInflector.class.php
## -28,10 +28,7 ## class sfInflector
public static function camelize($lower_case_and_underscored_word)
{
$tmp = $lower_case_and_underscored_word;
- $tmp = sfToolkit::pregtr($tmp, array('#/(.?)#e' => "'::'.strtoupper('\\1')",
- '/(^|_|-)+(.)/e' => "strtoupper('\\2')"));
-
- return $tmp;
+ return sfToolkit::camelize($tmp);;
}
/**
lib/vendor/symfony/lib/util/sfToolkit.class.php
## -608,4 +608,15 ## class sfToolkit
return set_include_path(join(PATH_SEPARATOR, $paths));
}
+
+ public static function camelize($text)
+ {
+ if (preg_match('#/(.?)#', $text, $matches)) {
+ $text = str_replace($matches[0], '::'.strtoupper($matches[1]), $text);
+ }
+ if (preg_match('/(^|_|-)+(.)/', $text, $matches)) {
+ $text = str_replace($matches[0], strtoupper($matches[2]), $text);
+ }
+ return $text;
+ }
}
--

Categories