Merge remote-tracking branch 'upstream/develop' into fix-85

This commit is contained in:
Paolo Agostinetto 2017-02-20 21:13:03 +01:00
commit f3c62b615e
8 changed files with 82 additions and 307 deletions

View File

@ -672,63 +672,3 @@ class Functions
return $value; return $value;
} }
} }
//
// There are a few mathematical functions that aren't available on all versions of PHP for all platforms
// These functions aren't available in Windows implementations of PHP prior to version 5.3.0
// So we test if they do exist for this version of PHP/operating platform; and if not we create them
//
if (!function_exists('acosh')) {
function acosh($x)
{
return 2 * log(sqrt(($x + 1) / 2) + sqrt(($x - 1) / 2));
} // function acosh()
}
if (!function_exists('asinh')) {
function asinh($x)
{
return log($x + sqrt(1 + $x * $x));
} // function asinh()
}
if (!function_exists('atanh')) {
function atanh($x)
{
return (log(1 + $x) - log(1 - $x)) / 2;
} // function atanh()
}
//
// Strangely, PHP doesn't have a mb_str_replace multibyte function
// As we'll only ever use this function with UTF-8 characters, we can simply "hard-code" the character set
//
if ((!function_exists('mb_str_replace')) &&
(function_exists('mb_substr')) && (function_exists('mb_strlen')) && (function_exists('mb_strpos'))
) {
function mb_str_replace($search, $replace, $subject)
{
if (is_array($subject)) {
$ret = [];
foreach ($subject as $key => $val) {
$ret[$key] = mb_str_replace($search, $replace, $val);
}
return $ret;
}
foreach ((array) $search as $key => $s) {
if ($s == '' && $s !== 0) {
continue;
}
$r = !is_array($replace) ? $replace : (isset($replace[$key]) ? $replace[$key] : '');
$pos = mb_strpos($subject, $s, 0, 'UTF-8');
while ($pos !== false) {
$subject = mb_substr($subject, 0, $pos, 'UTF-8') . $r . mb_substr($subject, $pos + mb_strlen($s, 'UTF-8'), null, 'UTF-8');
$pos = mb_strpos($subject, $s, $pos + mb_strlen($r, 'UTF-8'), 'UTF-8');
}
}
return $subject;
}
}

View File

