Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migration tool replaces any instances of PHPExcel with the filepath #598

Closed
elisimmonds opened this issue Jul 12, 2018 · 5 comments
Closed

Comments

@elisimmonds
Copy link

This is:

- [x] a bug report
- [ ] a feature request
- [ ] **not** a usage question (ask them on https://stackoverflow.com/questions/tagged/phpspreadsheet or https://gitter.im/PHPOffice/PhpSpreadsheet)

What is the expected behavior?

All variables containing $PHPExcel are kept the same

What is the current behavior?

The substring 'PHPExcel is replaced with the filepath to the framework.

What are the steps to reproduce?

Create a file with a variable (mine is $objPHPExcel) and then run the migration tool.

<?php

require __DIR__ . '/vendor/autoload.php';

// Create new Spreadsheet object
$spreadsheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet();

$objPHPExcel // used to be this
$obj\PhpOffice\PhpSpreadsheet\Spreadsheet->setActiveSheetIndex(4); // turns into this.

Which versions of PhpSpreadsheet and PHP are affected?

I am running 1.3

screen shot 2018-07-12 at 1 17 06 pm

@blunket
Copy link
Contributor

blunket commented Jul 13, 2018

This problem did affect me directly as well, while writing a bash script. Coincidentally I had precisely the same variable name as shown in the image above :)

I solved the problem by performing a find-replace on that variable name prior to running the migrator like so:

ack -Q '$objPHPExcel' -l | xargs perl -pi -E 's/\$objPHPExcel/\$objPHPSpreadsheet/g'

...hopefully that helps someone, but that's not an ideal solution 😄 I'd love to work on this soon. I expect I'll need to use PHP's built in tokenizer here. Seems exciting 🙂

@blunket
Copy link
Contributor

blunket commented Jul 14, 2018

@PowerKiKi -- I'd like to know your thoughts on the best way to approach this.

Consider the following code sample...

<?php
class AwesomePHPExcelFormatter {
    public $objPHPExcel  = null;
    const $ILovePHPExcel = 'PHPExcel Rocks';
    public function __construct(){
        require_once($_SERVER["DOCUMENT_ROOT"] . "/lib/PHPExcel/1.7.3/Classes/PHPExcel.php");
        $this->SetStyleDefault();
        $this->objPHPExcel = new PHPExcel();
        $this->objPHPExcel = new \PHPExcel();
        $myPHPExcel = new \namespaced\PHPExcel();
    }
    public function doRandomPHPExcelFunctions() {
    }
}

Currently, the migrator will replace every single instance of 'PHPExcel' with \PhpOffice\PhpSpreadsheet\Spreadsheet which is not what we want.

The intended result would be as follows:

<?php
class AwesomePHPExcelFormatter {
    public $objPHPExcel  = null;
    const $ILovePHPExcel = 'PHPExcel Rocks';
    public function __construct(){
        require_once($_SERVER["DOCUMENT_ROOT"] . "/lib/PHPExcel/1.7.3/Classes/PHPExcel.php");
        $this->SetStyleDefault();
        $this->objPHPExcel = new PhpOffice\PhpSpreadsheet\Spreadsheet();
        $this->objPHPExcel = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
        $myPHPExcel = new \namespaced\PhpOffice\PhpSpreadsheet\Spreadsheet();
    }
    public function doRandomPHPExcelFunctions() {
    }
}

By using the PHP tokenizer, I can filter out any variable names, and I can filter out T_CONSTANT_ENCAPSED_STRING (covering the require in my sample code above). However, this isn't really sufficient.

On line 2 in the sample code, the tokenizer gives the following (I've formatted this for readability):

T_CLASS     : class
T_WHITESPACE:  
T_STRING    : AwesomePHPExcelFormatter

... and on line 8 (where it should replace) it gives:

T_VARIABLE       : $this
T_OBJECT_OPERATOR: ->
T_STRING         : objPHPExcel
T_WHITESPACE     :
=
T_WHITESPACE:  
T_NEW       : new
T_WHITESPACE:  
T_STRING    : PHPExcel

notice that in this case, the tokenizer returns T_STRING in $this->objPHPExcel instead of T_VARIABLE, and it returns T_STRING again in new PHPExcel ...

So basically, I think we have to add a parser to get this right 🙁 We can't have it replacing in variable names, class variables, function names, class method names, and probably even more cases I'm not thinking about.

What are your thoughts? Should we add a parser? I'm willing to take a stab at it depending on what you think.

@PowerKiKi
Copy link
Member

PowerKiKi commented Jul 15, 2018 via email

@blunket
Copy link
Contributor

blunket commented Jul 18, 2018

Okay, fair enough. and good point.

How does this regex look to you?

(?<!(\$|->))\bPHPExcel\b

It matches the first two lines of the following, but none of the last five:

PHPExcel
\PHPExcel
$PHPExcel
objPHPExcel
$objPHPExcel
$this->objPHPExcel
$this->PHPExcel

Am I missing any cases? If not I'll have a PR for you soon!

@blunket
Copy link
Contributor

blunket commented Jul 20, 2018

I actually had to un-group the OR in my lookbehind above.

This regex seems to work fairly well!

In my example above, it only fails in the places within the quoted strings. Should I try to account for that too? Or is this good enough for now?

Dfred pushed a commit to Dfred/PhpSpreadsheet that referenced this issue Nov 20, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

3 participants