Skip to content

Commit 39c627e

Browse files
committed
Fix deprecated $php_errormsg in PHP 7.2
From the PHP 8.0 migration guide (https://www.php.net/manual/de/migration80.incompatible.php): The track_errors ini directive has been removed. This means that php_errormsg is no longer available. The error_get_last() function may be used instead. Also the documentation on $php_errormsg (https://www.php.net/manual/en/reserved.variables.phperrormsg.php) says: This feature has been DEPRECATED as of PHP 7.2.0. Relying on this feature is highly discouraged. Use error_get_last() instead. The functions Horde_String::convertCharset and Horde_String::_pos are broken up to assist in better testability and additional tests for the newly introduced functions are added. This commit breaks compatibility with PHP 5.6 Signed-off-by: Daniel Ziegenberg <daniel@ziegenberg.at>
1 parent c8ee322 commit 39c627e

File tree

3 files changed

+168
-27
lines changed

3 files changed

+168
-27
lines changed

lib/Horde/String.php

Lines changed: 85 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,10 @@ public static function convertCharset($input, $from, $to, $force = false)
9393
return $input;
9494
}
9595

96+
if(strlen($input) === 0) {
97+
return $input;
98+
}
99+
96100
return self::_convertCharset($input, $from, $to);
97101
}
98102

@@ -145,12 +149,7 @@ protected static function _convertCharset($input, $from, $to)
145149

146150
/* Try iconv with transliteration. */
147151
if (Horde_Util::extensionExists('iconv')) {
148-
unset($php_errormsg);
149-
ini_set('track_errors', 1);
150-
$out = @iconv($from, $to . '//TRANSLIT', $input);
151-
$errmsg = isset($php_errormsg);
152-
ini_restore('track_errors');
153-
if (!$errmsg && $out !== false) {
152+
if (($out = self::_convertCharsetIconv($input, $from, $to)) !== false) {
154153
return $out;
155154
}
156155
}
@@ -170,6 +169,25 @@ protected static function _convertCharset($input, $from, $to)
170169
return $input;
171170
}
172171

172+
/**
173+
* Internal function used to do charset transliteration with iconv.
174+
*
175+
* @param string $input See self::convertCharset().
176+
* @param string $from See self::convertCharset().
177+
* @param string $to See self::convertCharset().
178+
*
179+
* @return mixed The converted string, or false on error.
180+
*/
181+
protected static function _convertCharsetIconv(string $input, string $from, string $to): string
182+
{
183+
error_clear_last();
184+
$out = @iconv($from, $to . '//TRANSLIT', $input);
185+
if (is_null(error_get_last()) && $out !== false) {
186+
return $out;
187+
}
188+
return false;
189+
}
190+
173191
/**
174192
* Makes a string lowercase.
175193
*
@@ -488,37 +506,77 @@ protected static function _pos(
488506
)
489507
{
490508
if (Horde_Util::extensionExists('mbstring')) {
491-
unset($php_errormsg);
492-
$track_errors = ini_set('track_errors', 1);
493-
$ret = @call_user_func('mb_' . $func, $haystack, $needle, $offset, self::_mbstringCharset($charset));
494-
ini_set('track_errors', $track_errors);
495-
if (!isset($php_errormsg)) {
496-
return $ret;
509+
if (($out = @self::_posMbstring($haystack, $needle, $offset, $charset, $func)) !== false) {
510+
return $out;
497511
}
498512
}
499513

500514
if (Horde_Util::extensionExists('intl')) {
501-
unset($php_errormsg);
502-
$track_errors = ini_set('track_errors', 1);
503-
$ret = self::convertCharset(
504-
@call_user_func(
505-
'grapheme_' . $func,
506-
self::convertCharset($haystack, $charset, 'UTF-8'),
507-
self::convertCharset($needle, $charset, 'UTF-8'),
508-
$offset
509-
),
510-
'UTF-8',
511-
$charset
512-
);
513-
ini_set('track_errors', $track_errors);
514-
if (!isset($php_errormsg)) {
515-
return $ret;
515+
if(($out = @self::_posIntl($haystack, $needle, $offset, $charset, $func)) !== false) {
516+
return $out;
516517
}
517518
}
518519

519520
return $func($haystack, $needle, $offset);
520521
}
521522

523+
/**
524+
* Internal function to perform string position searches using mbstring.
525+
*
526+
* @param string $haystack See self::_pos
527+
* @param string $needle See self::_pos
528+
* @param integer $offset See self::_pos
529+
* @param string $charset See self::_pos
530+
* @param string $func See self::_pos
531+
*
532+
* @return mixed The position of occurrence, or false on error.
533+
*/
534+
protected static function _posMbstring(
535+
$haystack, $needle, $offset, $charset, $func
536+
)
537+
{
538+
error_clear_last();
539+
$ret = @call_user_func('mb_' . $func, $haystack, $needle, $offset, self::_mbstringCharset($charset));
540+
if (is_null(error_get_last())) {
541+
return $ret;
542+
}
543+
544+
return false;
545+
}
546+
547+
/**
548+
* Internal function to perform string position searches using intl.
549+
*
550+
* @param string $haystack See self::_pos
551+
* @param string $needle See self::_pos
552+
* @param integer $offset See self::_pos
553+
* @param string $charset See self::_pos
554+
* @param string $func See self::_pos
555+
*
556+
* @return mixed The position of occurrence, or false on error.
557+
*/
558+
protected static function _posIntl(
559+
$haystack, $needle, $offset, $charset, $func
560+
)
561+
{
562+
error_clear_last();
563+
$ret = self::convertCharset(
564+
@call_user_func(
565+
'grapheme_' . $func,
566+
self::convertCharset($haystack, $charset, 'UTF-8'),
567+
self::convertCharset($needle, $charset, 'UTF-8'),
568+
$offset
569+
),
570+
'UTF-8',
571+
$charset
572+
);
573+
if (is_null(error_get_last())) {
574+
return $ret;
575+
}
576+
577+
return false;
578+
}
579+
522580
/**
523581
* Returns a string padded to a certain length with another string.
524582
* This method behaves exactly like str_pad() but is multibyte safe.

test/Horde/Util/Mock/String.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
/**
3+
* Wrapper to test internal Horde_String methods.
4+
*
5+
* @author Daniel Ziegenberg <daniel@ziegenberg.at>
6+
* @category Horde
7+
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
8+
* @package Util
9+
*/
10+
class Horde_Util_Mock_String extends Horde_String
11+
{
12+
public static function testConvertCharsetIconv(string $input, string $from, string $to)
13+
{
14+
return self::_convertCharsetIconv($input, $from, $to);
15+
}
16+
17+
public static function testPosMbstring(string $haystack, string $needle, int $offset, string $charset, string $func)
18+
{
19+
return self::_posMbstring($haystack, $needle, $offset, $charset, $func);
20+
}
21+
22+
public static function testPosIntl(string $haystack, string $needle, int $offset, string $charset, string $func)
23+
{
24+
return self::_posIntl($haystack, $needle, $offset, $charset, $func);
25+
}
26+
}