@ -124,18 +124,11 @@ class TextData
} }
$character = $characters; $character = $characters;
if ((function_exists('mb_strlen')) && (function_exists('mb_substr'))) { if (mb_strlen($characters, 'UTF-8') > 1) {
if (mb_strlen($characters, 'UTF-8') > 1) { $character = mb_substr($characters, 0, 1, 'UTF-8');
$character = mb_substr($characters, 0, 1, 'UTF-8');
}
return self::unicodeToOrd($character);
}
if (strlen($characters) > 0) {
$character = substr($characters, 0, 1);
} }
return ord($character); return self::unicodeToOrd($character);
} }
/** /**
@ -225,11 +218,8 @@ class TextData
if (\PhpOffice\PhpSpreadsheet\Shared\StringHelper::countCharacters($needle) == 0) { if (\PhpOffice\PhpSpreadsheet\Shared\StringHelper::countCharacters($needle) == 0) {
return $offset; return $offset;
} }
if (function_exists('mb_strpos')) {
$pos = mb_strpos($haystack, $needle, --$offset, 'UTF-8'); $pos = mb_strpos($haystack, $needle, --$offset, 'UTF-8');
} else {
$pos = strpos($haystack, $needle, --$offset);
}
if ($pos !== false) { if ($pos !== false) {
return ++$pos; return ++$pos;
} }
@ -263,11 +253,8 @@ class TextData
if (\PhpOffice\PhpSpreadsheet\Shared\StringHelper::countCharacters($needle) == 0) { if (\PhpOffice\PhpSpreadsheet\Shared\StringHelper::countCharacters($needle) == 0) {
return $offset; return $offset;
} }
if (function_exists('mb_stripos')) {
$pos = mb_stripos($haystack, $needle, --$offset, 'UTF-8'); $pos = mb_stripos($haystack, $needle, --$offset, 'UTF-8');
} else {
$pos = stripos($haystack, $needle, --$offset);
}
if ($pos !== false) { if ($pos !== false) {
return ++$pos; return ++$pos;
} }
@ -330,11 +317,7 @@ class TextData
$value = ($value) ? \PhpOffice\PhpSpreadsheet\Calculation::getTRUE() : \PhpOffice\PhpSpreadsheet\Calculation::getFALSE(); $value = ($value) ? \PhpOffice\PhpSpreadsheet\Calculation::getTRUE() : \PhpOffice\PhpSpreadsheet\Calculation::getFALSE();
} }
if (function_exists('mb_substr')) { return mb_substr($value, 0, $chars, 'UTF-8');
return mb_substr($value, 0, $chars, 'UTF-8');
}
return substr($value, 0, $chars);
} }
/** /**
@ -363,11 +346,8 @@ class TextData
if (empty($chars)) { if (empty($chars)) {
return ''; return '';
} }
if (function_exists('mb_substr')) {
return mb_substr($value, --$start, $chars, 'UTF-8');
}
return substr($value, --$start, $chars); return mb_substr($value, --$start, $chars, 'UTF-8');
} }
/** /**
@ -391,11 +371,7 @@ class TextData
$value = ($value) ? \PhpOffice\PhpSpreadsheet\Calculation::getTRUE() : \PhpOffice\PhpSpreadsheet\Calculation::getFALSE(); $value = ($value) ? \PhpOffice\PhpSpreadsheet\Calculation::getTRUE() : \PhpOffice\PhpSpreadsheet\Calculation::getFALSE();
} }
if ((function_exists('mb_substr')) && (function_exists('mb_strlen'))) { return mb_substr($value, mb_strlen($value, 'UTF-8') - $chars, $chars, 'UTF-8');
return mb_substr($value, mb_strlen($value, 'UTF-8') - $chars, $chars, 'UTF-8');
}
return substr($value, strlen($value) - $chars);
} }
/** /**
@ -413,11 +389,7 @@ class TextData
$value = ($value) ? \PhpOffice\PhpSpreadsheet\Calculation::getTRUE() : \PhpOffice\PhpSpreadsheet\Calculation::getFALSE(); $value = ($value) ? \PhpOffice\PhpSpreadsheet\Calculation::getTRUE() : \PhpOffice\PhpSpreadsheet\Calculation::getFALSE();
} }
if (function_exists('mb_strlen')) { return mb_strlen($value, 'UTF-8');
return mb_strlen($value, 'UTF-8');
}
return strlen($value);
} }
/** /**
@ -521,30 +493,20 @@ class TextData
$instance = floor(Functions::flattenSingleValue($instance)); $instance = floor(Functions::flattenSingleValue($instance));
if ($instance == 0) { if ($instance == 0) {
if (function_exists('mb_str_replace')) { return \PhpOffice\PhpSpreadsheet\Shared\StringHelper::mbStrReplace($fromText, $toText, $text);
return mb_str_replace($fromText, $toText, $text);
}
return str_replace($fromText, $toText, $text);
} }
$pos = -1; $pos = -1;
while ($instance > 0) { while ($instance > 0) {
if (function_exists('mb_strpos')) { $pos = mb_strpos($text, $fromText, $pos + 1, 'UTF-8');
$pos = mb_strpos($text, $fromText, $pos + 1, 'UTF-8');
} else {
$pos = strpos($text, $fromText, $pos + 1);
}
if ($pos === false) { if ($pos === false) {
break; break;
} }
--$instance; --$instance;
} }
if ($pos !== false) {
if (function_exists('mb_strlen')) {
return self::REPLACE($text, ++$pos, mb_strlen($fromText, 'UTF-8'), $toText);
}
return self::REPLACE($text, ++$pos, strlen($fromText), $toText); if ($pos !== false) {
return self::REPLACE($text, ++$pos, mb_strlen($fromText, 'UTF-8'), $toText);
} }
return $text; return $text;

View File

@ -79,8 +79,8 @@ class DataSeriesValues
/** /**
* Create a new DataSeriesValues object. * Create a new DataSeriesValues object.
* *
* @param string $dataSource
* @param mixed $dataType * @param mixed $dataType
* @param string $dataSource
* @param null|mixed $formatCode * @param null|mixed $formatCode
* @param mixed $pointCount * @param mixed $pointCount
* @param mixed $dataValues * @param mixed $dataValues

View File

@ -1484,6 +1484,11 @@ class Xlsx extends BaseReader implements IReader
foreach ($shapes as $idx => $shape) { foreach ($shapes as $idx => $shape) {
$shape->registerXPathNamespace('v', 'urn:schemas-microsoft-com:vml'); $shape->registerXPathNamespace('v', 'urn:schemas-microsoft-com:vml');
$imageData = $shape->xpath('//v:imagedata'); $imageData = $shape->xpath('//v:imagedata');
if (!$imageData) {
continue;
}
$imageData = $imageData[$idx]; $imageData = $imageData[$idx];
$imageData = $imageData->attributes('urn:schemas-microsoft-com:office:office'); $imageData = $imageData->attributes('urn:schemas-microsoft-com:office:office');

View File

@ -142,40 +142,6 @@ class File
} }
} }
// sys_get_temp_dir is only available since PHP 5.2.1
// http://php.net/manual/en/function.sys-get-temp-dir.php#94119
if (!function_exists('sys_get_temp_dir')) {
if ($temp = getenv('TMP')) {
if ((!empty($temp)) && (file_exists($temp))) {
return realpath($temp);
}
}
if ($temp = getenv('TEMP')) {
if ((!empty($temp)) && (file_exists($temp))) {
return realpath($temp);
}
}
if ($temp = getenv('TMPDIR')) {
if ((!empty($temp)) && (file_exists($temp))) {
return realpath($temp);
}
}
// trick for creating a file in system's temporary dir
// without knowing the path of the system's temporary dir
$temp = tempnam(__FILE__, '');
if (file_exists($temp)) {
unlink($temp);
return realpath(dirname($temp));
}
return null;
}
// use ordinary built-in PHP function
// There should be no problem with the 5.2.4 Suhosin realpath() bug, because this line should only
// be called if we're running 5.2.1 or earlier
return realpath(sys_get_temp_dir()); return realpath(sys_get_temp_dir());
} }

View File

@ -66,13 +66,6 @@ class StringHelper
*/ */
private static $currencyCode; private static $currencyCode;
/**
* Is mbstring extension avalable?
*
* @var bool
*/
private static $isMbstringEnabled;
/** /**
* Is iconv extension avalable? * Is iconv extension avalable?
* *
@ -259,23 +252,6 @@ class StringHelper
]; ];
} }
/**
* Get whether mbstring extension is available.
*
* @return bool
*/
public static function getIsMbstringEnabled()
{
if (isset(self::$isMbstringEnabled)) {
return self::$isMbstringEnabled;
}
self::$isMbstringEnabled = function_exists('mb_convert_encoding') ?
true : false;
return self::$isMbstringEnabled;
}
/** /**
* Get whether iconv extension is available. * Get whether iconv extension is available.
* *
@ -387,13 +363,8 @@ class StringHelper
return $value; return $value;
} }
if (self::getIsMbstringEnabled()) { $value = mb_convert_encoding($value, 'UTF-8', 'UTF-8');
$value = mb_convert_encoding($value, 'UTF-8', 'UTF-8');
return $value;
}
// else, no conversion
return $value; return $value;
} }
@ -444,9 +415,7 @@ class StringHelper
$ln = self::countCharacters($value, 'UTF-8'); $ln = self::countCharacters($value, 'UTF-8');
// option flags // option flags
if (empty($arrcRuns)) { if (empty($arrcRuns)) {
$opt = (self::getIsIconvEnabled() || self::getIsMbstringEnabled()) ? $data = pack('CC', $ln, 0x0001);
0x0001 : 0x0000;
$data = pack('CC', $ln, $opt);
// characters // characters
$data .= self::convertEncoding($value, 'UTF-16LE', 'UTF-8'); $data .= self::convertEncoding($value, 'UTF-16LE', 'UTF-8');
} else { } else {
@ -479,20 +448,16 @@ class StringHelper
// character count // character count
$ln = self::countCharacters($value, 'UTF-8'); $ln = self::countCharacters($value, 'UTF-8');
// option flags
$opt = (self::getIsIconvEnabled() || self::getIsMbstringEnabled()) ?
0x0001 : 0x0000;
// characters // characters
$chars = self::convertEncoding($value, 'UTF-16LE', 'UTF-8'); $chars = self::convertEncoding($value, 'UTF-16LE', 'UTF-8');
$data = pack('vC', $ln, $opt) . $chars; $data = pack('vC', $ln, 0x0001) . $chars;
return $data; return $data;
} }
/** /**
* Convert string from one encoding to another. First try mbstring, then iconv, finally strlen. * Convert string from one encoding to another.
* *
* @param string $value * @param string $value
* @param string $to Encoding to convert to, e.g. 'UTF-8' * @param string $to Encoding to convert to, e.g. 'UTF-8'
@ -506,68 +471,11 @@ class StringHelper
return iconv($from, $to . '//IGNORE//TRANSLIT', $value); return iconv($from, $to . '//IGNORE//TRANSLIT', $value);
} }
if (self::getIsMbstringEnabled()) { return mb_convert_encoding($value, $to, $from);
return mb_convert_encoding($value, $to, $from);
}
if ($from == 'UTF-16LE') {
return self::utf16Decode($value, false);
} elseif ($from == 'UTF-16BE') {
return self::utf16Decode($value);
}
// else, no conversion
return $value;
} }
/** /**
* Decode UTF-16 encoded strings. * Get character count.
*
* Can handle both BOM'ed data and un-BOM'ed data.
* Assumes Big-Endian byte order if no BOM is available.
* This function was taken from http://php.net/manual/en/function.utf8-decode.php
* and $bom_be parameter added.
*
* @param string $str uTF-16 encoded data to decode
* @param mixed $bom_be
*
* @return string uTF-8 / ISO encoded data
*
* @version 0.2 / 2010-05-13
*
* @author Rasmus Andersson {@link http://rasmusandersson.se/}
* @author vadik56
*/
public static function utf16Decode($str, $bom_be = true)
{
if (strlen($str) < 2) {
return $str;
}
$c0 = ord($str[0]);
$c1 = ord($str[1]);
if ($c0 == 0xfe && $c1 == 0xff) {
$str = substr($str, 2);
} elseif ($c0 == 0xff && $c1 == 0xfe) {
$str = substr($str, 2);
$bom_be = false;
}
$len = strlen($str);
$newstr = '';
for ($i = 0; $i < $len; $i += 2) {
if ($bom_be) {
$val = ord($str[$i]) << 4;
$val += ord($str[$i + 1]);
} else {
$val = ord($str[$i + 1]) << 4;
$val += ord($str[$i]);
}
$newstr .= ($val == 0x228) ? "\n" : chr($val);
}
return $newstr;
}
/**
* Get character count. First try mbstring, then iconv, finally strlen.
* *
* @param string $value * @param string $value
* @param string $enc Encoding * @param string $enc Encoding
@ -576,20 +484,11 @@ class StringHelper
*/ */
public static function countCharacters($value, $enc = 'UTF-8') public static function countCharacters($value, $enc = 'UTF-8')
{ {
if (self::getIsMbstringEnabled()) { return mb_strlen($value, $enc);
return mb_strlen($value, $enc);
}
if (self::getIsIconvEnabled()) {
return iconv_strlen($value, $enc);
}
// else strlen
return strlen($value);
} }
/** /**
* Get a substring of a UTF-8 encoded string. First try mbstring, then iconv, finally strlen. * Get a substring of a UTF-8 encoded string.
* *
* @param string $pValue UTF-8 encoded string * @param string $pValue UTF-8 encoded string
* @param int $pStart Start offset * @param int $pStart Start offset
@ -599,16 +498,7 @@ class StringHelper
*/ */
public static function substring($pValue = '', $pStart = 0, $pLength = 0) public static function substring($pValue = '', $pStart = 0, $pLength = 0)
{ {
if (self::getIsMbstringEnabled()) { return mb_substr($pValue, $pStart, $pLength, 'UTF-8');
return mb_substr($pValue, $pStart, $pLength, 'UTF-8');
}
if (self::getIsIconvEnabled()) {
return iconv_substr($pValue, $pStart, $pLength, 'UTF-8');
}
// else substr
return substr($pValue, $pStart, $pLength);
} }
/** /**
@ -620,11 +510,7 @@ class StringHelper
*/ */
public static function strToUpper($pValue = '') public static function strToUpper($pValue = '')
{ {
if (function_exists('mb_convert_case')) { return mb_convert_case($pValue, MB_CASE_UPPER, 'UTF-8');
return mb_convert_case($pValue, MB_CASE_UPPER, 'UTF-8');
}
return strtoupper($pValue);
} }
/** /**
@ -636,11 +522,7 @@ class StringHelper
*/ */
public static function strToLower($pValue = '') public static function strToLower($pValue = '')
{ {
if (function_exists('mb_convert_case')) { return mb_convert_case($pValue, MB_CASE_LOWER, 'UTF-8');
return mb_convert_case($pValue, MB_CASE_LOWER, 'UTF-8');
}
return strtolower($pValue);
} }
/** /**
@ -653,11 +535,7 @@ class StringHelper
*/ */
public static function strToTitle($pValue = '') public static function strToTitle($pValue = '')
{ {
if (function_exists('mb_convert_case')) { return mb_convert_case($pValue, MB_CASE_TITLE, 'UTF-8');
return mb_convert_case($pValue, MB_CASE_TITLE, 'UTF-8');
}
return ucwords($pValue);
} }
public static function mbIsUpper($char) public static function mbIsUpper($char)
@ -672,6 +550,44 @@ class StringHelper
return preg_split('/(?<!^)(?!$)/u', $string); return preg_split('/(?<!^)(?!$)/u', $string);
} }
/**
* Replace into multi-bytes string.
*
* Strangely, PHP doesn't have a mb_str_replace multibyte function
* As we'll only ever use this function with UTF-8 characters, we can simply "hard-code" the character set
*
* @param string|string[] $search
* @param string|string[] $replace
* @param string $subject
*
* @return string
*/
public static function mbStrReplace($search, $replace, $subject)
{
if (is_array($subject)) {
$ret = [];
foreach ($subject as $key => $val) {
$ret[$key] = self::mbStrReplace($search, $replace, $val);
}
return $ret;
}
foreach ((array) $search as $key => $s) {
if ($s == '' && $s !== 0) {
continue;
}
$r = !is_array($replace) ? $replace : (isset($replace[$key]) ? $replace[$key] : '');
$pos = mb_strpos($subject, $s, 0, 'UTF-8');
while ($pos !== false) {
$subject = mb_substr($subject, 0, $pos, 'UTF-8') . $r . mb_substr($subject, $pos + mb_strlen($s, 'UTF-8'), null, 'UTF-8');
$pos = mb_strpos($subject, $s, $pos + mb_strlen($r, 'UTF-8'), 'UTF-8');
}
}
return $subject;
}
/** /**
* Reverse the case of a string, so that all uppercase characters become lowercase * Reverse the case of a string, so that all uppercase characters become lowercase
* and all lowercase characters become uppercase. * and all lowercase characters become uppercase.
@ -682,20 +598,16 @@ class StringHelper
*/ */
public static function strCaseReverse($pValue = '') public static function strCaseReverse($pValue = '')
{ {
if (self::getIsMbstringEnabled()) { $characters = self::mbStrSplit($pValue);
$characters = self::mbStrSplit($pValue); foreach ($characters as &$character) {
foreach ($characters as &$character) { if (self::mbIsUpper($character)) {
if (self::mbIsUpper($character)) { $character = mb_strtolower($character, 'UTF-8');
$character = mb_strtolower($character, 'UTF-8'); } else {
} else { $character = mb_strtoupper($character, 'UTF-8');
$character = mb_strtoupper($character, 'UTF-8');
}
} }
return implode('', $characters);
} }
return strtolower($pValue) ^ strtoupper($pValue) ^ $pValue; return implode('', $characters);
} }
/** /**

View File

@ -103,9 +103,9 @@ class XMLWriter extends \XMLWriter
} }
/** /**
* Fallback method for writeRaw, introduced in PHP 5.2. * Wrapper method for writeRaw.
* *
* @param string $text * @param string|string[] $text
* *
* @return bool * @return bool
*/ */
@ -115,10 +115,6 @@ class XMLWriter extends \XMLWriter
$text = implode("\n", $text); $text = implode("\n", $text);
} }
if (method_exists($this, 'writeRaw')) { return $this->writeRaw(htmlspecialchars($text));
return $this->writeRaw(htmlspecialchars($text));
}
return $this->text($text);
} }
} }

View File

@ -14,12 +14,6 @@ class StringTest extends \PHPUnit_Framework_TestCase
StringHelper::setCurrencyCode(null); StringHelper::setCurrencyCode(null);
} }
public function testGetIsMbStringEnabled()
{
$result = StringHelper::getIsMbstringEnabled();
$this->assertTrue($result);
}
public function testGetIsIconvEnabled() public function testGetIsIconvEnabled()
{ {
$result = StringHelper::getIsIconvEnabled(); $result = StringHelper::getIsIconvEnabled();