0

I have to parse a javascript file and replace the last function parameter every time a specific function is called. I have an array of replacement values that supplies the new ids.

Javascript code:

// every time this function is called I need to replace change_id with different value from array
function submitData(element_id, url, change_id) {...
    ...
}

... 

// I want to replace 3, 2 and 4 with values from my array
// 3,2,4 are just used for example, values are dynamic
window.addEventListener('beforeunload', function (e) { submitData(1, "http://mysite/metrics, 3");}); window.addEventListener('beforeunload', function (e) { submitData(1, "http://mysite/metrics, 2");}); window.addEventListener('beforeunload', function (e) { submitData(1, "http://mysite/metrics, 4");});

I have an array of ids, and I would like to loop through them and replace the value in each function call with one of the values from this array

My array:

$change_ids = [10,15,20];

So the result should be:

window.addEventListener('beforeunload', function (e) { submitData(1, "http://mysite/metrics, 10");}); window.addEventListener('beforeunload', function (e) { submitData(1, "http://mysite/metrics, 15");}); window.addEventListener('beforeunload', function (e) { submitData(1, "http://mysite/metrics, 20");});

Only third parameter in function call needs to be changed, so I thought about using something like this(found here):

$search = "/[^metrics,](.*)[^\"\)]/";
$replace = "10";
$string = file_get_contents($pathToJsFile);
echo preg_replace($search,$replace,$string);

But the problem is that $change_id will be equal in every function call

mickmackusa
  • 43,625
  • 12
  • 83
  • 136
failedCoder
  • 1,346
  • 1
  • 14
  • 38
  • 1
    Try https://3v4l.org/YH3l7, `$search = '/\bmetrics,\s*\K.*?(?="\))/'; $change_ids_copy = $change_ids; echo preg_replace_callback($search,function($m) use (&$change_ids_copy) { return array_shift($change_ids_copy); },$string);` – Wiktor Stribiżew Jun 26 '20 at 08:32
  • Just an idea. Seem to bi kind a dirty but, you could get all function calls with regex separate them in 3 variables and then replace each value separately and then get all back together? – some_guy Jun 26 '20 at 08:34

2 Answers2

1

You could avoid a native function call by converting your javascript string into a "template" with %d placeholders, then simply inject your new ids into those placeholders with vsprintf() (I'll demonstrate with vprintf() so that the string is printed to the screen).

Code: (Demo)

$string = <<<JS
function submitData(element_id, url, change_id) {...
    ...
}

... 
window.addEventListener('beforeunload', function (e) { submitData(1, "http://mysite/metrics, 3");}); window.addEventListener('beforeunload', function (e) { submitData(1, "http://mysite/metrics, 2");}); window.addEventListener('beforeunload', function (e) { submitData(1, "http://mysite/metrics, 4");});
JS;

$change_ids = [19, 7, 11];

vprintf(
    preg_replace('~metrics,\s*\K\d+~', '%d', $string),
    $change_ids
);
mickmackusa
  • 43,625
  • 12
  • 83
  • 136
0

I ended up with this solution:

$javascript = file_get_contents($path);
if (empty($javascript)) {
   return false;
}
$search = '/(?<=metrics\",)\s*.*?(?=\))/'; 

This pattern will return " 1"(whitespace 1) from this string:

window.addEventListener('beforeunload', function (e) { submitData(1, "http://mysite/metrics", 1);});

After that I replace the match with value from my array.

$javascript = preg_replace_callback($search,function($m) use (&$change_ids) {  
    $m = $m[key($m)];
    $m = ' '. array_shift($change_ids);
    return $m;
},$javascript);
        
return file_put_contents($path, $javascript);
failedCoder
  • 1,346
  • 1
  • 14
  • 38