Compare commits

..
31 Commits
Author SHA1 Message Date
Andrii Dembitskyi 0f20c99a7f Fix constant usage in example 2021-02-10 10:53:55 +01:00
jmsche 9ab0b10a0f Contributing: added info about code style 2021-02-09 17:39:42 +01:00
jmsche ed9322e309 Shorter (relevant) diff by php-cs-fixer for Travis CI 2021-02-09 13:58:05 +01:00
Oded Arbel 73347517f0 added comment with spec link, as requested 2021-02-09 11:21:25 +01:00
Oded Arbel ad913f0100 write boolean value according to http://docs.oasis-open.org/office/v1.2/os/OpenDocument-v1.2-os-part1.html#datatype-boolean instead of just "1" for true or "" for false; 2021-02-09 11:21:25 +01:00
jmsche c29d1877b8 Fixed code style (probably due to recent php-cs-fixer version) 2021-02-08 22:03:03 +01:00
Petr Skoda 816596183f Add full support for PHP 8.0
Unfortunately due to PHPUnit 8.5 dependency
this also drops support for PHP 7.1
2021-02-08 14:31:55 +01:00
madflow ab973cab34 use existing base folder 2019-12-19 23:24:24 +01:00
madflow b8eb2bb814 error_reporting set to -1 2019-12-16 13:42:24 +01:00
madflow f54f7a400c add PHP 7.4 2019-12-16 13:42:24 +01:00
Adrien Loison 7964dadc21 Add support for cells in error when writing XLSX and ODS
When appending data to an existing sheet, it was possible to get cells in error when reading (DIV/0 for instance). When trying to write them back, `addRow` would throw because `Cell`s in error were not supported by the writers.
2019-12-02 22:21:41 +01:00
drowe eb88bb4c3a Automated native_function_invocation fixes 2019-11-18 12:17:27 +01:00
madflow 94b654175c disable no_superfluous_phpdoc_tags 2019-11-18 11:20:20 +01:00
Adrien Loison dbdf5f7f38 [ODS] Add support for whitespaces inside <text:span>
The `<text:p>` node can contain the string value directly or contain child elements. In this case, whitespaces contain in the child elements should be replaced by their XML equivalent:
 - space => `<text:s />`
 - tab => `<text:tab />`
 - line break => `<text:line-break />`

@see https://docs.oasis-open.org/office/v1.2/os/OpenDocument-v1.2-os-part1.html#__RefHeading__1415200_253892949
2019-10-27 20:14:51 +01:00
Adrien Loison 9f4c094fa0 Cell alignment
This PR adds support for cell alignment for XLSX and ODS files.
You can now align the content of the cells this way:
```
use Box\Spout\Common\Entity\Style\CellAlignment;
use Box\Spout\Writer\Common\Creator\Style\StyleBuilder;

$style = (new StyleBuilder())
    ->setCellAlignment(CellAlignment::RIGHT)
    ->build();
...
```

Possible cell alignments are: LEFT, RIGHT, CENTER and JUSTIFY.
2019-10-27 18:58:56 +01:00
Adrien Loison 0a0b1f7196 [docs] Fix site_url - take 2 2019-10-17 13:12:40 +00:00
Adrien Loison db32a7c7db [docs] Fix site_url 2019-10-17 11:15:55 +00:00
Adrien Loison 859b8d336e [Docs] Force using current protocol scheme for resources and links
If the docs is accessed with https, change all links to be https as well.
2019-10-17 10:32:39 +00:00
Adrien Loison 8a2dcc946b Improve docs for local dev 2019-10-17 09:29:03 +00:00
Adrien Loison 74146c6224 Switch documentation site to HTTPS
Accessing the website through HTTP may be blocked in some regions of the world.
Using HTTPS should help with this problem and is the good thing to do anyway.
2019-10-17 07:44:13 +00:00
Adrien Loison 6a6d1df9df Fix typo - Boder => Border 2019-10-17 07:37:37 +00:00
Alexander Rakushin 52312b7045 Added tests for StyleRegistry and StyleMerger 2019-10-01 20:08:54 +00:00
Alexander Rakushin d4e12b1812 Simplification of the code 2019-10-01 20:08:54 +00:00
Alexander Rakushin e8c6d83104 сode formatting (CS Fixer) 2019-10-01 20:08:54 +00:00
Alexander Rakushin 40aecd7b90 Added support for cell formats when writing Excel files 2019-10-01 20:08:54 +00:00
Adrien Loison 16a2f91a22 Cell indexes not being respected when rendering row
Fixes #682
When calling `Row::setCellIndex`, it's possible to create a Row with holes.
Instead of iterating over existing cells of a Row, we should instead use the cell indexes (from 0 to max cell index).
2019-09-28 14:02:23 +00:00
Ilya Troy 2d297e954b Update getting-started.md
Fix writer usage example
2019-07-30 22:14:20 +02:00
Adrien Loison 2716d7eeed [PHP 7.4] Updated way to disable the fgetcsv/fputcsv escape character
From PHP 7.4, the recommended way to disable the escape character for fgetcsv() and fputcsv() is an empty string, instead of "\0".
Discussed here: https://github.com/php/php-src/pull/3515
2019-07-21 23:15:34 +02:00
Adrien Loison 1bbfd45b82 Support for missing styles XML file in XLSX
Some files don't have a "styles.xml" file. Excel supports these files, Spout should do too.
2019-07-20 16:48:51 +02:00
Adrien Loison 6c4086cf97 Fix reading of 1904 dates option
Whether the spreadsheet is using 1904 dates or not is controlled by a XML property. Its value can be the string "false" that is not mapped to the boolean "false" but to the boolean "true"... Therefore Spout was previously using the wrong date system when this property was set.
2019-06-04 09:36:51 +02:00
Adrien Loison a296f73a98 Fix Github icon in docs 2019-05-24 10:12:35 +02:00
124 changed files with 1181 additions and 502 deletions

No files matched your search

+1
View File
@@ -6,3 +6,4 @@
/vendor
/composer.lock
/.php_cs.cache
/.phpunit.result.cache
+1
View File
@@ -21,6 +21,7 @@ $config = PhpCsFixer\Config::create()
'no_null_property_initialization' => true,
'no_short_echo_tag' => true,
'no_superfluous_elseif' => true,
'no_superfluous_phpdoc_tags' => false,
'no_unneeded_control_parentheses' => ['statements' => ['break', 'clone', 'continue', 'echo_print', 'switch_case', 'yield']],
'no_unneeded_curly_braces' => true,
'no_unneeded_final_method' => true,
+9 -6
View File
@@ -1,18 +1,21 @@
dist: trusty
dist: bionic
sudo: false
language: php
matrix:
include:
- php: 7.1
env: WITH_CS=true
- php: 7.1
env: WITH_PHPUNIT=true WITH_COVERAGE=true
- php: 7.2
env: WITH_PHPUNIT=true
- php: 7.3
env: WITH_PHPUNIT=true
- php: 7.3
env: WITH_PHPUNIT=true WITH_COVERAGE=true
- php: 7.4
env: WITH_PHPUNIT=true
- php: 8.0
env: WITH_PHPUNIT=true
cache:
directories:
@@ -39,7 +42,7 @@ before_script:
script:
- |
if [[ "$WITH_CS" == "true" ]]; then
vendor/bin/php-cs-fixer fix --config=.php_cs.dist --verbose --diff --dry-run
vendor/bin/php-cs-fixer fix --config=.php_cs.dist --verbose --diff --dry-run --diff-format=udiff
fi
- |
if [[ "$WITH_PHPUNIT" == "true" ]]; then
+16 -2
View File
@@ -6,7 +6,7 @@ All contributions are welcome to this project.
Before a contribution can be merged into this project, please fill out the Contributor License Agreement (CLA) located at:
http://opensource.box.com/cla
https://opensource.box.com/cla
To learn more about CLAs and why they are important to open source projects, please see the [Wikipedia entry](http://en.wikipedia.org/wiki/Contributor_License_Agreement).
@@ -68,7 +68,21 @@ This will add your changes on top of what's already in upstream, minimizing merg
Make sure that all tests are passing before submitting a pull request.
### Step 8: Send the pull request
### Step 8: Fix code style
Run the following command to check the code style of your changes:
```
vendor/bin/php-cs-fixer fix --config=.php_cs.dist --verbose --diff --dry-run --diff-format=udiff
```
This will print a diff of proposed code style changes. To apply these suggestions, run the following command:
```
vendor/bin/php-cs-fixer fix --config=.php_cs.dist
```
### Step 9: Send the pull request
Send the pull request from your feature branch to us. Be sure to include a description that lets us know what work you did.
+3 -3
View File
@@ -1,7 +1,7 @@
# Spout
[![Latest Stable Version](https://poser.pugx.org/box/spout/v/stable)](https://packagist.org/packages/box/spout)
[![Project Status](http://opensource.box.com/badges/active.svg)](http://opensource.box.com/badges)
[![Project Status](https://opensource.box.com/badges/active.svg)](https://opensource.box.com/badges)
[![Build Status](https://travis-ci.org/box/spout.svg?branch=master)](https://travis-ci.org/box/spout)
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/box/spout/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/box/spout/?branch=master)
[![Code Coverage](https://scrutinizer-ci.com/g/box/spout/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/box/spout/?branch=master)
@@ -15,12 +15,12 @@ Join the community and come discuss about Spout: [![Gitter](https://badges.gitte
## Documentation
Full documentation can be found at [http://opensource.box.com/spout/](http://opensource.box.com/spout/).
Full documentation can be found at [https://opensource.box.com/spout/](https://opensource.box.com/spout/).
## Requirements
* PHP version 7.1 or higher
* PHP version 7.2 or higher
* PHP extension `php_zip` enabled
* PHP extension `php_xmlreader` enabled
+1 -1
View File
@@ -11,7 +11,7 @@ With the 3.0 version, this is now possible: each cell can have its own style.
Spout 3.0 tries to enforce better typing. For instance, instead of using/returning generic arrays, Spout now makes use of specific `Row` and `Cell` objects that can encapsulate more data such as type, style, value.
Finally, **_Spout 3.0 only supports PHP 7.1 and above_**, as other PHP versions are no longer supported by the community.
Finally, **_Spout 3.2 only supports PHP 7.2 and above_**, as other PHP versions are no longer supported by the community.
Reader changes
--------------
+3 -3
View File
@@ -12,12 +12,12 @@
}
],
"require": {
"php": ">=7.1.0",
"php": ">=7.2.0",
"ext-zip": "*",
"ext-xmlreader" : "*"
},
"require-dev": {
"phpunit/phpunit": "^7",
"phpunit/phpunit": "^8",
"friendsofphp/php-cs-fixer": "^2"
},
"suggest": {
@@ -36,7 +36,7 @@
},
"config": {
"platform": {
"php": "7.1"
"php": "7.2"
}
}
}
+1 -1
View File
@@ -10,7 +10,7 @@ title: Spout
email: oss@box.com
description: "An open source PHP library to read and write spreadsheet files (XLSX, ODS and CSV), in a fast and scalable way."
baseurl: "" # the subpath of your site, e.g. /blog
url: "http://opensource.box.com" # the base hostname & protocol for your site
url: "https://opensource.box.com" # the base hostname & protocol for your site
# Build settings
markdown: kramdown
+7
View File
@@ -0,0 +1,7 @@
# Github Metadata plugin
repository: box/spout
plugins:
- "jekyll-github-metadata"
github:
url: http://localhost:8080
+1 -1
View File
@@ -11,7 +11,7 @@
<div class="footer-col footer-col-2">
<ul class="social-media-list">
<li><a href="https://github.com/box/spout/issues"><span class="icon icon--github">{% include icon-github.svg %}</span><span class="username">GitHub Issues</span></a></li>
<li><a href="{{ site.github.issues_url }}"><span class="icon icon--github">{% include icon-github.svg %}</span><span class="username">GitHub Issues</span></a></li>
</ul>
</div>
+2 -2
View File
@@ -6,12 +6,12 @@
<title>{% if page.title %}{{ page.title | escape }}{% else %}{{ site.title | escape }}{% endif %}</title>
<meta name="description" content="{% if page.excerpt %}{{ page.excerpt | strip_html | strip_newlines | truncate: 160 }}{% else %}{{ site.description }}{% endif %}">
<link rel="stylesheet" href="{{ "/css/main.css" | prepend: site.github.url }}">
<link rel="stylesheet" href="{{ "/css/main.css" | prepend: site_url }}">
{% if site.algolia.enabled %}
<link rel="stylesheet" href="//cdn.jsdelivr.net/docsearch.js/1/docsearch.min.css" />
{% endif %}
{% if jekyll.environment == 'production' %}
{% include analytics.html %}
{% include analytics.html %}
{% endif %}
</head>
+8 -10
View File
@@ -1,7 +1,7 @@
<header class="site-header">
<div class="wrapper">
<a class="site-title" href="{{ site.github.url }}/">{{ site.title }}</a>
<a class="site-title" href="{{ site_url }}/">{{ site.title }}</a>
<nav class="site-nav">
<a href="#" class="menu-icon">
@@ -12,15 +12,13 @@
</svg>
</a>
<div class="trigger">
<a class="page-link" href="{{ site.github.url }}/getting-started/">Getting Started</a>
<a class="page-link" href="{{ site.github.url }}/docs/">Documentation</a>
<a class="page-link" href="{{ site.github.url }}/guides/">Guides</a>
<a class="page-link" href="{{ site.github.url }}/faq/">FAQ</a>
<a class="page-link" href="https://github.com/box/spout">
GitHub
<svg width="12" height="12">
<image xlink:href="/images/external-link.svg" src="/images/external-link.png" width="12" height="12"/>
</svg>
<a class="page-link" href="{{ site_url }}/getting-started/">Getting Started</a>
<a class="page-link" href="{{ site_url }}/docs/">Documentation</a>
<a class="page-link" href="{{ site_url }}/guides/">Guides</a>
<a class="page-link" href="{{ site_url }}/faq/">FAQ</a>
<a class="page-link" href="{{ site.github.repository_url }}">
<span class="icon icon--github">{% include icon-github.svg %}</span>
<span class="username">GitHub</span>
</a>
{% if site.algolia.enabled %}
<span class="site-search">
@@ -8,4 +8,4 @@
Writing an ODS file with millions of rows? {{ site.spout_html }} can do it in no time!
{% endcapture %}
{% include section.html %}
{% include section.html site_url = include.site_url %}
@@ -11,4 +11,4 @@
Switching from one type to another is ridiculously easy!
{% endcapture %}
{% include section.html %}
{% include section.html site_url=include.site_url %}
+3 -2
View File
@@ -13,8 +13,9 @@
<li class="feature-check">{{ site.spout_html }}'s API is {{emS}}developer-friendly{{emE}}.</li>
</ul><br>
<div class="btn-wrapper">
<a href="{{ site.github.url }}/getting-started/" class="page-link"><button class="btn">Get started</button></a>
<a href="{{ include.site_url }}/getting-started/" class="page-link"><button class="btn">Get started</button></a>
</div>
{% endcapture %}
{% include section.html %}
{% include section.html site_url=include.site_url %}
+1 -2
View File
@@ -1,4 +1,3 @@
<div class="section {{ sectionClass }} vertical-align-middle">
<div class="wrapper">
<div class="description mbl">
@@ -9,7 +8,7 @@
{% assign sectionIconsAsArray = sectionIcons | split:'~~' %}
<div class="icons">
{% for icon in sectionIconsAsArray %}
<img src="{{ site.github.url }}/images/{{ icon }}"/>
<img src="{{ include.site_url }}/images/{{ icon }}"/>
{% endfor %}
</div>
{% endif %}
+12
View File
@@ -0,0 +1,12 @@
{% comment %}
This is a hack to force using HTTPS...
The URL of the docs should be changed in the repo settings instead
{% endcomment %}
{% assign protocol_scheme = page.url | absolute_url | truncate: 5, "" %}
{%- capture site_url -%}
{%- if protocol_scheme == "https" -%}
{{ site.github.url | replace: "http://", "https://" }}
{%- else -%}
{{ site.github.url }}
{%- endif -%}
{%- endcapture -%}
+2 -8
View File
@@ -1,6 +1,8 @@
<!DOCTYPE html>
<html>
{% include set-global-site-url.html %}
{% include head.html %}
<body>
@@ -13,14 +15,6 @@
{{ content }}
<!--
<div class="page-content">
<div class="wrapper">
</div>
</div>
-->
{% include footer.html %}
{% include algolia.html %}
+1
View File
@@ -1,6 +1,7 @@
---
layout: default
---
<article class="post">
<div class="wrapper">
<header class="post-header">
-15
View File
@@ -1,15 +0,0 @@
---
layout: default
---
<article class="post" itemscope itemtype="http://schema.org/BlogPosting">
<header class="post-header">
<h1 class="post-title" itemprop="name headline">{{ page.title }}</h1>
<p class="post-meta"><time datetime="{{ page.date | date_to_xmlschema }}" itemprop="datePublished">{{ page.date | date: "%b %-d, %Y" }}</time>{% if page.author %} • <span itemprop="author" itemscope itemtype="http://schema.org/Person"><span itemprop="name">{{ page.author }}</span></span>{% endif %}</p>
</header>
<div class="post-content" itemprop="articleBody">
{{ content }}
</div>
</article>
+13 -10
View File
@@ -116,16 +116,17 @@ $reader->setShouldPreserveEmptyRows(true);
For fonts and alignments, {{ site.spout_html }} does not support all the possible formatting options yet. But you can find the most important ones:
| Category | Property | API
|:----------|:--------------|:--------------------------------------
| Font | Bold | `StyleBuilder::setFontBold()`
| | Italic | `StyleBuilder::setFontItalic()`
| | Underline | `StyleBuilder::setFontUnderline()`
| | Strikethrough | `StyleBuilder::setFontStrikethrough()`
| | Font name | `StyleBuilder::setFontName('Arial')`
| | Font size | `StyleBuilder::setFontSize(14)`
| | Font color | `StyleBuilder::setFontColor(Color::BLUE)`<br>`StyleBuilder::setFontColor(Color::rgb(0, 128, 255))`
| Alignment | Wrap text | `StyleBuilder::setShouldWrapText(true|false)`
| Category | Property | API
|:----------|:---------------|:--------------------------------------
| Font | Bold | `StyleBuilder::setFontBold()`
| | Italic | `StyleBuilder::setFontItalic()`
| | Underline | `StyleBuilder::setFontUnderline()`
| | Strikethrough | `StyleBuilder::setFontStrikethrough()`
| | Font name | `StyleBuilder::setFontName('Arial')`
| | Font size | `StyleBuilder::setFontSize(14)`
| | Font color | `StyleBuilder::setFontColor(Color::BLUE)`<br>`StyleBuilder::setFontColor(Color::rgb(0, 128, 255))`
| Alignment | Cell alignment | `StyleBuilder::setCellAlignment(CellAlignment::CENTER)`
| | Wrap text | `StyleBuilder::setShouldWrapText(true)`
### Styling rows
@@ -135,6 +136,7 @@ It is possible to apply some formatting options to a row. In this case, all cell
```php
use Box\Spout\Writer\Common\Creator\WriterEntityFactory;
use Box\Spout\Writer\Common\Creator\Style\StyleBuilder;
use Box\Spout\Common\Entity\Style\CellAlignment;
use Box\Spout\Common\Entity\Style\Color;
$writer = WriterEntityFactory::createXLSXWriter();
@@ -146,6 +148,7 @@ $style = (new StyleBuilder())
->setFontSize(15)
->setFontColor(Color::BLUE)
->setShouldWrapText()
->setCellAlignment(CellAlignment::RIGHT)
->setBackgroundColor(Color::YELLOW)
->build();
+7 -3
View File
@@ -4,11 +4,13 @@ title: Getting Started
permalink: /getting-started/
---
{% include set-global-site-url.html %}
This guide will help you install {{ site.spout_html }} and teach you how to use it.
## Requirements
* PHP version 7.1 or higher
* PHP version 7.2 or higher
* PHP extension `ext-zip` enabled
* PHP extension `ext-xmlreader` enabled
@@ -86,7 +88,9 @@ As with the reader, there is one common interface to write data to a file:
use Box\Spout\Writer\Common\Creator\WriterEntityFactory;
use Box\Spout\Common\Entity\Row;
$reader = ReaderEntityFactory::createReaderFromFile('/path/to/file.ext');
$writer = WriterEntityFactory::createXLSXWriter();
// $writer = WriterEntityFactory::createODSWriter();
// $writer = WriterEntityFactory::createCSVWriter();
$writer->openToFile($filePath); // write data to a file or to a PHP stream
//$writer->openToBrowser($fileName); // stream data directly to the browser
@@ -132,4 +136,4 @@ For XLSX and ODS files, the number of rows per sheet is limited to *1,048,576*.
## Advanced usage
You can do a lot more with {{ site.spout_html }}! Check out the [full documentation]({{ site.github.url }}/docs/) to learn about all the features.
You can do a lot more with {{ site.spout_html }}! Check out the [full documentation]({{ site_url }}/docs/) to learn about all the features.
+4 -2
View File
@@ -4,15 +4,17 @@ title: Guides
permalink: /guides/
---
{% include set-global-site-url.html %}
These guides focus on common and more advanced usages of {{ site.spout_html }}.<br>
If you are just starting with {{ site.spout_html }}, check out the [Getting Started page]({{ site.github.url }}/getting-started/) and the [Documentation]({{ site.github.url }}/docs/) first.
If you are just starting with {{ site.spout_html }}, check out the [Getting Started page]({{ site_url }}/getting-started/) and the [Documentation]({{ site_url }}/docs/) first.
{% assign pages=site.pages | sort: 'path' %}
<ul>
{% for page in pages %}
{% if page.title and page.category contains 'guide' %}
<li>
<a class="page-link" href="{{ page.url | prepend: site.github.url }}">{{ page.title }}</a>
<a class="page-link" href="{{ page.url | prepend: site_url }}">{{ page.title }}</a>
</li>
{% endif %}
{% endfor %}
@@ -94,7 +94,7 @@ class MyStreamController extends Controller
$i++;
// Flushing the buffer every N rows to stream echo'ed content.
if ($i % FLUSH_THRESHOLD === 0) {
if ($i % self::FLUSH_THRESHOLD === 0) {
flush();
}
}
+5 -3
View File
@@ -5,6 +5,8 @@ title: Spout - Read and write spreadsheets, quickly and at scale
permalink: /
---
{% include section-supported-spreadsheet-types.html %}
{% include section-fast-and-scalable.html %}
{% include section-why-use-spout.html %}
{% include set-global-site-url.html %}
{% include section-supported-spreadsheet-types.html site_url=site_url %}
{% include section-fast-and-scalable.html site_url=site_url %}
{% include section-why-use-spout.html site_url=site_url %}
+4
View File
@@ -43,6 +43,10 @@
&:not(:last-child) {
margin-right: 20px;
}
svg {
padding-bottom: 3px;
}
}
@include media-query($on-palm) {
+4 -2
View File
@@ -1,7 +1,9 @@
version: "3"
services:
site:
command: jekyll serve
command: bash -c "
gem install 'jekyll-github-metadata'
&& jekyll serve --config _config.yml,_config_local.yml"
image: jekyll/jekyll:latest
volumes:
- $PWD:/srv/jekyll
@@ -10,4 +12,4 @@ services:
- 4000:4000
- 35729:35729
- 3000:3000
- 8080:4000
- 8080:4000
Binary file not shown.

Before

Width:  |  Height:  |  Size: 555 B

-59
View File
@@ -1,59 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
viewBox="0 -256 1850 1850"
id="svg3025"
version="1.1"
inkscape:version="0.48.3.1 r9886"
width="100%"
height="100%"
sodipodi:docname="external_link_font_awesome.svg">
<metadata
id="metadata3035">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs3033" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="640"
inkscape:window-height="480"
id="namedview3031"
showgrid="false"
inkscape:zoom="0.13169643"
inkscape:cx="896"
inkscape:cy="896"
inkscape:window-x="0"
inkscape:window-y="25"
inkscape:window-maximized="0"
inkscape:current-layer="svg3025" />
<g
transform="matrix(1,0,0,-1,30.372881,1426.9492)"
id="g3027">
<path
d="M 1408,608 V 288 Q 1408,169 1323.5,84.5 1239,0 1120,0 H 288 Q 169,0 84.5,84.5 0,169 0,288 v 832 Q 0,1239 84.5,1323.5 169,1408 288,1408 h 704 q 14,0 23,-9 9,-9 9,-23 v -64 q 0,-14 -9,-23 -9,-9 -23,-9 H 288 q -66,0 -113,-47 -47,-47 -47,-113 V 288 q 0,-66 47,-113 47,-47 113,-47 h 832 q 66,0 113,47 47,47 47,113 v 320 q 0,14 9,23 9,9 23,9 h 64 q 14,0 23,-9 9,-9 9,-23 z m 384,864 V 960 q 0,-26 -19,-45 -19,-19 -45,-19 -26,0 -45,19 L 1507,1091 855,439 q -10,-10 -23,-10 -13,0 -23,10 L 695,553 q -10,10 -10,23 0,13 10,23 l 652,652 -176,176 q -19,19 -19,45 0,26 19,45 19,19 45,19 h 512 q 26,0 45,-19 19,-19 19,-45 z"
id="path3029"
inkscape:connector-curvature="0"
style="fill:currentColor" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.2 KiB

+5 -1
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/7.5/phpunit.xsd"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/8.5/phpunit.xsd"
bootstrap="tests/bootstrap.php"
colors="true"
convertErrorsToExceptions="false"
@@ -8,6 +8,10 @@
defaultTestSuite="unit-tests"
verbose="false">
<php>
<ini name="error_reporting" value="-1" />
</php>
<testsuites>
<testsuite name="unit-tests">
+11 -11
View File
@@ -23,7 +23,7 @@ class Psr4Autoloader
*/
public function register()
{
spl_autoload_register([$this, 'loadClass']);
\spl_autoload_register([$this, 'loadClass']);
}
/**
@@ -40,10 +40,10 @@ class Psr4Autoloader
public function addNamespace($prefix, $baseDir, $prepend = false)
{
// normalize namespace prefix
$prefix = trim($prefix, '\\') . '\\';
$prefix = \trim($prefix, '\\') . '\\';
// normalize the base directory with a trailing separator
$baseDir = rtrim($baseDir, DIRECTORY_SEPARATOR) . '/';
$baseDir = \rtrim($baseDir, DIRECTORY_SEPARATOR) . '/';
// initialize the namespace prefix array
if (isset($this->prefixes[$prefix]) === false) {
@@ -52,9 +52,9 @@ class Psr4Autoloader
// retain the base directory for the namespace prefix
if ($prepend) {
array_unshift($this->prefixes[$prefix], $baseDir);
\array_unshift($this->prefixes[$prefix], $baseDir);
} else {
array_push($this->prefixes[$prefix], $baseDir);
\array_push($this->prefixes[$prefix], $baseDir);
}
}
@@ -72,12 +72,12 @@ class Psr4Autoloader
// work backwards through the namespace names of the fully-qualified
// class name to find a mapped file name
while (($pos = strrpos($prefix, '\\')) !== false) {
while (($pos = \strrpos($prefix, '\\')) !== false) {
// retain the trailing namespace separator in the prefix
$prefix = substr($class, 0, $pos + 1);
$prefix = \substr($class, 0, $pos + 1);
// the rest is the relative class name
$relativeClass = substr($class, $pos + 1);
$relativeClass = \substr($class, $pos + 1);
// try to load a mapped file for the prefix and relative class
$mappedFile = $this->loadMappedFile($prefix, $relativeClass);
@@ -87,7 +87,7 @@ class Psr4Autoloader
// remove the trailing namespace separator for the next iteration
// of strrpos()
$prefix = rtrim($prefix, '\\');
$prefix = \rtrim($prefix, '\\');
}
// never found a mapped file
@@ -115,7 +115,7 @@ class Psr4Autoloader
// replace namespace separators with directory separators
// in the relative class name, append with .php
$file = $baseDir
. str_replace('\\', '/', $relativeClass)
. \str_replace('\\', '/', $relativeClass)
. '.php';
// if the mapped file exists, require it
@@ -137,7 +137,7 @@ class Psr4Autoloader
*/
protected function requireFile($file)
{
if (file_exists($file)) {
if (\file_exists($file)) {
require $file;
return true;
+1 -1
View File
@@ -8,7 +8,7 @@ require_once 'Psr4Autoloader.php';
* @var string
* Full path to "src/Spout" which is what we want "Box\Spout" to map to.
*/
$srcBaseDirectory = dirname(dirname(__FILE__));
$srcBaseDirectory = \dirname(\dirname(__FILE__));
$loader = new Psr4Autoloader();
$loader->register();
+8
View File
@@ -91,6 +91,14 @@ class Cell
return !$this->isError() ? $this->value : null;
}
/**
* @return mixed
*/
public function getValueEvenIfError()
{
return $this->value;
}
/**
* @param Style|null $style
*/
+9 -3
View File
@@ -70,7 +70,7 @@ class Row
*/
public function getCellAtIndex($cellIndex)
{
return isset($this->cells[$cellIndex]) ? $this->cells[$cellIndex] : null;
return $this->cells[$cellIndex] ?? null;
}
/**
@@ -89,7 +89,13 @@ class Row
*/
public function getNumCells()
{
return count($this->cells);
// When using "setCellAtIndex", it's possible to
// have "$this->cells" contain holes.
if (empty($this->cells)) {
return 0;
}
return \max(\array_keys($this->cells)) + 1;
}
/**
@@ -116,7 +122,7 @@ class Row
*/
public function toArray()
{
return array_map(function (Cell $cell) {
return \array_map(function (Cell $cell) {
return $cell->getValue();
}, $this->cells);
}
+3 -3
View File
@@ -93,7 +93,7 @@ class BorderPart
*/
public function setName($name)
{
if (!in_array($name, self::$allowedNames)) {
if (!\in_array($name, self::$allowedNames)) {
throw new InvalidNameException($name);
}
$this->name = $name;
@@ -114,7 +114,7 @@ class BorderPart
*/
public function setStyle($style)
{
if (!in_array($style, self::$allowedStyles)) {
if (!\in_array($style, self::$allowedStyles)) {
throw new InvalidStyleException($style);
}
$this->style = $style;
@@ -152,7 +152,7 @@ class BorderPart
*/
public function setWidth($width)
{
if (!in_array($width, self::$allowedWidths)) {
if (!\in_array($width, self::$allowedWidths)) {
throw new InvalidWidthException($width);
}
$this->width = $width;
@@ -0,0 +1,32 @@
<?php
namespace Box\Spout\Common\Entity\Style;
/**
* Class Alignment
* This class provides constants to work with text alignment.
*/
abstract class CellAlignment
{
const LEFT = 'left';
const RIGHT = 'right';
const CENTER = 'center';
const JUSTIFY = 'justify';
private static $VALID_ALIGNMENTS = [
self::LEFT => 1,
self::RIGHT => 1,
self::CENTER => 1,
self::JUSTIFY => 1,
];
/**
* @param string $cellAlignment
*
* @return bool Whether the given cell alignment is valid
*/
public static function isValid($cellAlignment)
{
return isset(self::$VALID_ALIGNMENTS[$cellAlignment]);
}
}
+4 -4
View File
@@ -8,7 +8,7 @@ use Box\Spout\Common\Exception\InvalidColorException;
* Class Color
* This class provides constants and functions to work with colors
*/
class Color
abstract class Color
{
/** Standard colors - based on Office Online */
const BLACK = '000000';
@@ -38,7 +38,7 @@ class Color
self::throwIfInvalidColorComponentValue($green);
self::throwIfInvalidColorComponentValue($blue);
return strtoupper(
return \strtoupper(
self::convertColorComponentToHex($red) .
self::convertColorComponentToHex($green) .
self::convertColorComponentToHex($blue)
@@ -54,7 +54,7 @@ class Color
*/
protected static function throwIfInvalidColorComponentValue($colorComponent)
{
if (!is_int($colorComponent) || $colorComponent < 0 || $colorComponent > 255) {
if (!\is_int($colorComponent) || $colorComponent < 0 || $colorComponent > 255) {
throw new InvalidColorException("The RGB components must be between 0 and 255. Received: $colorComponent");
}
}
@@ -67,7 +67,7 @@ class Color
*/
protected static function convertColorComponentToHex($colorComponent)
{
return str_pad(dechex($colorComponent), 2, '0', STR_PAD_LEFT);
return \str_pad(\dechex($colorComponent), 2, '0', STR_PAD_LEFT);
}
/**
+81 -1
View File
@@ -8,7 +8,7 @@ namespace Box\Spout\Common\Entity\Style;
*/
class Style
{
/** Default font values */
/** Default values */
const DEFAULT_FONT_SIZE = 11;
const DEFAULT_FONT_COLOR = Color::BLACK;
const DEFAULT_FONT_NAME = 'Arial';
@@ -54,6 +54,13 @@ class Style
/** @var bool Whether specific font properties should be applied */
private $shouldApplyFont = false;
/** @var bool Whether specific cell alignment should be applied */
private $shouldApplyCellAlignment = false;
/** @var string Cell alignment */
private $cellAlignment;
/** @var bool Whether the cell alignment property was set */
private $hasSetCellAlignment = false;
/** @var bool Whether the text should wrap in the cell (useful for long or multi-lines text) */
private $shouldWrapText = false;
/** @var bool Whether the wrap text property was set */
@@ -71,6 +78,12 @@ class Style
/** @var bool */
private $hasSetBackgroundColor = false;
/** @var string Format */
private $format;
/** @var bool */
private $hasSetFormat = false;
/**
* @return int|null
*/
@@ -319,6 +332,44 @@ class Style
return $this->hasSetFontName;
}
/**
* @return string
*/
public function getCellAlignment()
{
return $this->cellAlignment;
}
/**
* @param string $cellAlignment The cell alignment
*
* @return Style
*/
public function setCellAlignment($cellAlignment)
{
$this->cellAlignment = $cellAlignment;
$this->hasSetCellAlignment = true;
$this->shouldApplyCellAlignment = true;
return $this;
}
/**
* @return bool
*/
public function hasSetCellAlignment()
{
return $this->hasSetCellAlignment;
}
/**
* @return bool Whether specific cell alignment should be applied
*/
public function shouldApplyCellAlignment()
{
return $this->shouldApplyCellAlignment;
}
/**
* @return bool
*/
@@ -383,4 +434,33 @@ class Style
{
return $this->hasSetBackgroundColor;
}
/**
* Sets format
* @param string $format
* @return Style
*/
public function setFormat($format)
{
$this->hasSetFormat = true;
$this->format = $format;
return $this;
}
/**
* @return string
*/
public function getFormat()
{
return $this->format;
}
/**
* @return bool Whether format should be applied
*/
public function shouldApplyFormat()
{
return $this->hasSetFormat;
}
}
+3 -3
View File
@@ -23,7 +23,7 @@ class CellTypeHelper
*/
public static function isNonEmptyString($value)
{
return (gettype($value) === 'string' && $value !== '');
return (\gettype($value) === 'string' && $value !== '');
}
/**
@@ -35,7 +35,7 @@ class CellTypeHelper
*/
public static function isNumeric($value)
{
$valueType = gettype($value);
$valueType = \gettype($value);
return ($valueType === 'integer' || $valueType === 'double');
}
@@ -49,7 +49,7 @@ class CellTypeHelper
*/
public static function isBoolean($value)
{
return gettype($value) === 'boolean';
return \gettype($value) === 'boolean';
}
/**
+3 -3
View File
@@ -61,7 +61,7 @@ class EncodingHelper
$bomUsed = $this->supportedEncodingsWithBom[$encoding];
// we skip the N first bytes
$byteOffsetToSkipBom = strlen($bomUsed);
$byteOffsetToSkipBom = \strlen($bomUsed);
}
return $byteOffsetToSkipBom;
@@ -80,9 +80,9 @@ class EncodingHelper
$this->globalFunctionsHelper->rewind($filePointer);
if (array_key_exists($encoding, $this->supportedEncodingsWithBom)) {
if (\array_key_exists($encoding, $this->supportedEncodingsWithBom)) {
$potentialBom = $this->supportedEncodingsWithBom[$encoding];
$numBytesInBom = strlen($potentialBom);
$numBytesInBom = \strlen($potentialBom);
$hasBOM = ($this->globalFunctionsHelper->fgets($filePointer, $numBytesInBom + 1) === $potentialBom);
}
+4 -4
View File
@@ -18,14 +18,14 @@ class ODS implements EscaperInterface
{
// @NOTE: Using ENT_QUOTES as XML entities ('<', '>', '&') as well as
// single/double quotes (for XML attributes) need to be encoded.
if (defined('ENT_DISALLOWED')) {
if (\defined('ENT_DISALLOWED')) {
// 'ENT_DISALLOWED' ensures that invalid characters in the given document type are replaced.
// Otherwise control characters like a vertical tab "\v" will make the XML document unreadable by the XML processor
// @link https://github.com/box/spout/issues/329
$replacedString = htmlspecialchars($string, ENT_QUOTES | ENT_DISALLOWED, 'UTF-8');
$replacedString = \htmlspecialchars($string, ENT_QUOTES | ENT_DISALLOWED, 'UTF-8');
} else {
// We are on hhvm or any other engine that does not support ENT_DISALLOWED.
$escapedString = htmlspecialchars($string, ENT_QUOTES, 'UTF-8');
$escapedString = \htmlspecialchars($string, ENT_QUOTES, 'UTF-8');
// control characters values are from 0 to 1F (hex values) in the ASCII table
// some characters should not be escaped though: "\t", "\r" and "\n".
@@ -34,7 +34,7 @@ class ODS implements EscaperInterface
'\x0B-\x0C' .
// skipping "\r" (0xD)
'\x0E-\x1F]';
$replacedString = preg_replace("/$regexPattern/", '�', $escapedString);
$replacedString = \preg_replace("/$regexPattern/", '�', $escapedString);
}
return $replacedString;
+11 -11
View File
@@ -28,7 +28,7 @@ class XLSX implements EscaperInterface
if (!$this->isAlreadyInitialized) {
$this->escapableControlCharactersPattern = $this->getEscapableControlCharactersPattern();
$this->controlCharactersEscapingMap = $this->getControlCharactersEscapingMap();
$this->controlCharactersEscapingReverseMap = array_flip($this->controlCharactersEscapingMap);
$this->controlCharactersEscapingReverseMap = \array_flip($this->controlCharactersEscapingMap);
$this->isAlreadyInitialized = true;
}
@@ -47,7 +47,7 @@ class XLSX implements EscaperInterface
$escapedString = $this->escapeControlCharacters($string);
// @NOTE: Using ENT_QUOTES as XML entities ('<', '>', '&') as well as
// single/double quotes (for XML attributes) need to be encoded.
$escapedString = htmlspecialchars($escapedString, ENT_QUOTES, 'UTF-8');
$escapedString = \htmlspecialchars($escapedString, ENT_QUOTES, 'UTF-8');
return $escapedString;
}
@@ -103,10 +103,10 @@ class XLSX implements EscaperInterface
// control characters values are from 0 to 1F (hex values) in the ASCII table
for ($charValue = 0x00; $charValue <= 0x1F; $charValue++) {
$character = chr($charValue);
if (preg_match("/{$this->escapableControlCharactersPattern}/", $character)) {
$charHexValue = dechex($charValue);
$escapedChar = '_x' . sprintf('%04s', strtoupper($charHexValue)) . '_';
$character = \chr($charValue);
if (\preg_match("/{$this->escapableControlCharactersPattern}/", $character)) {
$charHexValue = \dechex($charValue);
$escapedChar = '_x' . \sprintf('%04s', \strtoupper($charHexValue)) . '_';
$controlCharactersEscapingMap[$escapedChar] = $character;
}
}
@@ -132,11 +132,11 @@ class XLSX implements EscaperInterface
$escapedString = $this->escapeEscapeCharacter($string);
// if no control characters
if (!preg_match("/{$this->escapableControlCharactersPattern}/", $escapedString)) {
if (!\preg_match("/{$this->escapableControlCharactersPattern}/", $escapedString)) {
return $escapedString;
}
return preg_replace_callback("/({$this->escapableControlCharactersPattern})/", function ($matches) {
return \preg_replace_callback("/({$this->escapableControlCharactersPattern})/", function ($matches) {
return $this->controlCharactersEscapingReverseMap[$matches[0]];
}, $escapedString);
}
@@ -149,7 +149,7 @@ class XLSX implements EscaperInterface
*/
protected function escapeEscapeCharacter($string)
{
return preg_replace('/_(x[\dA-F]{4})_/', '_x005F_$1_', $string);
return \preg_replace('/_(x[\dA-F]{4})_/', '_x005F_$1_', $string);
}
/**
@@ -171,7 +171,7 @@ class XLSX implements EscaperInterface
foreach ($this->controlCharactersEscapingMap as $escapedCharValue => $charValue) {
// only unescape characters that don't contain the escaped escape character for now
$unescapedString = preg_replace("/(?<!_x005F)($escapedCharValue)/", $charValue, $unescapedString);
$unescapedString = \preg_replace("/(?<!_x005F)($escapedCharValue)/", $charValue, $unescapedString);
}
return $this->unescapeEscapeCharacter($unescapedString);
@@ -185,6 +185,6 @@ class XLSX implements EscaperInterface
*/
protected function unescapeEscapeCharacter($string)
{
return preg_replace('/_x005F(_x[\dA-F]{4}_)/', '$1', $string);
return \preg_replace('/_x005F(_x[\dA-F]{4}_)/', '$1', $string);
}
}
+17 -13
View File
@@ -17,9 +17,9 @@ class FileSystemHelper implements FileSystemHelperInterface
/**
* @param string $baseFolderPath The path of the base folder where all the I/O can occur
*/
public function __construct($baseFolderPath)
public function __construct(string $baseFolderPath)
{
$this->baseFolderRealPath = realpath($baseFolderPath);
$this->baseFolderRealPath = \realpath($baseFolderPath);
}
/**
@@ -36,7 +36,7 @@ class FileSystemHelper implements FileSystemHelperInterface
$folderPath = $parentFolderPath . '/' . $folderName;
$wasCreationSuccessful = mkdir($folderPath, 0777, true);
$wasCreationSuccessful = \mkdir($folderPath, 0777, true);
if (!$wasCreationSuccessful) {
throw new IOException("Unable to create folder: $folderPath");
}
@@ -60,7 +60,7 @@ class FileSystemHelper implements FileSystemHelperInterface
$filePath = $parentFolderPath . '/' . $fileName;
$wasCreationSuccessful = file_put_contents($filePath, $fileContents);
$wasCreationSuccessful = \file_put_contents($filePath, $fileContents);
if ($wasCreationSuccessful === false) {
throw new IOException("Unable to create file: $filePath");
}
@@ -79,8 +79,8 @@ class FileSystemHelper implements FileSystemHelperInterface
{
$this->throwIfOperationNotInBaseFolder($filePath);
if (file_exists($filePath) && is_file($filePath)) {
unlink($filePath);
if (\file_exists($filePath) && \is_file($filePath)) {
\unlink($filePath);
}
}
@@ -102,13 +102,13 @@ class FileSystemHelper implements FileSystemHelperInterface
foreach ($itemIterator as $item) {
if ($item->isDir()) {
rmdir($item->getPathname());
\rmdir($item->getPathname());
} else {
unlink($item->getPathname());
\unlink($item->getPathname());
}
}
rmdir($folderPath);
\rmdir($folderPath);
}
/**
@@ -117,13 +117,17 @@ class FileSystemHelper implements FileSystemHelperInterface
* should occur is not inside the base folder.
*
* @param string $operationFolderPath The path of the folder where the I/O operation should occur
* @throws \Box\Spout\Common\Exception\IOException If the folder where the I/O operation should occur is not inside the base folder
* @throws \Box\Spout\Common\Exception\IOException If the folder where the I/O operation should occur
* is not inside the base folder or the base folder does not exist
* @return void
*/
protected function throwIfOperationNotInBaseFolder($operationFolderPath)
protected function throwIfOperationNotInBaseFolder(string $operationFolderPath)
{
$operationFolderRealPath = realpath($operationFolderPath);
$isInBaseFolder = (strpos($operationFolderRealPath, $this->baseFolderRealPath) === 0);
$operationFolderRealPath = \realpath($operationFolderPath);
if (!$this->baseFolderRealPath) {
throw new IOException("The base folder path is invalid: {$this->baseFolderRealPath}");
}
$isInBaseFolder = (\strpos($operationFolderRealPath, $this->baseFolderRealPath) === 0);
if (!$isInBaseFolder) {
throw new IOException("Cannot perform I/O operation outside of the base folder: {$this->baseFolderRealPath}");
}
@@ -20,7 +20,7 @@ class GlobalFunctionsHelper
*/
public function fopen($fileName, $mode)
{
return fopen($fileName, $mode);
return \fopen($fileName, $mode);
}
/**
@@ -33,7 +33,7 @@ class GlobalFunctionsHelper
*/
public function fgets($handle, $length = null)
{
return fgets($handle, $length);
return \fgets($handle, $length);
}
/**
@@ -46,7 +46,7 @@ class GlobalFunctionsHelper
*/
public function fputs($handle, $string)
{
return fputs($handle, $string);
return \fputs($handle, $string);
}
/**
@@ -58,7 +58,7 @@ class GlobalFunctionsHelper
*/
public function fflush($handle)
{
return fflush($handle);
return \fflush($handle);
}
/**
@@ -71,7 +71,7 @@ class GlobalFunctionsHelper
*/
public function fseek($handle, $offset)
{
return fseek($handle, $offset);
return \fseek($handle, $offset);
}
/**
@@ -90,9 +90,9 @@ class GlobalFunctionsHelper
// To fix that, simply disable the escape character.
// @see https://bugs.php.net/bug.php?id=43225
// @see http://tools.ietf.org/html/rfc4180
$escapeCharacter = "\0";
$escapeCharacter = PHP_VERSION_ID >= 70400 ? '' : "\0";
return fgetcsv($handle, $length, $delimiter, $enclosure, $escapeCharacter);
return \fgetcsv($handle, $length, $delimiter, $enclosure, $escapeCharacter);
}
/**
@@ -111,9 +111,9 @@ class GlobalFunctionsHelper
// To fix that, simply disable the escape character.
// @see https://bugs.php.net/bug.php?id=43225
// @see http://tools.ietf.org/html/rfc4180
$escapeCharacter = "\0";
$escapeCharacter = PHP_VERSION_ID >= 70400 ? '' : "\0";
return fputcsv($handle, $fields, $delimiter, $enclosure, $escapeCharacter);
return \fputcsv($handle, $fields, $delimiter, $enclosure, $escapeCharacter);
}
/**
@@ -126,7 +126,7 @@ class GlobalFunctionsHelper
*/
public function fwrite($handle, $string)
{
return fwrite($handle, $string);
return \fwrite($handle, $string);
}
/**
@@ -138,7 +138,7 @@ class GlobalFunctionsHelper
*/
public function fclose($handle)
{
return fclose($handle);
return \fclose($handle);
}
/**
@@ -150,7 +150,7 @@ class GlobalFunctionsHelper
*/
public function rewind($handle)
{
return rewind($handle);
return \rewind($handle);
}
/**
@@ -162,7 +162,7 @@ class GlobalFunctionsHelper
*/
public function file_exists($fileName)
{
return file_exists($fileName);
return \file_exists($fileName);
}
/**
@@ -176,7 +176,7 @@ class GlobalFunctionsHelper
{
$realFilePath = $this->convertToUseRealPath($filePath);
return file_get_contents($realFilePath);
return \file_get_contents($realFilePath);
}
/**
@@ -191,13 +191,13 @@ class GlobalFunctionsHelper
$realFilePath = $filePath;
if ($this->isZipStream($filePath)) {
if (preg_match('/zip:\/\/(.*)#(.*)/', $filePath, $matches)) {
if (\preg_match('/zip:\/\/(.*)#(.*)/', $filePath, $matches)) {
$documentPath = $matches[1];
$documentInsideZipPath = $matches[2];
$realFilePath = 'zip://' . realpath($documentPath) . '#' . $documentInsideZipPath;
$realFilePath = 'zip://' . \realpath($documentPath) . '#' . $documentInsideZipPath;
}
} else {
$realFilePath = realpath($filePath);
$realFilePath = \realpath($filePath);
}
return $realFilePath;
@@ -211,7 +211,7 @@ class GlobalFunctionsHelper
*/
protected function isZipStream($path)
{
return (strpos($path, 'zip://') === 0);
return (\strpos($path, 'zip://') === 0);
}
/**
@@ -223,7 +223,7 @@ class GlobalFunctionsHelper
*/
public function feof($handle)
{
return feof($handle);
return \feof($handle);
}
/**
@@ -235,7 +235,7 @@ class GlobalFunctionsHelper
*/
public function is_readable($fileName)
{
return is_readable($fileName);
return \is_readable($fileName);
}
/**
@@ -248,7 +248,7 @@ class GlobalFunctionsHelper
*/
public function basename($path, $suffix = null)
{
return basename($path, $suffix);
return \basename($path, $suffix);
}
/**
@@ -260,7 +260,7 @@ class GlobalFunctionsHelper
*/
public function header($string)
{
header($string);
\header($string);
}
/**
@@ -271,8 +271,8 @@ class GlobalFunctionsHelper
*/
public function ob_end_clean()
{
if (ob_get_length() > 0) {
ob_end_clean();
if (\ob_get_length() > 0) {
\ob_end_clean();
}
}
@@ -287,7 +287,7 @@ class GlobalFunctionsHelper
*/
public function iconv($string, $sourceEncoding, $targetEncoding)
{
return iconv($sourceEncoding, $targetEncoding, $string);
return \iconv($sourceEncoding, $targetEncoding, $string);
}
/**
@@ -301,7 +301,7 @@ class GlobalFunctionsHelper
*/
public function mb_convert_encoding($string, $sourceEncoding, $targetEncoding)
{
return mb_convert_encoding($string, $targetEncoding, $sourceEncoding);
return \mb_convert_encoding($string, $targetEncoding, $sourceEncoding);
}
/**
@@ -312,7 +312,7 @@ class GlobalFunctionsHelper
*/
public function stream_get_wrappers()
{
return stream_get_wrappers();
return \stream_get_wrappers();
}
/**
@@ -324,6 +324,6 @@ class GlobalFunctionsHelper
*/
public function function_exists($functionName)
{
return function_exists($functionName);
return \function_exists($functionName);
}
}
+4 -4
View File
@@ -18,7 +18,7 @@ class StringHelper
*/
public function __construct()
{
$this->hasMbstringSupport = extension_loaded('mbstring');
$this->hasMbstringSupport = \extension_loaded('mbstring');
}
/**
@@ -32,7 +32,7 @@ class StringHelper
*/
public function getStringLength($string)
{
return $this->hasMbstringSupport ? mb_strlen($string) : strlen($string);
return $this->hasMbstringSupport ? \mb_strlen($string) : \strlen($string);
}
/**
@@ -47,7 +47,7 @@ class StringHelper
*/
public function getCharFirstOccurrencePosition($char, $string)
{
$position = $this->hasMbstringSupport ? mb_strpos($string, $char) : strpos($string, $char);
$position = $this->hasMbstringSupport ? \mb_strpos($string, $char) : \strpos($string, $char);
return ($position !== false) ? $position : -1;
}
@@ -64,7 +64,7 @@ class StringHelper
*/
public function getCharLastOccurrencePosition($char, $string)
{
$position = $this->hasMbstringSupport ? mb_strrpos($string, $char) : strrpos($string, $char);
$position = $this->hasMbstringSupport ? \mb_strrpos($string, $char) : \strrpos($string, $char);
return ($position !== false) ? $position : -1;
}
@@ -46,7 +46,7 @@ abstract class OptionsManagerAbstract implements OptionsManagerInterface
*/
public function setOption($optionName, $optionValue)
{
if (in_array($optionName, $this->supportedOptions)) {
if (\in_array($optionName, $this->supportedOptions)) {
$this->options[$optionName] = $optionValue;
}
}
@@ -89,7 +89,7 @@ class InternalEntityFactory implements InternalEntityFactoryInterface
*/
public function createRowFromArray(array $cellValues = [])
{
$cells = array_map(function ($cellValue) {
$cells = \array_map(function ($cellValue) {
return $this->createCell($cellValue);
}, $cellValues);
+3 -3
View File
@@ -84,8 +84,8 @@ class Reader extends ReaderAbstract
*/
protected function openReader($filePath)
{
$this->originalAutoDetectLineEndings = ini_get('auto_detect_line_endings');
ini_set('auto_detect_line_endings', '1');
$this->originalAutoDetectLineEndings = \ini_get('auto_detect_line_endings');
\ini_set('auto_detect_line_endings', '1');
$this->filePointer = $this->globalFunctionsHelper->fopen($filePath, 'r');
if (!$this->filePointer) {
@@ -123,6 +123,6 @@ class Reader extends ReaderAbstract
$this->globalFunctionsHelper->fclose($this->filePointer);
}
ini_set('auto_detect_line_endings', $this->originalAutoDetectLineEndings);
\ini_set('auto_detect_line_endings', $this->originalAutoDetectLineEndings);
}
}
+4 -4
View File
@@ -147,7 +147,7 @@ class RowIterator implements IteratorInterface
if ($rowData !== false) {
// str_replace will replace NULL values by empty strings
$rowDataBufferAsArray = str_replace(null, null, $rowData);
$rowDataBufferAsArray = \str_replace(null, null, $rowData);
$this->rowBuffer = $this->entityFactory->createRowFromArray($rowDataBufferAsArray);
$this->numReadRows++;
} else {
@@ -193,13 +193,13 @@ class RowIterator implements IteratorInterface
case EncodingHelper::ENCODING_UTF16_LE:
case EncodingHelper::ENCODING_UTF32_LE:
// remove whitespace from the beginning of a string as fgetcsv() add extra whitespace when it try to explode non UTF-8 data
$cellValue = ltrim($cellValue);
$cellValue = \ltrim($cellValue);
break;
case EncodingHelper::ENCODING_UTF16_BE:
case EncodingHelper::ENCODING_UTF32_BE:
// remove whitespace from the end of a string as fgetcsv() add extra whitespace when it try to explode non UTF-8 data
$cellValue = rtrim($cellValue);
$cellValue = \rtrim($cellValue);
break;
}
@@ -215,7 +215,7 @@ class RowIterator implements IteratorInterface
*/
protected function isEmptyLine($lineData)
{
return (is_array($lineData) && count($lineData) === 1 && $lineData[0] === null);
return (\is_array($lineData) && \count($lineData) === 1 && $lineData[0] === null);
}
/**
@@ -37,7 +37,7 @@ class ReaderFactory
*/
public static function createFromFile(string $path)
{
$extension = strtolower(pathinfo($path, PATHINFO_EXTENSION));
$extension = \strtolower(\pathinfo($path, PATHINFO_EXTENSION));
return self::createFromType($extension);
}
@@ -47,12 +47,14 @@ class RowManager
*/
public function fillMissingIndexesWithEmptyCells(Row $row)
{
if ($row->getNumCells() === 0) {
$numCells = $row->getNumCells();
if ($numCells === 0) {
return $row;
}
$rowCells = $row->getCells();
$maxCellIndex = max(array_keys($rowCells));
$maxCellIndex = $numCells;
for ($cellIndex = 0; $cellIndex < $maxCellIndex; $cellIndex++) {
if (!isset($rowCells[$cellIndex])) {
+1 -1
View File
@@ -73,7 +73,7 @@ class XMLProcessor
{
$callbackObject = $callback[0];
$callbackMethodName = $callback[1];
$reflectionMethod = new \ReflectionMethod(get_class($callbackObject), $callbackMethodName);
$reflectionMethod = new \ReflectionMethod(\get_class($callbackObject), $callbackMethodName);
$reflectionMethod->setAccessible(true);
return [
@@ -22,9 +22,11 @@ class CellValueFormatter
/** Definition of XML nodes names used to parse data */
const XML_NODE_P = 'p';
const XML_NODE_S = 'text:s';
const XML_NODE_A = 'text:a';
const XML_NODE_SPAN = 'text:span';
const XML_NODE_TEXT_A = 'text:a';
const XML_NODE_TEXT_SPAN = 'text:span';
const XML_NODE_TEXT_S = 'text:s';
const XML_NODE_TEXT_TAB = 'text:tab';
const XML_NODE_TEXT_LINE_BREAK = 'text:line-break';
/** Definition of XML attributes used to parse data */
const XML_ATTRIBUTE_TYPE = 'office:value-type';
@@ -41,6 +43,13 @@ class CellValueFormatter
/** @var \Box\Spout\Common\Helper\Escaper\ODS Used to unescape XML data */
protected $escaper;
/** @var array List of XML nodes representing whitespaces and their corresponding value */
private static $WHITESPACE_XML_NODES = [
self::XML_NODE_TEXT_S => ' ',
self::XML_NODE_TEXT_TAB => "\t",
self::XML_NODE_TEXT_LINE_BREAK => "\n",
];
/**
* @param bool $shouldFormatDates Whether date/time values should be returned as PHP objects or be formatted as strings
* @param \Box\Spout\Common\Helper\Escaper\ODS $escaper Used to unescape XML data
@@ -96,29 +105,71 @@ class CellValueFormatter
$pNodes = $node->getElementsByTagName(self::XML_NODE_P);
foreach ($pNodes as $pNode) {
$currentPValue = '';
foreach ($pNode->childNodes as $childNode) {
if ($childNode instanceof \DOMText) {
$currentPValue .= $childNode->nodeValue;
} elseif ($childNode->nodeName === self::XML_NODE_S) {
$spaceAttribute = $childNode->getAttribute(self::XML_ATTRIBUTE_C);
$numSpaces = (!empty($spaceAttribute)) ? (int) $spaceAttribute : 1;
$currentPValue .= str_repeat(' ', $numSpaces);
} elseif ($childNode->nodeName === self::XML_NODE_A || $childNode->nodeName === self::XML_NODE_SPAN) {
$currentPValue .= $childNode->nodeValue;
}
}
$pNodeValues[] = $currentPValue;
$pNodeValues[] = $this->extractTextValueFromNode($pNode);
}
$escapedCellValue = implode("\n", $pNodeValues);
$escapedCellValue = \implode("\n", $pNodeValues);
$cellValue = $this->escaper->unescape($escapedCellValue);
return $cellValue;
}
/**
* @param $pNode
* @return string
*/
private function extractTextValueFromNode($pNode)
{
$textValue = '';
foreach ($pNode->childNodes as $childNode) {
if ($childNode instanceof \DOMText) {
$textValue .= $childNode->nodeValue;
} elseif ($this->isWhitespaceNode($childNode->nodeName)) {
$textValue .= $this->transformWhitespaceNode($childNode);
} elseif ($childNode->nodeName === self::XML_NODE_TEXT_A || $childNode->nodeName === self::XML_NODE_TEXT_SPAN) {
$textValue .= $this->extractTextValueFromNode($childNode);
}
}
return $textValue;
}
/**
* Returns whether the given node is a whitespace node. It must be one of these:
* - <text:s />
* - <text:tab />
* - <text:line-break />
*
* @param string $nodeName
* @return bool
*/
private function isWhitespaceNode($nodeName)
{
return isset(self::$WHITESPACE_XML_NODES[$nodeName]);
}
/**
* The "<text:p>" node can contain the string value directly
* or contain child elements. In this case, whitespaces contain in
* the child elements should be replaced by their XML equivalent:
* - space => <text:s />
* - tab => <text:tab />
* - line break => <text:line-break />
*
* @see https://docs.oasis-open.org/office/v1.2/os/OpenDocument-v1.2-os-part1.html#__RefHeading__1415200_253892949
*
* @param \DOMNode $node The XML node representing a whitespace
* @return string The corresponding whitespace value
*/
private function transformWhitespaceNode($node)
{
$countAttribute = $node->getAttribute(self::XML_ATTRIBUTE_C); // only defined for "<text:s>"
$numWhitespaces = (!empty($countAttribute)) ? (int) $countAttribute : 1;
return \str_repeat(self::$WHITESPACE_XML_NODES[$node->nodeName], $numWhitespaces);
}
/**
* Returns the cell Numeric value from the given node.
*
+2 -2
View File
@@ -28,13 +28,13 @@ class SheetIterator implements IteratorInterface
const XML_ATTRIBUTE_TABLE_STYLE_NAME = 'table:style-name';
const XML_ATTRIBUTE_TABLE_DISPLAY = 'table:display';
/** @var string $filePath Path of the file to be read */
/** @var string Path of the file to be read */
protected $filePath;
/** @var \Box\Spout\Common\Manager\OptionsManagerInterface Reader's options manager */
protected $optionsManager;
/** @var InternalEntityFactory $entityFactory Factory to create entities */
/** @var InternalEntityFactory Factory to create entities */
protected $entityFactory;
/** @var XMLReader The XMLReader object that will help read sheet's XML data */
+3 -3
View File
@@ -145,7 +145,7 @@ abstract class ReaderAbstract implements ReaderInterface
}
// Need to use realpath to fix "Can't open file" on some Windows setup
return realpath($filePath);
return \realpath($filePath);
}
/**
@@ -158,7 +158,7 @@ abstract class ReaderAbstract implements ReaderInterface
protected function getStreamWrapperScheme($filePath)
{
$streamScheme = null;
if (preg_match('/^(\w+):\/\//', $filePath, $matches)) {
if (\preg_match('/^(\w+):\/\//', $filePath, $matches)) {
$streamScheme = $matches[1];
}
@@ -190,7 +190,7 @@ abstract class ReaderAbstract implements ReaderInterface
$streamScheme = $this->getStreamWrapperScheme($filePath);
return ($streamScheme !== null) ?
in_array($streamScheme, $this->globalFunctionsHelper->stream_get_wrappers()) :
\in_array($streamScheme, $this->globalFunctionsHelper->stream_get_wrappers()) :
true;
}
@@ -20,8 +20,8 @@ trait XMLInternalErrorsHelper
*/
protected function useXMLInternalErrors()
{
libxml_clear_errors();
$this->initialUseInternalErrorsValue = libxml_use_internal_errors(true);
\libxml_clear_errors();
$this->initialUseInternalErrorsValue = \libxml_use_internal_errors(true);
}
/**
@@ -48,7 +48,7 @@ trait XMLInternalErrorsHelper
*/
private function hasXMLErrorOccured()
{
return (libxml_get_last_error() !== false);
return (\libxml_get_last_error() !== false);
}
/**
@@ -60,10 +60,10 @@ trait XMLInternalErrorsHelper
private function getLastXMLErrorMessage()
{
$errorMessage = null;
$error = libxml_get_last_error();
$error = \libxml_get_last_error();
if ($error !== false) {
$errorMessage = trim($error->message);
$errorMessage = \trim($error->message);
}
return $errorMessage;
@@ -74,6 +74,6 @@ trait XMLInternalErrorsHelper
*/
protected function resetXMLInternalErrorsSetting()
{
libxml_use_internal_errors($this->initialUseInternalErrorsValue);
\libxml_use_internal_errors($this->initialUseInternalErrorsValue);
}
}
+4 -4
View File
@@ -46,9 +46,9 @@ class XMLReader extends \XMLReader
public function getRealPathURIForFileInZip($zipFilePath, $fileInsideZipPath)
{
// The file path should not start with a '/', otherwise it won't be found
$fileInsideZipPathWithoutLeadingSlash = ltrim($fileInsideZipPath, '/');
$fileInsideZipPathWithoutLeadingSlash = \ltrim($fileInsideZipPath, '/');
return (self::ZIP_WRAPPER . realpath($zipFilePath) . '#' . $fileInsideZipPathWithoutLeadingSlash);
return (self::ZIP_WRAPPER . \realpath($zipFilePath) . '#' . $fileInsideZipPathWithoutLeadingSlash);
}
/**
@@ -62,7 +62,7 @@ class XMLReader extends \XMLReader
$doesFileExists = false;
$pattern = '/zip:\/\/([^#]+)#(.*)/';
if (preg_match($pattern, $zipStreamURI, $matches)) {
if (\preg_match($pattern, $zipStreamURI, $matches)) {
$zipFilePath = $matches[1];
$innerFilePath = $matches[2];
@@ -158,7 +158,7 @@ class XMLReader extends \XMLReader
// In some cases, the node has a prefix (for instance, "<sheet>" can also be "<x:sheet>").
// So if the given node name does not have a prefix, we need to look at the unprefixed name ("localName").
// @see https://github.com/box/spout/issues/233
$hasPrefix = (strpos($nodeName, ':') !== false);
$hasPrefix = (\strpos($nodeName, ':') !== false);
$currentNodeName = ($hasPrefix) ? $this->name : $this->localName;
return ($this->nodeType === $nodeType && $currentNodeName === $nodeName);
+2 -2
View File
@@ -37,7 +37,7 @@ class CellHelper
$columnIndex = 0;
// Remove row information
$columnLetters = preg_replace('/\d/', '', $cellIndex);
$columnLetters = \preg_replace('/\d/', '', $cellIndex);
// strlen() is super slow too... Using isset() is way faster and not too unreadable,
// since we checked before that there are between 1 and 3 letters.
@@ -75,6 +75,6 @@ class CellHelper
*/
protected static function isValidCellIndex($cellIndex)
{
return (preg_match('/^[A-Z]{1,3}\d+$/', $cellIndex) === 1);
return (\preg_match('/^[A-Z]{1,3}\d+$/', $cellIndex) === 1);
}
}
@@ -163,7 +163,7 @@ class CellValueFormatter
*/
protected function formatStrCellValue($nodeValue)
{
$escapedCellValue = trim($nodeValue);
$escapedCellValue = \trim($nodeValue);
$cellValue = $this->escaper->unescape($escapedCellValue);
return $cellValue;
@@ -248,8 +248,8 @@ class CellValueFormatter
$baseDate = $this->shouldUse1904Dates ? '1904-01-01' : '1899-12-30';
$daysSinceBaseDate = (int) $nodeValue;
$timeRemainder = fmod($nodeValue, 1);
$secondsRemainder = round($timeRemainder * self::NUM_SECONDS_IN_ONE_DAY, 0);
$timeRemainder = \fmod($nodeValue, 1);
$secondsRemainder = \round($timeRemainder * self::NUM_SECONDS_IN_ONE_DAY, 0);
$dateObj = \DateTime::createFromFormat('|Y-m-d', $baseDate);
$dateObj->modify('+' . $daysSinceBaseDate . 'days');
@@ -62,13 +62,13 @@ class DateFormatHelper
// Remove brackets potentially present at the beginning of the format string
// and text portion of the format at the end of it (starting with ";")
// See §18.8.31 of ECMA-376 for more detail.
$dateFormat = preg_replace('/^(?:\[\$[^\]]+?\])?([^;]*).*/', '$1', $excelDateFormat);
$dateFormat = \preg_replace('/^(?:\[\$[^\]]+?\])?([^;]*).*/', '$1', $excelDateFormat);
// Double quotes are used to escape characters that must not be interpreted.
// For instance, ["Day " dd] should result in "Day 13" and we should not try to interpret "D", "a", "y"
// By exploding the format string using double quote as a delimiter, we can get all parts
// that must be transformed (even indexes) and all parts that must not be (odd indexes).
$dateFormatParts = explode('"', $dateFormat);
$dateFormatParts = \explode('"', $dateFormat);
foreach ($dateFormatParts as $partIndex => $dateFormatPart) {
// do not look at odd indexes
@@ -77,19 +77,19 @@ class DateFormatHelper
}
// Make sure all characters are lowercase, as the mapping table is using lowercase characters
$transformedPart = strtolower($dateFormatPart);
$transformedPart = \strtolower($dateFormatPart);
// Remove escapes related to non-format characters
$transformedPart = str_replace('\\', '', $transformedPart);
$transformedPart = \str_replace('\\', '', $transformedPart);
// Apply general transformation first...
$transformedPart = strtr($transformedPart, self::$excelDateFormatToPHPDateFormatMapping[self::KEY_GENERAL]);
$transformedPart = \strtr($transformedPart, self::$excelDateFormatToPHPDateFormatMapping[self::KEY_GENERAL]);
// ... then apply hour transformation, for 12-hour or 24-hour format
if (self::has12HourFormatMarker($dateFormatPart)) {
$transformedPart = strtr($transformedPart, self::$excelDateFormatToPHPDateFormatMapping[self::KEY_HOUR_12]);
$transformedPart = \strtr($transformedPart, self::$excelDateFormatToPHPDateFormatMapping[self::KEY_HOUR_12]);
} else {
$transformedPart = strtr($transformedPart, self::$excelDateFormatToPHPDateFormatMapping[self::KEY_HOUR_24]);
$transformedPart = \strtr($transformedPart, self::$excelDateFormatToPHPDateFormatMapping[self::KEY_HOUR_24]);
}
// overwrite the parts array with the new transformed part
@@ -97,16 +97,16 @@ class DateFormatHelper
}
// Merge all transformed parts back together
$phpDateFormat = implode('"', $dateFormatParts);
$phpDateFormat = \implode('"', $dateFormatParts);
// Finally, to have the date format compatible with the DateTime::format() function, we need to escape
// all characters that are inside double quotes (and double quotes must be removed).
// For instance, ["Day " dd] should become [\D\a\y\ dd]
$phpDateFormat = preg_replace_callback('/"(.+?)"/', function ($matches) {
$phpDateFormat = \preg_replace_callback('/"(.+?)"/', function ($matches) {
$stringToEscape = $matches[1];
$letters = preg_split('//u', $stringToEscape, -1, PREG_SPLIT_NO_EMPTY);
$letters = \preg_split('//u', $stringToEscape, -1, PREG_SPLIT_NO_EMPTY);
return '\\' . implode('\\', $letters);
return '\\' . \implode('\\', $letters);
}, $phpDateFormat);
return $phpDateFormat;
@@ -118,6 +118,6 @@ class DateFormatHelper
*/
private static function has12HourFormatMarker($excelDateFormat)
{
return (stripos($excelDateFormat, 'am/pm') !== false);
return (\stripos($excelDateFormat, 'am/pm') !== false);
}
}
@@ -29,7 +29,7 @@ class OptionsManager extends OptionsManagerAbstract
*/
protected function setDefaultOptions()
{
$this->setOption(Options::TEMP_FOLDER, sys_get_temp_dir());
$this->setOption(Options::TEMP_FOLDER, \sys_get_temp_dir());
$this->setOption(Options::SHOULD_FORMAT_DATES, false);
$this->setOption(Options::SHOULD_PRESERVE_EMPTY_ROWS, false);
$this->setOption(Options::SHOULD_USE_1904_DATES, false);
@@ -103,14 +103,14 @@ class CachingStrategyFactory
protected function getMemoryLimitInKB()
{
$memoryLimitFormatted = $this->getMemoryLimitFromIni();
$memoryLimitFormatted = strtolower(trim($memoryLimitFormatted));
$memoryLimitFormatted = \strtolower(\trim($memoryLimitFormatted));
// No memory limit
if ($memoryLimitFormatted === '-1') {
return -1;
}
if (preg_match('/(\d+)([bkmgt])b?/', $memoryLimitFormatted, $matches)) {
if (\preg_match('/(\d+)([bkmgt])b?/', $memoryLimitFormatted, $matches)) {
$amount = (int) ($matches[1]);
$unit = $matches[2];
@@ -133,6 +133,6 @@ class CachingStrategyFactory
*/
protected function getMemoryLimitFromIni()
{
return ini_get('memory_limit');
return \ini_get('memory_limit');
}
}
@@ -55,7 +55,7 @@ class FileBasedStrategy implements CachingStrategyInterface
public function __construct($tempFolder, $maxNumStringsPerTempFile, $helperFactory)
{
$this->fileSystemHelper = $helperFactory->createFileSystemHelper($tempFolder);
$this->tempFolder = $this->fileSystemHelper->createFolder($tempFolder, uniqid('sharedstrings'));
$this->tempFolder = $this->fileSystemHelper->createFolder($tempFolder, \uniqid('sharedstrings'));
$this->maxNumStringsPerTempFile = $maxNumStringsPerTempFile;
@@ -135,7 +135,7 @@ class FileBasedStrategy implements CachingStrategyInterface
// free memory
unset($this->inMemoryTempFileContents);
$this->inMemoryTempFileContents = explode(PHP_EOL, $this->globalFunctionsHelper->file_get_contents($tempFilePath));
$this->inMemoryTempFileContents = \explode(PHP_EOL, $this->globalFunctionsHelper->file_get_contents($tempFilePath));
$this->inMemoryTempFilePath = $tempFilePath;
}
@@ -151,7 +151,7 @@ class FileBasedStrategy implements CachingStrategyInterface
throw new SharedStringNotFoundException("Shared string not found for index: $sharedStringIndex");
}
return rtrim($sharedString, PHP_EOL);
return \rtrim($sharedString, PHP_EOL);
}
/**
@@ -162,7 +162,7 @@ class FileBasedStrategy implements CachingStrategyInterface
*/
private function escapeLineFeed($unescapedString)
{
return str_replace("\n", self::ESCAPED_LINE_FEED_CHARACTER, $unescapedString);
return \str_replace("\n", self::ESCAPED_LINE_FEED_CHARACTER, $unescapedString);
}
/**
@@ -173,7 +173,7 @@ class FileBasedStrategy implements CachingStrategyInterface
*/
private function unescapeLineFeed($escapedString)
{
return str_replace(self::ESCAPED_LINE_FEED_CHARACTER, "\n", $escapedString);
return \str_replace(self::ESCAPED_LINE_FEED_CHARACTER, "\n", $escapedString);
}
/**
@@ -43,7 +43,7 @@ class SharedStringsManager
/** @var InternalEntityFactory Factory to create entities */
protected $entityFactory;
/** @var HelperFactory $helperFactory Factory to create helpers */
/** @var HelperFactory Factory to create helpers */
protected $helperFactory;
/** @var CachingStrategyFactory Factory to create shared strings caching strategies */
@@ -190,7 +190,7 @@ class SharedStringsManager
$textNodeValue = $textNode->nodeValue;
$shouldPreserveWhitespace = $this->shouldPreserveWhitespace($textNode);
$sharedStringValue .= ($shouldPreserveWhitespace) ? $textNodeValue : trim($textNodeValue);
$sharedStringValue .= ($shouldPreserveWhitespace) ? $textNodeValue : \trim($textNodeValue);
}
}
@@ -114,7 +114,9 @@ class SheetManager
*/
protected function processWorkbookPropertiesStartingNode($xmlReader)
{
$shouldUse1904Dates = (bool) $xmlReader->getAttribute(self::XML_ATTRIBUTE_DATE_1904);
// Using "filter_var($x, FILTER_VALIDATE_BOOLEAN)" here because the value of the "date1904" attribute
// may be the string "false", that is not mapped to the boolean "false" by default...
$shouldUse1904Dates = \filter_var($xmlReader->getAttribute(self::XML_ATTRIBUTE_DATE_1904), FILTER_VALIDATE_BOOLEAN);
$this->optionsManager->setOption(Options::SHOULD_USE_1904_DATES, $shouldUse1904Dates);
return XMLProcessor::PROCESSING_CONTINUE;
@@ -209,7 +211,7 @@ class SheetManager
$sheetDataXMLFilePath = $xmlReader->getAttribute(self::XML_ATTRIBUTE_TARGET);
// sometimes, the sheet data file path already contains "/xl/"...
if (strpos($sheetDataXMLFilePath, '/xl/') !== 0) {
if (\strpos($sheetDataXMLFilePath, '/xl/') !== 0) {
$sheetDataXMLFilePath = '/xl/' . $sheetDataXMLFilePath;
break;
}
+17 -7
View File
@@ -48,7 +48,10 @@ class StyleManager
/** @var string Path of the XLSX file being read */
protected $filePath;
/** @var string Path of the styles XML file */
/** @var bool Whether the XLSX file contains a styles XML file */
protected $hasStylesXMLFile;
/** @var string|null Path of the styles XML file */
protected $stylesXMLFilePath;
/** @var InternalEntityFactory Factory to create entities */
@@ -75,8 +78,11 @@ class StyleManager
{
$this->filePath = $filePath;
$this->entityFactory = $entityFactory;
$this->builtinNumFmtIdIndicatingDates = array_keys(self::$builtinNumFmtIdToNumFormatMapping);
$this->stylesXMLFilePath = $workbookRelationshipsManager->getStylesXMLFilePath();
$this->builtinNumFmtIdIndicatingDates = \array_keys(self::$builtinNumFmtIdToNumFormatMapping);
$this->hasStylesXMLFile = $workbookRelationshipsManager->hasStylesXMLFile();
if ($this->hasStylesXMLFile) {
$this->stylesXMLFilePath = $workbookRelationshipsManager->getStylesXMLFilePath();
}
}
/**
@@ -88,6 +94,10 @@ class StyleManager
*/
public function shouldFormatNumericValueAsDate($styleId)
{
if (!$this->hasStylesXMLFile) {
return false;
}
$stylesAttributes = $this->getStylesAttributes();
// Default style (0) does not format numeric values as timestamps. Only custom styles do.
@@ -263,7 +273,7 @@ class StyleManager
*/
protected function isNumFmtIdBuiltInDateFormat($numFmtId)
{
return in_array($numFmtId, $this->builtinNumFmtIdIndicatingDates);
return \in_array($numFmtId, $this->builtinNumFmtIdIndicatingDates);
}
/**
@@ -273,7 +283,7 @@ class StyleManager
protected function isFormatCodeCustomDateFormat($formatCode)
{
// if no associated format code or if using the default "General" format
if ($formatCode === null || strcasecmp($formatCode, self::NUMBER_FORMAT_GENERAL) === 0) {
if ($formatCode === null || \strcasecmp($formatCode, self::NUMBER_FORMAT_GENERAL) === 0) {
return false;
}
@@ -288,7 +298,7 @@ class StyleManager
{
// Remove extra formatting (what's between [ ], the brackets should not be preceded by a "\")
$pattern = '((?<!\\\)\[.+?(?<!\\\)\])';
$formatCode = preg_replace($pattern, '', $formatCode);
$formatCode = \preg_replace($pattern, '', $formatCode);
// custom date formats contain specific characters to represent the date:
// e - yy - m - d - h - s
@@ -300,7 +310,7 @@ class StyleManager
// character not preceded by "\" (case insensitive)
$pattern = '/(?<!\\\)' . $dateFormatCharacter . '/i';
if (preg_match($pattern, $formatCode)) {
if (\preg_match($pattern, $formatCode)) {
$hasFoundDateFormatCharacter = true;
break;
}
@@ -55,7 +55,7 @@ class WorkbookRelationshipsManager
$sharedStringsXMLFilePath = $workbookRelationships[self::RELATIONSHIP_TYPE_SHARED_STRINGS];
// the file path can be relative (e.g. "styles.xml") or absolute (e.g. "/xl/styles.xml")
$doesContainBasePath = (strpos($sharedStringsXMLFilePath, self::BASE_PATH) !== false);
$doesContainBasePath = (\strpos($sharedStringsXMLFilePath, self::BASE_PATH) !== false);
if (!$doesContainBasePath) {
// make sure we return an absolute file path
$sharedStringsXMLFilePath = self::BASE_PATH . $sharedStringsXMLFilePath;
@@ -75,7 +75,17 @@ class WorkbookRelationshipsManager
}
/**
* @return string|null The path of the styles XML file
* @return bool Whether the XLSX file contains a styles XML file
*/
public function hasStylesXMLFile()
{
$workbookRelationships = $this->getWorkbookRelationships();
return isset($workbookRelationships[self::RELATIONSHIP_TYPE_STYLES]);
}
/**
* @return string The path of the styles XML file
*/
public function getStylesXMLFilePath()
{
@@ -83,7 +93,7 @@ class WorkbookRelationshipsManager
$stylesXMLFilePath = $workbookRelationships[self::RELATIONSHIP_TYPE_STYLES];
// the file path can be relative (e.g. "styles.xml") or absolute (e.g. "/xl/styles.xml")
$doesContainBasePath = (strpos($stylesXMLFilePath, self::BASE_PATH) !== false);
$doesContainBasePath = (\strpos($stylesXMLFilePath, self::BASE_PATH) !== false);
if (!$doesContainBasePath) {
// make sure we return a full path
$stylesXMLFilePath = self::BASE_PATH . $stylesXMLFilePath;
+5 -5
View File
@@ -35,7 +35,7 @@ class RowIterator implements IteratorInterface
/** @var string Path of the XLSX file being read */
protected $filePath;
/** @var string $sheetDataXMLFilePath Path of the sheet data XML file as in [Content_Types].xml */
/** @var string Path of the sheet data XML file as in [Content_Types].xml */
protected $sheetDataXMLFilePath;
/** @var \Box\Spout\Reader\Wrapper\XMLReader The XMLReader object that will help read sheet's XML data */
@@ -127,7 +127,7 @@ class RowIterator implements IteratorInterface
*/
protected function normalizeSheetDataXMLFilePath($sheetDataXMLFilePath)
{
return ltrim($sheetDataXMLFilePath, '/');
return \ltrim($sheetDataXMLFilePath, '/');
}
/**
@@ -234,7 +234,7 @@ class RowIterator implements IteratorInterface
{
// Read dimensions of the sheet
$dimensionRef = $xmlReader->getAttribute(self::XML_ATTRIBUTE_REF); // returns 'A1:M13' for instance (or 'A1' for empty sheet)
if (preg_match('/[A-Z]+\d+:([A-Z]+\d+)/', $dimensionRef, $matches)) {
if (\preg_match('/[A-Z]+\d+:([A-Z]+\d+)/', $dimensionRef, $matches)) {
$this->numColumns = CellHelper::getColumnIndexFromCellIndex($matches[1]) + 1;
}
@@ -257,11 +257,11 @@ class RowIterator implements IteratorInterface
$numberOfColumnsForRow = $this->numColumns;
$spans = $xmlReader->getAttribute(self::XML_ATTRIBUTE_SPANS); // returns '1:5' for instance
if ($spans) {
list(, $numberOfColumnsForRow) = explode(':', $spans);
list(, $numberOfColumnsForRow) = \explode(':', $spans);
$numberOfColumnsForRow = (int) $numberOfColumnsForRow;
}
$cells = array_fill(0, $numberOfColumnsForRow, $this->entityFactory->createCell(''));
$cells = \array_fill(0, $numberOfColumnsForRow, $this->entityFactory->createCell(''));
$this->currentlyProcessedRow->setCells($cells);
return XMLProcessor::PROCESSING_CONTINUE;
+2 -2
View File
@@ -27,7 +27,7 @@ class SheetIterator implements IteratorInterface
// Fetch all available sheets
$this->sheets = $sheetManager->getSheets();
if (count($this->sheets) === 0) {
if (\count($this->sheets) === 0) {
throw new NoSheetsFoundException('The file must contain at least one sheet.');
}
}
@@ -51,7 +51,7 @@ class SheetIterator implements IteratorInterface
*/
public function valid()
{
return ($this->currentSheetIndex < count($this->sheets));
return ($this->currentSheetIndex < \count($this->sheets));
}
/**
@@ -3,7 +3,9 @@
namespace Box\Spout\Writer\Common\Creator\Style;
use Box\Spout\Common\Entity\Style\Border;
use Box\Spout\Common\Entity\Style\CellAlignment;
use Box\Spout\Common\Entity\Style\Style;
use Box\Spout\Common\Exception\InvalidArgumentException;
/**
* Class StyleBuilder
@@ -122,6 +124,25 @@ class StyleBuilder
return $this;
}
/**
* Sets the cell alignment.
*
* @param string $cellAlignment The cell alignment
*
* @throws InvalidArgumentException If the given cell alignment is not valid
* @return StyleBuilder
*/
public function setCellAlignment($cellAlignment)
{
if (!CellAlignment::isValid($cellAlignment)) {
throw new InvalidArgumentException('Invalid cell alignment value');
}
$this->style->setCellAlignment($cellAlignment);
return $this;
}
/**
* Set a border
*
@@ -148,6 +169,20 @@ class StyleBuilder
return $this;
}
/**
* Sets a format
*
* @param string $format Format
* @return StyleBuilder
* @api
*/
public function setFormat($format)
{
$this->style->setFormat($format);
return $this;
}
/**
* Returns the configured style. The style is cached and can be reused.
*
@@ -98,7 +98,7 @@ class WriterEntityFactory
*/
public static function createRowFromArray(array $cellValues = [], Style $rowStyle = null)
{
$cells = array_map(function ($cellValue) {
$cells = \array_map(function ($cellValue) {
return new Cell($cellValue);
}, $cellValues);
@@ -35,7 +35,7 @@ class WriterFactory
*/
public static function createFromFile(string $path)
{
$extension = strtolower(pathinfo($path, PATHINFO_EXTENSION));
$extension = \strtolower(\pathinfo($path, PATHINFO_EXTENSION));
return self::createFromType($extension);
}
+1 -1
View File
@@ -19,7 +19,7 @@ class Workbook
*/
public function __construct()
{
$this->internalId = uniqid();
$this->internalId = \uniqid();
}
/**
+16 -15
View File
@@ -8,38 +8,39 @@ namespace Box\Spout\Writer\Common\Helper;
*/
class CellHelper
{
/** @var array Cache containing the mapping column index => cell index */
private static $columnIndexToCellIndexCache = [];
/** @var array Cache containing the mapping column index => column letters */
private static $columnIndexToColumnLettersCache = [];
/**
* Returns the cell index (base 26) associated to the base 10 column index.
* Returns the column letters (base 26) associated to the base 10 column index.
* Excel uses A to Z letters for column indexing, where A is the 1st column,
* Z is the 26th and AA is the 27th.
* The mapping is zero based, so that 0 maps to A, B maps to 1, Z to 25 and AA to 26.
*
* @param int $columnIndex The Excel column index (0, 42, ...)
* @param int $columnIndexZeroBased The Excel column index (0, 42, ...)
*
* @return string The associated cell index ('A', 'BC', ...)
*/
public static function getCellIndexFromColumnIndex($columnIndex)
public static function getColumnLettersFromColumnIndex($columnIndexZeroBased)
{
$originalColumnIndex = $columnIndex;
$originalColumnIndex = $columnIndexZeroBased;
// Using isset here because it is way faster than array_key_exists...
if (!isset(self::$columnIndexToCellIndexCache[$originalColumnIndex])) {
$cellIndex = '';
$capitalAAsciiValue = ord('A');
if (!isset(self::$columnIndexToColumnLettersCache[$originalColumnIndex])) {
$columnLetters = '';
$capitalAAsciiValue = \ord('A');
do {
$modulus = $columnIndex % 26;
$cellIndex = chr($capitalAAsciiValue + $modulus) . $cellIndex;
$modulus = $columnIndexZeroBased % 26;
$columnLetters = \chr($capitalAAsciiValue + $modulus) . $columnLetters;
// substracting 1 because it's zero-based
$columnIndex = (int) ($columnIndex / 26) - 1;
} while ($columnIndex >= 0);
$columnIndexZeroBased = (int) ($columnIndexZeroBased / 26) - 1;
} while ($columnIndexZeroBased >= 0);
self::$columnIndexToCellIndexCache[$originalColumnIndex] = $cellIndex;
self::$columnIndexToColumnLettersCache[$originalColumnIndex] = $columnLetters;
}
return self::$columnIndexToCellIndexCache[$originalColumnIndex];
return self::$columnIndexToColumnLettersCache[$originalColumnIndex];
}
}
+7 -7
View File
@@ -135,7 +135,7 @@ class ZipHelper
public static function canChooseCompressionMethod()
{
// setCompressionName() is a PHP7+ method...
return (method_exists(new \ZipArchive(), 'setCompressionName'));
return (\method_exists(new \ZipArchive(), 'setCompressionName'));
}
/**
@@ -151,7 +151,7 @@ class ZipHelper
foreach ($itemIterator as $itemInfo) {
$itemRealPath = $this->getNormalizedRealPath($itemInfo->getPathname());
$itemLocalPath = str_replace($folderRealPath, '', $itemRealPath);
$itemLocalPath = \str_replace($folderRealPath, '', $itemRealPath);
if ($itemInfo->isFile() && !$this->shouldSkipFile($zip, $itemLocalPath, $existingFileMode)) {
$zip->addFile($itemRealPath, $itemLocalPath);
@@ -181,9 +181,9 @@ class ZipHelper
*/
protected function getNormalizedRealPath($path)
{
$realPath = realpath($path);
$realPath = \realpath($path);
return str_replace(DIRECTORY_SEPARATOR, '/', $realPath);
return \str_replace(DIRECTORY_SEPARATOR, '/', $realPath);
}
/**
@@ -210,8 +210,8 @@ class ZipHelper
*/
protected function copyZipToStream($zipFilePath, $pointer)
{
$zipFilePointer = fopen($zipFilePath, 'r');
stream_copy_to_stream($zipFilePointer, $pointer);
fclose($zipFilePointer);
$zipFilePointer = \fopen($zipFilePath, 'r');
\stream_copy_to_stream($zipFilePointer, $pointer);
\fclose($zipFilePointer);
}
}
@@ -45,8 +45,8 @@ class SheetManager
*/
public function throwIfNameIsInvalid($name, Sheet $sheet)
{
if (!is_string($name)) {
$actualType = gettype($name);
if (!\is_string($name)) {
$actualType = \gettype($name);
$errorMessage = "The sheet's name is invalid. It must be a string ($actualType given).";
throw new InvalidSheetNameException($errorMessage);
}
@@ -74,9 +74,9 @@ class SheetManager
}
}
if (count($failedRequirements) !== 0) {
if (\count($failedRequirements) !== 0) {
$errorMessage = "The sheet's name (\"$name\") is invalid. It did not respect these rules:\n - ";
$errorMessage .= implode("\n - ", $failedRequirements);
$errorMessage .= \implode("\n - ", $failedRequirements);
throw new InvalidSheetNameException($errorMessage);
}
}
@@ -90,7 +90,7 @@ class SheetManager
*/
private function doesContainInvalidCharacters($name)
{
return (str_replace(self::$INVALID_CHARACTERS_IN_SHEET_NAME, '', $name) !== $name);
return (\str_replace(self::$INVALID_CHARACTERS_IN_SHEET_NAME, '', $name) !== $name);
}
/**
@@ -80,7 +80,7 @@ class StyleManager implements StyleManagerInterface
return $cellStyle;
}
if ($cell->isString() && strpos($cell->getValue(), "\n") !== false) {
if ($cell->isString() && \strpos($cell->getValue(), "\n") !== false) {
$cellStyle->setShouldWrapText();
}
@@ -85,9 +85,15 @@ class StyleMerger
if (!$style->hasSetWrapText() && $baseStyle->shouldWrapText()) {
$styleToUpdate->setShouldWrapText();
}
if (!$style->hasSetCellAlignment() && $baseStyle->shouldApplyCellAlignment()) {
$styleToUpdate->setCellAlignment($baseStyle->getCellAlignment());
}
if (!$style->getBorder() && $baseStyle->shouldApplyBorder()) {
$styleToUpdate->setBorder($baseStyle->getBorder());
}
if (!$style->getFormat() && $baseStyle->shouldApplyFormat()) {
$styleToUpdate->setFormat($baseStyle->getFormat());
}
if (!$style->shouldApplyBackgroundColor() && $baseStyle->shouldApplyBackgroundColor()) {
$styleToUpdate->setBackgroundColor($baseStyle->getBackgroundColor());
}
@@ -37,7 +37,7 @@ class StyleRegistry
$serializedStyle = $this->serialize($style);
if (!$this->hasStyleAlreadyBeenRegistered($style)) {
$nextStyleId = count($this->serializedStyleToStyleIdMappingTable);
$nextStyleId = \count($this->serializedStyleToStyleIdMappingTable);
$style->setId($nextStyleId);
$this->serializedStyleToStyleIdMappingTable[$serializedStyle] = $nextStyleId;
@@ -79,7 +79,7 @@ class StyleRegistry
*/
public function getRegisteredStyles()
{
return array_values($this->styleIdToStyleMappingTable);
return \array_values($this->styleIdToStyleMappingTable);
}
/**
@@ -105,7 +105,7 @@ class StyleRegistry
$currentId = $style->getId();
$style->setId(0);
$serializedStyle = serialize($style);
$serializedStyle = \serialize($style);
$style->setId($currentId);
@@ -44,7 +44,7 @@ abstract class WorkbookManagerAbstract implements WorkbookManagerInterface
/** @var InternalEntityFactory Factory to create entities */
protected $entityFactory;
/** @var ManagerFactoryInterface $managerFactory Factory to create managers */
/** @var ManagerFactoryInterface Factory to create managers */
protected $managerFactory;
/** @var Worksheet The worksheet where data will be written to */
@@ -124,7 +124,7 @@ abstract class WorkbookManagerAbstract implements WorkbookManagerInterface
{
$worksheets = $this->getWorksheets();
$newSheetIndex = count($worksheets);
$newSheetIndex = \count($worksheets);
$sheetManager = $this->managerFactory->createSheetManager();
$sheet = $this->entityFactory->createSheet($newSheetIndex, $this->workbook->getInternalId(), $sheetManager);
@@ -260,7 +260,7 @@ abstract class WorkbookManagerAbstract implements WorkbookManagerInterface
// update max num columns for the worksheet
$currentMaxNumColumns = $worksheet->getMaxNumColumns();
$cellsCount = $row->getNumCells();
$worksheet->setMaxNumColumns(max($currentMaxNumColumns, $cellsCount));
$worksheet->setMaxNumColumns(\max($currentMaxNumColumns, $cellsCount));
}
/**
@@ -11,6 +11,6 @@ class InvalidNameException extends WriterException
{
$msg = '%s is not a valid name identifier for a border. Valid identifiers are: %s.';
parent::__construct(sprintf($msg, $name, implode(',', BorderPart::getAllowedNames())));
parent::__construct(\sprintf($msg, $name, \implode(',', BorderPart::getAllowedNames())));
}
}
@@ -11,6 +11,6 @@ class InvalidStyleException extends WriterException
{
$msg = '%s is not a valid style identifier for a border. Valid identifiers are: %s.';
parent::__construct(sprintf($msg, $name, implode(',', BorderPart::getAllowedStyles())));
parent::__construct(\sprintf($msg, $name, \implode(',', BorderPart::getAllowedStyles())));
}
}
@@ -11,6 +11,6 @@ class InvalidWidthException extends WriterException
{
$msg = '%s is not a valid width identifier for a border. Valid identifiers are: %s.';
parent::__construct(sprintf($msg, $name, implode(',', BorderPart::getAllowedWidths())));
parent::__construct(\sprintf($msg, $name, \implode(',', BorderPart::getAllowedWidths())));
}
}
@@ -22,7 +22,7 @@ class ManagerFactory implements ManagerFactoryInterface
/** @var InternalEntityFactory */
protected $entityFactory;
/** @var HelperFactory $helperFactory */
/** @var HelperFactory */
protected $helperFactory;
/**
+2 -2
View File
@@ -53,14 +53,14 @@ class BorderHelper
$definition = 'fo:border-%s="%s"';
if ($borderPart->getStyle() === Border::STYLE_NONE) {
$borderPartDefinition = sprintf($definition, $borderPart->getName(), 'none');
$borderPartDefinition = \sprintf($definition, $borderPart->getName(), 'none');
} else {
$attributes = [
self::$widthMap[$borderPart->getWidth()],
self::$styleMap[$borderPart->getStyle()],
'#' . $borderPart->getColor(),
];
$borderPartDefinition = sprintf($definition, $borderPart->getName(), implode(' ', $attributes));
$borderPartDefinition = \sprintf($definition, $borderPart->getName(), \implode(' ', $attributes));
}
return $borderPartDefinition;
@@ -89,7 +89,7 @@ class FileSystemHelper extends \Box\Spout\Common\Helper\FileSystemHelper impleme
*/
protected function createRootFolder()
{
$this->rootFolder = $this->createFolder($this->baseFolderRealPath, uniqid('ods'));
$this->rootFolder = $this->createFolder($this->baseFolderRealPath, \uniqid('ods'));
return $this;
}
@@ -210,22 +210,22 @@ EOD;
// Append sheets content to "content.xml"
$contentXmlFilePath = $this->rootFolder . '/' . self::CONTENT_XML_FILE_NAME;
$contentXmlHandle = fopen($contentXmlFilePath, 'a');
$contentXmlHandle = \fopen($contentXmlFilePath, 'a');
foreach ($worksheets as $worksheet) {
// write the "<table:table>" node, with the final sheet's name
fwrite($contentXmlHandle, $worksheetManager->getTableElementStartAsString($worksheet));
\fwrite($contentXmlHandle, $worksheetManager->getTableElementStartAsString($worksheet));
$worksheetFilePath = $worksheet->getFilePath();
$this->copyFileContentsToTarget($worksheetFilePath, $contentXmlHandle);
fwrite($contentXmlHandle, '</table:table>');
\fwrite($contentXmlHandle, '</table:table>');
}
$contentXmlFileContents = '</office:spreadsheet></office:body></office:document-content>';
fwrite($contentXmlHandle, $contentXmlFileContents);
fclose($contentXmlHandle);
\fwrite($contentXmlHandle, $contentXmlFileContents);
\fclose($contentXmlHandle);
return $this;
}
@@ -241,9 +241,9 @@ EOD;
*/
protected function copyFileContentsToTarget($sourceFilePath, $targetResource)
{
$sourceHandle = fopen($sourceFilePath, 'r');
stream_copy_to_stream($sourceHandle, $targetResource);
fclose($sourceHandle);
$sourceHandle = \fopen($sourceFilePath, 'r');
\stream_copy_to_stream($sourceHandle, $targetResource);
\fclose($sourceHandle);
}
/**
@@ -42,7 +42,7 @@ class OptionsManager extends OptionsManagerAbstract
*/
protected function setDefaultOptions()
{
$this->setOption(Options::TEMP_FOLDER, sys_get_temp_dir());
$this->setOption(Options::TEMP_FOLDER, \sys_get_temp_dir());
$this->setOption(Options::DEFAULT_ROW_STYLE, $this->styleBuilder->build());
$this->setOption(Options::SHOULD_CREATE_NEW_SHEETS_AUTOMATICALLY, true);
}
@@ -3,6 +3,7 @@
namespace Box\Spout\Writer\ODS\Manager\Style;
use Box\Spout\Common\Entity\Style\BorderPart;
use Box\Spout\Common\Entity\Style\CellAlignment;
use Box\Spout\Writer\Common\Entity\Worksheet;
use Box\Spout\Writer\ODS\Helper\BorderHelper;
@@ -199,6 +200,7 @@ EOD;
$content = '<style:style style:data-style-name="N0" style:family="table-cell" style:name="ce' . $styleIndex . '" style:parent-style-name="Default">';
$content .= $this->getTextPropertiesSectionContent($style);
$content .= $this->getParagraphPropertiesSectionContent($style);
$content .= $this->getTableCellPropertiesSectionContent($style);
$content .= '</style:style>';
@@ -214,26 +216,26 @@ EOD;
*/
private function getTextPropertiesSectionContent($style)
{
$content = '';
if ($style->shouldApplyFont()) {
$content .= $this->getFontSectionContent($style);
if (!$style->shouldApplyFont()) {
return '';
}
return $content;
return '<style:text-properties '
. $this->getFontSectionContent($style)
. '/>';
}
/**
* Returns the contents of the "<style:text-properties>" section, inside "<style:style>" section
* Returns the contents of the fonts definition section, inside "<style:text-properties>" section
*
* @param \Box\Spout\Common\Entity\Style\Style $style
*
* @return string
*/
private function getFontSectionContent($style)
{
$defaultStyle = $this->getDefaultStyle();
$content = '<style:text-properties';
$content = '';
$fontColor = $style->getFontColor();
if ($fontColor !== $defaultStyle->getFontColor()) {
@@ -263,11 +265,60 @@ EOD;
$content .= ' style:text-line-through-style="solid"';
}
$content .= '/>';
return $content;
}
/**
* Returns the contents of the "<style:paragraph-properties>" section, inside "<style:style>" section
*
* @param \Box\Spout\Common\Entity\Style\Style $style
*
* @return string
*/
private function getParagraphPropertiesSectionContent($style)
{
if (!$style->shouldApplyCellAlignment()) {
return '';
}
return '<style:paragraph-properties '
. $this->getCellAlignmentSectionContent($style)
. '/>';
}
/**
* Returns the contents of the cell alignment definition for the "<style:paragraph-properties>" section
*
* @param \Box\Spout\Common\Entity\Style\Style $style
*
* @return string
*/
private function getCellAlignmentSectionContent($style)
{
return \sprintf(
' fo:text-align="%s" ',
$this->transformCellAlignment($style->getCellAlignment())
);
}
/**
* Even though "left" and "right" alignments are part of the spec, and interpreted
* respectively as "start" and "end", using the recommended values increase compatibility
* with software that will read the created ODS file.
*
* @param string $cellAlignment
*
* @return string
*/
private function transformCellAlignment($cellAlignment)
{
switch ($cellAlignment) {
case CellAlignment::LEFT: return 'start';
case CellAlignment::RIGHT: return 'end';
default: return $cellAlignment;
}
}
/**
* Returns the contents of the "<style:table-cell-properties>" section, inside "<style:style>" section
*
@@ -276,7 +327,7 @@ EOD;
*/
private function getTableCellPropertiesSectionContent($style)
{
$content = '';
$content = '<style:table-cell-properties ';
if ($style->shouldWrapText()) {
$content .= $this->getWrapTextXMLContent();
@@ -290,6 +341,8 @@ EOD;
$content .= $this->getBackgroundColorXMLContent($style);
}
$content .= '/>';
return $content;
}
@@ -300,7 +353,7 @@ EOD;
*/
private function getWrapTextXMLContent()
{
return '<style:table-cell-properties fo:wrap-option="wrap" style:vertical-align="automatic"/>';
return ' fo:wrap-option="wrap" style:vertical-align="automatic" ';
}
/**
@@ -311,13 +364,11 @@ EOD;
*/
private function getBorderXMLContent($style)
{
$borderProperty = '<style:table-cell-properties %s />';
$borders = array_map(function (BorderPart $borderPart) {
$borders = \array_map(function (BorderPart $borderPart) {
return BorderHelper::serializeBorderPart($borderPart);
}, $style->getBorder()->getParts());
return sprintf($borderProperty, implode(' ', $borders));
return \sprintf(' %s ', \implode(' ', $borders));
}
/**
@@ -328,9 +379,6 @@ EOD;
*/
private function getBackgroundColorXMLContent($style)
{
return sprintf(
'<style:table-cell-properties fo:background-color="#%s"/>',
$style->getBackgroundColor()
);
return \sprintf(' fo:background-color="#%s" ', $style->getBackgroundColor());
}
}
@@ -33,6 +33,6 @@ class StyleRegistry extends \Box\Spout\Writer\Common\Manager\Style\StyleRegistry
*/
public function getUsedFonts()
{
return array_keys($this->usedFontsSet);
return \array_keys($this->usedFontsSet);
}
}
@@ -56,7 +56,7 @@ class WorkbookManager extends WorkbookManagerAbstract
protected function writeAllFilesToDiskAndZipThem($finalFilePointer)
{
$worksheets = $this->getWorksheets();
$numWorksheets = count($worksheets);
$numWorksheets = \count($worksheets);
$this->fileSystemHelper
->createContentFile($this->worksheetManager, $this->styleManager, $worksheets)
@@ -61,7 +61,7 @@ class WorksheetManager implements WorksheetManagerInterface
*/
public function startSheet(Worksheet $worksheet)
{
$sheetFilePointer = fopen($worksheet->getFilePath(), 'w');
$sheetFilePointer = \fopen($worksheet->getFilePath(), 'w');
$this->throwIfSheetFilePointerIsNotAvailable($sheetFilePointer);
$worksheet->setFilePointer($sheetFilePointer);
@@ -134,7 +134,7 @@ class WorksheetManager implements WorksheetManagerInterface
$data .= '</table:table-row>';
$wasWriteSuccessful = fwrite($worksheet->getFilePointer(), $data);
$wasWriteSuccessful = \fwrite($worksheet->getFilePointer(), $data);
if ($wasWriteSuccessful === false) {
throw new IOException("Unable to write data in {$worksheet->getFilePath()}");
}
@@ -190,24 +190,30 @@ class WorksheetManager implements WorksheetManagerInterface
if ($cell->isString()) {
$data .= ' office:value-type="string" calcext:value-type="string">';
$cellValueLines = explode("\n", $cell->getValue());
$cellValueLines = \explode("\n", $cell->getValue());
foreach ($cellValueLines as $cellValueLine) {
$data .= '<text:p>' . $this->stringsEscaper->escape($cellValueLine) . '</text:p>';
}
$data .= '</table:table-cell>';
} elseif ($cell->isBoolean()) {
$data .= ' office:value-type="boolean" calcext:value-type="boolean" office:boolean-value="' . $cell->getValue() . '">';
$value = $cell->getValue() ? 'true' : 'false'; // boolean-value spec: http://docs.oasis-open.org/office/v1.2/os/OpenDocument-v1.2-os-part1.html#datatype-boolean
$data .= ' office:value-type="boolean" calcext:value-type="boolean" office:boolean-value="' . $value . '">';
$data .= '<text:p>' . $cell->getValue() . '</text:p>';
$data .= '</table:table-cell>';
} elseif ($cell->isNumeric()) {
$data .= ' office:value-type="float" calcext:value-type="float" office:value="' . $cell->getValue() . '">';
$data .= '<text:p>' . $cell->getValue() . '</text:p>';
$data .= '</table:table-cell>';
} elseif ($cell->isError() && is_string($cell->getValueEvenIfError())) {
// only writes the error value if it's a string
$data .= ' office:value-type="string" calcext:value-type="error" office:value="">';
$data .= '<text:p>' . $cell->getValueEvenIfError() . '</text:p>';
$data .= '</table:table-cell>';
} elseif ($cell->isEmpty()) {
$data .= '/>';
} else {
throw new InvalidArgumentException('Trying to add a value with an unsupported type: ' . gettype($cell->getValue()));
throw new InvalidArgumentException('Trying to add a value with an unsupported type: ' . \gettype($cell->getValue()));
}
return $data;
@@ -223,10 +229,10 @@ class WorksheetManager implements WorksheetManagerInterface
{
$worksheetFilePointer = $worksheet->getFilePointer();
if (!is_resource($worksheetFilePointer)) {
if (!\is_resource($worksheetFilePointer)) {
return;
}
fclose($worksheetFilePointer);
\fclose($worksheetFilePointer);
}
}
+3 -3
View File
@@ -33,7 +33,7 @@ abstract class WriterAbstract implements WriterInterface
/** @var GlobalFunctionsHelper Helper to work with global functions */
protected $globalFunctionsHelper;
/** @var HelperFactory $helperFactory */
/** @var HelperFactory */
protected $helperFactory;
/** @var OptionsManagerInterface Writer options manager */
@@ -223,7 +223,7 @@ abstract class WriterAbstract implements WriterInterface
$this->closeWriter();
if (is_resource($this->filePointer)) {
if (\is_resource($this->filePointer)) {
$this->globalFunctionsHelper->fclose($this->filePointer);
}
@@ -243,7 +243,7 @@ abstract class WriterAbstract implements WriterInterface
// remove output file if it was created
if ($this->globalFunctionsHelper->file_exists($this->outputFilePath)) {
$outputFolderPath = dirname($this->outputFilePath);
$outputFolderPath = \dirname($this->outputFilePath);
$fileSystemHelper = $this->helperFactory->createFileSystemHelper($outputFolderPath);
$fileSystemHelper->deleteFile($this->outputFilePath);
}
@@ -24,7 +24,7 @@ class ManagerFactory implements ManagerFactoryInterface
/** @var InternalEntityFactory */
protected $entityFactory;
/** @var HelperFactory $helperFactory */
/** @var HelperFactory */
protected $helperFactory;
/**
@@ -43,8 +43,8 @@ class BorderHelper
{
$borderStyle = self::getBorderStyle($borderPart);
$colorEl = $borderPart->getColor() ? sprintf('<color rgb="%s"/>', $borderPart->getColor()) : '';
$partEl = sprintf(
$colorEl = $borderPart->getColor() ? \sprintf('<color rgb="%s"/>', $borderPart->getColor()) : '';
$partEl = \sprintf(
'<%s style="%s">%s</%s>',
$borderPart->getName(),
$borderStyle,
@@ -112,7 +112,7 @@ class FileSystemHelper extends \Box\Spout\Common\Helper\FileSystemHelper impleme
*/
private function createRootFolder()
{
$this->rootFolder = $this->createFolder($this->baseFolderRealPath, uniqid('xlsx', true));
$this->rootFolder = $this->createFolder($this->baseFolderRealPath, \uniqid('xlsx', true));
return $this;
}
@@ -52,7 +52,7 @@ class OptionsManager extends OptionsManagerAbstract
->setFontName(self::DEFAULT_FONT_NAME)
->build();
$this->setOption(Options::TEMP_FOLDER, sys_get_temp_dir());
$this->setOption(Options::TEMP_FOLDER, \sys_get_temp_dir());
$this->setOption(Options::DEFAULT_ROW_STYLE, $defaultRowStyle);
$this->setOption(Options::SHOULD_CREATE_NEW_SHEETS_AUTOMATICALLY, true);
$this->setOption(Options::SHOULD_USE_INLINE_STRINGS, true);
@@ -40,13 +40,13 @@ EOD;
public function __construct($xlFolder, $stringsEscaper)
{
$sharedStringsFilePath = $xlFolder . '/' . self::SHARED_STRINGS_FILE_NAME;
$this->sharedStringsFilePointer = fopen($sharedStringsFilePath, 'w');
$this->sharedStringsFilePointer = \fopen($sharedStringsFilePath, 'w');
$this->throwIfSharedStringsFilePointerIsNotAvailable();
// the headers is split into different parts so that we can fseek and put in the correct count and uniqueCount later
$header = self::SHARED_STRINGS_XML_FILE_FIRST_PART_HEADER . ' ' . self::DEFAULT_STRINGS_COUNT_PART . '>';
fwrite($this->sharedStringsFilePointer, $header);
\fwrite($this->sharedStringsFilePointer, $header);
$this->stringsEscaper = $stringsEscaper;
}
@@ -73,7 +73,7 @@ EOD;
*/
public function writeString($string)
{
fwrite($this->sharedStringsFilePointer, '<si><t xml:space="preserve">' . $this->stringsEscaper->escape($string) . '</t></si>');
\fwrite($this->sharedStringsFilePointer, '<si><t xml:space="preserve">' . $this->stringsEscaper->escape($string) . '</t></si>');
$this->numSharedStrings++;
// Shared string ID is zero-based
@@ -87,20 +87,20 @@ EOD;
*/
public function close()
{
if (!is_resource($this->sharedStringsFilePointer)) {
if (!\is_resource($this->sharedStringsFilePointer)) {
return;
}
fwrite($this->sharedStringsFilePointer, '</sst>');
\fwrite($this->sharedStringsFilePointer, '</sst>');
// Replace the default strings count with the actual number of shared strings in the file header
$firstPartHeaderLength = strlen(self::SHARED_STRINGS_XML_FILE_FIRST_PART_HEADER);
$defaultStringsCountPartLength = strlen(self::DEFAULT_STRINGS_COUNT_PART);
$firstPartHeaderLength = \strlen(self::SHARED_STRINGS_XML_FILE_FIRST_PART_HEADER);
$defaultStringsCountPartLength = \strlen(self::DEFAULT_STRINGS_COUNT_PART);
// Adding 1 to take into account the space between the last xml attribute and "count"
fseek($this->sharedStringsFilePointer, $firstPartHeaderLength + 1);
fwrite($this->sharedStringsFilePointer, sprintf("%-{$defaultStringsCountPartLength}s", 'count="' . $this->numSharedStrings . '" uniqueCount="' . $this->numSharedStrings . '"'));
\fseek($this->sharedStringsFilePointer, $firstPartHeaderLength + 1);
\fwrite($this->sharedStringsFilePointer, \sprintf("%-{$defaultStringsCountPartLength}s", 'count="' . $this->numSharedStrings . '" uniqueCount="' . $this->numSharedStrings . '"'));
fclose($this->sharedStringsFilePointer);
\fclose($this->sharedStringsFilePointer);
}
}
@@ -33,7 +33,10 @@ class StyleManager extends \Box\Spout\Writer\Common\Manager\Style\StyleManager
$associatedBorderId = $this->styleRegistry->getBorderIdForStyleId($styleId);
$hasStyleCustomBorders = ($associatedBorderId !== null && $associatedBorderId !== 0);
return ($hasStyleCustomFill || $hasStyleCustomBorders);
$associatedFormatId = $this->styleRegistry->getFormatIdForStyleId($styleId);
$hasStyleCustomFormats = ($associatedFormatId !== null && $associatedFormatId !== 0);
return ($hasStyleCustomFill || $hasStyleCustomBorders || $hasStyleCustomFormats);
}
/**
@@ -48,6 +51,7 @@ class StyleManager extends \Box\Spout\Writer\Common\Manager\Style\StyleManager
<styleSheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
EOD;
$content .= $this->getFormatsSectionContent();
$content .= $this->getFontsSectionContent();
$content .= $this->getFillsSectionContent();
$content .= $this->getBordersSectionContent();
@@ -62,6 +66,35 @@ EOD;
return $content;
}
/**
* Returns the content of the "<numFmts>" section.
*
* @return string
*/
protected function getFormatsSectionContent()
{
$tags = [];
$registeredFormats = $this->styleRegistry->getRegisteredFormats();
foreach ($registeredFormats as $styleId) {
$numFmtId = $this->styleRegistry->getFormatIdForStyleId($styleId);
//Built-in formats do not need to be declared, skip them
if ($numFmtId < 164) {
continue;
}
/** @var Style $style */
$style = $this->styleRegistry->getStyleFromStyleId($styleId);
$format = $style->getFormat();
$tags[] = '<numFmt numFmtId="' . $numFmtId . '" formatCode="' . $format . '"/>';
}
$content = '<numFmts count="' . \count($tags) . '">';
$content .= \implode('', $tags);
$content .= '</numFmts>';
return $content;
}
/**
* Returns the content of the "<fonts>" section.
*
@@ -71,7 +104,7 @@ EOD;
{
$registeredStyles = $this->styleRegistry->getRegisteredStyles();
$content = '<fonts count="' . count($registeredStyles) . '">';
$content = '<fonts count="' . \count($registeredStyles) . '">';
/** @var Style $style */
foreach ($registeredStyles as $style) {
@@ -112,8 +145,8 @@ EOD;
$registeredFills = $this->styleRegistry->getRegisteredFills();
// Excel reserves two default fills
$fillsCount = count($registeredFills) + 2;
$content = sprintf('<fills count="%d">', $fillsCount);
$fillsCount = \count($registeredFills) + 2;
$content = \sprintf('<fills count="%d">', $fillsCount);
$content .= '<fill><patternFill patternType="none"/></fill>';
$content .= '<fill><patternFill patternType="gray125"/></fill>';
@@ -124,7 +157,7 @@ EOD;
$style = $this->styleRegistry->getStyleFromStyleId($styleId);
$backgroundColor = $style->getBackgroundColor();
$content .= sprintf(
$content .= \sprintf(
'<fill><patternFill patternType="solid"><fgColor rgb="%s"/></patternFill></fill>',
$backgroundColor
);
@@ -145,7 +178,7 @@ EOD;
$registeredBorders = $this->styleRegistry->getRegisteredBorders();
// There is one default border with index 0
$borderCount = count($registeredBorders) + 1;
$borderCount = \count($registeredBorders) + 1;
$content = '<borders count="' . $borderCount . '">';
@@ -200,24 +233,32 @@ EOD;
{
$registeredStyles = $this->styleRegistry->getRegisteredStyles();
$content = '<cellXfs count="' . count($registeredStyles) . '">';
$content = '<cellXfs count="' . \count($registeredStyles) . '">';
foreach ($registeredStyles as $style) {
$styleId = $style->getId();
$fillId = $this->getFillIdForStyleId($styleId);
$borderId = $this->getBorderIdForStyleId($styleId);
$numFmtId = $this->getFormatIdForStyleId($styleId);
$content .= '<xf numFmtId="0" fontId="' . $styleId . '" fillId="' . $fillId . '" borderId="' . $borderId . '" xfId="0"';
$content .= '<xf numFmtId="' . $numFmtId . '" fontId="' . $styleId . '" fillId="' . $fillId . '" borderId="' . $borderId . '" xfId="0"';
if ($style->shouldApplyFont()) {
$content .= ' applyFont="1"';
}
$content .= sprintf(' applyBorder="%d"', $style->shouldApplyBorder() ? 1 : 0);
$content .= \sprintf(' applyBorder="%d"', $style->shouldApplyBorder() ? 1 : 0);
if ($style->shouldWrapText()) {
if ($style->shouldApplyCellAlignment() || $style->shouldWrapText()) {
$content .= ' applyAlignment="1">';
$content .= '<alignment wrapText="1"/>';
$content .= '<alignment';
if ($style->shouldApplyCellAlignment()) {
$content .= \sprintf(' horizontal="%s"', $style->getCellAlignment());
}
if ($style->shouldWrapText()) {
$content .= ' wrapText="1"';
}
$content .= '/>';
$content .= '</xf>';
} else {
$content .= '/>';
@@ -261,6 +302,22 @@ EOD;
return $isDefaultStyle ? 0 : ($this->styleRegistry->getBorderIdForStyleId($styleId) ?: 0);
}
/**
* Returns the format ID associated to the given style ID.
* For the default style use general format.
*
* @param int $styleId
* @return int
*/
private function getFormatIdForStyleId($styleId)
{
// For the default style (ID = 0), we don't want to override the format.
// Otherwise all cells of the spreadsheet will have a format.
$isDefaultStyle = ($styleId === 0);
return $isDefaultStyle ? 0 : ($this->styleRegistry->getFormatIdForStyleId($styleId) ?: 0);
}
/**
* Returns the content of the "<cellStyles>" section.
*
@@ -10,6 +10,79 @@ use Box\Spout\Common\Entity\Style\Style;
*/
class StyleRegistry extends \Box\Spout\Writer\Common\Manager\Style\StyleRegistry
{
/**
* @see https://msdn.microsoft.com/en-us/library/ff529597(v=office.12).aspx
* @var array Mapping between built-in format and the associated numFmtId
*/
protected static $builtinNumFormatToIdMapping = [
'General' => 0,
'0' => 1,
'0.00' => 2,
'#,##0' => 3,
'#,##0.00' => 4,
'$#,##0,\-$#,##0' => 5,
'$#,##0,[Red]\-$#,##0' => 6,
'$#,##0.00,\-$#,##0.00' => 7,
'$#,##0.00,[Red]\-$#,##0.00' => 8,
'0%' => 9,
'0.00%' => 10,
'0.00E+00' => 11,
'# ?/?' => 12,
'# ??/??' => 13,
'mm-dd-yy' => 14,
'd-mmm-yy' => 15,
'd-mmm' => 16,
'mmm-yy' => 17,
'h:mm AM/PM' => 18,
'h:mm:ss AM/PM' => 19,
'h:mm' => 20,
'h:mm:ss' => 21,
'm/d/yy h:mm' => 22,
'#,##0 ,(#,##0)' => 37,
'#,##0 ,[Red](#,##0)' => 38,
'#,##0.00,(#,##0.00)' => 39,
'#,##0.00,[Red](#,##0.00)' => 40,
'_("$"* #,##0.00_),_("$"* \(#,##0.00\),_("$"* "-"??_),_(@_)' => 44,
'mm:ss' => 45,
'[h]:mm:ss' => 46,
'mm:ss.0' => 47,
'##0.0E+0' => 48,
'@' => 49,
'[$-404]e/m/d' => 27,
'm/d/yy' => 30,
't0' => 59,
't0.00' => 60,
't#,##0' => 61,
't#,##0.00' => 62,
't0%' => 67,
't0.00%' => 68,
't# ?/?' => 69,
't# ??/??' => 70,
];
/**
* @var array
*/
protected $registeredFormats = [];
/**
* @var array [STYLE_ID] => [FORMAT_ID] maps a style to a format declaration
*/
protected $styleIdToFormatsMappingTable = [];
/**
* If the numFmtId is lower than 0xA4 (164 in decimal)
* then it's a built-in number format.
* Since Excel is the dominant vendor - we play along here
*
* @var int The fill index counter for custom fills.
*/
protected $formatIndex = 164;
/**
* @var array
*/
@@ -48,11 +121,52 @@ class StyleRegistry extends \Box\Spout\Writer\Common\Manager\Style\StyleRegistry
{
$registeredStyle = parent::registerStyle($style);
$this->registerFill($registeredStyle);
$this->registerFormat($registeredStyle);
$this->registerBorder($registeredStyle);
return $registeredStyle;
}
/**
* Register a format definition
*
* @param Style $style
*/
protected function registerFormat(Style $style)
{
$styleId = $style->getId();
$format = $style->getFormat();
if ($format) {
$isFormatRegistered = isset($this->registeredFormats[$format]);
// We need to track the already registered format definitions
if ($isFormatRegistered) {
$registeredStyleId = $this->registeredFormats[$format];
$registeredFormatId = $this->styleIdToFormatsMappingTable[$registeredStyleId];
$this->styleIdToFormatsMappingTable[$styleId] = $registeredFormatId;
} else {
$this->registeredFormats[$format] = $styleId;
$id = self::$builtinNumFormatToIdMapping[$format] ?? $this->formatIndex++;
$this->styleIdToFormatsMappingTable[$styleId] = $id;
}
} else {
// The formatId maps a style to a format declaration
// When there is no format definition - we default to 0 ( General )
$this->styleIdToFormatsMappingTable[$styleId] = 0;
}
}
/**
* @param int $styleId
* @return int|null Format ID associated to the given style ID
*/
public function getFormatIdForStyleId($styleId)
{
return $this->styleIdToFormatsMappingTable[$styleId] ?? null;
}
/**
* Register a fill definition
*
@@ -107,7 +221,7 @@ class StyleRegistry extends \Box\Spout\Writer\Common\Manager\Style\StyleRegistry
if ($style->shouldApplyBorder()) {
$border = $style->getBorder();
$serializedBorder = serialize($border);
$serializedBorder = \serialize($border);
$isBorderAlreadyRegistered = isset($this->registeredBorders[$serializedBorder]);
@@ -117,7 +231,7 @@ class StyleRegistry extends \Box\Spout\Writer\Common\Manager\Style\StyleRegistry
$this->styleIdToBorderMappingTable[$styleId] = $registeredBorderId;
} else {
$this->registeredBorders[$serializedBorder] = $styleId;
$this->styleIdToBorderMappingTable[$styleId] = count($this->registeredBorders);
$this->styleIdToBorderMappingTable[$styleId] = \count($this->registeredBorders);
}
} else {
// If no border should be applied - the mapping is the default border: 0
@@ -151,4 +265,12 @@ class StyleRegistry extends \Box\Spout\Writer\Common\Manager\Style\StyleRegistry
{
return $this->registeredBorders;
}
/**
* @return array
*/
public function getRegisteredFormats()
{
return $this->registeredFormats;
}
}
@@ -44,7 +44,7 @@ class WorkbookManager extends WorkbookManagerAbstract
{
$worksheetFilesFolder = $this->fileSystemHelper->getXlWorksheetsFolder();
return $worksheetFilesFolder . '/' . strtolower($sheet->getName()) . '.xml';
return $worksheetFilesFolder . '/' . \strtolower($sheet->getName()) . '.xml';
}
/**
Loaded 100 of 124 files, more files were not shown because too many files have changed in this diff. Show more