From 29748cfe590cdfca06c830f9a9e29655325262b0 Mon Sep 17 00:00:00 2001
From: Erik Landvall
Date: Sat, 28 Sep 2013 16:49:04 +0200
Subject: [PATCH 01/42] Namespace definition..
For clarity asked for in issue #10
---
README.md | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/README.md b/README.md
index 3426137..6fd4f8a 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
forceutf8
=========
-PHP Class Encoding featuring popular Encoding::toUTF8() function --formerly known as forceUTF8()-- that fixes mixed encoded strings.
+PHP Class Encoding featuring popular \ForceUTF8\Encoding::toUTF8() function --formerly known as forceUTF8()-- that fixes mixed encoded strings.
Description
===========
@@ -21,20 +21,20 @@ I've included another function, Encoding::fixUTF8(), wich will fix the double (o
Usage:
======
- $utf8_string = Encoding::toUTF8($utf8_or_latin1_or_mixed_string);
+ $utf8_string = \ForceUTF8\Encoding::toUTF8($utf8_or_latin1_or_mixed_string);
$latin1_string = Encoding::toLatin1($utf8_or_latin1_or_mixed_string);
also:
- $utf8_string = Encoding::fixUTF8($garbled_utf8_string);
+ $utf8_string = \ForceUTF8\Encoding::fixUTF8($garbled_utf8_string);
Examples:
- echo Encoding::fixUTF8("Fédération Camerounaise de Football");
- echo Encoding::fixUTF8("FÃédÃération Camerounaise de Football");
- echo Encoding::fixUTF8("FÃÃédÃÃération Camerounaise de Football");
- echo Encoding::fixUTF8("FÃÃÃédÃÃÃération Camerounaise de Football");
+ echo \ForceUTF8\Encoding::fixUTF8("Fédération Camerounaise de Football");
+ echo \ForceUTF8\Encoding::fixUTF8("FÃédÃération Camerounaise de Football");
+ echo \ForceUTF8\Encoding::fixUTF8("FÃÃédÃÃération Camerounaise de Football");
+ echo \ForceUTF8\Encoding::fixUTF8("FÃÃÃédÃÃÃération Camerounaise de Football");
will output:
From f7960f1a31d8377eab5d828ca9171a6cfe9d0f85 Mon Sep 17 00:00:00 2001
From: Jason Pirkey
Date: Wed, 2 Apr 2014 13:37:03 -0300
Subject: [PATCH 02/42] Fix issue where truncation or infinite loop might
occur.
Text is truncated when calling Encoding::fixUTF8 if mb_strlen is overloading strlen. This is because mb_strlen returns the char length instead of the byte length of the string.
---
src/ForceUTF8/Encoding.php | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/src/ForceUTF8/Encoding.php b/src/ForceUTF8/Encoding.php
index 219bc25..ec49528 100644
--- a/src/ForceUTF8/Encoding.php
+++ b/src/ForceUTF8/Encoding.php
@@ -180,8 +180,13 @@ static function toUTF8($text){
}
return $text;
} elseif(is_string($text)) {
+
+ if ( function_exists('mb_strlen') && ((int) ini_get('mbstring.func_overload')) & 2) {
+ $max = mb_strlen($text,'8bit');
+ } else {
+ $max = strlen($text);
+ }
- $max = strlen($text);
$buf = "";
for($i = 0; $i < $max; $i++){
$c1 = $text{$i};
From 09955a49947a00521f1f88923e795709bb653810 Mon Sep 17 00:00:00 2001
From: Pascal Borreli
Date: Mon, 14 Apr 2014 21:40:50 +0100
Subject: [PATCH 03/42] Fixed typos
---
README.md | 4 ++--
src/ForceUTF8/Encoding.php | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/README.md b/README.md
index 3426137..e245611 100644
--- a/README.md
+++ b/README.md
@@ -10,13 +10,13 @@ If you apply the PHP function utf8_encode() to an already-UTF8 string it will re
This class addresses this issue and provides a handy static function called Encoding::toUTF8().
-You dont need to know what the encoding of your strings is. It can be Latin1 (iso 8859-1), Windows-1252 or UTF8, or the string can have a mix of them. Encoding::toUTF8() will convert everything to UTF8.
+You don't need to know what the encoding of your strings is. It can be Latin1 (iso 8859-1), Windows-1252 or UTF8, or the string can have a mix of them. Encoding::toUTF8() will convert everything to UTF8.
Sometimes you have to deal with services that are unreliable in terms of encoding, possibly mixing UTF8 and Latin1 in the same string.
Update:
-I've included another function, Encoding::fixUTF8(), wich will fix the double (or multiple) encoded UTF8 string that looks garbled.
+I've included another function, Encoding::fixUTF8(), which will fix the double (or multiple) encoded UTF8 string that looks garbled.
Usage:
======
diff --git a/src/ForceUTF8/Encoding.php b/src/ForceUTF8/Encoding.php
index 219bc25..6750bf0 100644
--- a/src/ForceUTF8/Encoding.php
+++ b/src/ForceUTF8/Encoding.php
@@ -229,7 +229,7 @@ static function toUTF8($text){
$cc2 = (($c1 & "\x3f") | "\x80");
$buf .= $cc1 . $cc2;
}
- } else { // it doesn't need convesion
+ } else { // it doesn't need conversion
$buf .= $c1;
}
}
From a3d35e030c49124e6e8c1209d20b23e428b83ad4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sebasti=C3=A1n=20Grignoli?=
Date: Wed, 25 Jun 2014 13:45:07 -0300
Subject: [PATCH 04/42] Readme
---
README.md | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/README.md b/README.md
index 3f6dc72..2fc9fe0 100644
--- a/README.md
+++ b/README.md
@@ -8,22 +8,22 @@ Description
If you apply the PHP function utf8_encode() to an already-UTF8 string it will return a garbled UTF8 string.
-This class addresses this issue and provides a handy static function called Encoding::toUTF8().
+This class addresses this issue and provides a handy static function called \ForceUTF8\Encoding::toUTF8().
-You don't need to know what the encoding of your strings is. It can be Latin1 (iso 8859-1), Windows-1252 or UTF8, or the string can have a mix of them. Encoding::toUTF8() will convert everything to UTF8.
+You don't need to know what the encoding of your strings is. It can be Latin1 (iso 8859-1), Windows-1252 or UTF8, or the string can have a mix of them. \ForceUTF8\Encoding::toUTF8() will convert everything to UTF8.
Sometimes you have to deal with services that are unreliable in terms of encoding, possibly mixing UTF8 and Latin1 in the same string.
Update:
-I've included another function, Encoding::fixUTF8(), which will fix the double (or multiple) encoded UTF8 string that looks garbled.
+I've included another function, \ForceUTF8\Encoding::fixUTF8(), which will fix the double (or multiple) encoded UTF8 string that looks garbled.
Usage:
======
$utf8_string = \ForceUTF8\Encoding::toUTF8($utf8_or_latin1_or_mixed_string);
- $latin1_string = Encoding::toLatin1($utf8_or_latin1_or_mixed_string);
+ $latin1_string = \ForceUTF8\Encoding::toLatin1($utf8_or_latin1_or_mixed_string);
also:
From 3f071b2c2ecd050089312b57b46063ea5607e414 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sebasti=C3=A1n=20Grignoli?=
Date: Wed, 25 Jun 2014 13:50:33 -0300
Subject: [PATCH 05/42] Instructions on how to install via composer
---
README.md | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/README.md b/README.md
index 2fc9fe0..a42d757 100644
--- a/README.md
+++ b/README.md
@@ -42,3 +42,22 @@ will output:
Fédération Camerounaise de Football
Fédération Camerounaise de Football
Fédération Camerounaise de Football
+
+Install via composer:
+=====================
+Edit your composer.json file to include the following:
+
+```json
+{
+ "repositories": [
+ {
+ "type": "vcs",
+ "url": "https://github.com/neitanod/forceutf8"
+ }
+ ],
+
+ "require" : {
+ "neitanod/forceutf8" : "master"
+ }
+}
+```
From f3aef1e208346733d677ece8cc42011d1fa6d415 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sebasti=C3=A1n=20Grignoli?=
Date: Wed, 25 Jun 2014 13:56:05 -0300
Subject: [PATCH 06/42] Added author to composer.json
---
composer.json | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/composer.json b/composer.json
index 7f3fc0d..7924dfa 100644
--- a/composer.json
+++ b/composer.json
@@ -6,6 +6,12 @@
"require": {
"php": ">=5.2.0"
},
+ "authors": [
+ {
+ "name": "Sebastián Grignoli",
+ "email": "grignoli@gmail.com"
+ }
+ ],
"autoload": {
"psr-0": {
"ForceUTF8\\": "src/"
From 0623c8892f2d56c0c3eec2294490ef5bf0e26407 Mon Sep 17 00:00:00 2001
From: John Kelly
Date: Thu, 26 Jun 2014 08:30:34 -0700
Subject: [PATCH 07/42] Fix composer install instructions
---
README.md | 11 ++---------
1 file changed, 2 insertions(+), 9 deletions(-)
diff --git a/README.md b/README.md
index a42d757..71a785c 100644
--- a/README.md
+++ b/README.md
@@ -49,15 +49,8 @@ Edit your composer.json file to include the following:
```json
{
- "repositories": [
- {
- "type": "vcs",
- "url": "https://github.com/neitanod/forceutf8"
- }
- ],
-
- "require" : {
- "neitanod/forceutf8" : "master"
+ "require": {
+ "neitanod/forceutf8": "dev-master"
}
}
```
From ce0484691199027c54d00afd003b0048e59db4cd Mon Sep 17 00:00:00 2001
From: Mark Stewart
Date: Mon, 11 Aug 2014 17:29:16 -0600
Subject: [PATCH 08/42] Fixed issue with 4-byte characters not being written
properly
---
src/ForceUTF8/Encoding.php | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/ForceUTF8/Encoding.php b/src/ForceUTF8/Encoding.php
index b22b59a..91a15e8 100644
--- a/src/ForceUTF8/Encoding.php
+++ b/src/ForceUTF8/Encoding.php
@@ -214,8 +214,8 @@ static function toUTF8($text){
}
} elseif($c1 >= "\xf0" & $c1 <= "\xf7"){ //looks like 4 bytes UTF8
if($c2 >= "\x80" && $c2 <= "\xbf" && $c3 >= "\x80" && $c3 <= "\xbf" && $c4 >= "\x80" && $c4 <= "\xbf"){ //yeah, almost sure it's UTF8 already
- $buf .= $c1 . $c2 . $c3;
- $i = $i + 2;
+ $buf .= $c1 . $c2 . $c3 . $c4;
+ $i = $i + 3;
} else { //not valid UTF8. Convert it.
$cc1 = (chr(ord($c1) / 64) | "\xc0");
$cc2 = ($c1 & "\x3f") | "\x80";
From 174c97af230866d15cc459953fd04a4262b4112a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sebasti=C3=A1n=20Grignoli?=
Date: Thu, 14 Aug 2014 13:40:09 -0300
Subject: [PATCH 09/42] Normalize encoding label
---
src/ForceUTF8/Encoding.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/ForceUTF8/Encoding.php b/src/ForceUTF8/Encoding.php
index b22b59a..00b2eff 100644
--- a/src/ForceUTF8/Encoding.php
+++ b/src/ForceUTF8/Encoding.php
@@ -300,7 +300,7 @@ static function removeBOM($str=""){
public static function normalizeEncoding($encodingLabel)
{
$encoding = strtoupper($encodingLabel);
- $enc = preg_replace('/[^a-zA-Z0-9\s]/', '', $encoding);
+ $encoding = preg_replace('/[^a-zA-Z0-9\s]/', '', $encoding);
$equivalences = array(
'ISO88591' => 'ISO-8859-1',
'ISO8859' => 'ISO-8859-1',
From b2010fb491660ee1e3644ea23c7b443305b075f7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sebasti=C3=A1n=20Grignoli?=
Date: Tue, 23 Sep 2014 19:26:55 -0300
Subject: [PATCH 10/42] Fixed
---
README.md | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/README.md b/README.md
index a42d757..e8e246f 100644
--- a/README.md
+++ b/README.md
@@ -31,17 +31,15 @@ also:
Examples:
- echo \ForceUTF8\Encoding::fixUTF8("Fédération Camerounaise de Football");
- echo \ForceUTF8\Encoding::fixUTF8("FÃédÃération Camerounaise de Football");
- echo \ForceUTF8\Encoding::fixUTF8("FÃÃédÃÃération Camerounaise de Football");
- echo \ForceUTF8\Encoding::fixUTF8("FÃÃÃédÃÃÃération Camerounaise de Football");
+ echo \ForceUTF8\Encoding::fixUTF8("Fédération Camerounaise de Football\n");
+ echo \ForceUTF8\Encoding::fixUTF8("Fédération Camerounaise de Football\n");
+ echo \ForceUTF8\Encoding::fixUTF8("Fédération Camerounaise de Football\n");
will output:
Fédération Camerounaise de Football
Fédération Camerounaise de Football
Fédération Camerounaise de Football
- Fédération Camerounaise de Football
Install via composer:
=====================
@@ -61,3 +59,5 @@ Edit your composer.json file to include the following:
}
}
```
+=======
+>>>>>>> Stashed changes
From 20549d94dd55c6bb843f4d6ac5637c95cff22d64 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sebasti=C3=A1n=20Grignoli?=
Date: Tue, 23 Sep 2014 19:37:06 -0300
Subject: [PATCH 11/42] Fixed
---
README.md | 2 ++
1 file changed, 2 insertions(+)
diff --git a/README.md b/README.md
index cbe760e..bade661 100644
--- a/README.md
+++ b/README.md
@@ -34,12 +34,14 @@ Examples:
echo \ForceUTF8\Encoding::fixUTF8("Fédération Camerounaise de Football\n");
echo \ForceUTF8\Encoding::fixUTF8("Fédération Camerounaise de Football\n");
echo \ForceUTF8\Encoding::fixUTF8("Fédération Camerounaise de Football\n");
+ echo \ForceUTF8\Encoding::fixUTF8("Fédération Camerounaise de Football\n");
will output:
Fédération Camerounaise de Football
Fédération Camerounaise de Football
Fédération Camerounaise de Football
+ Fédération Camerounaise de Football
Install via composer:
=====================
From f707da221208edcf2a472facbbae3a1d23f5ff47 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sebasti=C3=A1n=20Grignoli?=
Date: Tue, 23 Sep 2014 21:01:33 -0300
Subject: [PATCH 12/42] Attempt to fix Euro sign and other Win1252 chars
---
src/ForceUTF8/Encoding.php | 20 ++++++++++++++------
1 file changed, 14 insertions(+), 6 deletions(-)
diff --git a/src/ForceUTF8/Encoding.php b/src/ForceUTF8/Encoding.php
index 811ae0b..b6197f9 100644
--- a/src/ForceUTF8/Encoding.php
+++ b/src/ForceUTF8/Encoding.php
@@ -29,9 +29,9 @@
*/
/**
- * @author "Sebastián Grignoli"
+ * @author "Sebastián Grignoli"
* @package Encoding
- * @version 1.2
+ * @version 1.4
* @link https://github.com/neitanod/forceutf8
* @example https://github.com/neitanod/forceutf8
* @license Revised BSD
@@ -148,7 +148,7 @@ class Encoding {
static function toUTF8($text){
/**
- * Function Encoding::toUTF8
+ * Function \ForceUTF8\Encoding::toUTF8
*
* This function leaves UTF8 characters alone, while converting almost all non-UTF8 to UTF8.
*
@@ -251,7 +251,7 @@ static function toWin1252($text) {
}
return $text;
} elseif(is_string($text)) {
- return utf8_decode(str_replace(array_keys(self::$utf8ToWin1252), array_values(self::$utf8ToWin1252), self::toUTF8($text)));
+ return static::utf8_decode($text);
} else {
return $text;
}
@@ -276,9 +276,9 @@ static function fixUTF8($text){
$last = "";
while($last <> $text){
$last = $text;
- $text = self::toUTF8(utf8_decode(str_replace(array_keys(self::$utf8ToWin1252), array_values(self::$utf8ToWin1252), $text)));
+ $text = self::toUTF8(static::utf8_decode($text));
}
- $text = self::toUTF8(utf8_decode(str_replace(array_keys(self::$utf8ToWin1252), array_values(self::$utf8ToWin1252), $text)));
+ $text = self::toUTF8(static::utf8_decode($text));
return $text;
}
@@ -327,4 +327,12 @@ public static function encode($encodingLabel, $text)
if($encodingLabel == 'ISO-8859-1') return Encoding::toLatin1($text);
}
+ protected static function utf8_decode($text)
+ {
+ // $o = utf8_decode(
+ // str_replace(array_keys(self::$utf8ToWin1252), array_values(self::$utf8ToWin1252), self::toUTF8($text))
+ // );
+ $o = iconv("UTF-8", "Windows-1252//TRANSLIT", $text);
+ return $o;
+ }
}
From 42703773fbc7e6e61db7751f96ff78b97dd9641f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sebasti=C3=A1n=20Grignoli?=
Date: Wed, 24 Sep 2014 11:49:38 -0300
Subject: [PATCH 13/42] Minor fix to README.md
---
README.md | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/README.md b/README.md
index bade661..11cd15a 100644
--- a/README.md
+++ b/README.md
@@ -54,5 +54,4 @@ Edit your composer.json file to include the following:
}
}
```
-=======
->>>>>>> Stashed changes
+
From 28d50d579179abac1f6a55b03c6d9d3f6573867c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sebasti=C3=A1n=20Grignoli?=
Date: Wed, 24 Sep 2014 11:59:43 -0300
Subject: [PATCH 14/42] Minor fix to README.md
---
README.md | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/README.md b/README.md
index bade661..11cd15a 100644
--- a/README.md
+++ b/README.md
@@ -54,5 +54,4 @@ Edit your composer.json file to include the following:
}
}
```
-=======
->>>>>>> Stashed changes
+
From 00e19a44f6f674152c4ef35cb3995c3bbcceb5d8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sebasti=C3=A1n=20Grignoli?=
Date: Wed, 24 Sep 2014 12:26:05 -0300
Subject: [PATCH 15/42] Version 2: new dependencies (iconv)
---
src/ForceUTF8/Encoding.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/ForceUTF8/Encoding.php b/src/ForceUTF8/Encoding.php
index b6197f9..cf2f767 100644
--- a/src/ForceUTF8/Encoding.php
+++ b/src/ForceUTF8/Encoding.php
@@ -31,7 +31,7 @@
/**
* @author "Sebastián Grignoli"
* @package Encoding
- * @version 1.4
+ * @version 2.0
* @link https://github.com/neitanod/forceutf8
* @example https://github.com/neitanod/forceutf8
* @license Revised BSD
From 9bef82817d8de3c284b7d76489cf5990b47b089d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sebasti=C3=A1n=20Grignoli?=
Date: Wed, 8 Oct 2014 12:13:25 -0300
Subject: [PATCH 16/42] Readme
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 11cd15a..d081dc2 100644
--- a/README.md
+++ b/README.md
@@ -50,7 +50,7 @@ Edit your composer.json file to include the following:
```json
{
"require": {
- "neitanod/forceutf8": "dev-master"
+ "neitanod/forceutf8": "1.*"
}
}
```
From a86eab3f13f14b2c4a8b2ac758b441db434f4b5a Mon Sep 17 00:00:00 2001
From: Joao Gilberto Magalhaes
Date: Sat, 11 Oct 2014 22:36:44 -0300
Subject: [PATCH 17/42] Added a parameter in fixUTF8 method for the user choose
if use iconv for conversion or dont
---
src/ForceUTF8/Encoding.php | 73 +++++++++++++++++++++-----------------
1 file changed, 40 insertions(+), 33 deletions(-)
diff --git a/src/ForceUTF8/Encoding.php b/src/ForceUTF8/Encoding.php
index cf2f767..1860c46 100644
--- a/src/ForceUTF8/Encoding.php
+++ b/src/ForceUTF8/Encoding.php
@@ -40,7 +40,11 @@
namespace ForceUTF8;
class Encoding {
-
+
+ const ICONV_TRANSLIT = "TRANSLIT";
+ const ICONV_IGNORE = "IGNORE";
+ const WITHOUT_ICONV = "";
+
protected static $win1252ToUtf8 = array(
128 => "\xe2\x82\xac",
@@ -75,10 +79,10 @@ class Encoding {
158 => "\xc5\xbe",
159 => "\xc5\xb8"
);
-
+
protected static $brokenUtf8ToUtf8 = array(
"\xc2\x80" => "\xe2\x82\xac",
-
+
"\xc2\x82" => "\xe2\x80\x9a",
"\xc2\x83" => "\xc6\x92",
"\xc2\x84" => "\xe2\x80\x9e",
@@ -90,10 +94,10 @@ class Encoding {
"\xc2\x8a" => "\xc5\xa0",
"\xc2\x8b" => "\xe2\x80\xb9",
"\xc2\x8c" => "\xc5\x92",
-
+
"\xc2\x8e" => "\xc5\xbd",
-
-
+
+
"\xc2\x91" => "\xe2\x80\x98",
"\xc2\x92" => "\xe2\x80\x99",
"\xc2\x93" => "\xe2\x80\x9c",
@@ -106,14 +110,14 @@ class Encoding {
"\xc2\x9a" => "\xc5\xa1",
"\xc2\x9b" => "\xe2\x80\xba",
"\xc2\x9c" => "\xc5\x93",
-
+
"\xc2\x9e" => "\xc5\xbe",
"\xc2\x9f" => "\xc5\xb8"
);
-
+
protected static $utf8ToWin1252 = array(
"\xe2\x82\xac" => "\x80",
-
+
"\xe2\x80\x9a" => "\x82",
"\xc6\x92" => "\x83",
"\xe2\x80\x9e" => "\x84",
@@ -125,10 +129,10 @@ class Encoding {
"\xc5\xa0" => "\x8a",
"\xe2\x80\xb9" => "\x8b",
"\xc5\x92" => "\x8c",
-
+
"\xc5\xbd" => "\x8e",
-
-
+
+
"\xe2\x80\x98" => "\x91",
"\xe2\x80\x99" => "\x92",
"\xe2\x80\x9c" => "\x93",
@@ -141,7 +145,7 @@ class Encoding {
"\xc5\xa1" => "\x9a",
"\xe2\x80\xba" => "\x9b",
"\xc5\x93" => "\x9c",
-
+
"\xc5\xbe" => "\x9e",
"\xc5\xb8" => "\x9f"
);
@@ -151,7 +155,7 @@ static function toUTF8($text){
* Function \ForceUTF8\Encoding::toUTF8
*
* This function leaves UTF8 characters alone, while converting almost all non-UTF8 to UTF8.
- *
+ *
* It assumes that the encoding of the original string is either Windows-1252 or ISO 8859-1.
*
* It may fail to convert characters to UTF-8 if they fall into one of these scenarios:
@@ -160,7 +164,7 @@ static function toUTF8($text){
* are followed by any of these: ("group B")
* ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶•¸¹º»¼½¾¿
* For example: %ABREPRESENT%C9%BB. «REPRESENTÉ»
- * The "«" (%AB) character will be converted, but the "É" followed by "»" (%C9%BB)
+ * The "«" (%AB) character will be converted, but the "É" followed by "»" (%C9%BB)
* is also a valid unicode character, and will be left unchanged.
*
* 2) when any of these: àáâãäåæçèéêëìíîï are followed by TWO chars from group B,
@@ -180,13 +184,13 @@ static function toUTF8($text){
}
return $text;
} elseif(is_string($text)) {
-
+
if ( function_exists('mb_strlen') && ((int) ini_get('mbstring.func_overload')) & 2) {
$max = mb_strlen($text,'8bit');
} else {
$max = strlen($text);
}
-
+
$buf = "";
for($i = 0; $i < $max; $i++){
$c1 = $text{$i};
@@ -265,10 +269,10 @@ static function toLatin1($text) {
return self::toWin1252($text);
}
- static function fixUTF8($text){
+ static function fixUTF8($text, $option = self::WITHOUT_ICONV){
if(is_array($text)) {
foreach($text as $k => $v) {
- $text[$k] = self::fixUTF8($v);
+ $text[$k] = self::fixUTF8($v, $option);
}
return $text;
}
@@ -276,27 +280,27 @@ static function fixUTF8($text){
$last = "";
while($last <> $text){
$last = $text;
- $text = self::toUTF8(static::utf8_decode($text));
+ $text = self::toUTF8(static::utf8_decode($text, $option));
}
- $text = self::toUTF8(static::utf8_decode($text));
+ $text = self::toUTF8(static::utf8_decode($text, $option));
return $text;
}
-
+
static function UTF8FixWin1252Chars($text){
- // If you received an UTF-8 string that was converted from Windows-1252 as it was ISO8859-1
+ // If you received an UTF-8 string that was converted from Windows-1252 as it was ISO8859-1
// (ignoring Windows-1252 chars from 80 to 9F) use this function to fix it.
// See: http://en.wikipedia.org/wiki/Windows-1252
-
+
return str_replace(array_keys(self::$brokenUtf8ToUtf8), array_values(self::$brokenUtf8ToUtf8), $text);
}
-
+
static function removeBOM($str=""){
if(substr($str, 0,3) == pack("CCC",0xef,0xbb,0xbf)) {
$str=substr($str, 3);
}
return $str;
}
-
+
public static function normalizeEncoding($encodingLabel)
{
$encoding = strtoupper($encodingLabel);
@@ -312,11 +316,11 @@ public static function normalizeEncoding($encodingLabel)
'WIN1252' => 'ISO-8859-1',
'WINDOWS1252' => 'ISO-8859-1'
);
-
+
if(empty($equivalences[$encoding])){
return 'UTF-8';
}
-
+
return $equivalences[$encoding];
}
@@ -327,12 +331,15 @@ public static function encode($encodingLabel, $text)
if($encodingLabel == 'ISO-8859-1') return Encoding::toLatin1($text);
}
- protected static function utf8_decode($text)
+ protected static function utf8_decode($text, $option)
{
- // $o = utf8_decode(
- // str_replace(array_keys(self::$utf8ToWin1252), array_values(self::$utf8ToWin1252), self::toUTF8($text))
- // );
- $o = iconv("UTF-8", "Windows-1252//TRANSLIT", $text);
+ if ($option == self::WITHOUT_ICONV || !function_exists('iconv')) {
+ $o = utf8_decode(
+ str_replace(array_keys(self::$utf8ToWin1252), array_values(self::$utf8ToWin1252), self::toUTF8($text))
+ );
+ } else {
+ $o = iconv("UTF-8", "Windows-1252" . ($option == self::ICONV_TRANSLIT ? '//TRANSLIT' : ($option == self::ICONV_IGNORE ? '//IGNORE' : '')), $text);
+ }
return $o;
}
}
From fc5fdc9fb66aa1a294bc775b7732a8b268ac9368 Mon Sep 17 00:00:00 2001
From: Joao Gilberto Magalhaes
Date: Fri, 17 Oct 2014 14:11:47 -0300
Subject: [PATCH 18/42] Added missing parameter
---
src/ForceUTF8/Encoding.php | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/ForceUTF8/Encoding.php b/src/ForceUTF8/Encoding.php
index 1860c46..a7686f5 100644
--- a/src/ForceUTF8/Encoding.php
+++ b/src/ForceUTF8/Encoding.php
@@ -248,14 +248,14 @@ static function toUTF8($text){
}
}
- static function toWin1252($text) {
+ static function toWin1252($text, $option = self::WITHOUT_ICONV) {
if(is_array($text)) {
foreach($text as $k => $v) {
- $text[$k] = self::toWin1252($v);
+ $text[$k] = self::toWin1252($v, $option);
}
return $text;
} elseif(is_string($text)) {
- return static::utf8_decode($text);
+ return static::utf8_decode($text, $option);
} else {
return $text;
}
From f300c0ce372ea3601d6d3d0e08a3baaf0b3e8cdc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sebasti=C3=A1n=20Grignoli?=
Date: Tue, 2 Dec 2014 15:32:42 -0300
Subject: [PATCH 19/42] Added some simple tests
---
test/ForceUTF8Test.php | 88 ++++++++++++++++++++++++++++++++++++++++
test/Test.class.php | 63 ++++++++++++++++++++++++++++
test/data/test1.txt | 1 +
test/data/test1Latin.txt | 1 +
4 files changed, 153 insertions(+)
create mode 100644 test/ForceUTF8Test.php
create mode 100644 test/Test.class.php
create mode 100644 test/data/test1.txt
create mode 100644 test/data/test1Latin.txt
diff --git a/test/ForceUTF8Test.php b/test/ForceUTF8Test.php
new file mode 100644
index 0000000..9ebebae
--- /dev/null
+++ b/test/ForceUTF8Test.php
@@ -0,0 +1,88 @@
+ FAILED\n";
+ static::$failed++;
+ }
+
+ private static function passed($test_name){
+ static::character(".");
+ static::$passed++;
+ }
+
+ private static function character($char){
+ echo $char;
+ static::$last_echoed = 'char';
+ }
+
+ private static function line($msg){
+ if(static::$last_echoed == 'char') echo "\n";
+ echo $msg."\n";
+ static::$last_echoed = 'line';
+ }
+ }
+
diff --git a/test/data/test1.txt b/test/data/test1.txt
new file mode 100644
index 0000000..771829e
--- /dev/null
+++ b/test/data/test1.txt
@@ -0,0 +1 @@
+Hírek
diff --git a/test/data/test1Latin.txt b/test/data/test1Latin.txt
new file mode 100644
index 0000000..0aa69d6
--- /dev/null
+++ b/test/data/test1Latin.txt
@@ -0,0 +1 @@
+Hrek
From dc58242858eebffb383212e3f880d2a0986818f7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sebasti=C3=A1n=20Grignoli?=
Date: Tue, 2 Dec 2014 15:34:36 -0300
Subject: [PATCH 20/42] Revert "Readme"
This reverts commit 9bef82817d8de3c284b7d76489cf5990b47b089d.
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index d081dc2..11cd15a 100644
--- a/README.md
+++ b/README.md
@@ -50,7 +50,7 @@ Edit your composer.json file to include the following:
```json
{
"require": {
- "neitanod/forceutf8": "1.*"
+ "neitanod/forceutf8": "dev-master"
}
}
```
From f303dc8217101bf78ae807157ceec9fdf634d3e0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sebasti=C3=A1n=20Grignoli?=
Date: Tue, 2 Dec 2014 15:37:28 -0300
Subject: [PATCH 21/42] Removed unnecessary elseif
---
src/ForceUTF8/Encoding.php | 121 +++++++++++++++++++------------------
1 file changed, 61 insertions(+), 60 deletions(-)
diff --git a/src/ForceUTF8/Encoding.php b/src/ForceUTF8/Encoding.php
index 811ae0b..e63bdcc 100644
--- a/src/ForceUTF8/Encoding.php
+++ b/src/ForceUTF8/Encoding.php
@@ -179,69 +179,70 @@ static function toUTF8($text){
$text[$k] = self::toUTF8($v);
}
return $text;
- } elseif(is_string($text)) {
-
- if ( function_exists('mb_strlen') && ((int) ini_get('mbstring.func_overload')) & 2) {
- $max = mb_strlen($text,'8bit');
- } else {
- $max = strlen($text);
- }
+ }
- $buf = "";
- for($i = 0; $i < $max; $i++){
- $c1 = $text{$i};
- if($c1>="\xc0"){ //Should be converted to UTF8, if it's not UTF8 already
- $c2 = $i+1 >= $max? "\x00" : $text{$i+1};
- $c3 = $i+2 >= $max? "\x00" : $text{$i+2};
- $c4 = $i+3 >= $max? "\x00" : $text{$i+3};
- if($c1 >= "\xc0" & $c1 <= "\xdf"){ //looks like 2 bytes UTF8
- if($c2 >= "\x80" && $c2 <= "\xbf"){ //yeah, almost sure it's UTF8 already
- $buf .= $c1 . $c2;
- $i++;
- } else { //not valid UTF8. Convert it.
- $cc1 = (chr(ord($c1) / 64) | "\xc0");
- $cc2 = ($c1 & "\x3f") | "\x80";
- $buf .= $cc1 . $cc2;
- }
- } elseif($c1 >= "\xe0" & $c1 <= "\xef"){ //looks like 3 bytes UTF8
- if($c2 >= "\x80" && $c2 <= "\xbf" && $c3 >= "\x80" && $c3 <= "\xbf"){ //yeah, almost sure it's UTF8 already
- $buf .= $c1 . $c2 . $c3;
- $i = $i + 2;
- } else { //not valid UTF8. Convert it.
- $cc1 = (chr(ord($c1) / 64) | "\xc0");
- $cc2 = ($c1 & "\x3f") | "\x80";
- $buf .= $cc1 . $cc2;
- }
- } elseif($c1 >= "\xf0" & $c1 <= "\xf7"){ //looks like 4 bytes UTF8
- if($c2 >= "\x80" && $c2 <= "\xbf" && $c3 >= "\x80" && $c3 <= "\xbf" && $c4 >= "\x80" && $c4 <= "\xbf"){ //yeah, almost sure it's UTF8 already
- $buf .= $c1 . $c2 . $c3 . $c4;
- $i = $i + 3;
- } else { //not valid UTF8. Convert it.
- $cc1 = (chr(ord($c1) / 64) | "\xc0");
- $cc2 = ($c1 & "\x3f") | "\x80";
- $buf .= $cc1 . $cc2;
- }
- } else { //doesn't look like UTF8, but should be converted
- $cc1 = (chr(ord($c1) / 64) | "\xc0");
- $cc2 = (($c1 & "\x3f") | "\x80");
- $buf .= $cc1 . $cc2;
- }
- } elseif(($c1 & "\xc0") == "\x80"){ // needs conversion
- if(isset(self::$win1252ToUtf8[ord($c1)])) { //found in Windows-1252 special cases
- $buf .= self::$win1252ToUtf8[ord($c1)];
- } else {
- $cc1 = (chr(ord($c1) / 64) | "\xc0");
- $cc2 = (($c1 & "\x3f") | "\x80");
- $buf .= $cc1 . $cc2;
- }
- } else { // it doesn't need conversion
- $buf .= $c1;
- }
- }
- return $buf;
- } else {
+ if(!is_string($text)) {
return $text;
}
+
+ if ( function_exists('mb_strlen') && ((int) ini_get('mbstring.func_overload')) & 2) {
+ $max = mb_strlen($text,'8bit');
+ } else {
+ $max = strlen($text);
+ }
+
+ $buf = "";
+ for($i = 0; $i < $max; $i++){
+ $c1 = $text{$i};
+ if($c1>="\xc0"){ //Should be converted to UTF8, if it's not UTF8 already
+ $c2 = $i+1 >= $max? "\x00" : $text{$i+1};
+ $c3 = $i+2 >= $max? "\x00" : $text{$i+2};
+ $c4 = $i+3 >= $max? "\x00" : $text{$i+3};
+ if($c1 >= "\xc0" & $c1 <= "\xdf"){ //looks like 2 bytes UTF8
+ if($c2 >= "\x80" && $c2 <= "\xbf"){ //yeah, almost sure it's UTF8 already
+ $buf .= $c1 . $c2;
+ $i++;
+ } else { //not valid UTF8. Convert it.
+ $cc1 = (chr(ord($c1) / 64) | "\xc0");
+ $cc2 = ($c1 & "\x3f") | "\x80";
+ $buf .= $cc1 . $cc2;
+ }
+ } elseif($c1 >= "\xe0" & $c1 <= "\xef"){ //looks like 3 bytes UTF8
+ if($c2 >= "\x80" && $c2 <= "\xbf" && $c3 >= "\x80" && $c3 <= "\xbf"){ //yeah, almost sure it's UTF8 already
+ $buf .= $c1 . $c2 . $c3;
+ $i = $i + 2;
+ } else { //not valid UTF8. Convert it.
+ $cc1 = (chr(ord($c1) / 64) | "\xc0");
+ $cc2 = ($c1 & "\x3f") | "\x80";
+ $buf .= $cc1 . $cc2;
+ }
+ } elseif($c1 >= "\xf0" & $c1 <= "\xf7"){ //looks like 4 bytes UTF8
+ if($c2 >= "\x80" && $c2 <= "\xbf" && $c3 >= "\x80" && $c3 <= "\xbf" && $c4 >= "\x80" && $c4 <= "\xbf"){ //yeah, almost sure it's UTF8 already
+ $buf .= $c1 . $c2 . $c3 . $c4;
+ $i = $i + 3;
+ } else { //not valid UTF8. Convert it.
+ $cc1 = (chr(ord($c1) / 64) | "\xc0");
+ $cc2 = ($c1 & "\x3f") | "\x80";
+ $buf .= $cc1 . $cc2;
+ }
+ } else { //doesn't look like UTF8, but should be converted
+ $cc1 = (chr(ord($c1) / 64) | "\xc0");
+ $cc2 = (($c1 & "\x3f") | "\x80");
+ $buf .= $cc1 . $cc2;
+ }
+ } elseif(($c1 & "\xc0") == "\x80"){ // needs conversion
+ if(isset(self::$win1252ToUtf8[ord($c1)])) { //found in Windows-1252 special cases
+ $buf .= self::$win1252ToUtf8[ord($c1)];
+ } else {
+ $cc1 = (chr(ord($c1) / 64) | "\xc0");
+ $cc2 = (($c1 & "\x3f") | "\x80");
+ $buf .= $cc1 . $cc2;
+ }
+ } else { // it doesn't need conversion
+ $buf .= $c1;
+ }
+ }
+ return $buf;
}
static function toWin1252($text) {
From 9e0b9d11803cbc351a14e28a5bb972c8ce4c6526 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sebasti=C3=A1n=20Grignoli?=
Date: Tue, 2 Dec 2014 15:49:31 -0300
Subject: [PATCH 22/42] Removed unnecessary elseif
---
src/ForceUTF8/Encoding.php | 123 +++++++++++++++++++------------------
1 file changed, 62 insertions(+), 61 deletions(-)
diff --git a/src/ForceUTF8/Encoding.php b/src/ForceUTF8/Encoding.php
index a7686f5..73cf371 100644
--- a/src/ForceUTF8/Encoding.php
+++ b/src/ForceUTF8/Encoding.php
@@ -183,69 +183,70 @@ static function toUTF8($text){
$text[$k] = self::toUTF8($v);
}
return $text;
- } elseif(is_string($text)) {
-
- if ( function_exists('mb_strlen') && ((int) ini_get('mbstring.func_overload')) & 2) {
- $max = mb_strlen($text,'8bit');
- } else {
- $max = strlen($text);
- }
-
- $buf = "";
- for($i = 0; $i < $max; $i++){
- $c1 = $text{$i};
- if($c1>="\xc0"){ //Should be converted to UTF8, if it's not UTF8 already
- $c2 = $i+1 >= $max? "\x00" : $text{$i+1};
- $c3 = $i+2 >= $max? "\x00" : $text{$i+2};
- $c4 = $i+3 >= $max? "\x00" : $text{$i+3};
- if($c1 >= "\xc0" & $c1 <= "\xdf"){ //looks like 2 bytes UTF8
- if($c2 >= "\x80" && $c2 <= "\xbf"){ //yeah, almost sure it's UTF8 already
- $buf .= $c1 . $c2;
- $i++;
- } else { //not valid UTF8. Convert it.
- $cc1 = (chr(ord($c1) / 64) | "\xc0");
- $cc2 = ($c1 & "\x3f") | "\x80";
- $buf .= $cc1 . $cc2;
- }
- } elseif($c1 >= "\xe0" & $c1 <= "\xef"){ //looks like 3 bytes UTF8
- if($c2 >= "\x80" && $c2 <= "\xbf" && $c3 >= "\x80" && $c3 <= "\xbf"){ //yeah, almost sure it's UTF8 already
- $buf .= $c1 . $c2 . $c3;
- $i = $i + 2;
- } else { //not valid UTF8. Convert it.
- $cc1 = (chr(ord($c1) / 64) | "\xc0");
- $cc2 = ($c1 & "\x3f") | "\x80";
- $buf .= $cc1 . $cc2;
- }
- } elseif($c1 >= "\xf0" & $c1 <= "\xf7"){ //looks like 4 bytes UTF8
- if($c2 >= "\x80" && $c2 <= "\xbf" && $c3 >= "\x80" && $c3 <= "\xbf" && $c4 >= "\x80" && $c4 <= "\xbf"){ //yeah, almost sure it's UTF8 already
- $buf .= $c1 . $c2 . $c3 . $c4;
- $i = $i + 3;
- } else { //not valid UTF8. Convert it.
- $cc1 = (chr(ord($c1) / 64) | "\xc0");
- $cc2 = ($c1 & "\x3f") | "\x80";
- $buf .= $cc1 . $cc2;
- }
- } else { //doesn't look like UTF8, but should be converted
- $cc1 = (chr(ord($c1) / 64) | "\xc0");
- $cc2 = (($c1 & "\x3f") | "\x80");
- $buf .= $cc1 . $cc2;
- }
- } elseif(($c1 & "\xc0") == "\x80"){ // needs conversion
- if(isset(self::$win1252ToUtf8[ord($c1)])) { //found in Windows-1252 special cases
- $buf .= self::$win1252ToUtf8[ord($c1)];
- } else {
- $cc1 = (chr(ord($c1) / 64) | "\xc0");
- $cc2 = (($c1 & "\x3f") | "\x80");
- $buf .= $cc1 . $cc2;
- }
- } else { // it doesn't need conversion
- $buf .= $c1;
- }
- }
- return $buf;
- } else {
+ }
+
+ if(!is_string($text)) {
return $text;
}
+
+ if ( function_exists('mb_strlen') && ((int) ini_get('mbstring.func_overload')) & 2) {
+ $max = mb_strlen($text,'8bit');
+ } else {
+ $max = strlen($text);
+ }
+
+ $buf = "";
+ for($i = 0; $i < $max; $i++){
+ $c1 = $text{$i};
+ if($c1>="\xc0"){ //Should be converted to UTF8, if it's not UTF8 already
+ $c2 = $i+1 >= $max? "\x00" : $text{$i+1};
+ $c3 = $i+2 >= $max? "\x00" : $text{$i+2};
+ $c4 = $i+3 >= $max? "\x00" : $text{$i+3};
+ if($c1 >= "\xc0" & $c1 <= "\xdf"){ //looks like 2 bytes UTF8
+ if($c2 >= "\x80" && $c2 <= "\xbf"){ //yeah, almost sure it's UTF8 already
+ $buf .= $c1 . $c2;
+ $i++;
+ } else { //not valid UTF8. Convert it.
+ $cc1 = (chr(ord($c1) / 64) | "\xc0");
+ $cc2 = ($c1 & "\x3f") | "\x80";
+ $buf .= $cc1 . $cc2;
+ }
+ } elseif($c1 >= "\xe0" & $c1 <= "\xef"){ //looks like 3 bytes UTF8
+ if($c2 >= "\x80" && $c2 <= "\xbf" && $c3 >= "\x80" && $c3 <= "\xbf"){ //yeah, almost sure it's UTF8 already
+ $buf .= $c1 . $c2 . $c3;
+ $i = $i + 2;
+ } else { //not valid UTF8. Convert it.
+ $cc1 = (chr(ord($c1) / 64) | "\xc0");
+ $cc2 = ($c1 & "\x3f") | "\x80";
+ $buf .= $cc1 . $cc2;
+ }
+ } elseif($c1 >= "\xf0" & $c1 <= "\xf7"){ //looks like 4 bytes UTF8
+ if($c2 >= "\x80" && $c2 <= "\xbf" && $c3 >= "\x80" && $c3 <= "\xbf" && $c4 >= "\x80" && $c4 <= "\xbf"){ //yeah, almost sure it's UTF8 already
+ $buf .= $c1 . $c2 . $c3 . $c4;
+ $i = $i + 3;
+ } else { //not valid UTF8. Convert it.
+ $cc1 = (chr(ord($c1) / 64) | "\xc0");
+ $cc2 = ($c1 & "\x3f") | "\x80";
+ $buf .= $cc1 . $cc2;
+ }
+ } else { //doesn't look like UTF8, but should be converted
+ $cc1 = (chr(ord($c1) / 64) | "\xc0");
+ $cc2 = (($c1 & "\x3f") | "\x80");
+ $buf .= $cc1 . $cc2;
+ }
+ } elseif(($c1 & "\xc0") == "\x80"){ // needs conversion
+ if(isset(self::$win1252ToUtf8[ord($c1)])) { //found in Windows-1252 special cases
+ $buf .= self::$win1252ToUtf8[ord($c1)];
+ } else {
+ $cc1 = (chr(ord($c1) / 64) | "\xc0");
+ $cc2 = (($c1 & "\x3f") | "\x80");
+ $buf .= $cc1 . $cc2;
+ }
+ } else { // it doesn't need conversion
+ $buf .= $c1;
+ }
+ }
+ return $buf;
}
static function toWin1252($text, $option = self::WITHOUT_ICONV) {
From 4a41012e37c206d633e5176865dbf2c32e8aa4fd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sebasti=C3=A1n=20Grignoli?=
Date: Tue, 2 Dec 2014 15:53:55 -0300
Subject: [PATCH 23/42] A little refactoring
---
src/ForceUTF8/Encoding.php | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/src/ForceUTF8/Encoding.php b/src/ForceUTF8/Encoding.php
index e63bdcc..2b27e2d 100644
--- a/src/ForceUTF8/Encoding.php
+++ b/src/ForceUTF8/Encoding.php
@@ -185,11 +185,7 @@ static function toUTF8($text){
return $text;
}
- if ( function_exists('mb_strlen') && ((int) ini_get('mbstring.func_overload')) & 2) {
- $max = mb_strlen($text,'8bit');
- } else {
- $max = strlen($text);
- }
+ $max = self::strlen($text);
$buf = "";
for($i = 0; $i < $max; $i++){
@@ -297,7 +293,12 @@ static function removeBOM($str=""){
}
return $str;
}
-
+
+ static function strlen($text){
+ return (function_exists('mb_strlen') && ((int) ini_get('mbstring.func_overload')) & 2) ?
+ mb_strlen($text,'8bit') : strlen($text);
+ }
+
public static function normalizeEncoding($encodingLabel)
{
$encoding = strtoupper($encodingLabel);
From 6b59b30e67a5201162bfe99fe5ddfebf844845dc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sebasti=C3=A1n=20Grignoli?=
Date: Tue, 2 Dec 2014 16:01:15 -0300
Subject: [PATCH 24/42] Changes on README
---
README.md | 18 +++++++++++-------
test/ForceUTF8Test.php | 2 +-
2 files changed, 12 insertions(+), 8 deletions(-)
diff --git a/README.md b/README.md
index d081dc2..5ac5047 100644
--- a/README.md
+++ b/README.md
@@ -21,20 +21,24 @@ I've included another function, \ForceUTF8\Encoding::fixUTF8(), which will fix t
Usage:
======
- $utf8_string = \ForceUTF8\Encoding::toUTF8($utf8_or_latin1_or_mixed_string);
+ use \ForceUTF8\Encoding;
- $latin1_string = \ForceUTF8\Encoding::toLatin1($utf8_or_latin1_or_mixed_string);
+ $utf8_string = Encoding::toUTF8($utf8_or_latin1_or_mixed_string);
+
+ $latin1_string = Encoding::toLatin1($utf8_or_latin1_or_mixed_string);
also:
- $utf8_string = \ForceUTF8\Encoding::fixUTF8($garbled_utf8_string);
+ $utf8_string = Encoding::fixUTF8($garbled_utf8_string);
Examples:
- echo \ForceUTF8\Encoding::fixUTF8("Fédération Camerounaise de Football\n");
- echo \ForceUTF8\Encoding::fixUTF8("Fédération Camerounaise de Football\n");
- echo \ForceUTF8\Encoding::fixUTF8("Fédération Camerounaise de Football\n");
- echo \ForceUTF8\Encoding::fixUTF8("Fédération Camerounaise de Football\n");
+ use \ForceUTF8\Encoding;
+
+ echo Encoding::fixUTF8("Fédération Camerounaise de Football\n");
+ echo Encoding::fixUTF8("Fédération Camerounaise de Football\n");
+ echo Encoding::fixUTF8("Fédération Camerounaise de Football\n");
+ echo Encoding::fixUTF8("Fédération Camerounaise de Football\n");
will output:
diff --git a/test/ForceUTF8Test.php b/test/ForceUTF8Test.php
index 9ebebae..2aa1543 100644
--- a/test/ForceUTF8Test.php
+++ b/test/ForceUTF8Test.php
@@ -2,7 +2,7 @@
require_once(dirname(__FILE__)."/Test.class.php");
require_once(dirname(dirname(__FILE__))."/src/ForceUTF8/Encoding.php");
-use ForceUTF8\Encoding;
+use \ForceUTF8\Encoding;
// Test the testing class itself.
Test::is("'yes' is true", 'yes', true);
From 1283466e2412ac4595c13cc78e2ca944899825a1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sebasti=C3=A1n=20Grignoli?=
Date: Tue, 2 Dec 2014 16:10:23 -0300
Subject: [PATCH 25/42] Some more tests
---
test/ForceUTF8Test.php | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/test/ForceUTF8Test.php b/test/ForceUTF8Test.php
index 2aa1543..a1a9bd9 100644
--- a/test/ForceUTF8Test.php
+++ b/test/ForceUTF8Test.php
@@ -85,4 +85,17 @@ function test_double_encoded_arrays_fix(){
Test::true("Source arrays are different (fixUTF8).", test_double_encoded_arrays_are_different());
Test::true("Fixing of double encoded array works.", test_double_encoded_arrays_fix());
+Test::identical("fixUTF8() Example 1 still working.",
+ Encoding::fixUTF8("Fédération Camerounaise de Football\n"),
+ "Fédération Camerounaise de Football\n");
+Test::identical("fixUTF8() Example 2 still working.",
+ Encoding::fixUTF8("Fédération Camerounaise de Football\n"),
+ "Fédération Camerounaise de Football\n");
+Test::identical("fixUTF8() Example 3 still working.",
+ Encoding::fixUTF8("Fédération Camerounaise de Football\n"),
+ "Fédération Camerounaise de Football\n");
+Test::identical("fixUTF8() Example 4 still working.",
+ Encoding::fixUTF8("Fédération Camerounaise de Football\n"),
+ "Fédération Camerounaise de Football\n");
+
Test::totals();
From 1b577b9430cb7bd20d8dd7435f36120b85880ace Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sebasti=C3=A1n=20Grignoli?=
Date: Fri, 2 Jan 2015 10:36:36 -0300
Subject: [PATCH 26/42] Fix in composer.json
---
composer.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/composer.json b/composer.json
index 7924dfa..aff71af 100644
--- a/composer.json
+++ b/composer.json
@@ -4,7 +4,7 @@
"type": "library",
"description": "PHP Class Encoding featuring popular Encoding::toUTF8() function --formerly known as forceUTF8()-- that fixes mixed encoded strings.",
"require": {
- "php": ">=5.2.0"
+ "php": ">=5.3.0"
},
"authors": [
{
From ee5e51661d94d8df7614ac096ffd1b03816f1aff Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sebasti=C3=A1n=20Grignoli?=
Date: Thu, 8 Jan 2015 11:26:56 -0300
Subject: [PATCH 27/42] Missing return statement
---
src/ForceUTF8/Encoding.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/ForceUTF8/Encoding.php b/src/ForceUTF8/Encoding.php
index 1827928..3b9a593 100644
--- a/src/ForceUTF8/Encoding.php
+++ b/src/ForceUTF8/Encoding.php
@@ -329,8 +329,8 @@ public static function normalizeEncoding($encodingLabel)
public static function encode($encodingLabel, $text)
{
$encodingLabel = self::normalizeEncoding($encodingLabel);
- if($encodingLabel == 'UTF-8') return Encoding::toUTF8($text);
if($encodingLabel == 'ISO-8859-1') return Encoding::toLatin1($text);
+ return Encoding::toUTF8($text);
}
protected static function utf8_decode($text, $option)
From 0fb6983af43fae715eff1bb0f3653fbabd984f15 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sebasti=C3=A1n=20Grignoli?=
Date: Tue, 10 Feb 2015 18:22:33 -0300
Subject: [PATCH 28/42] Minor adjustments
---
test/ForceUTF8Test.php | 42 +++++++++++++++++++++---------------------
test/Test.class.php | 13 ++++++-------
test/data/russian.txt | 1 +
3 files changed, 28 insertions(+), 28 deletions(-)
create mode 100644 test/data/russian.txt
diff --git a/test/ForceUTF8Test.php b/test/ForceUTF8Test.php
index a1a9bd9..02ec687 100644
--- a/test/ForceUTF8Test.php
+++ b/test/ForceUTF8Test.php
@@ -1,4 +1,4 @@
-
Date: Thu, 7 May 2015 15:47:36 +0200
Subject: [PATCH 29/42] changed calling from concrete class name to self
---
src/ForceUTF8/Encoding.php | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/ForceUTF8/Encoding.php b/src/ForceUTF8/Encoding.php
index 3b9a593..6530576 100644
--- a/src/ForceUTF8/Encoding.php
+++ b/src/ForceUTF8/Encoding.php
@@ -329,8 +329,8 @@ public static function normalizeEncoding($encodingLabel)
public static function encode($encodingLabel, $text)
{
$encodingLabel = self::normalizeEncoding($encodingLabel);
- if($encodingLabel == 'ISO-8859-1') return Encoding::toLatin1($text);
- return Encoding::toUTF8($text);
+ if($encodingLabel == 'ISO-8859-1') return self::toLatin1($text);
+ return self::toUTF8($text);
}
protected static function utf8_decode($text, $option)
From bd2ac454cf5af3d967b7105ab83321a34b88c421 Mon Sep 17 00:00:00 2001
From: Jeremy Benoist
Date: Tue, 16 Feb 2016 16:11:06 +0100
Subject: [PATCH 30/42] Add License to composer
composer validate --strict
> No license specified, it is recommended to do so.
---
composer.json | 1 +
1 file changed, 1 insertion(+)
diff --git a/composer.json b/composer.json
index aff71af..3584731 100644
--- a/composer.json
+++ b/composer.json
@@ -1,6 +1,7 @@
{
"name": "neitanod/forceutf8",
"homepage": "https://github.com/neitanod/forceutf8",
+ "license": "BSD-3-Clause",
"type": "library",
"description": "PHP Class Encoding featuring popular Encoding::toUTF8() function --formerly known as forceUTF8()-- that fixes mixed encoded strings.",
"require": {
From 47c883ab2739e7938a8bb0bfd1c29d48c88858de Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sebasti=C3=A1n=20Grignoli?=
Date: Mon, 22 May 2017 15:50:57 -0300
Subject: [PATCH 31/42] Update README.md
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index d2131c3..765c637 100644
--- a/README.md
+++ b/README.md
@@ -54,7 +54,7 @@ Edit your composer.json file to include the following:
```json
{
"require": {
- "neitanod/forceutf8": "dev-master"
+ "neitanod/forceutf8": "~2.0"
}
}
```
From 0e8f0e5f55091c182e93ef6987726f19a0c4bb84 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sebasti=C3=A1n=20Grignoli?=
Date: Thu, 21 Sep 2017 17:48:18 -0300
Subject: [PATCH 32/42] Tip jar
---
README.md | 4 ++++
resources/wallet.jpg | Bin 0 -> 77210 bytes
2 files changed, 4 insertions(+)
create mode 100644 resources/wallet.jpg
diff --git a/README.md b/README.md
index 765c637..faf5700 100644
--- a/README.md
+++ b/README.md
@@ -59,3 +59,7 @@ Edit your composer.json file to include the following:
}
```
+Tips:
+=====
+You can tip me with Bitcoin if you want. :)
+
diff --git a/resources/wallet.jpg b/resources/wallet.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..fc2e849d863f7286a07acce31519946b983fd0cc
GIT binary patch
literal 77210
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