test/Horde/Util/StringTest.php

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -731,4 +731,61 @@ public function invalidUtf8Provider()
731731
);
732732
}
733733

734+
/**
735+
* @dataProvider ConvertCharsetIconvProvider
736+
*/
737+
public function testConvertCharsetIconv(string $input, string $from, string $to, $expected): void
738+
{
739+
$this->assertEquals(
740+
$expected,
741+
Horde_Util_Mock_String::testConvertCharsetIconv($input, $from, $to)
742+
);
743+
}
744+
745+
public function ConvertCharsetIconvProvider()
746+
{
747+
return [
748+
'valid character sequence' => ['This will work.', 'UTF-8', 'ISO-8859-1', 'This will work.'],
749+
'illegal character in input string' => ["This is the Euro symbol '€'.", 'UTF-8', 'ISO-8859-1', false]
750+
];
751+
}
752+
753+
/**
754+
* @dataProvider posMbstringProvider
755+
*/
756+
public function testPosMbstring(string $haystack, string $needle, int $offset, string $charset, string $func, $expected): void
757+
{
758+
$this->assertEquals(
759+
$expected,
760+
Horde_Util_Mock_String::testPosMbstring($haystack, $needle, $offset, $charset, $func)
761+
);
762+
}
763+
764+
public function posMbstringProvider()
765+
{
766+
return [
767+
'valid character sequence' => ['Some random string.', 'Some', 0, 'UTF-8', 'strpos', 0],
768+
'invalid search offset' => ['Some random string', 'Some', 50, 'UTF-8', 'strpos', false]
769+
];
770+
}
771+
772+
/**
773+
* @dataProvider posIntlProvider
774+
*/
775+
public function testPosIntl(string $haystack, string $needle, int $offset, string $charset, string $func, $expected): void
776+
{
777+
$this->assertEquals(
778+
$expected,
779+
Horde_Util_Mock_String::testPosIntl($haystack, $needle, $offset, $charset, $func)
780+
);
781+
}
782+
783+
public function posIntlProvider()
784+
{
785+
return [
786+
'valid character sequence' => ['Some random string.', 'Some', 0, 'UTF-8', 'strpos', 0],
787+
'invalid search offset' => ['Some random string', 'Some', 50, 'UTF-8', 'strpos', false]
788+
];
789+
}
790+
734791
}

0 commit comments

Comments
 (0)