Repository navigation
Writer WPS: basic support of Microsoft Works documents - #2929
Conversation
Add a WPS writer producing an OLE compound file whose CONTENTS stream holds the CHNKWKS chunks of the document, with the text and the page breaks of the elements. Co-Authored-By: business.arshgoyal@gmail.com <business.arshgoyal@gmail.com>
Co-Authored-By: business.arshgoyal@gmail.com <business.arshgoyal@gmail.com>
Progi1984
left a comment
There was a problem hiding this comment.
Rather than adding file src/PhpWord/Shared/OLEWrite.php, could use PhpOffice/Common ?
|
Happy to, but PhpOffice/Common only has Two ways I can go, tell me which you prefer:
Default is 2 unless you say otherwise |
|
Go to 1 |
|
Done: PHPOffice/Common#65 adds Once that lands and Common tags a release, I'll update this PR to require |
Co-Authored-By: business.arshgoyal@gmail.com <business.arshgoyal@gmail.com>
|
@businessarshgoyal It's published : https://github.com/PHPOffice/Common/releases/tag/1.1.0 |
…mmon 1.1 Drops the interim Shared\OLEWrite copy now that PHPOffice/Common 1.1.0 ships the writer. Co-Authored-By: business.arshgoyal@gmail.com <business.arshgoyal@gmail.com>
|
Thanks @Progi1984. Switched in |
|
@businessarshgoyal |
…loadable via phpoffice/common Co-Authored-By: business.arshgoyal@gmail.com <business.arshgoyal@gmail.com>
|
Thanks @Progi1984 — fixed in a84bae6. The static-analysis failure was a side effect of requiring |
|
@businessarshgoyal It's merged for the writer. Thanks. Do you plan a reader too ? |
- Rebase on current master (WPS Writer PHPOffice#2929 merged) - Add Reader WPS entry to docs/changes/1.x/1.5.0.md - Make internal helpers protected and non-static - Align @SInCE with 1.5.0
* Reader WPS: add Microsoft Works (.wps) text reader Implements PhpOffice\PhpWord\Reader\WPS per issue #69: - Reuses Shared\OLERead to parse the OLE compound container and extract the 'CONTENTS' stream (handles both regular and mini streams). - Walks the WPS chunk list: CHNKWKS magic, 0x01F8 chunk tags, TEXT chunk lookup with linked-block traversal. - Decodes UTF-16LE text, normalizes \r line breaks, and maps paragraphs to Text elements in a single section. - canRead() validates the OLE signature + CHNKWKS magic (gracefully false for non-OLE/non-WPS files). - Ships a generated CFB/WPS fixture (tests/_files/documents/reader.wps) with 3 known paragraphs, plus unit tests: canRead true/false, full load with exact text assertions. Verification: phpunit WPSTest 3/3 green; phpstan analyse clean; php-cs-fixer 0 fixable violations across the repo. * fix: handle false returns from preg_split() and unpack() flagged by PHPStan The CI static analysis config (full phpstan.neon.dist) is stricter than a single-file level-6 run: preg_split() and unpack() both return array|false. Throw a dedicated Exception on the impossible-by-construction failure paths so the types are honest and the analysis passes on PHP 7.1-8.5. * Reader WPS: address review feedback - Rebase on current master (WPS Writer #2929 merged) - Add Reader WPS entry to docs/changes/1.x/1.5.0.md - Make internal helpers protected and non-static - Align @SInCE with 1.5.0 * Reader WPS: add types to methods per review feedback Apply the return type and native type hints requested in review on the protected helpers (no inheritance constraints) and add return types on canRead()/load(). Note on canRead()/load(): the parameter types from the review suggestions (string $filename / string $docFile) cannot be applied right now because AbstractReader and ReaderInterface declare canRead() and load() without parameter types, and PHP requires overriding parameter types to be contravariant (a typed narrower parameter in a child is a fatal incompatibility). Full param typing needs the whole Reader hierarchy typed in one sweep; happy to do that as a follow-up maintained separately if preferred.
Description
Adds a
WPSwriter producing documents for the word processor of Microsoft Works 7 and 8, ie an OLE compound file whoseCONTENTSstream holds theCHNKWKSchunks of the document, as described by the format notes linked in the issue and implemented by libwps (WPS8Parser).What is added:
Shared\OLEWrite: a small compound file (CFB v3, 512 bytes sectors) writer, counterpart of the existingShared\OLERead, building the FAT, the mini FAT, the mini stream and the red-black directory from a set of named streams. No new dependency.Writer\WPSandWriter\WPS\Part\Contents, following the structure of theRTFwriter: the part writes the stream header, the chunk index and theTEXTandFONTchunks; the text is UTF-16LE, paragraphs are terminated by\rand page breaks by\f.WPSinIOFactory::createWriter().First iteration scope, as suggested in the issue: text and basic paragraph output. Text, text runs, titles, links, list items, text breaks, page breaks and the text of the cells of a table are written as paragraphs. Not supported yet (silently ignored, no error): character and paragraph styles, table and list structure, images, objects, headers, footers, footnotes, endnotes, comments, table of contents, document properties, form fields, and reading
.wpsfiles.About #2769
I looked at #2769 first and did not build on it: it writes a ZIP package of ODF-like XML parts (
content.xml,styles.xml,META-INF/manifest.xml), which is not the Microsoft Works binary format the issue asks for — such a file is not an OLE document and is not recognised by Works or by libwps-based readers (LibreOffice). This PR writes theCONTENTS/CHNKWKSstream instead, so the two approaches do not share code.Validation
Besides the unit tests, the generated files were checked against the reference implementation,
wps2text(libwps 0.4.12), which extracts the expected text, and againstolefile/file(1), which validate the compound file structure.Fixes #69
/claim #69
Checklist: