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

Cell object formulaAttributes property stores SimpleXMLElement preventing serialization #1757

Closed
tristanleboss opened this issue Dec 15, 2020 · 2 comments · Fixed by #4326
Closed

Comments

@tristanleboss
Copy link

This is:

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

What is the expected behavior?

For example, if you want to cache a PhpSpreadsheet object using redis or apcu to avoid re-reading an excel file again and again, you need to be able to serialize a PhpSpreadsheet object. Unfortunately, PHP can't serialize a SimpleXMLElement and you will receive an exception Serialization of 'SimpleXMLElement' is not allowed.

The culprit is the formulaAttributes private property of class PhpOffice\PhpSpreadsheet\Cell\Cell.
This property is used by a getter and a setter in this class but doesn't really seems to be used (yet!) anywhere else in the project.

There is just one use of the setter in the Xslx reader and some commented code in the Worksheet class in writeCellFormula method.

What is the current behavior?

I think it would be a good idea to transform this SimpleXMLElement object containing the attributes of the c (cell) XML tag into a real basic PHP array. So, the formulaAttributes property would be a basic array instead of a SimpleXMLElement.

What are the steps to reproduce?

Create an excel file with value 1 in A1 and =A1+1 formula in A2, then extend the formula to 10 rows.
This will create a shared formula. This way some c XML tag will have both t="shared" and s="(int)" attributes.

Then, read the Excel file and try to serialize the resulting PhpOffice\PhpSpreadsheet\Spreadsheet object with:

serialize($spreadsheet)

Which versions of PhpSpreadsheet and PHP are affected?

1.15.0

@tristanleboss
Copy link
Author

tristanleboss commented Dec 15, 2020

The code in the load method of class PhpSpreadsheet\Reader\Xlsx.php stores the full XML node and not just the attributes.

                                                    if (isset($c->f['t'])) {
                                                        $att = $c->f;
                                                        $docSheet->getCell($r)->setFormulaAttributes($att);
                                                    }

It seems it's possible to get attributes as a real basic PHP array with:

$att = $c->f['@attributes'];

or by looping:

$att = array();
$attr = $c->f->attributes();

foreach($attr as $key=>$val){
    $att[(string)$key] = (string)$val;
}

@oleibman
Copy link
Collaborator

Closing. PR #3199 (November 2022) will throw an exception whenever an attempt is made to serialize the spreadsheet, whether or not formulaAttributes in part of it.

@oleibman oleibman reopened this Jan 26, 2025
oleibman added a commit to oleibman/PhpSpreadsheet that referenced this issue Jan 26, 2025
Fix PHPOffice#4324. Serialization was explicity forbidden by PR PHPOffice#3199. This was in response to several issues, and concern that the Spreadsheet object contained non-serializable properties. This PR restores the ability to serialize a spreadsheet. Json serialization remains unsupported.

Fix PHPOffice#1757, closed in Nov. 2023 but just reopened. At the time, Cell property `formulaAttributes` was stored as a SimpleXmlElement. Dynamic arrays PR PHPOffice#3962 defined that property as `null|array<string, string>` in the doc block. However, it left the formal Php type for the property as `mixed`. This PR changes the formal type to `?array`.

Fix PHPOffice#1741, closed in Dec. 2020 but just reopened. Calculation property `referenceHelper` was defined as static, and, since static properties don't take part in serialization, this caused a problem after unserialization. There are at least 3 trivial ways to deal with this - make it an instance property, reinitialize it when unserialized using a wakeup method, or remove the property altogether. This PR uses the last of those 3.

Calculation does have other static properties. Almost all of these deal with locale. So serialize/unserialize might wind up using a default locale when non-default is desired (but not necessarily required). If that is a problem for end-users, it will be a new one, and I will work on a solution if and when the time comes.

Static property `returnArrayAsType` is potentially problematic. However, instance property `instanceArrayReturnType` is the preferred method of handling this, and using that will avoid any problems.

Issue PHPOffice#932 also dealt with serialization. I do not have the wherewithal to investigate that issue. If it is not solved by this and the earlier PR's, I will have to leave it to others to re-raise it.

Spreadsheet `copy` is now simplified to use serialize followed by unserialize. Formal tests are added. In addition, I have made a number of informal tests on very complicated spreadsheets, and it has performed correctly for all of them.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging a pull request may close this issue.

2 participants