Repository: jawira/case-converter
Branch: master
Commit: 869a0780f069
Files: 80
Total size: 147.0 KB
Directory structure:
gitextract_86zso1k9/
├── .codeclimate.yml
├── .editorconfig
├── .gitattributes
├── .github/
│ └── workflows/
│ ├── docs.yaml
│ └── qa.yaml
├── .gitignore
├── LICENSE.md
├── README.md
├── build.xml
├── composer.json
├── config/
│ ├── behat.yml
│ └── phpunit.xml
├── docs/
│ ├── api.md
│ ├── case-mapping.md
│ ├── detection-algorithm.md
│ ├── dev.md
│ ├── images/
│ │ ├── build.puml
│ │ ├── detection-algorithm.puml
│ │ ├── number-problem.puml
│ │ ├── railroad.js
│ │ ├── uml-case-converter.puml
│ │ ├── uml-glue.puml
│ │ └── uml-split.puml
│ ├── index.md
│ ├── known-issues.md
│ ├── naming-conventions.md
│ └── using-the-factory.md
├── mkdocs.yml
├── src/
│ ├── CaseConverter.php
│ ├── CaseConverterException.php
│ ├── CaseConverterInterface.php
│ ├── Convert.php
│ ├── Glue/
│ │ ├── AdaCase.php
│ │ ├── CamelCase.php
│ │ ├── CobolCase.php
│ │ ├── DashGluer.php
│ │ ├── DotNotation.php
│ │ ├── Gluer.php
│ │ ├── KebabCase.php
│ │ ├── LowerCase.php
│ │ ├── MacroCase.php
│ │ ├── PascalCase.php
│ │ ├── SentenceCase.php
│ │ ├── SnakeCase.php
│ │ ├── SpaceGluer.php
│ │ ├── TitleCase.php
│ │ ├── TrainCase.php
│ │ ├── UnderscoreGluer.php
│ │ ├── UpperCase.php
│ │ └── UppercaseGluer.php
│ └── Split/
│ ├── DashSplitter.php
│ ├── DotSplitter.php
│ ├── SpaceSplitter.php
│ ├── Splitter.php
│ ├── UnderscoreSplitter.php
│ └── UppercaseSplitter.php
└── tests/
├── behat/
│ ├── bootstrap/
│ │ └── FeatureContext.php
│ └── case-converter.feature
└── phpunit/
├── AdaCaseTest.php
├── CamelCaseTest.php
├── CaseConverterTest.php
├── CobolCaseTest.php
├── ConvertTest.php
├── DashSplitterTest.php
├── DotNotationTest.php
├── DotSplitterTest.php
├── GluerTest.php
├── KebabCaseTest.php
├── LowerCaseTest.php
├── MacroCaseTest.php
├── PascalCaseTest.php
├── SentenceCaseTest.php
├── SnakeCaseTest.php
├── SpaceSplitterTest.php
├── SplitterTest.php
├── TitleCaseTest.php
├── TrainCaseTest.php
├── UnderscoreSplitterTest.php
├── UpperCaseTest.php
└── UppercaseSplitterTest.php
================================================
FILE CONTENTS
================================================
================================================
FILE: .codeclimate.yml
================================================
plugins:
sonar-php:
enabled: true
config:
tests_patterns:
- tests/**
fixme:
enabled: true
================================================
FILE: .editorconfig
================================================
root = true
[*]
charset = utf-8
trim_trailing_whitespace = true
end_of_line = lf
insert_final_newline = true
indent_style = space
ij_visual_guides = 80, 120
[*.php]
indent_size = 4
max_line_length = 120
ij_php_align_multiline_chained_methods = true
ij_php_align_phpdoc_comments = true
ij_php_align_phpdoc_param_names = true
ij_php_align_assignments = true
ij_php_align_multiline_array_initializer_expression = true
ij_php_align_key_value_pairs = true
ij_php_align_match_arm_bodies = true
ij_php_phpdoc_use_fqcn = true
[*.{yml, yaml, neon, xml, svg, json, js}]
indent_size = 2
[*.{md, markdown}]
trim_trailing_whitespace = false
indent_size = 2
max_line_length = 80
ij_markdown_wrap_text_if_long = true
================================================
FILE: .gitattributes
================================================
/.github export-ignore
/.idea export-ignore
/config export-ignore
/docs export-ignore
/resources export-ignore
/tests export-ignore
/.codeclimate.yml export-ignore
/.editorconfig export-ignore
/.gitattributes export-ignore
/.gitignore export-ignore
/build.xml export-ignore
/mkdocs.yml export-ignore
/README.md export-ignore
================================================
FILE: .github/workflows/docs.yaml
================================================
name: Publish documentation
on:
release:
types: [ published ]
jobs:
build:
name: Deploy docs
runs-on: ubuntu-20.04
steps:
- name: Checkout main
uses: actions/checkout@v2
- name: Deploy docs
uses: mhausenblas/mkdocs-deploy-gh-pages@master
env:
SITE_NAME: "Case Converter ${{ github.event.release.tag_name }}"
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
================================================
FILE: .github/workflows/qa.yaml
================================================
name: Quality assurance
on:
pull_request:
push:
branches:
- master
jobs:
tests:
strategy:
matrix:
php: [ '7.4','8.0','8.1','8.2','8.3','8.4' ]
runs-on: ubuntu-24.04
steps:
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
extensions: mbstring, intl
coverage: xdebug
tools: phing:v3
- uses: actions/checkout@v2
- name: Phing setup
run: phing setup
- name: lint php
run: phing php:lint
- name: validate composer
run: phing composer:validate
- name: behat
run: phing behat:run
- name: phpstan
run: phing phpstan:analyse
- name: CC before build
run: phing cc:before-build
env:
CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
- name: PHPUnit
run: phing phpunit:run
- name: CC after build
run: phing cc:after-build
env:
CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
================================================
FILE: .gitignore
================================================
/.idea/
!/.idea/dictionaries/
/resources/coverage/
/resources/phpdoc/
/vendor/
/bin/
/composer-setup.php
/composer.lock
/coverage/codeclimate.json
/resources/phploc.txt
/resources/coverage-html/
/site/
/docs/CONTRIBUTING.md
/docs/LICENSE.md
/docs/license.md
/docs/contributing.md
/docs/changelog.md
/build.png
/build.svg
/config/.phpunit.result.cache
/clover.xml
================================================
FILE: LICENSE.md
================================================
The MIT License (MIT)
=====================
Copyright © 2015-2022 Jawira Portugal
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
================================================
FILE: README.md
================================================
Case converter
==============
Use this library to convert string between:
| Name | Method | Output example |
|-------------------|----------------|-------------------|
| 🐪 Camel case | `toCamel()` | `myNameIsBond` |
| 👨🏫 Pascal case | `toPascal()` | `MyNameIsBond` |
| 🐍 Snake case | `toSnake()` | `my_name_is_bond` |
| 👩🏫 Ada case | `toAda()` | `My_Name_Is_Bond` |
| Ⓜ️ Macro case | `toMacro()` | `MY_NAME_IS_BOND` |
| 🥙 Kebab case | `toKebab()` | `my-name-is-bond` |
| 🚂 Train case | `toTrain()` | `My-Name-Is-Bond` |
| 🏦 Cobol case | `toCobol()` | `MY-NAME-IS-BOND` |
| 🔡 Lower case | `toLower()` | `my name is bond` |
| 🔠 Upper case | `toUpper()` | `MY NAME IS BOND` |
| 📰 Title case | `toTitle()` | `My Name Is Bond` |
| ✍️ Sentence case | `toSentence()` | `My name is bond` |
| ⚙️ Dot notation | `toDot()` | `my.name.is.bond` |
Features:
* 🔁 [automatic case detection][detection algorithm]
* 🏭 [factory][]
* 🌐 [i18n](#i18n)
[](https://packagist.org/packages/jawira/case-converter)
[](https://packagist.org/packages/jawira/case-converter)
[](https://packagist.org/packages/jawira/case-converter)
[](https://packagist.org/packages/jawira/case-converter)
[](https://codeclimate.com/github/jawira/case-converter/maintainability)
[](https://codeclimate.com/github/jawira/case-converter/test_coverage)
Usage
-----
Input string (i.e. _john-connor_) format is going to be
[detected automatically][detection algorithm]. Here's an example:
```php
use Jawira\CaseConverter\Convert;
$hero = new Convert('john-connor');
echo $hero->toCamel(); // output: johnConnor
```
Of course you can explicitly set the format of input string:
```php
echo $hero->fromKebab()->toSnake(); // output: john_connor
```
You can also use the [provided factory][factory] to instantiate `Convert` class.
A list of [all public methods] is also available.
i18n
----
Fully compatible with non-english alphabets:
```php
// Spanish
$esp = new Convert('DON_RAMÓN_Y_ÑOÑO');
echo $esp->toCamel(); // output: donRamónYÑoño
// Greek
$grc = new Convert('πολύ-Καλό');
echo $grc->toCamel(); // output: πολύΚαλό
// Russian
$rus = new Convert('ОЧЕНЬ_ПРИЯТНО');
echo $rus->toCamel(); // output: оченьПриятно
```
`case-converter` is compatible with _Simple Case-Mapping_ and _Full
Case-Mapping_.
[Learn more about Case-Mapping][Case-Mapping].
Installation
------------
```console
composer require jawira/case-converter
```
Documentation
-------------
Contributing
------------
- If you liked this project, ⭐ star it on GitHub.
[](https://github.com/jawira/case-converter)
- Or follow me on X.
[](https://twitter.com/jawira)
License
-------
This library is licensed under the [MIT LICENSE].
[all public methods]: https://jawira.github.io/case-converter/api.html
[CONTRIBUTING.md]: https://jawira.github.io/case-converter/contributing.html
[Countable interface]: https://php.net/manual/en/class.countable.php
[Case-Mapping]: https://jawira.github.io/case-converter/case-mapping.html
[magic method]: https://www.php.net/manual/en/language.oop5.magic.php#object.tostring
[MIT LICENSE]: https://jawira.github.io/case-converter/license.html
[open an issue]: https://github.com/jawira/case-converter/issues/new
[detection algorithm]: https://jawira.github.io/case-converter/detection-algorithm.html
[factory]: https://jawira.github.io/case-converter/using-the-factory.html
[GitHub]: https://github.com/jawira/case-converter/
***
Packages from jawira
--------------------
-
jawira/emoji-catalog
- Get access to +3000 emojis as class constants.
-
jawira/plantuml-client
- Convert PlantUML diagrams into images (svg, png, ...).
-
jawira/doctrine-diagram-bundle
- Symfony Bundle to generate database diagrams.
- more...
================================================
FILE: build.xml
================================================
================================================
FILE: composer.json
================================================
{
"name": "jawira/case-converter",
"type": "library",
"description": "Convert strings between 13 naming conventions: Snake case, Camel case, Pascal case, Kebab case, Ada case, Train case, Cobol case, Macro case, Upper case, Lower case, Sentence case, Title case and Dot notation.",
"keywords": [
"Ada case",
"Camel case",
"Cobol case",
"Dot notation",
"Kebab case",
"Lower case",
"Macro case",
"Pascal case",
"Sentence case",
"Snake case",
"Title case",
"Train case",
"Upper case"
],
"homepage": "https://jawira.github.io/case-converter/",
"license": "MIT",
"authors": [
{
"name": "Jawira Portugal",
"email": "dev@tugal.be"
}
],
"require": {
"php": ">=7.4",
"ext-mbstring": "*"
},
"require-dev": {
"behat/behat": "^3.0",
"phpstan/phpstan": "^v2",
"phpunit/phpunit": "^9.0"
},
"suggest": {
"pds/skeleton": "PHP Package Development Standards",
"phing/phing": "PHP Build Tool"
},
"config": {
"preferred-install": "dist",
"sort-packages": true
},
"autoload": {
"psr-4": {
"Jawira\\CaseConverter\\": "src/"
}
}
}
================================================
FILE: config/behat.yml
================================================
default:
autoload:
'': '%paths.base%/../tests/behat/bootstrap/'
suites:
default:
paths:
- '%paths.base%/../tests/behat/'
contexts:
- FeatureContext
formatters:
pretty: true
================================================
FILE: config/phpunit.xml
================================================
../src
../tests/phpunit
================================================
FILE: docs/api.md
================================================
API
===
List of public methods.
`\Jawira\CaseConverter\Convert`
-------------------------------
### String conversion
| Method | Description |
|----------------|-----------------------------------------|
| `toCamel()` | Return string in _Camel case_ format |
| `toPascal()` | Return string in _Pascal case_ format |
| `toSnake()` | Return string in _Snake case_ format |
| `toAda()` | Return string in _Ada case_ format |
| `toMacro()` | Return string in _Macro case_ format |
| `toKebab()` | Return string in _Kebab case_ format |
| `toTrain()` | Return string in _Train case_ format |
| `toCobol()` | Return string in _Cobol case_ format |
| `toLower()` | Return string in _Lower case_ format |
| `toUpper()` | Return string in _Upper case_ format |
| `toTitle()` | Return string in _Title case_ format |
| `toSentence()` | Return string in _Sentence case_ format |
| `toDot()` | Return string in _Dot notation_ |
### Explicit case detection
| Method | Description |
|------------------|-----------------------------------------------------|
| `fromAuto()` | (default) Auto-detect naming convention |
| `fromCamel()` | Split input string using uppercase characters |
| `fromPascal()` | Split input string using uppercase characters |
| `fromSnake()` | Split input string using `_` (underscore character) |
| `fromAda()` | Split input string using `_` (underscore character) |
| `fromMacro()` | Split input string using `_` (underscore character) |
| `fromKebab()` | Split input string using `-` (dash character) |
| `fromTrain()` | Split input string using `-` (dash character) |
| `fromCobol()` | Split input string using `-` (dash character) |
| `fromLower()` | Split input string using `␣` (space character) |
| `fromUpper()` | Split input string using `␣` (space character) |
| `fromTitle()` | Split input string using `␣` (space character) |
| `fromSentence()` | Split input string using `␣` (space character) |
| `fromDot()` | Split input string using `.` (dot character) |
Please note that some methods are equivalent and have the same effect:
- `fromDot()`
- `fromCamel()` ≈ `fromPascal()`
- `fromSnake()` ≈ `fromAda()` ≈ `fromMacro()`
- `fromKebab()` ≈ `fromTrain()` ≈ `fromCobol()`
- `fromLower()` ≈ `fromUpper()` ≈ `fromTitle()` ≈ `fromSentence()`
All these methods exists only for sake of completeness.
### Utility methods
| Method | Description |
|----------------------------|--------------------------------------------------------------------------------|
| `getSource()` | Returns original input string |
| `toArray()` | Returns array with detected words |
| `forceSimpleCaseMapping()` | Output sting uses [Simple Case-Mapping] even if you are using PHP 7.3 or newer |
`\Jawira\CaseConverter\CaseConverter`
-------------------------------------
### Factory method
| Method | Description |
|-------------|----------------------------|
| `convert()` | Creates a `Convert` object |
[Simple Case-Mapping]: ./case-mapping.md
================================================
FILE: docs/case-mapping.md
================================================
Case-Mapping
============
Introduction
------------
_Case-mapping_ or _case conversion_ is performed everytime a character is
changed from _upper case_ to _lower case_, or from _lower case_ to _upper case_.
_Case converter_ performs _case-mapping_ everytime you use it.
There are two kind of case-mapping:
1. _Simple case-mapping_
2. _Full case-mapping_
_Simple case-mapping_ is one-to-one character mapping, for example a single
character "`A`" is replaced with another single character "`a`".
As you can image, _Full case-mapping_ performs one-to-many character
replacements (more precisely one-to-many code-points).
In real world use-cases, it's rare to perform _full case-mapping_, this is
because it only concerns a very small set of characters. For example in german
language, the letter "`ß`" is strictly lowercase and should be mapped to "`SS`"
in uppercase words.
Case-Converter behaviour
------------------------
By default, Case-Converter will perform _full case-mapping_
```php
// Full case-mapping
$ger = new Convert('Straße');
echo $ger->toUpper(); // output: STRASSE
```
If you want to perform _simple case-mapping_ then you have to
call `->forceSimpleCaseMapping()`:
```php
// Simple case-mapping
$ger = new Convert('Straße');
$ger->forceSimpleCaseMapping();
echo $ger->toUpper(); // output: STRAßE
```
As you can see, in _full case-mapping_ string length can change.
Case-Mapping in PHP
-------------------
PHP 7.3 introduced _full case-mapping_, you can have one-to-many character
mapping. In practice this means than you can have different results depending on
your PHP version.
Internally Case-Converter uses _mb_convert_case()_ . This function works in
conjunction with specific constants to tell what action to perform. For example:
```php
mb_convert_case('Foo', MB_CASE_UPPER); // FOO
```
Prior to PHP 7.3, these were the available constants and their use:
| Constant | Meaning |
|---------------|---------------------------------------------|
| MB_CASE_UPPER | Performs simple upper-case fold conversion. |
| MB_CASE_LOWER | Performs simple lower-case fold conversion. |
| MB_CASE_TITLE | Performs simple title-case fold conversion. |
But from PHP 7.3, new constants were added and their meaning changed:
| Constant | Meaning |
|----------------------|---------------------------------------------|
| MB_CASE_UPPER | Performs a full upper-case folding. |
| MB_CASE_LOWER | Performs a full lower-case folding. |
| MB_CASE_TITLE | Performs a full title-case conversion. |
| MB_CASE_UPPER_SIMPLE | Performs simple upper-case fold conversion. |
| MB_CASE_LOWER_SIMPLE | Performs simple lower-case fold conversion. |
| MB_CASE_TITLE_SIMPLE | Performs simple title-case fold conversion. |
Locale dependent mapping
------------------------
Some case-mapping are locale dependent. This is the case of Turkish where the
small letter "`i`" should be replaced by a capital letter with a dot "`İ`".
However, according to documentation:
> Only unconditional, language agnostic full case-mapping is performed.
This means that locale dependent mapping are ignored and not performed.
Resources
---------
- PHP 7.3 Full Case-Mapping and Case-Folding Support
- https://www.php.net/manual/en/migration73.new-features.php#migration73.new-features.mbstring.case-mapping-folding
- mb_convert_case()
- https://www.php.net/manual/en/function.mb-convert-case.php
- mbstring constant
- https://www.php.net/manual/en/mbstring.constants.php
================================================
FILE: docs/detection-algorithm.md
================================================
Detection algorithm
===================
When `\Jawira\CaseConverter\Convert` class is instantiated, the input string is
analyzed to detect the words in it.
This is also the algorithm used by `Convert::fromAuto` method.

1. If input string contains `_` (underscore character), then `_` is used to
split string.
2. If input string contains `-` (dash character), then `-` is used to split
string.
3. If input string contains `␣` (space character), then `␣` is used to split
string.
4. If input string contains `.` (space character), then `.` is used to split
string.
5. If input string contains uppercase characters only, then the input string is
considered to be a single word.
6. Finally, uppercase characters are used to split string.
================================================
FILE: docs/dev.md
================================================
Development notes
=================
Phing targets
-------------
[](./images/build.png)
- `$ phing setup`: Prepare project for development.
- `$ phing qa`: Run quality tests, use this before every commit.
Documentation
-------------
Documentation is built when a `release` is created.
To install **mkdocs** locally type:
[comment]: <> (https://stackoverflow.com/a/41352413/4345061)
```console
sudo -H pip install mkdocs
```
Using Phing behind a proxy
--------------------------
If you are developing behind a proxy, you have to set the environment
variable `http_proxy`. This variable already is imported in `build.xml`, so you
have nothing to do.
Creating new convention
-----------------------
1. Create new Gluer class.
2. Create new Split class.
3. Update `\Jawira\CaseConverter\Convert::analyse` if needed.
4. Register into `\Jawira\CaseConverter\Convert::handleSplitterMethod`.
5. Register into `\Jawira\CaseConverter\Convert::handleGluerMethod`.
6. Update docblock `\Jawira\CaseConverter\Convert` to register new methods.
7. Update documentation.
Railroad diagram
----------------
-
Class diagrams
--------------
[](./images/uml-case-converter.png)
[](./images/uml-glue.png)
[](./images/uml-split.png)
[git-flow]: https://github.com/petervanderdoes/gitflow-avh
[Keep a changelog]: http://keepachangelog.com/en/1.0.0/
[mkdocs]: https://www.mkdocs.org/#installation
[mkdocs-material]: https://github.com/squidfunk/mkdocs-material
[pds/skeleton]: https://github.com/php-pds/skeleton
[Phive]: https://phar.io/
[Semantic Versioning]: http://semver.org/
[Composer]: https://getcomposer.org/
================================================
FILE: docs/images/build.puml
================================================
@startuml
title
Case Converter
end title
top to bottom direction
skinparam Shadowing false
skinparam ArrowFontColor Black
skinparam ArrowThickness 2
skinparam UseCaseBackgroundColor #FFFECC
skinparam UseCaseBorderColor #333333
skinparam UseCaseBorderThickness 2
skinparam UseCaseFontColor Black
(setup) -[#1A85FF]-> (composer:install) : depend:1
(setup) -[#1A85FF]-> (cc:get) : depend:2
(qa) -[#1A85FF]-> (php:lint) : depend:1
(qa) -[#1A85FF]-> (composer:validate) : depend:2
(qa) -[#1A85FF]-> (phpunit:run) : depend:3
(qa) -[#1A85FF]-> (behat:run) : depend:4
(qa) -[#1A85FF]-> (phpstan:analyse) : depend:5
(qa) -[#1A85FF]-> (psalm:run) : depend:6
(docs:refresh-images) -[#1A85FF]-> (phing:visualize) : depend:1
(docs:refresh-images) -[#1A85FF]-> (plantuml:puml-to-png) : depend:2
(phpunit:open-coverage) -[#1A85FF]-> (phpunit:run) : depend:1
(docs:serve) -[#1A85FF]-> (docs:build) : depend:1
(docs:build) -[#1A85FF]-> (docs:refresh-images) : depend:1
(help)
(setup)
(qa)
(docs:refresh-images)
(composer:validate)
(composer:install)
(phpunit:open-coverage)
(php:lint)
(behat:run)
(phpunit:run)
(changelog:links)
(cc:get)
(cc:before-build)
(cc:after-build)
(plantuml:puml-to-png)
(git:tags-listing)
(phing:visualize)
(docs:serve)
(docs:build)
(psalm:run)
(phpstan:analyse)
@enduml
================================================
FILE: docs/images/detection-algorithm.puml
================================================
@startuml
start
if ($input contains "**_**") then (yes)
:Split using "**_**";
elseif ($input contains "**-**") then (yes)
:Split using "**-**";
elseif ($input contains "**␣**") then (yes)
:Split using "**␣**";
elseif ($input contains "**.**") then (yes)
:Split using "**.**";
elseif ($input is in uppercase only) then (yes)
:$input is a single word;
else (no)
:Split using capital letters;
endif
stop
@enduml
================================================
FILE: docs/images/number-problem.puml
================================================
@startuml
left to right direction
hide empty description
state "hello-8-world" as state1
state "hello8World" as state2
state "hello8-world" as state3
state1 --> state2: toCamel
state2 --> state3: toKebab
state3 --> state2: toCamel
center footer It's impossible to go back to original string when a number is used as a word
@enduml
================================================
FILE: docs/images/railroad.js
================================================
// https://tabatkins.github.io/railroad-diagrams/generator.html
Diagram(
Choice(0,
Sequence(
Optional('->forceSimpleCaseMapping()', 'skip'),
Choice(7,
'->fromAda()',
'->fromAuto()',
'->fromCamel()',
'->fromCobol()',
'->fromDot()',
'->fromKebab()',
'->fromLower()',
Skip(),
'->fromMacro()',
'->fromPascal()',
'->fromSentence()',
'->fromSnake()',
'->fromTitle()',
'->fromTrain()',
'->fromUpper()'
),
Choice(7,
'->toAda()',
'->toArray()',
'->toCamel()',
'->toCobol()',
'->toDot()',
'->toKebab()',
'->toLower()',
'->toMacro()',
'->toPascal()',
'->toSentence()',
'->toSnake()',
'->toTitle()',
'->toTrain()',
'->toUpper()'
)
),
'->getSource()'
)
);
================================================
FILE: docs/images/uml-case-converter.puml
================================================
@startuml
namespace Jawira.CaseConverter {
exception CaseConverterException {
}
interface CaseConverterInterface << interface >> {
+convert()
}
class CaseConverter << class >> {
+convert()
}
class Convert << class >> {
#source
#words
#forceSimpleCaseMapping
--
+__construct()
+fromAuto()
#analyse()
#contains()
#isUppercaseWord()
#extractWords()
+getSource()
+__call()
#handleSplitterMethod()
#createSplitter()
#handleGluerMethod()
#createGluer()
+toArray()
+forceSimpleCaseMapping()
}
}
exception Exception {
}
Exception <|-- Jawira.CaseConverter.CaseConverterException
Jawira.CaseConverter.CaseConverterInterface <|.. Jawira.CaseConverter.CaseConverter
@enduml
================================================
FILE: docs/images/uml-glue.puml
================================================
@startuml
namespace Jawira.CaseConverter.Glue {
class TitleCase << class >> {
+glue()
}
abstract SpaceGluer << abstract >> {
+DELIMITER
}
abstract Gluer << abstract >> {
+ENCODING
..
#words
#lowerCase
#upperCase
#titleCase
--
+__construct()
#setSimpleCaseMappingConstants()
+glue()
#glueUsingRules()
#changeWordsCase()
#changeFirstWordCase()
}
abstract DashGluer << abstract >> {
+DELIMITER
}
class CamelCase << class >> {
+glue()
}
abstract UppercaseGluer << abstract >> {
+DELIMITER
}
class AdaCase << class >> {
+glue()
}
abstract UnderscoreGluer << abstract >> {
+DELIMITER
}
class SnakeCase << class >> {
+glue()
}
class KebabCase << class >> {
+glue()
}
class CobolCase << class >> {
+glue()
}
class DotNotation << class >> {
+DELIMITER
--
+glue()
}
class UpperCase << class >> {
+glue()
}
class TrainCase << class >> {
+glue()
}
class SentenceCase << class >> {
+glue()
}
class PascalCase << class >> {
+glue()
}
class MacroCase << class >> {
+glue()
}
class LowerCase << class >> {
+glue()
}
}
Jawira.CaseConverter.Glue.SpaceGluer --|> Jawira.CaseConverter.Glue.Gluer
Jawira.CaseConverter.Glue.TitleCase --|> Jawira.CaseConverter.Glue.SpaceGluer
Jawira.CaseConverter.Glue.DashGluer --|> Jawira.CaseConverter.Glue.Gluer
Jawira.CaseConverter.Glue.UppercaseGluer --|> Jawira.CaseConverter.Glue.Gluer
Jawira.CaseConverter.Glue.CamelCase --|> Jawira.CaseConverter.Glue.UppercaseGluer
Jawira.CaseConverter.Glue.UnderscoreGluer --|> Jawira.CaseConverter.Glue.Gluer
Jawira.CaseConverter.Glue.AdaCase --|> Jawira.CaseConverter.Glue.UnderscoreGluer
Jawira.CaseConverter.Glue.SnakeCase --|> Jawira.CaseConverter.Glue.UnderscoreGluer
Jawira.CaseConverter.Glue.KebabCase --|> Jawira.CaseConverter.Glue.DashGluer
Jawira.CaseConverter.Glue.CobolCase --|> Jawira.CaseConverter.Glue.DashGluer
Jawira.CaseConverter.Glue.DotNotation --|> Jawira.CaseConverter.Glue.Gluer
Jawira.CaseConverter.Glue.UpperCase --|> Jawira.CaseConverter.Glue.SpaceGluer
Jawira.CaseConverter.Glue.TrainCase --|> Jawira.CaseConverter.Glue.DashGluer
Jawira.CaseConverter.Glue.SentenceCase --|> Jawira.CaseConverter.Glue.SpaceGluer
Jawira.CaseConverter.Glue.PascalCase --|> Jawira.CaseConverter.Glue.UppercaseGluer
Jawira.CaseConverter.Glue.MacroCase --|> Jawira.CaseConverter.Glue.UnderscoreGluer
Jawira.CaseConverter.Glue.LowerCase --|> Jawira.CaseConverter.Glue.SpaceGluer
@enduml
================================================
FILE: docs/images/uml-split.puml
================================================
@startuml
namespace Jawira.CaseConverter.Split {
abstract Splitter << abstract >> {
#inputString
--
+__construct()
+split()
#splitUsingPattern()
}
class SpaceSplitter << class >> {
+PATTERN
--
+split()
}
class DotSplitter << class >> {
+PATTERN
--
+split()
}
class UppercaseSplitter << class >> {
+PATTERN
--
+split()
}
class UnderscoreSplitter << class >> {
+PATTERN
--
+split()
}
class DashSplitter << class >> {
+PATTERN
--
+split()
}
}
Jawira.CaseConverter.Split.SpaceSplitter --|> Jawira.CaseConverter.Split.Splitter
Jawira.CaseConverter.Split.DotSplitter --|> Jawira.CaseConverter.Split.Splitter
Jawira.CaseConverter.Split.UppercaseSplitter --|> Jawira.CaseConverter.Split.Splitter
Jawira.CaseConverter.Split.UnderscoreSplitter --|> Jawira.CaseConverter.Split.Splitter
Jawira.CaseConverter.Split.DashSplitter --|> Jawira.CaseConverter.Split.Splitter
@enduml
================================================
FILE: docs/index.md
================================================
Case Converter
==============
To use **Case Converter** you have to instantiate `Convert` class, to do so you
can use the `new` keyword or the [CaseConverter factory] class.
The string you want to convert should be passed at instantiation. This cannot be
changed later since `Convert` class is immutable.
```php
$var = new Convert('string-to-convert');
```
Typically, you are going to call `Convert` methods this way:

Basic usage
-----------
Code:
```php
use Jawira\CaseConverter\Convert;
$robot = new Convert('The-Terminator');
echo $robot->toPascal(); // TheTerminator
echo $robot->toCobol(); // THE-TERMINATOR
echo $robot->toSnake(); // the_terminator
```
Explicit case detection
-----------------------
In some edge cases you have to explicitly set the format of input string to have
the desired output:
```php
use Jawira\CaseConverter\Convert;
$agency = new Convert('FBI');
$agency->fromAda();
echo $agency->toCobol(); // FBI
echo $agency->toSnake(); // fbi
$agency->fromCamel();
echo $agency->toCobol(); // F-B-I
echo $agency->toSnake(); // f_b_i
$agency->fromAuto();
echo $agency->toCobol(); // FBI
echo $agency->toSnake(); // fbi
```
Force _Simple Case-Mapping_
---------------------------
You can still use _Simple Case-Mapping_ even if you are using PHP 7.3 or newer:
```php
forceSimpleCaseMapping();
echo $robot->toMacro(); // output: STRAßE
```
[Learn more about Case-Mapping][Case-Mapping].
Using the factory
-----------------
[CaseConverter factory] is going to instantiate `Convert` class for you.
In the following code `$this->cc` is an instance of
`\Jawira\CaseConverter\CaseConverter` and implements
`\Jawira\CaseConverter\CaseConverterInterface`. This is useful because the
factory should be instantiated by the _Dependency Injection_ mechanism provided
by your favorite framework.
```php
// Convert string to Pascal case
$this->cc->convert('XML')->toPascal(); // Xml
// Convert string to Snake case
$this->cc->convert('v3.0.2')->toSnake(); // v3_0_2
// Convert string to Camel case
$this->cc->convert('first-name')->toCamel(); // firstName
// Convert from Lower case to Dot case
$this->cc->convert('non-SI units')->fromLower()->toDot(); // non-si.units
// Get detected words
$this->cc->convert('Mario Bros')->toArray(); // ['Mario', 'Bros']
// Retrieve original string
$this->cc->convert('use_the_force')->getSource(); // use_the_force
```
More about [CaseConverter factory].
[Case-Mapping]: ./case-mapping.md
[CaseConverter factory]: ./using-the-factory.md
================================================
FILE: docs/known-issues.md
================================================
Known issues
============
Number is not a word
--------------------
When using `case-converter` you cannot use a number as separator.
In practice this means a number is always identified as a lower case letter.

As shown in the previous example, there is no way to go back to the original input string (i.e. `hello-8-world`), in _
kebab case_ this sting is written as
`hello8-world`.
Other examples (with automatic case detection):
```php
(new Convert('REEL2REAL'))->toDot(); // r.e.e.l2.r.e.a.l
(new Convert('reel2real'))->toDot(); // reel2real
(new Convert('Reel2Real'))->toDot(); // reel2.real
```
I strongly suggest to avoid numbers in strings to be converted.
Mixed conventions
-----------------
It might be evident, but _Case Converter_ cannot handle string with mixed naming conventions.
For example the string `XMLHttpRequest` will result in `x.m.l.http.request` when using _dot notation_:
```php
$xhr = new Convert('XMLHttpRequest');
$xhr->toDot() // x.m.l.http.request
```
The correct way to name this string (for Case Converter) should have been `XmlHttpRequest`.
Another example of mixed conventions:
| ❌ Wrong | ✅ Good |
|-----------------|------------------|
| PHP_CodeSniffer | php_code_sniffer |
| PHP_CodeSniffer | PhpCodeSniffer |
| PHPUnit | PhpUnit |
| PHPUnit | php-unit |
================================================
FILE: docs/naming-conventions.md
================================================
Naming conventions
==================
Naming conventions are also referred as:
- Naming style
- Case convention
Reference matrix
----------------
| | Lower case | Title case | Upper case | Sentence case |
|--------------------|--------------|---------------------------|------------|---------------|
| `_` (underscore) | Snake case | Ada case | Macro case | - |
| `-` (dash) | Kebab case | Train case | Cobol case | - |
| `.` (dot) | Dot notation | - | - | - |
| `␣` (space) | Lower case | Title case | Upper case | Sentence case |
| ` ` (empty string) | - | Camel case
Pascal case | - | - |
Description table (wip)
-----------------
| Convention name | Description | Usage | AKA |
|-----------------|-------------------------------------------------------------|------------------|-----------------------------------------------|
| Camel case | | PHP method names | Camel caps, Medial capitals, Lower camel case |
| Pascal case | | PHP class names | Upper camel case |
| Snake case | All letters in lower-case separated with a `_` (underscore) | PHP functions | |
| Ada case | | | |
| Macro case | | PHP constants | |
| Kebab case | | | |
| Train case | | | |
| Cobol case | | | |
| Dot notation | | | |
| Lower case | | | |
| Title case | | | |
| Upper case | | | |
| Sentence case | | | |
Resources
---------
-
-
-
================================================
FILE: docs/using-the-factory.md
================================================
Using the factory
=================
Besides `\Jawira\CaseConverter\Convert` you also have at your disposal:
- `\Jawira\CaseConverter\CaseConverter`
- `\Jawira\CaseConverter\CaseConverterInterface`
Instead of using `new Convert();` you can use the convenience method from
`CaseConverter` class.
In concrete, you have to call `\Jawira\CaseConverter\CaseConverter::convert` to
create `Convert` objects.
Here an example:
```php
cc = $cc;
}
public function variableName(string $slug): string
{
// `->convert()` returns a `Convert` object.
$myConvert = $this->cc->convert($slug);
return $myConvert->toCamel();
}
public function constantName(string $slug): string
{
// Of course you can also chain everything.
return $this->cc->convert($slug)->fromKebab()->toMacro();
}
}
```
Please note that an interface -`CaseConverterInterface`- is also provided. If
you are using _Symfony_ you can use this interface with [Symfony autowiring][]
to automatically instantiate `CaseConverter`, otherwise if you are working in a
standalone project you should try [php-di project][].
Using `\Jawira\CaseConverter\CaseConverter::convert` is preferred because:
- Usually the `new` operator is considered harmful.
- You can easily mock dependencies when writing tests.
- [It's SOLID]
[It's SOLID]: https://github.com/jawira/case-converter/issues/40
[php-di project]: http://php-di.org/#autowiring
[Symfony autowiring]: https://symfony.com/doc/current/service_container/autowiring.html
================================================
FILE: mkdocs.yml
================================================
site_name: !ENV [SITE_NAME, 'Case Converter']
site_author: 'Jawira Portugal'
site_url: 'https://jawira.github.io/case-converter/'
copyright: 'The MIT License (MIT)'
theme:
name: 'material'
highlightjs: true
titles_only: true
prev_next_buttons_location: 'both'
collapse_navigation: false
use_directory_urls: false
strict: true
repo_url: 'https://github.com/jawira/case-converter/'
edit_uri: ''
markdown_extensions:
- codehilite
extra:
disqus: case-converter
================================================
FILE: src/CaseConverter.php
================================================
*/
class CaseConverter implements CaseConverterInterface
{
/**
* Returns a Convert object
*
* @param string $source Input string to be converted
*
* @return \Jawira\CaseConverter\Convert
* @throws \Jawira\CaseConverter\CaseConverterException
*/
public function convert(string $source): Convert
{
return new Convert($source);
}
}
================================================
FILE: src/CaseConverterException.php
================================================
*/
interface CaseConverterInterface
{
public function convert(string $source): Convert;
}
================================================
FILE: src/Convert.php
================================================
*/
class Convert
{
/** @var string Input string to convert */
protected string $source;
/** @var string[] Words extracted from input string */
protected array $words;
protected bool $forceSimpleCaseMapping;
/**
* Constructor method
*
* @param string $source String to convert
*
* @throws \Jawira\CaseConverter\CaseConverterException
*/
public function __construct(string $source)
{
$this->source = $source;
$this->forceSimpleCaseMapping = false;
$this->fromAuto();
}
/**
* Handle `to*` methods and `from*` methods
*
* @param string $methodName
* @param mixed[] $arguments
*
* @return string|\Jawira\CaseConverter\Convert
* @throws \Jawira\CaseConverter\CaseConverterException
*/
public function __call(string $methodName, array $arguments)
{
$strStartsWith = static fn(string $haystack, string $needle): bool => 0 === mb_strpos($haystack, $needle);
if ($strStartsWith($methodName, 'from')) {
$result = $this->handleSplitterMethod($methodName);
} elseif ($strStartsWith($methodName, 'to')) {
$result = $this->handleGluerMethod($methodName);
} else {
throw new CaseConverterException("Unknown method: $methodName");
}
return $result;
}
/**
* Auto-detect naming convention.
*
* This is the default method when you don't call a "from*" method.
*
* @param bool $digitsAreLowercase When `true`, digits in input string are considered to be equivalent to a lowercase character. When `false` digits are considered to be uppercase.
* @return \Jawira\CaseConverter\Convert
*/
public function fromAuto(bool $digitsAreLowercase = true): self
{
$splitter = $this->analyse($this->source, $digitsAreLowercase);
$this->extractWords($splitter);
return $this;
}
/**
* Returns original input string
*
* @return string Original input string
*/
public function getSource(): string
{
return $this->source;
}
/**
* Detected words extracted from original string.
*
* @return string[]
*/
public function toArray(): array
{
return $this->words;
}
/**
* Forces to use Simple Case-Mapping
*
* Call this method if you want to maintain the behaviour before PHP 7.3
*
* @see https://unicode.org/faq/casemap_charprop.html
* @return \Jawira\CaseConverter\Convert
*/
public function forceSimpleCaseMapping(): self
{
$this->forceSimpleCaseMapping = true;
return $this;
}
/**
* Detects word separator of $input string and tells you what strategy you should use.
*
* @param string $input String to be analysed
* @param bool $digitsAreLowercase When `true`, digits in input string are considered to be equivalent to a lowercase character. When `false` digits are considered to be uppercase.
*
* @return \Jawira\CaseConverter\Split\Splitter
* @throws \Jawira\CaseConverter\CaseConverterException
*/
protected function analyse(string $input, bool $digitsAreLowercase): Splitter
{
$strContains = static fn(string $input, string $needle): bool => is_int(mb_strpos($input, $needle));
switch (true) {
case $strContains($input, UnderscoreGluer::DELIMITER):
$splittingStrategy = new UnderscoreSplitter($input);
break;
case $strContains($input, DashGluer::DELIMITER):
$splittingStrategy = new DashSplitter($input);
break;
case $strContains($input, SpaceGluer::DELIMITER):
$splittingStrategy = new SpaceSplitter($input);
break;
case $strContains($input, DotNotation::DELIMITER):
$splittingStrategy = new DotSplitter($input);
break;
case $this->isUppercaseWord($input, $digitsAreLowercase):
$splittingStrategy = new UnderscoreSplitter($input);
break;
default:
$splittingStrategy = new UppercaseSplitter($input);
break;
}
return $splittingStrategy;
}
/**
* Returns true if $input string is a single word composed only by uppercase characters.
*
* ```
* isUppercaseWord('BRUSSELS'); // true
* isUppercaseWord('Brussels'); // false
* ```
*
* @see https://www.regular-expressions.info/unicode.html#category
*
* @param string $input String to be tested.
*
* @return bool
* @throws \Jawira\CaseConverter\CaseConverterException
*/
protected function isUppercaseWord(string $input, bool $digitsAreLowercase): bool
{
$pattern = $digitsAreLowercase ? '#^\p{Lu}+$#u' : '#^[\p{Lu}\p{Nd}]+$#u';
$match = preg_match($pattern, $input);
if (false === $match) {
throw new CaseConverterException('Error executing regex'); // @codeCoverageIgnore
}
return 1 === $match;
}
/**
* Main function, receives input string and then it stores extracted words into an array.
*
* @param \Jawira\CaseConverter\Split\Splitter $splitter
*
* @return $this
*/
protected function extractWords(Splitter $splitter): self
{
$this->words = $splitter->split();
return $this;
}
/**
* Methods to explicitly define naming conventions for input string
*
* @param string $methodName
*
* @return $this
* @throws \Jawira\CaseConverter\CaseConverterException
*/
protected function handleSplitterMethod(string $methodName): self
{
switch ($methodName) {
case 'fromCamel':
case 'fromPascal':
$splitterName = UppercaseSplitter::class;
break;
case 'fromSnake':
case 'fromAda':
case 'fromMacro':
$splitterName = UnderscoreSplitter::class;
break;
case 'fromKebab':
case 'fromTrain':
case 'fromCobol':
$splitterName = DashSplitter::class;
break;
case 'fromLower':
case 'fromUpper':
case 'fromTitle':
case 'fromSentence':
$splitterName = SpaceSplitter::class;
break;
case 'fromDot':
$splitterName = DotSplitter::class;
break;
default:
throw new CaseConverterException("Unknown method: $methodName");
}
$splitter = $this->createSplitter($splitterName, $this->source);
$this->extractWords($splitter);
return $this;
}
/**
* @param string $className Class name in string format
* @param string $source Input string to be split
*
* @return \Jawira\CaseConverter\Split\Splitter
*/
protected function createSplitter(string $className, string $source): Splitter
{
assert(is_subclass_of($className, Splitter::class));
return new $className($source);
}
/**
* Handles all methods starting by `to*`
*
* @param string $methodName
*
* @return string
* @throws \Jawira\CaseConverter\CaseConverterException
*/
protected function handleGluerMethod(string $methodName): string
{
switch ($methodName) {
case 'toAda':
$className = AdaCase::class;
break;
case 'toCamel':
$className = CamelCase::class;
break;
case 'toCobol':
$className = CobolCase::class;
break;
case 'toKebab':
$className = KebabCase::class;
break;
case 'toLower':
$className = LowerCase::class;
break;
case 'toMacro':
$className = MacroCase::class;
break;
case 'toPascal':
$className = PascalCase::class;
break;
case 'toSentence':
$className = SentenceCase::class;
break;
case 'toSnake':
$className = SnakeCase::class;
break;
case 'toTitle':
$className = TitleCase::class;
break;
case 'toTrain':
$className = TrainCase::class;
break;
case 'toUpper':
$className = UpperCase::class;
break;
case 'toDot':
$className = DotNotation::class;
break;
default:
throw new CaseConverterException("Unknown method: $methodName");
}
$gluer = $this->createGluer($className, $this->words, $this->forceSimpleCaseMapping);
return $gluer->glue();
}
/**
* @param string $className Class name in string format
* @param string[] $words Words to glue
* @param bool $forceSimpleCaseMapping Should _Simple Case-Mapping_ be forced?
*
* @return \Jawira\CaseConverter\Glue\Gluer
*/
protected function createGluer(string $className, array $words, bool $forceSimpleCaseMapping): Gluer
{
assert(is_subclass_of($className, Gluer::class));
return new $className($words, $forceSimpleCaseMapping);
}
}
================================================
FILE: src/Glue/AdaCase.php
================================================
glueUsingRules(self::DELIMITER, $this->titleCase);
}
}
================================================
FILE: src/Glue/CamelCase.php
================================================
glueUsingRules(self::DELIMITER, $this->titleCase, $this->lowerCase);
}
}
================================================
FILE: src/Glue/CobolCase.php
================================================
glueUsingRules(self::DELIMITER, $this->upperCase);
}
}
================================================
FILE: src/Glue/DashGluer.php
================================================
glueUsingRules(self::DELIMITER, $this->lowerCase);
}
}
================================================
FILE: src/Glue/Gluer.php
================================================
*/
abstract class Gluer
{
/**
* Encoding to be used by `mb_convert_case()` function.
*
* This value should never change.
*/
protected const ENCODING = 'UTF-8';
/**
* @var string[] Words extracted from input string
*/
protected array $words;
/**
* @var int MB_CASE_LOWER or MB_CASE_LOWER_SIMPLE
*/
protected int $lowerCase;
/**
* @var int MB_CASE_UPPER or MB_CASE_UPPER_SIMPLE
*/
protected int $upperCase;
/**
* @var int MB_CASE_TITLE or MB_CASE_TITLE_SIMPLE
*/
protected int $titleCase;
/**
* Gluer constructor.
*
* @param string[] $words
* @param bool $forceSimpleCaseMapping
*/
final public function __construct(array $words, bool $forceSimpleCaseMapping)
{
$this->words = $words;
$this->lowerCase = $forceSimpleCaseMapping ? MB_CASE_LOWER_SIMPLE : MB_CASE_LOWER;
$this->upperCase = $forceSimpleCaseMapping ? MB_CASE_UPPER_SIMPLE : MB_CASE_UPPER;
$this->titleCase = $forceSimpleCaseMapping ? MB_CASE_TITLE_SIMPLE : MB_CASE_TITLE;
}
/**
* Creates a string which respects concrete naming convention.
*
* @return string
*/
abstract public function glue(): string;
/**
* Implode self::$words array using $glue.
*
* @param string $glue Character to glue words. Even if is assumed you are using underscore or dash character, this method should be capable to use any character as glue.
* @param int $wordsMode The mode of the conversion. It should be one of `Gluer::$lowerCase`, `Gluer::$upperCase` or `Gluer::$titleCase`.
* @param null|int $firstWordMode Sometimes first word requires special treatment. It should be one of `Gluer::$lowerCase`, `Gluer::$upperCase` or `Gluer::$titleCase`.
*
* @return string Converted words.
*/
protected function glueUsingRules(string $glue, int $wordsMode, ?int $firstWordMode = null): string
{
$convertedWords = $this->changeWordsCase($this->words, $wordsMode);
if (is_int($firstWordMode)) {
$convertedWords = $this->changeFirstWordCase($convertedWords, $firstWordMode);
}
return implode($glue, $convertedWords);
}
/**
* Changes the case of every $words element
*
* @param string[] $words Words to modify
* @param int $caseMode It should be one of `Gluer::$lowerCase`, `Gluer::$upperCase` or `Gluer::$titleCase`.
*
* @return string[]
*/
protected function changeWordsCase(array $words, int $caseMode): array
{
if (empty($words)) {
return $words;
}
$convertCase = static fn(string $word): string => mb_convert_case($word, $caseMode, self::ENCODING);
return array_map($convertCase, $words);
}
/**
* Changes the case of first $words element
*
* @param string[] $words Words to modify
* @param int $caseMode It should be one of `Gluer::$lowerCase`, `Gluer::$upperCase` or `Gluer::$titleCase`.
*
* @return string[]
*/
protected function changeFirstWordCase(array $words, int $caseMode): array
{
if (empty($words)) {
return $words;
}
$words[0] = mb_convert_case($words[0], $caseMode, self::ENCODING);
return $words;
}
}
================================================
FILE: src/Glue/KebabCase.php
================================================
glueUsingRules(self::DELIMITER, $this->lowerCase);
}
}
================================================
FILE: src/Glue/LowerCase.php
================================================
glueUsingRules(self::DELIMITER, $this->lowerCase);
}
}
================================================
FILE: src/Glue/MacroCase.php
================================================
glueUsingRules(self::DELIMITER, $this->upperCase);
}
}
================================================
FILE: src/Glue/PascalCase.php
================================================
glueUsingRules(self::DELIMITER, $this->titleCase);
}
}
================================================
FILE: src/Glue/SentenceCase.php
================================================
glueUsingRules(self::DELIMITER, $this->lowerCase, $this->titleCase);
}
}
================================================
FILE: src/Glue/SnakeCase.php
================================================
glueUsingRules(self::DELIMITER, $this->lowerCase);
}
}
================================================
FILE: src/Glue/SpaceGluer.php
================================================
glueUsingRules(self::DELIMITER, $this->titleCase);
}
}
================================================
FILE: src/Glue/TrainCase.php
================================================
glueUsingRules(self::DELIMITER, $this->titleCase);
}
}
================================================
FILE: src/Glue/UnderscoreGluer.php
================================================
glueUsingRules(self::DELIMITER, $this->upperCase);
}
}
================================================
FILE: src/Glue/UppercaseGluer.php
================================================
splitUsingPattern($this->inputString, self::PATTERN);
}
}
================================================
FILE: src/Split/DotSplitter.php
================================================
splitUsingPattern($this->inputString, self::PATTERN);
}
}
================================================
FILE: src/Split/SpaceSplitter.php
================================================
splitUsingPattern($this->inputString, self::PATTERN);
}
}
================================================
FILE: src/Split/Splitter.php
================================================
*/
abstract class Splitter
{
/**
* @var string Words extracted from input string
*/
protected string $inputString;
final public function __construct(string $inputString)
{
$this->inputString = $inputString;
}
/**
* Tells how to split a string into valid words.
*
* @return string[]
*/
abstract public function split(): array;
/**
* This is a utility method, typically this method is used by to split a string based on pattern.
*
* @param string $inputString
* @param string $pattern
*
* @return string[]
* @throws \Jawira\CaseConverter\CaseConverterException
*/
protected function splitUsingPattern(string $inputString, string $pattern): array
{
if (empty($pattern)) {
throw new CaseConverterException('Pattern must not be empty.'); // @codeCoverageIgnore
}
$words = preg_split($pattern, $inputString, 0, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
if ($words === false) {
throw new CaseConverterException("Error while processing $this->inputString"); // @codeCoverageIgnore
}
return $words;
}
}
================================================
FILE: src/Split/UnderscoreSplitter.php
================================================
splitUsingPattern($this->inputString, self::PATTERN);
}
}
================================================
FILE: src/Split/UppercaseSplitter.php
================================================
splitUsingPattern($this->inputString, self::PATTERN);
}
}
================================================
FILE: tests/behat/bootstrap/FeatureContext.php
================================================
instance = new Convert($arg1);
}
/**
* @When I cast object to string
*/
public function iCastObjectToString()
{
$this->result = (string)($this->instance);
}
/**
* @When I call :methodName
*
* @param $methodName
*/
public function iCall($methodName)
{
$this->result = ($this->instance)->$methodName();
}
/**
* @Then method should return string :returnString
*
* @param string $returnString Expected string
*
* @throws \Exception
*/
public function methodShouldReturnString($returnString)
{
if (!is_string($returnString)) {
throw new Exception('Result is not a string');
}
if ($this->result !== $returnString) {
$message = sprintf('Result "%s" is not equal to expected string "%s"', $this->result, $returnString);
throw new Exception($message);
}
}
/**
* @Then method should return array :returnArray
*
* @param array $returnArray
*
* @throws \Exception
*/
public function methodShouldReturnArray($returnArray)
{
if (!is_array($returnArray)) {
throw new Exception('Result is not array');
}
if ($this->result !== $returnArray) {
throw new Exception('Result is not the expected array');
}
}
/**
* Convert string to array.
*
* Array format is `[One;Two;Three]`.
*
* @Transform /^(\[.*\])$/
*
* @see https://behat.readthedocs.io/en/v2.5/guides/2.definitions.html#step-argument-transformations
*
* @param string $string The string to convert to array
*
* @return array
*/
public function transformStringToArray($string): array
{
$trimmed = trim($string, '[]');
if ($trimmed === false) {
$trimmed = '';
}
$exploded = explode(';', $trimmed);
// Filtering since CaseConverter does the same.
return array_filter($exploded);
}
/**
* @When I use count function
*/
public function iUseCountFunction()
{
$this->count = count($this->instance);
}
/**
* @Then functions should return :expectedCount
*
* @param $expectedCount
*
* @throws \Exception
*/
public function functionsShouldReturn($expectedCount)
{
if (!is_numeric($expectedCount)) {
throw new Exception('Count value is not numeric');
}
$expectedCount = (int)$expectedCount;
if ($this->count !== $expectedCount) {
throw new Exception('Invalid count');
}
}
}
================================================
FILE: tests/behat/case-converter.feature
================================================
Feature: Convert Case
In order to change string case
Dev should be able to
change case
Scenario Outline: Change naming convention from string using explicit methods
Given CaseConverter class is instantiated with ""
When I call ""
Then method should return string ""
Examples:
| method | input-string | output-string |
| toCamel | | |
| toCamel | a | a |
| toCamel | NASA | nasa |
| toCamel | Fbi | fbi |
| toCamel | B-C-D | bCD |
| toCamel | CamelCase | camelCase |
| toCamel | dataTransfer | dataTransfer |
| toCamel | eniac_computer | eniacComputer |
| toCamel | FIBONACCI_NUMBER | fibonacciNumber |
| toCamel | v5.3.0 | v530 |
| toCamel | Good_Morning_Vietnam | goodMorningVietnam |
| toCamel | Buenos Días | buenosDías |
| toCamel | Jag_förstår_inte | jagFörstårInte |
| toCamel | quicoYÑoño | quicoYÑoño |
| toCamel | Πολύ-καλό | πολύΚαλό |
| toCamel | ОЧЕНЬ_ПРИЯТНО | оченьПриятно |
| toCamel | Ես-հայերեն-չգիտեմ | եսՀայերենՉգիտեմ |
| toPascal | | |
| toPascal | a | A |
| toPascal | NASA | Nasa |
| toPascal | Fbi | Fbi |
| toPascal | B-C-D | BCD |
| toPascal | CamelCase | CamelCase |
| toPascal | dataTransfer | DataTransfer |
| toPascal | eniac_computer | EniacComputer |
| toPascal | FIBONACCI_NUMBER | FibonacciNumber |
| toPascal | v5.3.0 | V530 |
| toPascal | Good_Morning_Vietnam | GoodMorningVietnam |
| toPascal | Buenos Días | BuenosDías |
| toPascal | Jag_förstår_inte | JagFörstårInte |
| toPascal | quicoYÑoño | QuicoYÑoño |
| toPascal | Πολύ-καλό | ΠολύΚαλό |
| toPascal | ОЧЕНЬ_ПРИЯТНО | ОченьПриятно |
| toPascal | Ես-հայերեն-չգիտեմ | ԵսՀայերենՉգիտեմ |
| toSnake | | |
| toSnake | a | a |
| toSnake | NASA | nasa |
| toSnake | Fbi | fbi |
| toSnake | B-C-D | b_c_d |
| toSnake | CamelCase | camel_case |
| toSnake | dataTransfer | data_transfer |
| toSnake | eniac_computer | eniac_computer |
| toSnake | FIBONACCI_NUMBER | fibonacci_number |
| toSnake | v5.3.0 | v5_3_0 |
| toSnake | Good_Morning_Vietnam | good_morning_vietnam |
| toSnake | Good_Morning_Vietnam | good_morning_vietnam |
| toSnake | Buenos Días | buenos_días |
| toSnake | quicoYÑoño | quico_y_ñoño |
| toSnake | Πολύ-καλό | πολύ_καλό |
| toSnake | ОЧЕНЬ_ПРИЯТНО | очень_приятно |
| toSnake | Ես-հայերեն-չգիտեմ | ես_հայերեն_չգիտեմ |
| toMacro | | |
| toMacro | a | A |
| toMacro | NASA | NASA |
| toMacro | Fbi | FBI |
| toMacro | B-C-D | B_C_D |
| toMacro | CamelCase | CAMEL_CASE |
| toMacro | dataTransfer | DATA_TRANSFER |
| toMacro | eniac_computer | ENIAC_COMPUTER |
| toMacro | FIBONACCI_NUMBER | FIBONACCI_NUMBER |
| toMacro | v5.3.0 | V5_3_0 |
| toMacro | Good_Morning_Vietnam | GOOD_MORNING_VIETNAM |
| toMacro | Buenos Días | BUENOS_DÍAS |
| toMacro | Jag_förstår_inte | JAG_FÖRSTÅR_INTE |
| toMacro | quicoYÑoño | QUICO_Y_ÑOÑO |
| toMacro | Πολύ-καλό | ΠΟΛΎ_ΚΑΛΌ |
| toMacro | ОЧЕНЬ_ПРИЯТНО | ОЧЕНЬ_ПРИЯТНО |
| toMacro | Ես-հայերեն-չգիտեմ | ԵՍ_ՀԱՅԵՐԵՆ_ՉԳԻՏԵՄ |
| toAda | | |
| toAda | a | A |
| toAda | NASA | Nasa |
| toAda | Fbi | Fbi |
| toAda | B-C-D | B_C_D |
| toAda | CamelCase | Camel_Case |
| toAda | dataTransfer | Data_Transfer |
| toAda | eniac_computer | Eniac_Computer |
| toAda | FIBONACCI_NUMBER | Fibonacci_Number |
| toAda | v5.3.0 | V5_3_0 |
| toAda | Good_Morning_Vietnam | Good_Morning_Vietnam |
| toAda | Buenos Días | Buenos_Días |
| toAda | Jag_förstår_inte | Jag_Förstår_Inte |
| toAda | quicoYÑoño | Quico_Y_Ñoño |
| toAda | Πολύ-καλό | Πολύ_Καλό |
| toAda | ОЧЕНЬ_ПРИЯТНО | Очень_Приятно |
| toAda | Ես-հայերեն-չգիտեմ | Ես_Հայերեն_Չգիտեմ |
| toKebab | | |
| toKebab | a | a |
| toKebab | NASA | nasa |
| toKebab | Fbi | fbi |
| toKebab | B-C-D | b-c-d |
| toKebab | CamelCase | camel-case |
| toKebab | dataTransfer | data-transfer |
| toKebab | eniac_computer | eniac-computer |
| toKebab | FIBONACCI_NUMBER | fibonacci-number |
| toKebab | v5.3.0 | v5-3-0 |
| toKebab | Good_Morning_Vietnam | good-morning-vietnam |
| toKebab | Buenos Días | buenos-días |
| toKebab | Jag_förstår_inte | jag-förstår-inte |
| toKebab | quicoYÑoño | quico-y-ñoño |
| toKebab | Πολύ-καλό | πολύ-καλό |
| toKebab | ОЧЕНЬ_ПРИЯТНО | очень-приятно |
| toKebab | Ես-հայերեն-չգիտեմ | ես-հայերեն-չգիտեմ |
| toCobol | | |
| toCobol | a | A |
| toCobol | NASA | NASA |
| toCobol | Fbi | FBI |
| toCobol | B-C-D | B-C-D |
| toCobol | CamelCase | CAMEL-CASE |
| toCobol | dataTransfer | DATA-TRANSFER |
| toCobol | eniac_computer | ENIAC-COMPUTER |
| toCobol | FIBONACCI_NUMBER | FIBONACCI-NUMBER |
| toCobol | v5.3.0 | V5-3-0 |
| toCobol | Good_Morning_Vietnam | GOOD-MORNING-VIETNAM |
| toCobol | Buenos Días | BUENOS-DÍAS |
| toCobol | Jag_förstår_inte | JAG-FÖRSTÅR-INTE |
| toCobol | quicoYÑoño | QUICO-Y-ÑOÑO |
| toCobol | Πολύ-καλό | ΠΟΛΎ-ΚΑΛΌ |
| toCobol | ОЧЕНЬ_ПРИЯТНО | ОЧЕНЬ-ПРИЯТНО |
| toCobol | Ես-հայերեն-չգիտեմ | ԵՍ-ՀԱՅԵՐԵՆ-ՉԳԻՏԵՄ |
| toTrain | | |
| toTrain | a | A |
| toTrain | NASA | Nasa |
| toTrain | Fbi | Fbi |
| toTrain | B-C-D | B-C-D |
| toTrain | CamelCase | Camel-Case |
| toTrain | dataTransfer | Data-Transfer |
| toTrain | eniac_computer | Eniac-Computer |
| toTrain | FIBONACCI_NUMBER | Fibonacci-Number |
| toTrain | v5.3.0 | V5-3-0 |
| toTrain | Good_Morning_Vietnam | Good-Morning-Vietnam |
| toTrain | Buenos Días | Buenos-Días |
| toTrain | Jag_förstår_inte | Jag-Förstår-Inte |
| toTrain | quicoYÑoño | Quico-Y-Ñoño |
| toTrain | Πολύ-καλό | Πολύ-Καλό |
| toTrain | ОЧЕНЬ_ПРИЯТНО | Очень-Приятно |
| toTrain | Ես-հայերեն-չգիտեմ | Ես-Հայերեն-Չգիտեմ |
| toLower | | |
| toLower | a | a |
| toLower | NASA | nasa |
| toLower | Fbi | fbi |
| toLower | B-C-D | b c d |
| toLower | CamelCase | camel case |
| toLower | dataTransfer | data transfer |
| toLower | eniac_computer | eniac computer |
| toLower | FIBONACCI_NUMBER | fibonacci number |
| toLower | v5.3.0 | v5 3 0 |
| toLower | Good_Morning_Vietnam | good morning vietnam |
| toLower | Buenos Días | buenos días |
| toLower | Jag_förstår_inte | jag förstår inte |
| toLower | quicoYÑoño | quico y ñoño |
| toLower | Πολύ-καλό | πολύ καλό |
| toLower | ОЧЕНЬ_ПРИЯТНО | очень приятно |
| toLower | Ես-հայերեն-չգիտեմ | ես հայերեն չգիտեմ |
| toUpper | | |
| toUpper | a | A |
| toUpper | NASA | NASA |
| toUpper | Fbi | FBI |
| toUpper | B-C-D | B C D |
| toUpper | CamelCase | CAMEL CASE |
| toUpper | dataTransfer | DATA TRANSFER |
| toUpper | eniac_computer | ENIAC COMPUTER |
| toUpper | v5.3.0 | V5 3 0 |
| toUpper | FIBONACCI_NUMBER | FIBONACCI NUMBER |
| toUpper | Good_Morning_Vietnam | GOOD MORNING VIETNAM |
| toUpper | Buenos Días | BUENOS DÍAS |
| toUpper | Jag_förstår_inte | JAG FÖRSTÅR INTE |
| toUpper | quicoYÑoño | QUICO Y ÑOÑO |
| toUpper | Πολύ-καλό | ΠΟΛΎ ΚΑΛΌ |
| toUpper | ОЧЕНЬ_ПРИЯТНО | ОЧЕНЬ ПРИЯТНО |
| toUpper | Ես-հայերեն-չգիտեմ | ԵՍ ՀԱՅԵՐԵՆ ՉԳԻՏԵՄ |
| toTitle | | |
| toTitle | a | A |
| toTitle | NASA | Nasa |
| toTitle | Fbi | Fbi |
| toTitle | B-C-D | B C D |
| toTitle | CamelCase | Camel Case |
| toTitle | dataTransfer | Data Transfer |
| toTitle | eniac_computer | Eniac Computer |
| toTitle | FIBONACCI_NUMBER | Fibonacci Number |
| toTitle | v5.3.0 | V5 3 0 |
| toTitle | Good_Morning_Vietnam | Good Morning Vietnam |
| toTitle | Buenos Días | Buenos Días |
| toTitle | Jag_förstår_inte | Jag Förstår Inte |
| toTitle | quicoYÑoño | Quico Y Ñoño |
| toTitle | Πολύ-καλό | Πολύ Καλό |
| toTitle | ОЧЕНЬ_ПРИЯТНО | Очень Приятно |
| toTitle | Ես-հայերեն-չգիտեմ | Ես Հայերեն Չգիտեմ |
| toSentence | | |
| toSentence | a | A |
| toSentence | NASA | Nasa |
| toSentence | Fbi | Fbi |
| toSentence | B-C-D | B c d |
| toSentence | CamelCase | Camel case |
| toSentence | dataTransfer | Data transfer |
| toSentence | eniac_computer | Eniac computer |
| toSentence | FIBONACCI_NUMBER | Fibonacci number |
| toSentence | v5.3.0 | V5 3 0 |
| toSentence | Good_Morning_Vietnam | Good morning vietnam |
| toSentence | Buenos Días | Buenos días |
| toSentence | Jag_förstår_inte | Jag förstår inte |
| toSentence | quicoYÑoño | Quico y ñoño |
| toSentence | Πολύ-καλό | Πολύ καλό |
| toSentence | ОЧЕНЬ_ПРИЯТНО | Очень приятно |
| toSentence | Ես-հայերեն-չգիտեմ | Ես հայերեն չգիտեմ |
| toDot | | |
| toDot | a | a |
| toDot | NASA | nasa |
| toDot | Fbi | fbi |
| toDot | B-C-D | b.c.d |
| toDot | CamelCase | camel.case |
| toDot | dataTransfer | data.transfer |
| toDot | eniac_computer | eniac.computer |
| toDot | FIBONACCI_NUMBER | fibonacci.number |
| toDot | Good_Morning_Vietnam | good.morning.vietnam |
| toDot | Buenos Días | buenos.días |
| toDot | Jag_förstår_inte | jag.förstår.inte |
| toDot | quicoYÑoño | quico.y.ñoño |
| toDot | Πολύ-καλό | πολύ.καλό |
| toDot | ОЧЕНЬ_ПРИЯТНО | очень.приятно |
| toDot | Ես-հայերեն-չգիտեմ | ես.հայերեն.չգիտեմ |
| toDot | XMLHttpRequest | x.m.l.http.request |
| toLower | IJSJE | ijsje |
| toUpper | ijsje | IJSJE |
Scenario Outline: Convert a string to array
Given CaseConverter class is instantiated with ""
When I call ""
Then method should return array ""
Examples:
| method | input-string | output-string |
| toArray | | [] |
| toArray | a | [a] |
| toArray | HugoPacoLuis | [Hugo;Paco;Luis] |
| toArray | loremIpsum | [lorem;Ipsum] |
| toArray | aBc_DeF_hIj_KlM | [aBc;DeF;hIj;KlM] |
| toArray | one___two___ | [one;two] |
| toArray | Le Népal | [Le;Népal] |
| toArray | red.green.blue | [red;green;blue] |
Scenario Outline: Full case mapping (default behaviour)
Given CaseConverter class is instantiated with ""
When I call ""
Then method should return string ""
Examples:
| method | input-string | output-string |
| toUpper | Straße | STRASSE |
| toLower | İstanbul | i̇stanbul |
| toUpper | ʼn | ʼN |
| toUpper | ffl | FFL |
Scenario Outline: Simple case mapping
Given CaseConverter class is instantiated with ""
When I call "forceSimpleCaseMapping"
And I call ""
Then method should return string ""
Examples:
| method | input-string | output-string |
| toUpper | Straße | STRAßE |
| toLower | İstanbul | istanbul |
| toUpper | ʼn | ʼn |
| toUpper | ffl | ffl |
Scenario Outline: Using numbers in input strings
Given CaseConverter class is instantiated with ""
When I call ""
Then method should return string ""
Examples:
| method | input-string | output-string |
| toCamel | I-have-99-problems | iHave99Problems |
| toPascal | The Taking of Pelham 123 | TheTakingOfPelham123 |
| toSnake | 3_idiots_2009 | 3_idiots_2009 |
| toMacro | fantastic-4 | FANTASTIC_4 |
| toAda | the6ThDay | The6_Th_Day |
| toKebab | 7samurai | 7samurai |
| toCobol | Super8 | SUPER8 |
| toTrain | 8Mm | 8-Mm |
| toLower | 8MM | 8 m m |
| toUpper | DISTRICT_9 | DISTRICT 9 |
| toTitle | session9 | Session9 |
| toSentence | 9Songs | 9 songs |
| toCamel | STARTER-FOR-10 | starterFor10 |
| toPascal | Ocean's 11 | Ocean's11 |
| toSnake | 12_angry_men | 12_angry_men |
| toMacro | Apollo13 | APOLLO13 |
| toAda | Friday-the-13th | Friday_The_13Th |
| toKebab | 14BLADES | 14-b-l-a-d-e-s |
| toCobol | STALAG17-1953 | STALAG17-1953 |
| toTrain | 21-JUMP-STREET | 21-Jump-Street |
| toLower | TheNumber23 | the number23 |
| toUpper | The 40-Year-Old Virgin | THE 40 YEAR OLD VIRGIN |
| toTitle | planet_51 | Planet 51 |
| toSentence | Passenger 57 | Passenger 57 |
| toCamel | 10-10-a-a-10-10 | 1010AA1010 |
| toPascal | Hello5My5Name5Is5Bond | Hello5My5Name5Is5Bond |
| toSnake | 48-HOLA-mundo-6 | 48_hola_mundo_6 |
| toMacro | 0-0-0 | 0_0_0 |
| toAda | Interstate 60 | Interstate_60 |
| toKebab | Happy2-see-you | happy2-see-you |
| toCobol | 123BC456BC789 | 123-B-C456-B-C789 |
| toTrain | 21-test-test21-21Test | 21-Test-Test21-21Test |
| toLower | TheNumber23 | the number23 |
| toUpper | 88 Minutes | 88 MINUTES |
| toTitle | United9 | United9 |
| toSentence | 300 | 300 |
| toCamel | the__0__is_the_best | the0IsTheBest |
| toPascal | i-do--not--0like--number0 | IDoNot0LikeNumber0 |
| toSnake | IDoNot0LikeNumber0 | i_do_not0_like_number0 |
| toMacro | you-have-0-money | YOU_HAVE_0_MONEY |
| toDot | se7en | se7en |
| toDot | Red1Green2Blue3 | red1.green2.blue3 |
| toDot | REEL2REAL | r.e.e.l2.r.e.a.l |
| toDot | reel2real | reel2real |
| toDot | Reel2Real | reel2.real |
Scenario: Retrieving original string
Given CaseConverter class is instantiated with " A commissioned mirror swears. "
When I call "getSource"
Then method should return string " A commissioned mirror swears. "
Scenario Outline: Handling strings with mixed delimiters
Given CaseConverter class is instantiated with ""
When I call ""
And I call ""
Then method should return string ""
Examples:
| from-method | to-method | input-string | output-string |
| fromSnake | toSnake | C-3PO_and_R2-D2 | c-3po_and_r2-d2 |
| fromSnake | toPascal | C-3PO_and_R2-D2 | C-3PoAndR2-D2 |
| fromPascal | toSnake | C-3PoAndR2-D2 | c-3_po_and_r2-_d2 |
| fromUpper | toDot | non-SI units | non-si.units |
| fromCamel | toDot | EstosSon_losActores | estos.son_los.actores |
Scenario Outline: Manually set input string format (test from* methods)
Given CaseConverter class is instantiated with ""
When I call ""
And I call ""
Then method should return string ""
Examples:
| from-method | to-method | input-string | output-string |
| fromDot | toSnake | v5.0.2 | v5_0_2 |
================================================
FILE: tests/phpunit/AdaCaseTest.php
================================================
getMockBuilder(AdaCase::class)
->disableOriginalConstructor()
->setMethods(['glueUsingRules'])
->getMock();
// Setting proper titleCase property value
$reflectionObject = new ReflectionObject($mock);
$titleCaseProperty = $reflectionObject->getProperty('titleCase');
$titleCaseProperty->setAccessible(true);
$titleCaseProperty->setValue($mock, 123);
// Configuring stub
$mock->expects($this->once())
->method('glueUsingRules')
->with(AdaCase::DELIMITER, 123)
->willReturn('dummy-value-e1bfd');
/** @var \Jawira\CaseConverter\Glue\AdaCase $mock */
$returned = $mock->glue();
$this->assertSame('dummy-value-e1bfd', $returned, 'Returned value is not the expected');
}
}
================================================
FILE: tests/phpunit/CamelCaseTest.php
================================================
getMockBuilder(CamelCase::class)
->disableOriginalConstructor()
->setMethods(['glueUsingRules'])
->getMock();
// Setting titleCase and lowerCase properties
$reflectionObject = new ReflectionObject($mock);
$titleCaseProperty = $reflectionObject->getProperty('titleCase');
$titleCaseProperty->setAccessible(true);
$titleCaseProperty->setValue($mock, 123);
$lowerCaseProperty = $reflectionObject->getProperty('lowerCase');
$lowerCaseProperty->setAccessible(true);
$lowerCaseProperty->setValue($mock, 456);
// Configuring stub
$mock->expects($this->once())
->method('glueUsingRules')
->with(CamelCase::DELIMITER, 123, 456)
->willReturn('dummy-value-32ea');
/** @var \Jawira\CaseConverter\Glue\CamelCase $mock */
$returned = $mock->glue();
$this->assertSame('dummy-value-32ea', $returned, 'Returned value is not the expected');
}
}
================================================
FILE: tests/phpunit/CaseConverterTest.php
================================================
convert('hello-world-484');
$this->assertInstanceOf(Convert::class, $convertObject);
$this->assertSame('hello-world-484', $convertObject->getSource());
}
}
================================================
FILE: tests/phpunit/CobolCaseTest.php
================================================
getMockBuilder(CobolCase::class)
->disableOriginalConstructor()
->setMethods(['glueUsingRules'])
->getMock();
// Setting `upperCase` property value
$reflectionObject = new ReflectionObject($mock);
$titleCaseProperty = $reflectionObject->getProperty('upperCase');
$titleCaseProperty->setAccessible(true);
$titleCaseProperty->setValue($mock, 789);
// Configuring stub
$mock->expects($this->once())
->method('glueUsingRules')
->with(CobolCase::DELIMITER, 789)
->willReturn('e1bfd762321e409cee4ac0b6e841963c');
/** @var \Jawira\CaseConverter\CobolCase $mock */
$returned = $mock->glue();
$this->assertSame('e1bfd762321e409cee4ac0b6e841963c', $returned, 'Returned value is not the expected');
}
}
================================================
FILE: tests/phpunit/ConvertTest.php
================================================
getMockBuilder(Convert::class)
->disableOriginalConstructor()
->setMethods()
->getMock();
// Removing protected for analyze method
$reflection = new ReflectionObject($stub);
$method = $reflection->getMethod('isUppercaseWord');
$method->setAccessible(true);
$output = $method->invoke($stub, $inputString, $digitsAreLowercase);
$this->assertSame($expectedResult, $output);
}
public function isUppercaseWordProvider()
{
return [
['X', true, true],
['YES', true, true],
['HELLO', true, true],
['', true, false],
['x', true, false],
['HELLOxWORLD', true, false],
['HELLO-WORLD', true, false],
['HELLO_WORLD', true, false],
['HelloWorld', true, false],
['CPU486', true, false],
['CPU486', false, true],
['IR35', true, false],
['IR35', false, true],
['ISO8601', true, false],
['ISO8601', false, true],
];
}
/**
* Testing \Jawira\CaseConverter\Convert::analyse
*
* \Jawira\CaseConverter\Convert::analyse should return Convert::SNAKE if $input contains '_'.
*
* @covers \Jawira\CaseConverter\Convert::analyse
* @covers \Jawira\CaseConverter\Split\Splitter::__construct
*
* @dataProvider analyseProvider
*
* @param bool $isUppercaseWordReturn Return value for `isUppercaseWord()`
* @param string $expected Expected result
* @param string $inputString Input string
*
* @throws \ReflectionException
*/
public function testAnalyse(bool $isUppercaseWordReturn, string $expected, string $inputString)
{
// Disabling constructor with one stub method
$stub = $this->getMockBuilder(Convert::class)
->disableOriginalConstructor()
->setMethods(['isUppercaseWord'])
->getMock();
// Configuring expectation
$stub->expects($this->any())
->method('isUppercaseWord')
->withAnyParameters()
->willReturn($isUppercaseWordReturn);
// Removing protected for analyze method
$reflection = new ReflectionObject($stub);
$method = $reflection->getMethod('analyse');
$method->setAccessible(true);
// Testing
$output = $method->invoke($stub, $inputString, true);
$this->assertInstanceOf($expected, $output);
}
public function analyseProvider()
{
return [
'Underscore 1' => [false, UnderscoreSplitter::class, 'hola_mundo'],
'Underscore 2' => [false, UnderscoreSplitter::class, 'HELLO_WORLD'],
'Underscore 3' => [true, UnderscoreSplitter::class, 'Ñ'],
'Underscore 4' => [true, UnderscoreSplitter::class, 'HELLO'],
'Underscore 5' => [false, UnderscoreSplitter::class, '_'],
'Underscore 6' => [false, UnderscoreSplitter::class, '_____'],
'Uppercase 1' => [false, UppercaseSplitter::class, ''],
'Uppercase 2' => [false, UppercaseSplitter::class, 'ñ'],
'Uppercase 3' => [false, UppercaseSplitter::class, 'one'],
'Uppercase 4' => [false, UppercaseSplitter::class, 'helloWorld'],
'Dash 1' => [false, DashSplitter::class, 'hello-World'],
'Dash 2' => [false, DashSplitter::class, 'my-name-is-bond'],
'Dash 3' => [false, DashSplitter::class, '-my-name-is-bond-'],
'Dash 4' => [false, DashSplitter::class, '-'],
'Dash 5' => [false, DashSplitter::class, '------'],
'Space 1' => [false, SpaceSplitter::class, 'Hola mundo'],
'Space 2' => [false, SpaceSplitter::class, 'Mi nombre es bond'],
'Space 3' => [false, SpaceSplitter::class, 'Formule courte spéciale été'],
'Space 4' => [false, SpaceSplitter::class, ' '],
'Space 5' => [false, SpaceSplitter::class, ' '],
'Dot 1' => [false, DotSplitter::class, 'one.two'],
'Dot 2' => [false, DotSplitter::class, '.hello.'],
'Dot 3' => [false, DotSplitter::class, '.'],
'Dot 4' => [false, DotSplitter::class, '........'],
];
}
/**
* Test _converter methods_: _toCamel_, _toSnake_, ...
*
* This test do not force the use of _Simple Case-Mapping_ .
*
* @dataProvider handleGluerMethodProvider()
*
* @covers \Jawira\CaseConverter\Convert::handleGluerMethod
*
* @param string $methodName
* @param string $className
*
* @throws \ReflectionException
*/
public function testHandleGluerMethod(string $methodName, string $className)
{
// Gluer class
$gluerMock = $this->getMockBuilder($className)
->disableOriginalConstructor()
->setMethods(['glue'])
->getMock();
$gluerMock->expects($this->once())
->method('glue')
->willReturn('this is a dummy text');
// Convert class
$convertMock = $this->getMockBuilder(Convert::class)
->disableOriginalConstructor()
->setMethods(['createGluer'])
->getMock();
$convertMock->expects($this->once())
->method('createGluer')
->with($className, ['dummy', 'd455b'], false)
->willReturn($gluerMock);
// Setting detected words
$reflectionObject = new ReflectionObject($convertMock);
$wordsProperty = $reflectionObject->getProperty('words');
$wordsProperty->setAccessible(true);
$wordsProperty->setValue($convertMock, ['dummy', 'd455b']);
// Setting _Simple Case-Mapping_ as false
$forceProperty = $reflectionObject->getProperty('forceSimpleCaseMapping');
$forceProperty->setAccessible(true);
$forceProperty->setValue($convertMock, false);
// Invoking protected method
$method = new ReflectionMethod($convertMock, 'handleGluerMethod');
$method->setAccessible(true);
$result = $method->invokeArgs($convertMock, [$methodName]);
$this->assertSame('this is a dummy text', $result);
}
/**
* Test _converter methods_: _toCamel_, _toSnake_, ...
*
* This test do not force the use of _Simple Case-Mapping_ .
*
* @covers \Jawira\CaseConverter\Convert::handleGluerMethod
*
* @throws \ReflectionException
*/
public function testHandleGluerMethodWithException()
{
// Preparing exception
$this->expectException(CaseConverterException::class);
$this->expectExceptionMessage('Unknown method: myDummyMethod');
// Convert class
$convertMock = $this->getMockBuilder(Convert::class)
->disableOriginalConstructor()
->setMethods()
->getMock();
// Invoking protected method
$method = new ReflectionMethod($convertMock, 'handleGluerMethod');
$method->setAccessible(true);
$method->invokeArgs($convertMock, ['myDummyMethod']);
}
/**
* Return and array with the name of all _converter methods_.
*/
public function handleGluerMethodProvider()
{
return [
'toAda' => ['toAda', AdaCase::class],
'toCamel' => ['toCamel', CamelCase::class],
'toCobol' => ['toCobol', CobolCase::class],
'toKebab' => ['toKebab', KebabCase::class],
'toLower' => ['toLower', LowerCase::class],
'toMacro' => ['toMacro', MacroCase::class],
'toPascal' => ['toPascal', PascalCase::class],
'toSentence' => ['toSentence', SentenceCase::class],
'toSnake' => ['toSnake', SnakeCase::class],
'toTitle' => ['toTitle', TitleCase::class],
'toTrain' => ['toTrain', TrainCase::class],
'toUpper' => ['toUpper', UpperCase::class],
'toDot' => ['toDot', DotNotation::class],
];
}
/**
* Returns all valid splitters that can be used by Convert::extractWords()
*
* @return array
*/
public function extractWordsProviders()
{
return [
[SpaceSplitter::class],
[DashSplitter::class],
[UnderscoreSplitter::class],
[UppercaseSplitter::class],
];
}
/**
* @covers \Jawira\CaseConverter\Convert::toArray
*
* @throws \ReflectionException
*/
public function testToArray()
{
// Preparing Convert mock
$mock = $this->getMockBuilder(Convert::class)
->disableOriginalConstructor()
->setMethods()
->getMock();
// Setting value to protected property
$reflectionObject = new ReflectionObject($mock);
$reflectionProperty = $reflectionObject->getProperty('words');
$reflectionProperty->setAccessible(true);
$reflectionProperty->setValue($mock, ['dummy', 'array']);
/** @var \Jawira\CaseConverter\Convert $mock */
$currentArray = $mock->toArray();
$this->assertIsArray($currentArray);
$this->assertEquals(['dummy', 'array'], $currentArray);
}
/**
* @covers \Jawira\CaseConverter\Convert::createGluer
* @covers \Jawira\CaseConverter\Glue\Gluer::__construct
* @dataProvider createGluerProvider
*
* @param string $className
*
* @throws \ReflectionException
*/
public function testCreateGluer(string $className)
{
// Preparing Convert mock
$mock = $this->getMockBuilder(Convert::class)
->disableOriginalConstructor()
->setMethods()
->getMock();
// Calling protected method
$reflectionObject = new ReflectionObject($mock);
$reflectionMethod = $reflectionObject->getMethod('createGluer');
$reflectionMethod->setAccessible(true);
$gluerObject = $reflectionMethod->invoke($mock, $className, ['dummy', 'array'], false);
$this->assertInstanceOf(Gluer::class, $gluerObject);
}
public function createGluerProvider()
{
return [
[AdaCase::class],
[CamelCase::class],
[CobolCase::class],
[KebabCase::class],
[LowerCase::class],
[MacroCase::class],
[PascalCase::class],
[SentenceCase::class],
[SnakeCase::class],
[TitleCase::class],
[TrainCase::class],
[UpperCase::class],
];
}
/**
* @covers \Jawira\CaseConverter\Convert::getSource
* @throws \ReflectionException
*/
public function testGetSource()
{
// Preparing Convert object
$convertMock = $this->getMockBuilder(Convert::class)
->disableOriginalConstructor()
->setMethods()
->getMock();
// Setting detected words
$reflectionObject = new ReflectionObject($convertMock);
$sourceProperty = $reflectionObject->getProperty('source');
$sourceProperty->setAccessible(true);
$sourceProperty->setValue($convertMock, 'this is source string');
/** @var Convert $convertMock */
$result = $convertMock->getSource();
$this->assertSame('this is source string', $result);
}
/**
* @throws \ReflectionException
* @covers \Jawira\CaseConverter\Convert::fromAuto
*/
public function testFromAuto()
{
// Preparing Convert object
$convertMock = $this->getMockBuilder(Convert::class)
->disableOriginalConstructor()
->setMethods(['analyse', 'extractWords'])
->getMock();
$strategyMock = $this->getMockBuilder(Splitter::class)
->disableOriginalConstructor()
->getMockForAbstractClass();
// set 'source' attribute
$reflectionObject = new ReflectionObject($convertMock);
$wordsProperty = $reflectionObject->getProperty('source');
$wordsProperty->setAccessible(true);
$wordsProperty->setValue($convertMock, 'dummy-original-string');
// stub analyse
$convertMock->expects($this->once())
->method('analyse')
->with('dummy-original-string')
->willReturn($strategyMock);
// stub extractWords
$convertMock->expects($this->once())
->method('extractWords')
->with($strategyMock)
->willReturnSelf();
// Calling protected method
$reflectionObject = new ReflectionObject($convertMock);
$reflectionMethod = $reflectionObject->getMethod('fromAuto');
$reflectionMethod->setAccessible(true);
$result = $reflectionMethod->invoke($convertMock, 'fromAuto');
$this->assertInstanceOf(Convert::class, $result);
$this->assertSame($convertMock, $result);
}
/**
* @covers \Jawira\CaseConverter\Convert::handleSplitterMethod
*
* @param string $methodName
* @param string $splitterName
*
* @dataProvider handleSplitterMethodProvider
*
* @throws \ReflectionException
*/
public function testHandleSplitterMethod(string $methodName = 'fromKebab', string $splitterName = DashSplitter::class, string $sourceString = 'dummy-azer12')
{
// Splitter class
$splitterMock = $this->getMockBuilder($splitterName)
->disableOriginalConstructor()
->getMock();
// Convert class
$convertMock = $this->getMockBuilder(Convert::class)
->disableOriginalConstructor()
->setMethods(['createSplitter', 'extractWords'])
->getMock();
$convertMock->expects($this->once())
->method('createSplitter')
->with($splitterName, $sourceString)
->willReturn($splitterMock);
$convertMock->expects($this->once())
->method('extractWords')
->with($splitterMock);
// Add source attribute
$reflectionObject = new ReflectionObject($convertMock);
$wordsProperty = $reflectionObject->getProperty('source');
$wordsProperty->setAccessible(true);
$wordsProperty->setValue($convertMock, $sourceString);
// Invoking protected method
$method = new ReflectionMethod($convertMock, 'handleSplitterMethod');
$method->setAccessible(true);
$result = $method->invoke($convertMock, $methodName);
$this->assertSame($convertMock, $result);
}
public function handleSplitterMethodProvider()
{
return [
['fromCamel', UppercaseSplitter::class],
['fromPascal', UppercaseSplitter::class],
['fromSnake', UnderscoreSplitter::class],
['fromAda', UnderscoreSplitter::class],
['fromMacro', UnderscoreSplitter::class],
['fromKebab', DashSplitter::class],
['fromTrain', DashSplitter::class],
['fromCobol', DashSplitter::class],
['fromLower', SpaceSplitter::class],
['fromUpper', SpaceSplitter::class],
['fromTitle', SpaceSplitter::class],
['fromSentence', SpaceSplitter::class],
['fromDot', DotSplitter::class],
];
}
/**
* @covers \Jawira\CaseConverter\Convert::handleSplitterMethod
*
* @throws \ReflectionException
*/
public function testHandleSplitterMethodWithException()
{
// Preparing exception
$this->expectException(CaseConverterException::class);
$this->expectExceptionMessage('Unknown method: myDummyMethod');
// Convert class
$convertMock = $this->getMockBuilder(Convert::class)
->disableOriginalConstructor()
->setMethods()
->getMock();
// Invoking protected method
$method = new ReflectionMethod($convertMock, 'handleSplitterMethod');
$method->setAccessible(true);
$method->invokeArgs($convertMock, ['myDummyMethod']);
}
/**
* @covers \Jawira\CaseConverter\Convert::createSplitter
* @covers \Jawira\CaseConverter\Split\Splitter::__construct
*
* @dataProvider createSplitterProvider
*
* @param string $className
*
* @throws \ReflectionException
*/
public function testCreateSplitter(string $className)
{
// Preparing Convert mock
$mock = $this->getMockBuilder(Convert::class)
->disableOriginalConstructor()
->setMethods()
->getMock();
// Calling protected method
$reflectionObject = new ReflectionObject($mock);
$reflectionMethod = $reflectionObject->getMethod('createSplitter');
$reflectionMethod->setAccessible(true);
$splitterObject = $reflectionMethod->invoke($mock, $className, 'dummy-string', false);
$this->assertInstanceOf($className, $splitterObject);
}
public function createSplitterProvider()
{
return [
[DashSplitter::class, 'dummy-string'],
[SpaceSplitter::class, 'dummy-string'],
[UnderscoreSplitter::class, 'dummy-string'],
[UppercaseSplitter::class, 'dummy-string'],
];
}
/**
* Testing magic function call
*
* @covers \Jawira\CaseConverter\Convert::__call
* @dataProvider callProvider
*
* @param string $methodName
* @param array $arguments
* @param int $splitterCount
* @param int $gluerCount
* @param mixed $handlerResult
*/
public function testCall(string $methodName, $arguments, int $splitterCount, int $gluerCount, string $handlerResult = '')
{
// Preparing Convert mock
$convertMock = $this->getMockBuilder(Convert::class)
->disableOriginalConstructor()
->setMethods(['handleSplitterMethod', 'handleGluerMethod'])
->getMock();
$convertMock->expects($this->exactly($splitterCount))
->method('handleSplitterMethod')
->with($methodName)
->willReturnSelf();
$convertMock->expects($this->exactly($gluerCount))
->method('handleGluerMethod')
->with($methodName)
->willReturn($handlerResult);
/** @var string|\Jawira\CaseConverter\Split\Splitter $result */
$result = $convertMock->__call($methodName, $arguments);
if ($splitterCount) {
$this->assertInstanceOf(Convert::class, $result);
}
if ($gluerCount) {
$this->assertSame($handlerResult, $result);
}
}
public function callProvider()
{
return [
['toDummy', [], 0, 1, '46d54fd5'],
['toAda', [], 0, 1, 'ed65f'],
['toCamel', [], 0, 1, '65hg4jk45'],
['toCobol', [], 0, 1, 'a1g94a1'],
['toKebab', [], 0, 1, 'd4g2q1df'],
['toLower', [], 0, 1, 'ff4f1f'],
['toMacro', [], 0, 1, 'fe64df'],
['toPascal', [], 0, 1, 'ff1f1f1f'],
['toSentence', [], 0, 1, 'de9e1d'],
['toSnake', [], 0, 1, 'fdq1nh1jl'],
['toTitle', [], 0, 1, 'hjy94'],
['toTrain', [], 0, 1, 'g4i4ol'],
['toUpper', [], 0, 1, 'gu1ioo1'],
['fromDummy', [], 1, 0],
['fromAda', [], 1, 0],
['fromCamel', [], 1, 0],
['fromCobol', [], 1, 0],
['fromKebab', [], 1, 0],
['fromLower', [], 1, 0],
['fromMacro', [], 1, 0],
['fromPascal', [], 1, 0],
['fromSentence', [], 1, 0],
['fromSnake', [], 1, 0],
['fromTitle', [], 1, 0],
['fromTrain', [], 1, 0],
['fromUpper', [], 1, 0],
];
}
/**
* @covers \Jawira\CaseConverter\Convert::__call
*/
public function testCallException()
{
$this->expectException(Jawira\CaseConverter\CaseConverterException::class);
$this->expectExceptionMessage('Unknown method: invalidMethod');
// Preparing Convert mock
$convertMock = $this->getMockBuilder(Convert::class)
->disableOriginalConstructor()
->setMethods()
->getMock();
/** @var string|\Jawira\CaseConverter\Split\Splitter $result */
$convertMock->__call('invalidMethod', []);
}
}
================================================
FILE: tests/phpunit/DashSplitterTest.php
================================================
getMockBuilder(DashSplitter::class)
->disableOriginalConstructor()
->setMethods(['splitUsingPattern'])
->getMock();
// Setting value to protected property
$reflectionObject = new ReflectionObject($mock);
$reflectionProperty = $reflectionObject->getProperty('inputString');
$reflectionProperty->setAccessible(true);
$reflectionProperty->setValue($mock, 'dummyString');
// Configuring stub
$mock->expects($this->once())
->method('splitUsingPattern')
->with('dummyString', '#-+#u')
->willReturn(['dummy', 'array']);
/** @var \Jawira\CaseConverter\Split\DashSplitter $mock */
$returned = $mock->split();
$this->assertSame(['dummy', 'array'], $returned);
}
}
================================================
FILE: tests/phpunit/DotNotationTest.php
================================================
getMockBuilder(DotNotation::class)
->disableOriginalConstructor()
->setMethods(['glueUsingRules'])
->getMock();
// Setting `upperCase` property value
$reflectionObject = new ReflectionObject($mock);
$titleCaseProperty = $reflectionObject->getProperty('lowerCase');
$titleCaseProperty->setAccessible(true);
$titleCaseProperty->setValue($mock, 789);
// Configuring stub
$mock->expects($this->once())
->method('glueUsingRules')
->with(DotNotation::DELIMITER, 789)
->willReturn('e1bfd762321e409cee4ac0b6e841963c');
/** @var \Jawira\CaseConverter\Glue\MacroCase $mock */
$returned = $mock->glue();
$this->assertSame('e1bfd762321e409cee4ac0b6e841963c', $returned, 'Returned value is not the expected');
}
}
================================================
FILE: tests/phpunit/DotSplitterTest.php
================================================
getMockBuilder(DotSplitter::class)
->disableOriginalConstructor()
->setMethods(['splitUsingPattern'])
->getMock();
// Setting value to protected property
$reflectionObject = new ReflectionObject($mock);
$reflectionProperty = $reflectionObject->getProperty('inputString');
$reflectionProperty->setAccessible(true);
$reflectionProperty->setValue($mock, 'dummyString');
// Configuring stub
$mock->expects($this->once())
->method('splitUsingPattern')
->with('dummyString', '#\\.+#u')
->willReturn(['dummy', 'array']);
/** @var \Jawira\CaseConverter\Split\UnderscoreSplitter $mock */
$returned = $mock->split();
$this->assertSame(['dummy', 'array'], $returned);
}
}
================================================
FILE: tests/phpunit/GluerTest.php
================================================
getMockBuilder(Gluer::class)
->disableOriginalConstructor()
->setMethods(['changeWordsCase', 'changeFirstWordCase'])
->getMockForAbstractClass();
// Making "words" property accessible and setting a value
$reflection = new ReflectionObject($mock);
$property = $reflection->getProperty('words');
$property->setAccessible(true);
$property->setValue($mock, $words);
// Making public a protected method
$reflection = new ReflectionObject($mock);
$method = $reflection->getMethod('glueUsingRules');
$method->setAccessible(true);
// Expectations for changeWordsCase
$mock->expects($this->once())
->method('changeWordsCase')
->with($this->equalTo($words, $wordsMode))
->will($this->returnValue($words));
// Only checking that method is called
$expectation = ($firstWordMode) ? $this->once() : $this->never();
$mock->expects($expectation)
->method('changeFirstWordCase')
->with($words, $firstWordMode)
->will($this->returnValue($words));
// Testing
$output = $method->invoke($mock, $glue, $wordsMode, $firstWordMode);
$this->assertSame($expected, $output);
}
/**
* @return array
*/
public function glueUsingRulesProvider()
{
return [
[['fOo', 'bAr'], '§', MB_CASE_LOWER, null, 'fOo§bAr'],
[['fOo', 'bAr'], '§', MB_CASE_LOWER, MB_CASE_LOWER, 'fOo§bAr'],
[['fOo', 'bAr'], 'X', MB_CASE_LOWER, null, 'fOoXbAr'],
[['fOo', 'bAr'], 'X', MB_CASE_LOWER, MB_CASE_LOWER, 'fOoXbAr'],
];
}
/**
* @covers \Jawira\CaseConverter\Glue\Gluer::changeWordsCase
* @dataProvider changeWordsCaseProvider
*
* @param array $words
* @param int $caseMode
* @param array $expected
*
* @throws \ReflectionException
*/
public function testChangeWordsCase($words, $caseMode, $expected)
{
// Disabling constructor without stub methods
$mock = $this->getMockBuilder(Gluer::class)
->disableOriginalConstructor()
->setMethods(['glueUsingRules'])
->getMockForAbstractClass();
// Making public a protected method
$reflection = new ReflectionObject($mock);
$method = $reflection->getMethod('changeWordsCase');
$method->setAccessible(true);
$result = $method->invoke($mock, $words, $caseMode);
$this->assertSame($expected, $result);
}
public function changeWordsCaseProvider()
{
return [
[[], MB_CASE_LOWER, []],
[['hola', 'mundo'], MB_CASE_LOWER, ['hola', 'mundo']],
[['hola', 'mundo'], MB_CASE_UPPER, ['HOLA', 'MUNDO']],
[['hola', 'mundo'], MB_CASE_TITLE, ['Hola', 'Mundo']],
[['HoLa', 'MuNdO'], MB_CASE_LOWER, ['hola', 'mundo']],
[['HoLa', 'MuNdO'], MB_CASE_UPPER, ['HOLA', 'MUNDO']],
[['HoLa', 'MuNdO'], MB_CASE_TITLE, ['Hola', 'Mundo']],
];
}
/**
* @covers \Jawira\CaseConverter\Glue\Gluer::changeFirstWordCase
* @dataProvider changeFirstWordCaseProvider
*
* @param array $words
* @param int $caseMode
* @param array $expected
*
* @throws \ReflectionException
*/
public function testChangeFirstWordsCase($words, $caseMode, $expected)
{
// Disabling constructor without stub methods
$mock = $this->getMockBuilder(Gluer::class)
->disableOriginalConstructor()
->setMethods(['glueUsingRules'])
->getMockForAbstractClass();
// Making public a protected method
$reflection = new ReflectionObject($mock);
$method = $reflection->getMethod('changeFirstWordCase');
$method->setAccessible(true);
$result = $method->invoke($mock, $words, $caseMode);
$this->assertSame($expected, $result);
}
public function changeFirstWordCaseProvider()
{
return [
[[], MB_CASE_LOWER, []],
[['hola', 'mundo'], MB_CASE_LOWER, ['hola', 'mundo']],
[['hola', 'mundo'], MB_CASE_UPPER, ['HOLA', 'mundo']],
[['hola', 'mundo'], MB_CASE_TITLE, ['Hola', 'mundo']],
[['HoLa', 'MuNdO'], MB_CASE_LOWER, ['hola', 'MuNdO']],
[['HoLa', 'MuNdO'], MB_CASE_UPPER, ['HOLA', 'MuNdO']],
[['HoLa', 'MuNdO'], MB_CASE_TITLE, ['Hola', 'MuNdO']],
];
}
public function constructorProvider()
{
return [
[['dummy', 'f4s2Q'], false, 0],
[['dummy', '7e7e7'], true, 1],
];
}
}
================================================
FILE: tests/phpunit/KebabCaseTest.php
================================================
getMockBuilder(KebabCase::class)
->disableOriginalConstructor()
->setMethods(['glueUsingRules'])
->getMock();
// Setting lowerCase properties
$reflectionObject = new ReflectionObject($mock);
$titleCaseProperty = $reflectionObject->getProperty('lowerCase');
$titleCaseProperty->setAccessible(true);
$titleCaseProperty->setValue($mock, 456);
// Configuring stub
$mock->expects($this->once())
->method('glueUsingRules')
->with(KebabCase::DELIMITER, 456)
->willReturn('e1bfd762321e409cee4ac0b6e841963c');
/** @var \Jawira\CaseConverter\Glue\KebabCase $mock */
$returned = $mock->glue();
$this->assertSame('e1bfd762321e409cee4ac0b6e841963c', $returned, 'Returned value is not the expected');
}
}
================================================
FILE: tests/phpunit/LowerCaseTest.php
================================================
getMockBuilder(LowerCase::class)
->disableOriginalConstructor()
->setMethods(['glueUsingRules'])
->getMock();
// Setting lowerCase properties
$reflectionObject = new ReflectionObject($mock);
$titleCaseProperty = $reflectionObject->getProperty('lowerCase');
$titleCaseProperty->setAccessible(true);
$titleCaseProperty->setValue($mock, 456);
// Configuring stub
$mock->expects($this->once())
->method('glueUsingRules')
->with(LowerCase::DELIMITER, 456)
->willReturn('e1bfd762321e409cee4ac0b6e841963c');
/** @var \Jawira\CaseConverter\Glue\LowerCase $mock */
$returned = $mock->glue();
$this->assertSame('e1bfd762321e409cee4ac0b6e841963c', $returned, 'Returned value is not the expected');
}
}
================================================
FILE: tests/phpunit/MacroCaseTest.php
================================================
getMockBuilder(MacroCase::class)
->disableOriginalConstructor()
->setMethods(['glueUsingRules'])
->getMock();
// Setting `upperCase` property value
$reflectionObject = new ReflectionObject($mock);
$titleCaseProperty = $reflectionObject->getProperty('upperCase');
$titleCaseProperty->setAccessible(true);
$titleCaseProperty->setValue($mock, 789);
// Configuring stub
$mock->expects($this->once())
->method('glueUsingRules')
->with(MacroCase::DELIMITER, 789)
->willReturn('e1bfd762321e409cee4ac0b6e841963c');
/** @var \Jawira\CaseConverter\Glue\MacroCase $mock */
$returned = $mock->glue();
$this->assertSame('e1bfd762321e409cee4ac0b6e841963c', $returned, 'Returned value is not the expected');
}
}
================================================
FILE: tests/phpunit/PascalCaseTest.php
================================================
getMockBuilder(PascalCase::class)
->disableOriginalConstructor()
->setMethods(['glueUsingRules'])
->getMock();
// Setting titleCase and lowerCase properties
$reflectionObject = new ReflectionObject($mock);
$titleCaseProperty = $reflectionObject->getProperty('titleCase');
$titleCaseProperty->setAccessible(true);
$titleCaseProperty->setValue($mock, 789);
// Configuring stub
$mock->expects($this->once())
->method('glueUsingRules')
->with(PascalCase::DELIMITER, 789)
->willReturn('e1bfd762321e409cee4ac0b6e841963c');
/** @var \Jawira\CaseConverter\Glue\PascalCase $mock */
$returned = $mock->glue();
$this->assertSame('e1bfd762321e409cee4ac0b6e841963c', $returned, 'Returned value is not the expected');
}
}
================================================
FILE: tests/phpunit/SentenceCaseTest.php
================================================
getMockBuilder(SentenceCase::class)
->disableOriginalConstructor()
->setMethods(['glueUsingRules'])
->getMock();
// Setting titleCase and lowerCase properties
$reflectionObject = new ReflectionObject($mock);
$titleCaseProperty = $reflectionObject->getProperty('titleCase');
$titleCaseProperty->setAccessible(true);
$titleCaseProperty->setValue($mock, 123);
$lowerCaseProperty = $reflectionObject->getProperty('lowerCase');
$lowerCaseProperty->setAccessible(true);
$lowerCaseProperty->setValue($mock, 456);
// Configuring stub
$mock->expects($this->once())
->method('glueUsingRules')
->with(SentenceCase::DELIMITER, 456, 123)
->willReturn('e1bfd762321e409cee4ac0b6e841963c');
/** @var \Jawira\CaseConverter\Glue\SentenceCase $mock */
$returned = $mock->glue();
$this->assertSame('e1bfd762321e409cee4ac0b6e841963c', $returned, 'Returned value is not the expected');
}
}
================================================
FILE: tests/phpunit/SnakeCaseTest.php
================================================
getMockBuilder(SnakeCase::class)
->disableOriginalConstructor()
->setMethods(['glueUsingRules'])
->getMock();
// Setting titleCase and lowerCase properties
$reflectionObject = new ReflectionObject($mock);
$lowerCaseProperty = $reflectionObject->getProperty('lowerCase');
$lowerCaseProperty->setAccessible(true);
$lowerCaseProperty->setValue($mock, 456);
// Configuring stub
$mock->expects($this->once())
->method('glueUsingRules')
->with(SnakeCase::DELIMITER, 456)
->willReturn('e1bfd762321e409cee4ac0b6e841963c');
/** @var \Jawira\CaseConverter\Glue\SnakeCase $mock */
$returned = $mock->glue();
$this->assertSame('e1bfd762321e409cee4ac0b6e841963c', $returned, 'Returned value is not the expected');
}
}
================================================
FILE: tests/phpunit/SpaceSplitterTest.php
================================================
getMockBuilder(SpaceSplitter::class)
->disableOriginalConstructor()
->setMethods(['splitUsingPattern'])
->getMock();
// Setting value to protected property
$reflectionObject = new ReflectionObject($mock);
$reflectionProperty = $reflectionObject->getProperty('inputString');
$reflectionProperty->setAccessible(true);
$reflectionProperty->setValue($mock, 'dummyString');
// Configuring stub
$mock->expects($this->once())
->method('splitUsingPattern')
->with('dummyString', '# +#u')
->willReturn(['dummy', 'array']);
/** @var \Jawira\CaseConverter\Split\SpaceSplitter $mock */
$returned = $mock->split();
$this->assertSame(['dummy', 'array'], $returned);
}
}
================================================
FILE: tests/phpunit/SplitterTest.php
================================================
getMockBuilder(SpaceSplitter::class)
->disableOriginalConstructor()
->setMethods([])
->getMock();
// Invoking protected method
$method = new ReflectionMethod($mock, 'splitUsingPattern');
$method->setAccessible(true);
$result = $method->invokeArgs($mock, [$inputString, $pattern]);
$this->assertSame($expected, $result);
}
public function splitUsingPatternProvider()
{
return [
['', '#-+#u', []],
['hola-mundo', '#-+#u', ['hola', 'mundo']],
['-hola-mundo-', '#-+#u', ['hola', 'mundo']],
['---hola-----mundo---', '#-+#u', ['hola', 'mundo']],
['0', '#-+#u', ['0']],
['---0---0---', '#-+#u', ['0', '0']],
['---000---000---', '#-+#u', ['000', '000']],
];
}
}
================================================
FILE: tests/phpunit/TitleCaseTest.php
================================================
getMockBuilder(TitleCase::class)
->disableOriginalConstructor()
->setMethods(['glueUsingRules'])
->getMock();
// Setting titleCase and lowerCase properties
$reflectionObject = new ReflectionObject($mock);
$titleCaseProperty = $reflectionObject->getProperty('titleCase');
$titleCaseProperty->setAccessible(true);
$titleCaseProperty->setValue($mock, 123);
// Configuring stub
$mock->expects($this->once())
->method('glueUsingRules')
->with(TitleCase::DELIMITER, 123)
->willReturn('e1bfd762321e409cee4ac0b6e841963c');
/** @var \Jawira\CaseConverter\TitleCase $mock */
$returned = $mock->glue();
$this->assertSame('e1bfd762321e409cee4ac0b6e841963c', $returned, 'Returned value is not the expected');
}
}
================================================
FILE: tests/phpunit/TrainCaseTest.php
================================================
getMockBuilder(TrainCase::class)
->disableOriginalConstructor()
->setMethods(['glueUsingRules'])
->getMock();
// Setting titleCase and lowerCase properties
$reflectionObject = new ReflectionObject($mock);
$titleCaseProperty = $reflectionObject->getProperty('titleCase');
$titleCaseProperty->setAccessible(true);
$titleCaseProperty->setValue($mock, 123);
// Configuring stub
$mock->expects($this->once())
->method('glueUsingRules')
->with(TrainCase::DELIMITER, 123)
->willReturn('e1bfd762321e409cee4ac0b6e841963c');
/** @var \Jawira\CaseConverter\Glue\TrainCase $mock */
$returned = $mock->glue();
$this->assertSame('e1bfd762321e409cee4ac0b6e841963c', $returned, 'Returned value is not the expected');
}
}
================================================
FILE: tests/phpunit/UnderscoreSplitterTest.php
================================================
getMockBuilder(UnderscoreSplitter::class)
->disableOriginalConstructor()
->setMethods(['splitUsingPattern'])
->getMock();
// Setting value to protected property
$reflectionObject = new ReflectionObject($mock);
$reflectionProperty = $reflectionObject->getProperty('inputString');
$reflectionProperty->setAccessible(true);
$reflectionProperty->setValue($mock, 'dummyString');
// Configuring stub
$mock->expects($this->once())
->method('splitUsingPattern')
->with('dummyString', '#_+#u')
->willReturn(['dummy', 'array']);
/** @var \Jawira\CaseConverter\Split\UnderscoreSplitter $mock */
$returned = $mock->split();
$this->assertSame(['dummy', 'array'], $returned);
}
}
================================================
FILE: tests/phpunit/UpperCaseTest.php
================================================
getMockBuilder(UpperCase::class)
->disableOriginalConstructor()
->setMethods(['glueUsingRules'])
->getMock();
// Setting titleCase and lowerCase properties
$reflectionObject = new ReflectionObject($mock);
$titleCaseProperty = $reflectionObject->getProperty('upperCase');
$titleCaseProperty->setAccessible(true);
$titleCaseProperty->setValue($mock, 789);
// Configuring stub
$mock->expects($this->once())
->method('glueUsingRules')
->with(UpperCase::DELIMITER, 789)
->willReturn('e1bfd762321e409cee4ac0b6e841963c');
/** @var \Jawira\CaseConverter\Glue\UpperCase $mock */
$returned = $mock->glue();
$this->assertSame('e1bfd762321e409cee4ac0b6e841963c', $returned, 'Returned value is not the expected');
}
}
================================================
FILE: tests/phpunit/UppercaseSplitterTest.php
================================================
getMockBuilder(UppercaseSplitter::class)
->disableOriginalConstructor()
->setMethods(['splitUsingPattern'])
->getMock();
// Setting value to protected property
$reflectionObject = new ReflectionObject($mock);
$reflectionProperty = $reflectionObject->getProperty('inputString');
$reflectionProperty->setAccessible(true);
$reflectionProperty->setValue($mock, 'dummyString');
// Configuring stub
$mock->expects($this->once())
->method('splitUsingPattern')
->with('dummyString', '#(?=\p{Lu}{1})#u')
->willReturn(['dummy', 'array']);
/** @var \Jawira\CaseConverter\Split\UnderscoreSplitter $mock */
$returned = $mock->split();
$this->assertSame(['dummy', 'array'], $returned);
}
}