diff --git a/.appveyor.yml b/.appveyor.yml
new file mode 100644
index 00000000..3aa23717
--- /dev/null
+++ b/.appveyor.yml
@@ -0,0 +1,62 @@
+build: false
+platform:
+ - x64
+clone_folder: C:\projects\filesystem
+
+branches:
+ except:
+ - gh-pages
+
+## Build matrix for lowest and highest possible targets
+environment:
+ PHPBuild: "x64"
+ VC: "vc15"
+ WINCACHE: "2.0.0.8"
+ matrix:
+ - php_ver_target: 5.3.10
+ - php_ver_target: 5.3.29
+ - php_ver_target: 5.4.45
+ - php_ver_target: 7.0.33
+ - php_ver_target: 7.1.33
+ - php_ver_target: 7.2.34
+ - php_ver_target: 7.3.33
+ - php_ver_target: 7.4.27
+ - php_ver_target: 8.0.15
+ - php_ver_target: 8.1.2
+
+init:
+ - SET PATH=C:\Program Files\OpenSSL;C:\tools\php;%PATH%
+ - SET COMPOSER_NO_INTERACTION=1
+ - SET PHP=1 # This var relates to caching the php install
+ - SET ANSICON=121x90 (121x90)
+
+## Install PHP and composer, and run the appropriate composer command
+install:
+ - IF EXIST C:\tools\php (SET PHP=0)
+ - ps: >-
+ If ($env:PHP -eq "1") {
+ appveyor-retry cinst php --version=$env:php_ver_target --package-parameters='""/InstallDir:C:\tools\php""' --ignore-checksums -y --no-progress --limit-output
+ }
+ - cd C:\tools\php
+ - IF %PHP%==1 copy php.ini-production php.ini /Y
+ - IF %PHP%==1 echo date.timezone="UTC" >> php.ini
+ - IF %PHP%==1 echo extension_dir=ext >> php.ini
+ - IF %PHP%==1 echo extension=php_openssl.dll >> php.ini
+ - IF %PHP%==1 echo extension=php_mbstring.dll >> php.ini
+ - IF %PHP%==1 echo extension=php_fileinfo.dll >> php.ini
+ - IF %PHP%==1 echo extension=php_ftp.dll >> php.ini
+ - IF %PHP%==1 echo extension=php_gd2.dll >> php.ini
+ - IF %PHP%==1 echo extension=php_gmp.dll >> php.ini
+ - IF %PHP%==1 echo extension=php_pgsql.dll >> php.ini
+ - IF %PHP%==1 echo extension=php_curl.dll >> php.ini
+ - IF %PHP%==1 echo zend_extension=php_opcache.dll >> php.ini
+ - IF %PHP%==1 echo opcache.enable_cli=1 >> php.ini
+ - IF %PHP%==1 echo @php %%~dp0composer.phar %%* > composer.bat
+ - IF %PHP%==1 php -r "readfile('http://getcomposer.org/installer');" | php
+ - cd C:\projects\filesystem
+ - IF NOT %php_ver_target%=="8.0.0" composer update --prefer-stable --no-progress
+ - IF %php_ver_target%=="8.0.0" composer update --prefer-stable --no-progress --ignore-platform-req=php
+
+test_script:
+ - cd C:\projects\filesystem
+ - vendor\bin\phpunit
diff --git a/.drone.jsonnet b/.drone.jsonnet
index 849dac07..7a122183 100644
--- a/.drone.jsonnet
+++ b/.drone.jsonnet
@@ -18,7 +18,6 @@ local composer(phpversion, params) = {
volumes: volumes,
commands: [
"php -v",
- "composer --version",
"composer update " + params,
]
};
@@ -26,7 +25,6 @@ local composer(phpversion, params) = {
local phpunit(phpversion) = {
name: "PHPUnit",
image: "joomlaprojects/docker-images:php" + phpversion,
- [if phpversion == "8.0" then "failure"]: "ignore",
commands: ["vendor/bin/phpunit"]
};
@@ -52,17 +50,27 @@ local pipeline(name, phpversion, params) = {
volumes: volumes,
commands: [
"php -v",
- "composer update",
+ "composer update --prefer-stable",
"composer require phpmd/phpmd phpstan/phpstan"
]
},
{
- name: "phpcs",
+ name: "phpcs (loose)",
image: "joomlaprojects/docker-images:php7.4",
depends: [ "composer" ],
commands: [
"vendor/bin/phpcs --config-set installed_paths vendor/joomla/coding-standards",
- "vendor/bin/phpcs -p --report=full --extensions=php --standard=ruleset.xml src/"
+ "vendor/bin/phpcs -p --report=full --extensions=php --standard=ruleset.xml src/Inflector.php src/Normalise.php src/String.php src/StringHelper.php"
+ ]
+ },
+ {
+ name: "phpcs (strict)",
+ image: "joomlaprojects/docker-images:php7.4",
+ depends: [ "composer" ],
+ failure: "ignore",
+ commands: [
+ "vendor/bin/phpcs --config-set installed_paths vendor/joomla/coding-standards",
+ "vendor/bin/phpcs -p --report=full --extensions=php --standard=Joomla src/Inflector.php src/Normalise.php src/String.php src/StringHelper.php"
]
},
{
@@ -126,13 +134,12 @@ local pipeline(name, phpversion, params) = {
]
},
pipeline("5.3", "5.3", "--prefer-stable"),
- pipeline("5.4", "5.4", "--prefer-stable"),
- pipeline("5.5", "5.5", "--prefer-stable"),
pipeline("5.6", "5.6", "--prefer-stable"),
pipeline("7.0", "7.0", "--prefer-stable"),
pipeline("7.1", "7.1", "--prefer-stable"),
pipeline("7.2", "7.2", "--prefer-stable"),
pipeline("7.3", "7.3", "--prefer-stable"),
pipeline("7.4", "7.4", "--prefer-stable"),
- pipeline("8.0", "8.0", "--ignore-platform-reqs --prefer-stable")
+ pipeline("8.0", "8.0", "--prefer-stable"),
+ pipeline("8.1", "8.1", "--prefer-stable")
]
diff --git a/.drone.yml b/.drone.yml
index 0a0c59c6..6075525f 100644
--- a/.drone.yml
+++ b/.drone.yml
@@ -11,17 +11,24 @@ steps:
image: joomlaprojects/docker-images:php7.4
commands:
- php -v
- - composer update
+ - composer update --prefer-stable
- composer require phpmd/phpmd phpstan/phpstan
volumes:
- name: composer-cache
path: /tmp/composer-cache
-- name: phpcs
+- name: phpcs (loose)
+ image: joomlaprojects/docker-images:php7.4
+ commands:
+ - vendor/bin/phpcs --config-set installed_paths vendor/joomla/coding-standards
+ - vendor/bin/phpcs -p --report=full --extensions=php --standard=ruleset.xml src/Inflector.php src/Normalise.php src/String.php src/StringHelper.php
+
+- name: phpcs (strict)
image: joomlaprojects/docker-images:php7.4
commands:
- vendor/bin/phpcs --config-set installed_paths vendor/joomla/coding-standards
- - vendor/bin/phpcs -p --report=full --extensions=php --standard=ruleset.xml src/
+ - vendor/bin/phpcs -p --report=full --extensions=php --standard=Joomla src/Inflector.php src/Normalise.php src/String.php src/StringHelper.php
+ failure: ignore
- name: phpmd
image: joomlaprojects/docker-images:php7.4
@@ -98,7 +105,6 @@ steps:
image: joomlaprojects/docker-images:php5.3
commands:
- php -v
- - composer --version
- composer update --prefer-stable
volumes:
- name: composer-cache
@@ -116,7 +122,7 @@ volumes:
---
kind: pipeline
-name: PHP 5.4
+name: PHP 5.6
platform:
os: linux
@@ -124,17 +130,16 @@ platform:
steps:
- name: composer
- image: joomlaprojects/docker-images:php5.4
+ image: joomlaprojects/docker-images:php5.6
commands:
- php -v
- - composer --version
- composer update --prefer-stable
volumes:
- name: composer-cache
path: /tmp/composer-cache
- name: PHPUnit
- image: joomlaprojects/docker-images:php5.4
+ image: joomlaprojects/docker-images:php5.6
commands:
- vendor/bin/phpunit
@@ -145,7 +150,7 @@ volumes:
---
kind: pipeline
-name: PHP 5.5
+name: PHP 7.0
platform:
os: linux
@@ -153,17 +158,16 @@ platform:
steps:
- name: composer
- image: joomlaprojects/docker-images:php5.5
+ image: joomlaprojects/docker-images:php7.0
commands:
- php -v
- - composer --version
- composer update --prefer-stable
volumes:
- name: composer-cache
path: /tmp/composer-cache
- name: PHPUnit
- image: joomlaprojects/docker-images:php5.5
+ image: joomlaprojects/docker-images:php7.0
commands:
- vendor/bin/phpunit
@@ -174,7 +178,7 @@ volumes:
---
kind: pipeline
-name: PHP 5.6
+name: PHP 7.1
platform:
os: linux
@@ -182,17 +186,16 @@ platform:
steps:
- name: composer
- image: joomlaprojects/docker-images:php5.6
+ image: joomlaprojects/docker-images:php7.1
commands:
- php -v
- - composer --version
- composer update --prefer-stable
volumes:
- name: composer-cache
path: /tmp/composer-cache
- name: PHPUnit
- image: joomlaprojects/docker-images:php5.6
+ image: joomlaprojects/docker-images:php7.1
commands:
- vendor/bin/phpunit
@@ -203,7 +206,7 @@ volumes:
---
kind: pipeline
-name: PHP 7.0
+name: PHP 7.2
platform:
os: linux
@@ -211,17 +214,16 @@ platform:
steps:
- name: composer
- image: joomlaprojects/docker-images:php7.0
+ image: joomlaprojects/docker-images:php7.2
commands:
- php -v
- - composer --version
- composer update --prefer-stable
volumes:
- name: composer-cache
path: /tmp/composer-cache
- name: PHPUnit
- image: joomlaprojects/docker-images:php7.0
+ image: joomlaprojects/docker-images:php7.2
commands:
- vendor/bin/phpunit
@@ -232,7 +234,7 @@ volumes:
---
kind: pipeline
-name: PHP 7.1
+name: PHP 7.3
platform:
os: linux
@@ -240,17 +242,16 @@ platform:
steps:
- name: composer
- image: joomlaprojects/docker-images:php7.1
+ image: joomlaprojects/docker-images:php7.3
commands:
- php -v
- - composer --version
- composer update --prefer-stable
volumes:
- name: composer-cache
path: /tmp/composer-cache
- name: PHPUnit
- image: joomlaprojects/docker-images:php7.1
+ image: joomlaprojects/docker-images:php7.3
commands:
- vendor/bin/phpunit
@@ -261,7 +262,7 @@ volumes:
---
kind: pipeline
-name: PHP 7.2
+name: PHP 7.4
platform:
os: linux
@@ -269,17 +270,16 @@ platform:
steps:
- name: composer
- image: joomlaprojects/docker-images:php7.2
+ image: joomlaprojects/docker-images:php7.4
commands:
- php -v
- - composer --version
- composer update --prefer-stable
volumes:
- name: composer-cache
path: /tmp/composer-cache
- name: PHPUnit
- image: joomlaprojects/docker-images:php7.2
+ image: joomlaprojects/docker-images:php7.4
commands:
- vendor/bin/phpunit
@@ -290,7 +290,7 @@ volumes:
---
kind: pipeline
-name: PHP 7.3
+name: PHP 8.0
platform:
os: linux
@@ -298,17 +298,16 @@ platform:
steps:
- name: composer
- image: joomlaprojects/docker-images:php7.3
+ image: joomlaprojects/docker-images:php8.0
commands:
- php -v
- - composer --version
- composer update --prefer-stable
volumes:
- name: composer-cache
path: /tmp/composer-cache
- name: PHPUnit
- image: joomlaprojects/docker-images:php7.3
+ image: joomlaprojects/docker-images:php8.0
commands:
- vendor/bin/phpunit
@@ -319,7 +318,7 @@ volumes:
---
kind: pipeline
-name: PHP 7.4
+name: PHP 8.1
platform:
os: linux
@@ -327,49 +326,18 @@ platform:
steps:
- name: composer
- image: joomlaprojects/docker-images:php7.4
+ image: joomlaprojects/docker-images:php8.1
commands:
- php -v
- - composer --version
- composer update --prefer-stable
volumes:
- name: composer-cache
path: /tmp/composer-cache
- name: PHPUnit
- image: joomlaprojects/docker-images:php7.4
- commands:
- - vendor/bin/phpunit
-
-volumes:
-- name: composer-cache
- host:
- path: /tmp/composer-cache
-
----
-kind: pipeline
-name: PHP 8.0
-
-platform:
- os: linux
- arch: amd64
-
-steps:
-- name: composer
- image: joomlaprojects/docker-images:php8.0
- commands:
- - php -v
- - composer --version
- - composer update --ignore-platform-reqs --prefer-stable
- volumes:
- - name: composer-cache
- path: /tmp/composer-cache
-
-- name: PHPUnit
- image: joomlaprojects/docker-images:php8.0
+ image: joomlaprojects/docker-images:php8.1
commands:
- vendor/bin/phpunit
- failure: ignore
volumes:
- name: composer-cache
@@ -378,6 +346,6 @@ volumes:
---
kind: signature
-hmac: b33ff1875a669dbf7ce59daaab139a1c7c46ecb03f9e03790046649bf39c44f5
+hmac: 4ea7263b0fb1627bb70e35ea29bd159eba3ac029b0ba18e7d3567f818457988b
...
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 00000000..965065e3
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,9 @@
+# EditorConfig is awesome: https://EditorConfig.org
+
+# Unix-style newlines with a newline ending every file
+[*]
+indent_style=tab
+end_of_line=lf
+charset=utf-8
+trim_trailing_whitespace=true
+insert_final_newline=true
diff --git a/.gitattributes b/.gitattributes
index bfb8d891..54dbb6e8 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,5 +1,12 @@
+.github/ export-ignore
+docs/ export-ignore
+Tests/ export-ignore
+tests/ export-ignore
+.appveyor.yml export-ignore
+.drone.jsonnet export-ignore
+.drone.yml export-ignore
+.editorconfig export-ignore
.gitattributes export-ignore
.gitignore export-ignore
-.gitmodules export-ignore
-.travis/ export-ignore
-.travis.yml export-ignore
+phpunit.xml.dist export-ignore
+ruleset.xml export-ignore
diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md
index 368ba80a..e026a0cc 100644
--- a/.github/CONTRIBUTING.md
+++ b/.github/CONTRIBUTING.md
@@ -1,3 +1,3 @@
# Contributing to the Joomla! Framework
-Please review [http://framework.joomla.org/contribute](http://framework.joomla.org/contribute) for information on how to contribute to the Framework's development.
+Please review [https://framework.joomla.org/contribute](https://framework.joomla.org/contribute) for information on how to contribute to the Framework's development.
diff --git a/.gitignore b/.gitignore
index f432fce7..76367ee5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,4 @@
vendor/
-composer.phar
composer.lock
phpunit.xml
-.idea/
+.phpunit.result.cache
diff --git a/.mono b/.mono
new file mode 100644
index 00000000..da8b9b84
--- /dev/null
+++ b/.mono
@@ -0,0 +1 @@
+src="src/Inflector.php src/Normalise.php src/String.php src/StringHelper.php"
diff --git a/Tests/InflectorTest.php b/Tests/php53/InflectorTest.php
similarity index 99%
rename from Tests/InflectorTest.php
rename to Tests/php53/InflectorTest.php
index 89850852..16f597f6 100644
--- a/Tests/InflectorTest.php
+++ b/Tests/php53/InflectorTest.php
@@ -4,7 +4,7 @@
* @license GNU General Public License version 2 or later; see LICENSE
*/
-namespace Joomla\String\Tests;
+namespace Joomla\String\Tests\php53;
use Joomla\String\Inflector;
use Joomla\Test\TestHelper;
diff --git a/Tests/NormaliseTest.php b/Tests/php53/NormaliseTest.php
similarity index 99%
rename from Tests/NormaliseTest.php
rename to Tests/php53/NormaliseTest.php
index 19aa51ef..940e6be9 100644
--- a/Tests/NormaliseTest.php
+++ b/Tests/php53/NormaliseTest.php
@@ -4,7 +4,7 @@
* @license GNU General Public License version 2 or later; see LICENSE
*/
-namespace Joomla\String\Tests;
+namespace Joomla\String\Tests\php53;
use Joomla\String\Normalise;
use PHPUnit\Framework\TestCase;
diff --git a/Tests/StringHelperTest.php b/Tests/php53/StringHelperTest.php
similarity index 99%
rename from Tests/StringHelperTest.php
rename to Tests/php53/StringHelperTest.php
index c5e1300a..5aead739 100644
--- a/Tests/StringHelperTest.php
+++ b/Tests/php53/StringHelperTest.php
@@ -4,7 +4,7 @@
* @license GNU General Public License version 2 or later; see LICENSE
*/
-namespace Joomla\String\Tests;
+namespace Joomla\String\Tests\php53;
use Joomla\String\StringHelper;
use PHPUnit\Framework\TestCase;
diff --git a/Tests/php71/InflectorTest.php b/Tests/php71/InflectorTest.php
new file mode 100644
index 00000000..d4f420f9
--- /dev/null
+++ b/Tests/php71/InflectorTest.php
@@ -0,0 +1,576 @@
+inflector = Inflector::getInstance(true);
+ }
+
+ /**
+ * Method to test Inflector::addRule().
+ *
+ * @return void
+ *
+ * @covers Joomla\String\Inflector::addRule
+ * @since 1.0
+ */
+ public function testAddRule()
+ {
+ // Case 1
+ TestHelper::invoke($this->inflector, 'addRule', '/foo/', 'singular');
+
+ $rules = TestHelper::getValue($this->inflector, 'rules');
+
+ $this->assertContains(
+ '/foo/',
+ $rules['singular'],
+ 'Checks if the singular rule was added correctly.'
+ );
+
+ // Case 2
+ TestHelper::invoke($this->inflector, 'addRule', '/bar/', 'plural');
+
+ $rules = TestHelper::getValue($this->inflector, 'rules');
+
+ $this->assertContains(
+ '/bar/',
+ $rules['plural'],
+ 'Checks if the plural rule was added correctly.'
+ );
+
+ // Case 3
+ TestHelper::invoke($this->inflector, 'addRule', array('/goo/', '/car/'), 'singular');
+
+ $rules = TestHelper::getValue($this->inflector, 'rules');
+
+ $this->assertContains(
+ '/goo/',
+ $rules['singular'],
+ 'Checks if an array of rules was added correctly (1).'
+ );
+
+ $this->assertContains(
+ '/car/',
+ $rules['singular'],
+ 'Checks if an array of rules was added correctly (2).'
+ );
+ }
+
+ /**
+ * Method to test Inflector::addRule().
+ *
+ * @return void
+ *
+ * @covers Joomla\String\Inflector::addRule
+ *
+ * @since 1.0
+ */
+ public function testAddRuleException()
+ {
+ $this->expectException(\InvalidArgumentException::class);
+ TestHelper::invoke($this->inflector, 'addRule', new \stdClass, 'singular');
+ }
+
+ /**
+ * Method to test Inflector::getCachedPlural().
+ *
+ * @return void
+ *
+ * @covers Joomla\String\Inflector::getCachedPlural
+ * @since 1.0
+ */
+ public function testGetCachedPlural()
+ {
+ // Reset the cache.
+ TestHelper::setValue($this->inflector, 'cache', array('foo' => 'bar'));
+
+ $this->assertFalse(
+ TestHelper::invoke($this->inflector, 'getCachedPlural', 'bar'),
+ 'Checks for an uncached plural.'
+ );
+
+ $this->assertEquals(
+ 'bar',
+ TestHelper::invoke($this->inflector, 'getCachedPlural', 'foo'),
+ 'Checks for a cached plural word.'
+ );
+ }
+
+ /**
+ * Method to test Inflector::getCachedSingular().
+ *
+ * @return void
+ *
+ * @covers Joomla\String\Inflector::getCachedSingular
+ * @since 1.0
+ */
+ public function testGetCachedSingular()
+ {
+ // Reset the cache.
+ TestHelper::setValue($this->inflector, 'cache', array('foo' => 'bar'));
+
+ $this->assertFalse(
+ TestHelper::invoke($this->inflector, 'getCachedSingular', 'foo'),
+ 'Checks for an uncached singular.'
+ );
+
+ $this->assertThat(
+ TestHelper::invoke($this->inflector, 'getCachedSingular', 'bar'),
+ $this->equalTo('foo'),
+ 'Checks for a cached singular word.'
+ );
+ }
+
+ /**
+ * Method to test Inflector::matchRegexRule().
+ *
+ * @return void
+ *
+ * @covers Joomla\String\Inflector::matchRegexRule
+ * @since 1.0
+ */
+ public function testMatchRegexRule()
+ {
+ $this->assertThat(
+ TestHelper::invoke($this->inflector, 'matchRegexRule', 'xyz', 'plural'),
+ $this->equalTo('xyzs'),
+ 'Checks pluralising against the basic regex.'
+ );
+
+ $this->assertThat(
+ TestHelper::invoke($this->inflector, 'matchRegexRule', 'xyzs', 'singular'),
+ $this->equalTo('xyz'),
+ 'Checks singularising against the basic regex.'
+ );
+
+ $this->assertFalse(
+ TestHelper::invoke($this->inflector, 'matchRegexRule', 'xyz', 'singular'),
+ 'Checks singularising against an unmatched regex.'
+ );
+ }
+
+ /**
+ * Method to test Inflector::setCache().
+ *
+ * @return void
+ *
+ * @covers Joomla\String\Inflector::setCache
+ * @since 1.0
+ */
+ public function testSetCache()
+ {
+ TestHelper::invoke($this->inflector, 'setCache', 'foo', 'bar');
+
+ $cache = TestHelper::getValue($this->inflector, 'cache');
+
+ $this->assertThat(
+ $cache['foo'],
+ $this->equalTo('bar'),
+ 'Checks the cache was set.'
+ );
+
+ TestHelper::invoke($this->inflector, 'setCache', 'foo', 'car');
+
+ $cache = TestHelper::getValue($this->inflector, 'cache');
+
+ $this->assertThat(
+ $cache['foo'],
+ $this->equalTo('car'),
+ 'Checks an existing value in the cache was reset.'
+ );
+ }
+
+ /**
+ * Method to test Inflector::addCountableRule().
+ *
+ * @return void
+ *
+ * @covers Joomla\String\Inflector::addCountableRule
+ * @since 1.0
+ */
+ public function testAddCountableRule()
+ {
+ // Add string.
+ $this->inflector->addCountableRule('foo');
+
+ $rules = TestHelper::getValue($this->inflector, 'rules');
+
+ $this->assertContains(
+ 'foo',
+ $rules['countable'],
+ 'Checks a countable rule was added.'
+ );
+
+ // Add array.
+ $this->inflector->addCountableRule(array('goo', 'car'));
+
+ $rules = TestHelper::getValue($this->inflector, 'rules');
+
+ $this->assertContains(
+ 'car',
+ $rules['countable'],
+ 'Checks a countable rule was added by array.'
+ );
+ }
+
+ /**
+ * Method to test Inflector::addWord().
+ *
+ * @return void
+ *
+ * @covers Joomla\String\Inflector::addWord
+ * @since 1.2.0
+ */
+ public function testAddWord()
+ {
+ $this->assertEquals(
+ $this->inflector,
+ $this->inflector->addWord('foo')
+ );
+
+ $cache = TestHelper::getValue($this->inflector, 'cache');
+
+ $this->assertArrayHasKey('foo', $cache);
+
+ $this->assertEquals(
+ 'foo',
+ $cache['foo']
+ );
+
+ $this->assertEquals(
+ $this->inflector,
+ $this->inflector->addWord('bar', 'foo')
+ );
+
+ $cache = TestHelper::getValue($this->inflector, 'cache');
+
+ $this->assertArrayHasKey('bar', $cache);
+
+ $this->assertEquals(
+ 'foo',
+ $cache['bar']
+ );
+ }
+
+ /**
+ * Method to test Inflector::addPluraliseRule().
+ *
+ * @return void
+ *
+ * @covers Joomla\String\Inflector::addPluraliseRule
+ * @since 1.0
+ */
+ public function testAddPluraliseRule()
+ {
+ $chain = $this->inflector->addPluraliseRule(array('/foo/', '/bar/'));
+
+ $this->assertThat(
+ $chain,
+ $this->identicalTo($this->inflector),
+ 'Checks chaining.'
+ );
+
+ $rules = TestHelper::getValue($this->inflector, 'rules');
+
+ $this->assertCOntains(
+ '/bar/',
+ $rules['plural'],
+ 'Checks a pluralisation rule was added.'
+ );
+ }
+
+ /**
+ * Method to test Inflector::addSingulariseRule().
+ *
+ * @return void
+ *
+ * @covers Joomla\String\Inflector::addSingulariseRule
+ * @since 1.0
+ */
+ public function testAddSingulariseRule()
+ {
+ $chain = $this->inflector->addSingulariseRule(array('/foo/', '/bar/'));
+
+ $this->assertThat(
+ $chain,
+ $this->identicalTo($this->inflector),
+ 'Checks chaining.'
+ );
+
+ $rules = TestHelper::getValue($this->inflector, 'rules');
+
+ $this->assertContains(
+ '/bar/',
+ $rules['singular'],
+ 'Checks a singularisation rule was added.'
+ );
+ }
+
+ /**
+ * Method to test Inflector::getInstance().
+ *
+ * @return void
+ *
+ * @covers Joomla\String\Inflector::getInstance
+ * @since 1.0
+ */
+ public function testGetInstance()
+ {
+ $this->assertInstanceOf(
+ \Joomla\String\Inflector::class,
+ Inflector::getInstance(),
+ 'Check getInstance returns the right class.'
+ );
+
+ // Inject an instance an test.
+ TestHelper::setValue($this->inflector, 'instance', new \stdClass);
+
+ $this->assertThat(
+ Inflector::getInstance(),
+ $this->equalTo(new \stdClass),
+ 'Checks singleton instance is returned.'
+ );
+
+ $this->assertInstanceOf(
+ \Joomla\String\Inflector::class,
+ Inflector::getInstance(true),
+ 'Check getInstance a fresh object with true argument even though the instance is set to something else.'
+ );
+ }
+
+ /**
+ * Method to test Inflector::isCountable().
+ *
+ * @param string $input A string.
+ * @param boolean $expected The expected result of the function call.
+ *
+ * @return void
+ *
+ * @covers Joomla\String\Inflector::isCountable
+ * @dataProvider seedIsCountable
+ * @since 1.0
+ */
+ public function testIsCountable($input, $expected)
+ {
+ $this->assertThat(
+ $this->inflector->isCountable($input),
+ $this->equalTo($expected)
+ );
+ }
+
+ /**
+ * Method to test Inflector::isPlural().
+ *
+ * @param string $singular The singular form of a word.
+ * @param string $plural The plural form of a word.
+ *
+ * @return void
+ *
+ * @covers Joomla\String\Inflector::isPlural
+ * @dataProvider seedSinglePlural
+ * @since 1.0
+ */
+ public function testIsPlural($singular, $plural)
+ {
+ $this->assertTrue(
+ $this->inflector->isPlural($plural),
+ 'Checks the plural is a plural.'
+ );
+
+ if ($singular != $plural)
+ {
+ $this->assertFalse(
+ $this->inflector->isPlural($singular),
+ 'Checks the singular is not plural.'
+ );
+ }
+ }
+
+ /**
+ * Method to test Inflector::isSingular().
+ *
+ * @param string $singular The singular form of a word.
+ * @param string $plural The plural form of a word.
+ *
+ * @return void
+ *
+ * @covers Joomla\String\Inflector::isSingular
+ * @dataProvider seedSinglePlural
+ * @since 1.0
+ */
+ public function testIsSingular($singular, $plural)
+ {
+ $this->assertTrue(
+ $this->inflector->isSingular($singular),
+ 'Checks the singular is a singular.'
+ );
+
+ if ($singular != $plural)
+ {
+ $this->assertFalse(
+ $this->inflector->isSingular($plural),
+ 'Checks the plural is not singular.'
+ );
+ }
+ }
+
+ /**
+ * Method to test Inflector::toPlural().
+ *
+ * @param string $singular The singular form of a word.
+ * @param string $plural The plural form of a word.
+ *
+ * @return void
+ *
+ * @covers Joomla\String\Inflector::toPlural
+ * @dataProvider seedSinglePlural
+ * @since 1.0
+ */
+ public function testToPlural($singular, $plural)
+ {
+ $this->assertThat(
+ $this->inflector->toPlural($singular),
+ $this->equalTo($plural)
+ );
+ }
+
+ /**
+ * Method to test Inflector::toPlural().
+ *
+ * @return void
+ *
+ * @covers Joomla\String\Inflector::toPlural
+ * @since 1.2.0
+ */
+ public function testToPluralAlreadyPlural()
+ {
+ $this->assertFalse($this->inflector->toPlural('buses'));
+ }
+
+ /**
+ * Method to test Inflector::toPlural().
+ *
+ * @param string $singular The singular form of a word.
+ * @param string $plural The plural form of a word.
+ *
+ * @return void
+ *
+ * @covers Joomla\String\Inflector::toSingular
+ * @dataProvider seedSinglePlural
+ * @since 1.0
+ */
+ public function testToSingular($singular, $plural)
+ {
+ $this->assertThat(
+ $this->inflector->toSingular($plural),
+ $this->equalTo($singular)
+ );
+ }
+
+ /**
+ * Method to test Inflector::toPlural().
+ *
+ * @return void
+ *
+ * @covers Joomla\String\Inflector::toSingular
+ * @since 1.2.0
+ */
+ public function testToSingularRetFalse()
+ {
+ // Assertion for already singular
+ $this->assertFalse($this->inflector->toSingular('bus'));
+
+ $this->assertFalse($this->inflector->toSingular('foo'));
+ }
+}
diff --git a/Tests/php71/NormaliseTest.php b/Tests/php71/NormaliseTest.php
new file mode 100644
index 00000000..2459b0e9
--- /dev/null
+++ b/Tests/php71/NormaliseTest.php
@@ -0,0 +1,316 @@
+assertEquals($expected, Normalise::fromCamelcase($input));
+ }
+
+ /**
+ * Method to test Normalise::fromCamelCase(string, true).
+ *
+ * @param string $input The input value for the method.
+ * @param string $expected The expected value from the method.
+ *
+ * @return void
+ *
+ * @covers Joomla\String\Normalise::fromCamelcase
+ * @dataProvider seedTestFromCamelCase
+ * @since 1.0
+ */
+ public function testFromCamelCase_grouped($input, $expected)
+ {
+ $this->assertEquals($expected, Normalise::fromCamelcase($input, true));
+ }
+
+ /**
+ * Method to test Normalise::toCamelCase().
+ *
+ * @param string $expected The expected value from the method.
+ * @param string $input The input value for the method.
+ *
+ * @return void
+ *
+ * @covers Joomla\String\Normalise::toCamelcase
+ * @dataProvider seedTestToCamelCase
+ * @since 1.0
+ */
+ public function testToCamelCase($expected, $input)
+ {
+ $this->assertEquals($expected, Normalise::toCamelcase($input));
+ }
+
+ /**
+ * Method to test Normalise::toDashSeparated().
+ *
+ * @param string $expected The expected value from the method.
+ * @param string $input The input value for the method.
+ *
+ * @return void
+ *
+ * @covers Joomla\String\Normalise::toDashSeparated
+ * @dataProvider seedTestToDashSeparated
+ * @since 1.0
+ */
+ public function testToDashSeparated($expected, $input)
+ {
+ $this->assertEquals($expected, Normalise::toDashSeparated($input));
+ }
+
+ /**
+ * Method to test Normalise::toSpaceSeparated().
+ *
+ * @param string $expected The expected value from the method.
+ * @param string $input The input value for the method.
+ *
+ * @return void
+ *
+ * @covers Joomla\String\Normalise::toSpaceSeparated
+ * @dataProvider seedTestToSpaceSeparated
+ * @since 1.0
+ */
+ public function testToSpaceSeparated($expected, $input)
+ {
+ $this->assertEquals($expected, Normalise::toSpaceSeparated($input));
+ }
+
+ /**
+ * Method to test Normalise::toUnderscoreSeparated().
+ *
+ * @param string $expected The expected value from the method.
+ * @param string $input The input value for the method.
+ *
+ * @return void
+ *
+ * @covers Joomla\String\Normalise::toUnderscoreSeparated
+ * @dataProvider seedTestToUnderscoreSeparated
+ * @since 1.0
+ */
+ public function testToUnderscoreSeparated($expected, $input)
+ {
+ $this->assertEquals($expected, Normalise::toUnderscoreSeparated($input));
+ }
+
+ /**
+ * Method to test Normalise::toVariable().
+ *
+ * @param string $expected The expected value from the method.
+ * @param string $input The input value for the method.
+ *
+ * @return void
+ *
+ * @covers Joomla\String\Normalise::toVariable
+ * @dataProvider seedTestToVariable
+ * @since 1.0
+ */
+ public function testToVariable($expected, $input)
+ {
+ $this->assertEquals($expected, Normalise::toVariable($input));
+ }
+
+ /**
+ * Method to test Normalise::toKey().
+ *
+ * @param string $expected The expected value from the method.
+ * @param string $input The input value for the method.
+ *
+ * @return void
+ *
+ * @covers Joomla\String\Normalise::toKey
+ * @dataProvider seedTestToKey
+ * @since 1.0
+ */
+ public function testToKey($expected, $input)
+ {
+ $this->assertEquals($expected, Normalise::toKey($input));
+ }
+}
diff --git a/Tests/php71/StringHelperTest.php b/Tests/php71/StringHelperTest.php
new file mode 100644
index 00000000..ccff8d2c
--- /dev/null
+++ b/Tests/php71/StringHelperTest.php
@@ -0,0 +1,1090 @@
+ array('title', null, 0, 'title (2)'),
+ 'Second default increment' => array('title(2)', null, 0, 'title(3)'),
+ 'First dash increment' => array('title', 'dash', 0, 'title-2'),
+ 'Second dash increment' => array('title-2', 'dash', 0, 'title-3'),
+ 'Set default increment' => array('title', null, 4, 'title (4)'),
+ 'Unknown style fallback to default' => array('title', 'foo', 0, 'title (2)'),
+ );
+ }
+
+ /**
+ * Test...
+ *
+ * @return array
+ *
+ * @since 1.2.0
+ */
+ public function seedTestIs_ascii()
+ {
+ return array(
+ array('ascii', true),
+ array('1024', true),
+ array('#$#@$%', true),
+ array('áÑ', false),
+ array('ÿ©', false),
+ array('¡¾', false),
+ array('÷™', false),
+ );
+ }
+
+ /**
+ * Test...
+ *
+ * @return array
+ *
+ * @since 1.0
+ */
+ public function seedTestStrpos()
+ {
+ return array(
+ array(3, 'missing', 'sing', 0),
+ array(false, 'missing', 'sting', 0),
+ array(4, 'missing', 'ing', 0),
+ array(10, ' объектов на карте с', 'на карте', 0),
+ array(0, 'на карте с', 'на карте', 0, 0),
+ array(false, 'на карте с', 'на каррте', 0),
+ array(false, 'на карте с', 'на карте', 2),
+ array(3, 'missing', 'sing', false)
+ );
+ }
+
+ /**
+ * Test...
+ *
+ * @return array
+ *
+ * @since 1.0
+ */
+ public function seedTestGetStrrpos()
+ {
+ return array(
+ array(3, 'missing', 'sing', 0),
+ array(false, 'missing', 'sting', 0),
+ array(4, 'missing', 'ing', 0),
+ array(10, ' объектов на карте с', 'на карте', 0),
+ array(0, 'на карте с', 'на карте', 0),
+ array(false, 'на карте с', 'на каррте', 0),
+ array(3, 'на карте с', 'карт', 2)
+ );
+ }
+
+ /**
+ * Test...
+ *
+ * @return array
+ *
+ * @since 1.0
+ */
+ public function seedTestSubstr()
+ {
+ return array(
+ array('issauga', 'Mississauga', 4, false),
+ array('на карте с', ' объектов на карте с', 10, false),
+ array('на ка', ' объектов на карте с', 10, 5),
+ array('те с', ' объектов на карте с', -4, false),
+ array(false, ' объектов на карте с', 99, false)
+ );
+ }
+
+ /**
+ * Test...
+ *
+ * @return array
+ *
+ * @since 1.0
+ */
+ public function seedTestStrtolower()
+ {
+ return array(
+ array('Joomla! Rocks', 'joomla! rocks')
+ );
+ }
+
+ /**
+ * Test...
+ *
+ * @return array
+ *
+ * @since 1.0
+ */
+ public function seedTestStrtoupper()
+ {
+ return array(
+ array('Joomla! Rocks', 'JOOMLA! ROCKS')
+ );
+ }
+
+ /**
+ * Test...
+ *
+ * @return array
+ *
+ * @since 1.0
+ */
+ public function seedTestStrlen()
+ {
+ return array(
+ array('Joomla! Rocks', 13)
+ );
+ }
+
+ /**
+ * Test...
+ *
+ * @return array
+ *
+ * @since 1.0
+ */
+ public function seedTestStr_ireplace()
+ {
+ return array(
+ array('Pig', 'cow', 'the pig jumped', false, 'the cow jumped'),
+ array('Pig', 'cow', 'the pig jumped', true, 'the cow jumped'),
+ array('Pig', 'cow', 'the pig jumped over the cow', true, 'the cow jumped over the cow'),
+ array(array('PIG', 'JUMPED'), array('cow', 'hopped'), 'the pig jumped over the pig', true, 'the cow hopped over the cow'),
+ array('шил', 'биш', 'Би шил идэй чадна', true, 'Би биш идэй чадна'),
+ array('/', ':', '/test/slashes/', true, ':test:slashes:'),
+ );
+ }
+
+ /**
+ * Test...
+ *
+ * @return array
+ *
+ * @since 1.0
+ */
+ public function seedTestStr_split()
+ {
+ return array(
+ array('string', 1, array('s', 't', 'r', 'i', 'n', 'g')),
+ array('string', 2, array('st', 'ri', 'ng')),
+ array('волн', 3, array('вол', 'н')),
+ array('волн', 1, array('в', 'о', 'л', 'н'))
+ );
+ }
+
+ /**
+ * Test...
+ *
+ * @return array
+ *
+ * @since 1.0
+ */
+ public function seedTestStrcasecmp()
+ {
+ return array(
+ array('THIS IS STRING1', 'this is string1', false, 0),
+ array('this is string1', 'this is string2', false, -1),
+ array('this is string2', 'this is string1', false, 1),
+ array('бгдпт', 'бгдпт', false, 0),
+ array('àbc', 'abc', array('fr_FR.utf8', 'fr_FR.UTF-8', 'fr_FR.UTF-8@euro', 'French_Standard', 'french', 'fr_FR', 'fre_FR'), 1),
+ array('àbc', 'bcd', array('fr_FR.utf8', 'fr_FR.UTF-8', 'fr_FR.UTF-8@euro', 'French_Standard', 'french', 'fr_FR', 'fre_FR'), -1),
+ array('é', 'è', array('fr_FR.utf8', 'fr_FR.UTF-8', 'fr_FR.UTF-8@euro', 'French_Standard', 'french', 'fr_FR', 'fre_FR'), -1),
+ array('É', 'é', array('fr_FR.utf8', 'fr_FR.UTF-8', 'fr_FR.UTF-8@euro', 'French_Standard', 'french', 'fr_FR', 'fre_FR'), 0),
+ array('œ', 'p', array('fr_FR.utf8', 'fr_FR.UTF-8', 'fr_FR.UTF-8@euro', 'French_Standard', 'french', 'fr_FR', 'fre_FR'), -1),
+ array('œ', 'n', array('fr_FR.utf8', 'fr_FR.UTF-8', 'fr_FR.UTF-8@euro', 'French_Standard', 'french', 'fr_FR', 'fre_FR'), 1),
+ );
+ }
+
+ /**
+ * Test...
+ *
+ * @return array
+ *
+ * @since 1.0
+ */
+ public function seedTestStrcmp()
+ {
+ return array(
+ array('THIS IS STRING1', 'this is string1', false, -1),
+ array('this is string1', 'this is string2', false, -1),
+ array('this is string2', 'this is string1', false, 1),
+ array('a', 'B', false, 1),
+ array('A', 'b', false, -1),
+ array('Àbc', 'abc', array('fr_FR.utf8', 'fr_FR.UTF-8', 'fr_FR.UTF-8@euro', 'French_Standard', 'french', 'fr_FR', 'fre_FR'), 1),
+ array('Àbc', 'bcd', array('fr_FR.utf8', 'fr_FR.UTF-8', 'fr_FR.UTF-8@euro', 'French_Standard', 'french', 'fr_FR', 'fre_FR'), -1),
+ array('É', 'è', array('fr_FR.utf8', 'fr_FR.UTF-8', 'fr_FR.UTF-8@euro', 'French_Standard', 'french', 'fr_FR', 'fre_FR'), -1),
+ array('é', 'È', array('fr_FR.utf8', 'fr_FR.UTF-8', 'fr_FR.UTF-8@euro', 'French_Standard', 'french', 'fr_FR', 'fre_FR'), -1),
+ array('Œ', 'p', array('fr_FR.utf8', 'fr_FR.UTF-8', 'fr_FR.UTF-8@euro', 'French_Standard', 'french', 'fr_FR', 'fre_FR'), -1),
+ array('Œ', 'n', array('fr_FR.utf8', 'fr_FR.UTF-8', 'fr_FR.UTF-8@euro', 'French_Standard', 'french', 'fr_FR', 'fre_FR'), 1),
+ array('œ', 'N', array('fr_FR.utf8', 'fr_FR.UTF-8', 'fr_FR.UTF-8@euro', 'French_Standard', 'french', 'fr_FR', 'fre_FR'), 1),
+ array('œ', 'P', array('fr_FR.utf8', 'fr_FR.UTF-8', 'fr_FR.UTF-8@euro', 'French_Standard', 'french', 'fr_FR', 'fre_FR'), -1),
+ );
+ }
+
+ /**
+ * Test...
+ *
+ * @return array
+ *
+ * @since 1.0
+ */
+ public function seedTestStrcspn()
+ {
+ return array(
+ array('subject string ', '<>', false, false, 8),
+ array('Би шил {123} идэй {456} чадна', '}{', null, false, 7),
+ array('Би шил {123} идэй {456} чадна', '}{', 13, 10, 5)
+ );
+ }
+
+ /**
+ * Test...
+ *
+ * @return array
+ *
+ * @since 1.0
+ */
+ public function seedTestStristr()
+ {
+ return array(
+ array('haystack', 'needle', false),
+ array('before match, after match', 'match', 'match, after match'),
+ array('Би шил идэй чадна', 'шил', 'шил идэй чадна')
+ );
+ }
+
+ /**
+ * Test...
+ *
+ * @return array
+ *
+ * @since 1.0
+ */
+ public function seedTestStrrev()
+ {
+ return array(
+ array('abc def', 'fed cba'),
+ array('Би шил', 'лиш иБ')
+ );
+ }
+
+ /**
+ * Test...
+ *
+ * @return array
+ *
+ * @since 1.0
+ */
+ public function seedTestStrspn()
+ {
+ return array(
+ array('A321 Main Street', '0123456789', 1, 2, 2),
+ array('321 Main Street', '0123456789', null, 2, 2),
+ array('A321 Main Street', '0123456789', null, 10, 0),
+ array('321 Main Street', '0123456789', null, null, 3),
+ array('Main Street 321', '0123456789', null, -3, 0),
+ array('321 Main Street', '0123456789', null, -13, 2),
+ array('321 Main Street', '0123456789', null, -12, 3),
+ array('A321 Main Street', '0123456789', 0, null, 0),
+ array('A321 Main Street', '0123456789', 1, 10, 3),
+ array('A321 Main Street', '0123456789', 1, null, 3),
+ array('Би шил идэй чадна', 'Би', null, null, 2),
+ array('чадна Би шил идэй чадна', 'Би', null, null, 0)
+ );
+ }
+
+ /**
+ * Test...
+ *
+ * @return array
+ *
+ * @since 1.0
+ */
+ public function seedTestSubstr_replace()
+ {
+ return array(
+ array('321 Broadway Avenue', '321 Main Street', 'Broadway Avenue', 4, false),
+ array('321 Broadway Street', '321 Main Street', 'Broadway', 4, 4),
+ array('чадна 我能吞', 'чадна Би шил идэй чадна', '我能吞', 6, false),
+ array('чадна 我能吞 шил идэй чадна', 'чадна Би шил идэй чадна', '我能吞', 6, 2)
+ );
+ }
+
+ /**
+ * Test...
+ *
+ * @return array
+ *
+ * @since 1.0
+ */
+ public function seedTestLtrim()
+ {
+ return array(
+ array(' abc def', null, 'abc def'),
+ array(' abc def', '', ' abc def'),
+ array(' Би шил', null, 'Би шил'),
+ array("\t\n\r\x0BБи шил", null, 'Би шил'),
+ array("\x0B\t\n\rБи шил", "\t\n\x0B", "\rБи шил"),
+ array("\x09Би шил\x0A", "\x09\x0A", "Би шил\x0A"),
+ array('1234abc', '0123456789', 'abc')
+ );
+ }
+
+ /**
+ * Test...
+ *
+ * @return array
+ *
+ * @since 1.0
+ */
+ public function seedTestRtrim()
+ {
+ return array(
+ array('abc def ', null, 'abc def'),
+ array('abc def ', '', 'abc def '),
+ array('Би шил ', null, 'Би шил'),
+ array("Би шил\t\n\r\x0B", null, 'Би шил'),
+ array("Би шил\r\x0B\t\n", "\t\n\x0B", "Би шил\r"),
+ array("\x09Би шил\x0A", "\x09\x0A", "\x09Би шил"),
+ array('1234abc', 'abc', '1234')
+ );
+ }
+
+ /**
+ * Test...
+ *
+ * @return array
+ *
+ * @since 1.0
+ */
+ public function seedTestTrim()
+ {
+ return array(
+ array(' abc def ', null, 'abc def'),
+ array(' abc def ', '', ' abc def '),
+ array(' Би шил ', null, 'Би шил'),
+ array("\t\n\r\x0BБи шил\t\n\r\x0B", null, 'Би шил'),
+ array("\x0B\t\n\rБи шил\r\x0B\t\n", "\t\n\x0B", "\rБи шил\r"),
+ array("\x09Би шил\x0A", "\x09\x0A", "Би шил"),
+ array('1234abc56789', '0123456789', 'abc')
+ );
+ }
+
+ /**
+ * Test...
+ *
+ * @return array
+ *
+ * @since 1.0
+ */
+ public function seedTestUcfirst()
+ {
+ return array(
+ array('george', null, null, 'George'),
+ array('мога', null, null, 'Мога'),
+ array('ψυχοφθόρα', null, null, 'Ψυχοφθόρα'),
+ array('dr jekill and mister hyde', ' ', null, 'Dr Jekill And Mister Hyde'),
+ array('dr jekill and mister hyde', ' ', '_', 'Dr_Jekill_And_Mister_Hyde'),
+ array('dr jekill and mister hyde', ' ', '', 'DrJekillAndMisterHyde'),
+ );
+ }
+
+ /**
+ * Test...
+ *
+ * @return array
+ *
+ * @since 1.0
+ */
+ public function seedTestUcwords()
+ {
+ return array(
+ array('george washington', 'George Washington'),
+ array("george\r\nwashington", "George\r\nWashington"),
+ array('мога', 'Мога'),
+ array('αβγ δεζ', 'Αβγ Δεζ'),
+ array('åbc öde', 'Åbc Öde')
+ );
+ }
+
+ /**
+ * Test...
+ *
+ * @return array
+ *
+ * @since 1.0
+ */
+ public function seedTestTranscode()
+ {
+ return array(
+ array('Åbc Öde €100', 'UTF-8', 'ISO-8859-1', "\xc5bc \xd6de EUR100"),
+ array(array('Åbc Öde €100'), 'UTF-8', 'ISO-8859-1', null),
+ );
+ }
+
+ /**
+ * Test...
+ *
+ * @return array
+ *
+ * @since 1.0
+ */
+ public function seedTestValid()
+ {
+ return array(
+ array("\xCF\xB0", true),
+ array("\xFBa", false),
+ array("\xFDa", false),
+ array("foo\xF7bar", false),
+ array('george Мога Ž Ψυχοφθόρα ฉันกินกระจกได้ 我能吞下玻璃而不伤身体 ', true),
+ array("\xFF ABC", false),
+ array("0xfffd ABC", true),
+ array('', true)
+ );
+ }
+
+ /**
+ * Test...
+ *
+ * @return array
+ *
+ * @since 1.2.0
+ */
+ public function seedTestUnicodeToUtf8()
+ {
+ return array(
+ array("\u0422\u0435\u0441\u0442 \u0441\u0438\u0441\u0442\u0435\u043c\u044b", "Тест системы"),
+ array("\u00dcberpr\u00fcfung der Systemumstellung", "Überprüfung der Systemumstellung")
+ );
+ }
+
+ /**
+ * Test...
+ *
+ * @return array
+ *
+ * @since 1.2.0
+ */
+ public function seedTestUnicodeToUtf16()
+ {
+ return array(
+ array("\u0422\u0435\u0441\u0442 \u0441\u0438\u0441\u0442\u0435\u043c\u044b", "Тест системы"),
+ array("\u00dcberpr\u00fcfung der Systemumstellung", "Überprüfung der Systemumstellung")
+ );
+ }
+
+ /**
+ * Test...
+ *
+ * @param string $string @todo
+ * @param string $style @todo
+ * @param string $number @todo
+ * @param string $expected @todo
+ *
+ * @return void
+ *
+ * @covers Joomla\String\StringHelper::increment
+ * @dataProvider seedTestIncrement
+ * @since 1.0
+ */
+ public function testIncrement($string, $style, $number, $expected)
+ {
+ $this->assertEquals(
+ $expected,
+ StringHelper::increment($string, $style, $number)
+ );
+ }
+
+ /**
+ * Test...
+ *
+ * @param string $string @todo
+ * @param boolean $expected @todo
+ *
+ * @return void
+ *
+ * @covers Joomla\String\StringHelper::is_ascii
+ * @dataProvider seedTestIs_ascii
+ * @since 1.2.0
+ */
+ public function testIs_ascii($string, $expected)
+ {
+ $this->assertEquals(
+ $expected,
+ StringHelper::is_ascii($string)
+ );
+ }
+
+ /**
+ * Test...
+ *
+ * @param string $expect @todo
+ * @param string $haystack @todo
+ * @param string $needle @todo
+ * @param integer $offset @todo
+ *
+ * @return void
+ *
+ * @covers Joomla\String\StringHelper::strpos
+ * @dataProvider seedTestStrpos
+ * @since 1.0
+ */
+ public function testStrpos($expect, $haystack, $needle, $offset = 0)
+ {
+ $actual = StringHelper::strpos($haystack, $needle, $offset);
+ $this->assertEquals($expect, $actual);
+ }
+
+ /**
+ * Test...
+ *
+ * @param string $expect @todo
+ * @param string $haystack @todo
+ * @param string $needle @todo
+ * @param integer $offset @todo
+ *
+ * @return array
+ *
+ * @covers Joomla\String\StringHelper::strrpos
+ * @dataProvider seedTestGetStrrpos
+ * @since 1.0
+ */
+ public function testStrrpos($expect, $haystack, $needle, $offset = 0)
+ {
+ $actual = StringHelper::strrpos($haystack, $needle, $offset);
+ $this->assertEquals($expect, $actual);
+ }
+
+ /**
+ * Test...
+ *
+ * @param string $expect @todo
+ * @param string $string @todo
+ * @param string $start @todo
+ * @param bool|int $length @todo
+ *
+ * @return array
+ *
+ * @covers Joomla\String\StringHelper::substr
+ * @dataProvider seedTestSubstr
+ * @since 1.0
+ */
+ public function testSubstr($expect, $string, $start, $length = false)
+ {
+ $actual = StringHelper::substr($string, $start, $length);
+ $this->assertEquals($expect, $actual);
+ }
+
+ /**
+ * Test...
+ *
+ * @param string $string @todo
+ * @param string $expect @todo
+ *
+ * @return array
+ *
+ * @covers Joomla\String\StringHelper::strtolower
+ * @dataProvider seedTestStrtolower
+ * @since 1.0
+ */
+ public function testStrtolower($string, $expect)
+ {
+ $actual = StringHelper::strtolower($string);
+ $this->assertEquals($expect, $actual);
+ }
+
+ /**
+ * Test...
+ *
+ * @param string $string @todo
+ * @param string $expect @todo
+ *
+ * @return array
+ *
+ * @covers Joomla\String\StringHelper::strtoupper
+ * @dataProvider seedTestStrtoupper
+ * @since 1.0
+ */
+ public function testStrtoupper($string, $expect)
+ {
+ $actual = StringHelper::strtoupper($string);
+ $this->assertEquals($expect, $actual);
+ }
+
+ /**
+ * Test...
+ *
+ * @param string $string @todo
+ * @param string $expect @todo
+ *
+ * @return array
+ *
+ * @covers Joomla\String\StringHelper::strlen
+ * @dataProvider seedTestStrlen
+ * @since 1.0
+ */
+ public function testStrlen($string, $expect)
+ {
+ $actual = StringHelper::strlen($string);
+ $this->assertEquals($expect, $actual);
+ }
+
+ /**
+ * Test...
+ *
+ * @param string $search @todo
+ * @param string $replace @todo
+ * @param string $subject @todo
+ * @param integer $count @todo
+ * @param string $expect @todo
+ *
+ * @return array
+ *
+ * @covers Joomla\String\StringHelper::str_ireplace
+ * @dataProvider seedTestStr_ireplace
+ * @since 1.0
+ */
+ public function testStr_ireplace($search, $replace, $subject, $count, $expect)
+ {
+ $actual = StringHelper::str_ireplace($search, $replace, $subject, $count);
+ $this->assertEquals($expect, $actual);
+ }
+
+ /**
+ * Test...
+ *
+ * @param string $string @todo
+ * @param string $split_length @todo
+ * @param string $expect @todo
+ *
+ * @return array
+ *
+ * @covers Joomla\String\StringHelper::str_split
+ * @dataProvider seedTestStr_split
+ * @since 1.0
+ */
+ public function testStr_split($string, $split_length, $expect)
+ {
+ $actual = StringHelper::str_split($string, $split_length);
+ $this->assertEquals($expect, $actual);
+ }
+
+ /**
+ * Test...
+ *
+ * @param string $string1 @todo
+ * @param string $string2 @todo
+ * @param string $locale @todo
+ * @param string $expect @todo
+ *
+ * @return array
+ *
+ * @covers Joomla\String\StringHelper::strcasecmp
+ * @dataProvider seedTestStrcasecmp
+ * @since 1.0
+ */
+ public function testStrcasecmp($string1, $string2, $locale, $expect)
+ {
+ // Convert the $locale param to a string if it is an array
+ if (\is_array($locale))
+ {
+ $locale = "'" . implode("', '", $locale) . "'";
+ }
+
+ if (substr(php_uname(), 0, 6) == 'Darwin' && $locale != false)
+ {
+ $this->markTestSkipped('Darwin bug prevents foreign conversion from working properly');
+ }
+ elseif ($locale != false && !setlocale(LC_COLLATE, $locale))
+ {
+ $this->markTestSkipped("Locale {$locale} is not available.");
+ }
+ else
+ {
+ $actual = StringHelper::strcasecmp($string1, $string2, $locale);
+
+ if ($actual != 0)
+ {
+ $actual = $actual / abs($actual);
+ }
+
+ $this->assertEquals($expect, $actual);
+ }
+ }
+
+ /**
+ * Test...
+ *
+ * @param string $string1 @todo
+ * @param string $string2 @todo
+ * @param string $locale @todo
+ * @param string $expect @todo
+ *
+ * @return array
+ *
+ * @covers Joomla\String\StringHelper::strcmp
+ * @dataProvider seedTestStrcmp
+ * @since 1.0
+ */
+ public function testStrcmp($string1, $string2, $locale, $expect)
+ {
+ // Convert the $locale param to a string if it is an array
+ if (\is_array($locale))
+ {
+ $locale = "'" . implode("', '", $locale) . "'";
+ }
+
+ if (substr(php_uname(), 0, 6) == 'Darwin' && $locale != false)
+ {
+ $this->markTestSkipped('Darwin bug prevents foreign conversion from working properly');
+ }
+ elseif ($locale != false && !setlocale(LC_COLLATE, $locale))
+ {
+ // If the locale is not available, we can't have to transcode the string and can't reliably compare it.
+ $this->markTestSkipped("Locale {$locale} is not available.");
+ }
+ else
+ {
+ $actual = StringHelper::strcmp($string1, $string2, $locale);
+
+ if ($actual != 0)
+ {
+ $actual = $actual / abs($actual);
+ }
+
+ $this->assertEquals($expect, $actual);
+ }
+ }
+
+ /**
+ * Test...
+ *
+ * @param string $haystack @todo
+ * @param string $needles @todo
+ * @param integer $start @todo
+ * @param integer $len @todo
+ * @param string $expect @todo
+ *
+ * @return array
+ *
+ * @covers Joomla\String\StringHelper::strcspn
+ * @dataProvider seedTestStrcspn
+ * @since 1.0
+ */
+ public function testStrcspn($haystack, $needles, $start, $len, $expect)
+ {
+ $actual = StringHelper::strcspn($haystack, $needles, $start, $len);
+ $this->assertEquals($expect, $actual);
+ }
+
+ /**
+ * Test...
+ *
+ * @param string $haystack @todo
+ * @param string $needle @todo
+ * @param string $expect @todo
+ *
+ * @return array
+ *
+ * @covers Joomla\String\StringHelper::stristr
+ * @dataProvider seedTestStristr
+ * @since 1.0
+ */
+ public function testStristr($haystack, $needle, $expect)
+ {
+ $actual = StringHelper::stristr($haystack, $needle);
+ $this->assertEquals($expect, $actual);
+ }
+
+ /**
+ * Test...
+ *
+ * @param string $string @todo
+ * @param string $expect @todo
+ *
+ * @return array
+ *
+ * @covers Joomla\String\StringHelper::strrev
+ * @dataProvider seedTestStrrev
+ * @since 1.0
+ */
+ public function testStrrev($string, $expect)
+ {
+ $actual = StringHelper::strrev($string);
+ $this->assertEquals($expect, $actual);
+ }
+
+ /**
+ * Test...
+ *
+ * @param string $subject @todo
+ * @param string $mask @todo
+ * @param integer $start @todo
+ * @param integer $length @todo
+ * @param string $expect @todo
+ *
+ * @return array
+ *
+ * @covers Joomla\String\StringHelper::strspn
+ * @dataProvider seedTestStrspn
+ * @since 1.0
+ */
+ public function testStrspn($subject, $mask, $start, $length, $expect)
+ {
+ $actual = StringHelper::strspn($subject, $mask, $start, $length);
+ $this->assertEquals($expect, $actual);
+ }
+
+ /**
+ * Test...
+ *
+ * @param string $expect @todo
+ * @param string $string @todo
+ * @param string $replacement @todo
+ * @param integer $start @todo
+ * @param integer $length @todo
+ *
+ * @return array
+ *
+ * @covers Joomla\String\StringHelper::substr_replace
+ * @dataProvider seedTestSubstr_replace
+ * @since 1.0
+ */
+ public function testSubstr_replace($expect, $string, $replacement, $start, $length)
+ {
+ $actual = StringHelper::substr_replace($string, $replacement, $start, $length);
+ $this->assertEquals($expect, $actual);
+ }
+
+ /**
+ * Test...
+ *
+ * @param string $string @todo
+ * @param string $charlist @todo
+ * @param string $expect @todo
+ *
+ * @return array
+ *
+ * @covers Joomla\String\StringHelper::ltrim
+ * @dataProvider seedTestLtrim
+ * @since 1.0
+ */
+ public function testLtrim($string, $charlist, $expect)
+ {
+ if ($charlist === null)
+ {
+ $actual = StringHelper::ltrim($string);
+ }
+ else
+ {
+ $actual = StringHelper::ltrim($string, $charlist);
+ }
+
+ $this->assertEquals($expect, $actual);
+ }
+
+ /**
+ * Test...
+ *
+ * @param string $string @todo
+ * @param string $charlist @todo
+ * @param string $expect @todo
+ *
+ * @return array
+ *
+ * @covers Joomla\String\StringHelper::rtrim
+ * @dataProvider seedTestRtrim
+ * @since 1.0
+ */
+ public function testRtrim($string, $charlist, $expect)
+ {
+ if ($charlist === null)
+ {
+ $actual = StringHelper::rtrim($string);
+ }
+ else
+ {
+ $actual = StringHelper::rtrim($string, $charlist);
+ }
+
+ $this->assertEquals($expect, $actual);
+ }
+
+ /**
+ * Test...
+ *
+ * @param string $string @todo
+ * @param string $charlist @todo
+ * @param string $expect @todo
+ *
+ * @return array
+ *
+ * @covers Joomla\String\StringHelper::trim
+ * @dataProvider seedTestTrim
+ * @since 1.0
+ */
+ public function testTrim($string, $charlist, $expect)
+ {
+ if ($charlist === null)
+ {
+ $actual = StringHelper::trim($string);
+ }
+ else
+ {
+ $actual = StringHelper::trim($string, $charlist);
+ }
+
+ $this->assertEquals($expect, $actual);
+ }
+
+ /**
+ * Test...
+ *
+ * @param string $string @todo
+ * @param string $delimiter @todo
+ * @param string $newDelimiter @todo
+ * @param string $expect @todo
+ *
+ * @return array
+ *
+ * @covers Joomla\String\StringHelper::ucfirst
+ * @dataProvider seedTestUcfirst
+ * @since 1.0
+ */
+ public function testUcfirst($string, $delimiter, $newDelimiter, $expect)
+ {
+ $actual = StringHelper::ucfirst($string, $delimiter, $newDelimiter);
+ $this->assertEquals($expect, $actual);
+ }
+
+ /**
+ * Test...
+ *
+ * @param string $string @todo
+ * @param string $expect @todo
+ *
+ * @return array
+ *
+ * @covers Joomla\String\StringHelper::ucwords
+ * @dataProvider seedTestUcwords
+ * @since 1.0
+ */
+ public function testUcwords($string, $expect)
+ {
+ $actual = StringHelper::ucwords($string);
+ $this->assertEquals($expect, $actual);
+ }
+
+ /**
+ * Test...
+ *
+ * @param string $source @todo
+ * @param string $from_encoding @todo
+ * @param string $to_encoding @todo
+ * @param string $expect @todo
+ *
+ * @return array
+ *
+ * @covers Joomla\String\StringHelper::transcode
+ * @dataProvider seedTestTranscode
+ * @since 1.0
+ */
+ public function testTranscode($source, $from_encoding, $to_encoding, $expect)
+ {
+ $actual = StringHelper::transcode($source, $from_encoding, $to_encoding);
+ $this->assertEquals($expect, $actual);
+ }
+
+ /**
+ * Test...
+ *
+ * @param string $string @todo
+ * @param string $expect @todo
+ *
+ * @return array
+ *
+ * @covers Joomla\String\StringHelper::valid
+ * @dataProvider seedTestValid
+ * @since 1.0
+ */
+ public function testValid($string, $expect)
+ {
+ $actual = StringHelper::valid($string);
+ $this->assertEquals($expect, $actual);
+ }
+
+ /**
+ * Test...
+ *
+ * @param string $string @todo
+ * @param string $expect @todo
+ *
+ * @return array
+ *
+ * @covers Joomla\String\StringHelper::unicode_to_utf8
+ * @dataProvider seedTestUnicodeToUtf8
+ * @since 1.2.0
+ */
+ public function testUnicodeToUtf8($string, $expect)
+ {
+ $actual = StringHelper::unicode_to_utf8($string);
+ $this->assertEquals($expect, $actual);
+ }
+
+ /**
+ * Test...
+ *
+ * @param string $string @todo
+ * @param string $expect @todo
+ *
+ * @return array
+ *
+ * @covers Joomla\String\StringHelper::unicode_to_utf16
+ * @dataProvider seedTestUnicodeToUtf16
+ * @since 1.2.0
+ */
+ public function testUnicodeToUtf16($string, $expect)
+ {
+ $actual = StringHelper::unicode_to_utf16($string);
+ $this->assertEquals($expect, $actual);
+ }
+
+ /**
+ * Test...
+ *
+ * @param string $string @todo
+ * @param string $expect @todo
+ *
+ * @return array
+ *
+ * @covers Joomla\String\StringHelper::compliant
+ * @dataProvider seedTestValid
+ * @since 1.0
+ */
+ public function testCompliant($string, $expect)
+ {
+ $actual = StringHelper::compliant($string);
+ $this->assertEquals($expect, $actual);
+ }
+}
diff --git a/composer.json b/composer.json
index b15fe4a4..44df8f12 100644
--- a/composer.json
+++ b/composer.json
@@ -2,16 +2,20 @@
"name": "joomla/string",
"type": "joomla-package",
"description": "Joomla String Package",
- "keywords": ["joomla", "framework", "string"],
+ "keywords": [
+ "joomla",
+ "framework",
+ "string"
+ ],
"homepage": "https://github.com/joomla-framework/string",
"license": "GPL-2.0-or-later",
"require": {
- "php": "^5.3.10|~7.0"
+ "php": "^5.3.10|^7.0|^8.0"
},
"require-dev": {
- "joomla/coding-standards": "~2.0@alpha",
- "joomla/test": "~1.0",
- "phpunit/phpunit": "^4.8.35|^5.4.3|~6.0"
+ "joomla/coding-standards": "^2.0@alpha",
+ "joomla/test": "^1.0",
+ "phpunit/phpunit": "^4.8.35|^5.4.3|^6.0|^7.0|^8.0"
},
"suggest": {
"ext-mbstring": "For improved processing"
@@ -43,6 +47,7 @@
"Joomla\\String\\Tests\\": "Tests/"
}
},
+ "minimum-stability": "dev",
"extra": {
"branch-alias": {
"dev-master": "1.x-dev"
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index f867589b..11468057 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -1,13 +1,25 @@
-
-
- src/phputf8
-
-
- Tests
+ Tests/php53
+ Tests/php71
+
+
+
+
+
+
+
+
+ src
+
+
diff --git a/ruleset.xml b/ruleset.xml
index d9f24b82..626812e3 100644
--- a/ruleset.xml
+++ b/ruleset.xml
@@ -1,21 +1,33 @@
-
-
-
-
-
+
+
+
+
+
-
- */.github/*
+
+ */.github/*
-
- */src/phputf8/*
- */vendor/*
+
+ */vendor/*
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/phputf8/mbstring/core.php b/src/phputf8/mbstring/core.php
index 6cb5501d..997bca67 100644
--- a/src/phputf8/mbstring/core.php
+++ b/src/phputf8/mbstring/core.php
@@ -91,9 +91,9 @@ function utf8_strrpos($str, $search, $offset = FALSE){
*/
function utf8_substr($str, $offset, $length = FALSE){
if ( $length === FALSE ) {
- return mb_substr($str, $offset);
+ return mb_substr($str, (int)$offset);
} else {
- return mb_substr($str, $offset, $length);
+ return mb_substr($str, (int)$offset, (int)$length);
}
}
diff --git a/src/phputf8/utf8.php b/src/phputf8/utf8.php
index af8b4127..e498763f 100644
--- a/src/phputf8/utf8.php
+++ b/src/phputf8/utf8.php
@@ -34,7 +34,7 @@
* Also need to check we have the correct internal mbstring
* encoding
*/
-if ( extension_loaded('mbstring')) {
+if (extension_loaded('mbstring')) {
/*
* Joomla modification - As of PHP 8, the `mbstring.func_overload` configuration has been removed and the
* MB_OVERLOAD_STRING constant will no longer be present, so this check only runs for PHP 7 and older
@@ -42,9 +42,10 @@
* and https://github.com/php/php-src/commit/97df99a6d7d96a886ac143337fecad775907589a
* for additional references
*/
- if ( PHP_VERSION_ID < 80000 && ((int) ini_get('mbstring.func_overload')) & MB_OVERLOAD_STRING ) {
+ if (defined('MB_OVERLOAD_STRING') && ((int) ini_get('mbstring.func_overload')) & MB_OVERLOAD_STRING) {
trigger_error('String functions are overloaded by mbstring',E_USER_ERROR);
}
+
mb_internal_encoding('UTF-8');
}