├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── composer.json ├── phpunit.xml.dist ├── src └── Camel │ ├── CaseTransformer.php │ ├── CaseTransformerInterface.php │ └── Format │ ├── CamelCase.php │ ├── FormatInterface.php │ ├── ScreamingSnakeCase.php │ ├── SnakeCase.php │ ├── SpinalCase.php │ └── StudlyCaps.php └── tests ├── Camel └── Tests │ ├── CaseTransformerTest.php │ └── Format │ ├── CamelCaseTest.php │ ├── FormatTest.php │ ├── ScreamingSnakeCaseTest.php │ ├── SnakeCaseTest.php │ ├── SpinalCaseTest.php │ └── StudlyCapsTest.php └── bootstrap.php /.gitignore: -------------------------------------------------------------------------------- 1 | vendor 2 | composer.lock 3 | phpunit.xml 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | php: 4 | - 5.3 5 | - 5.4 6 | - 7.0 7 | 8 | before_script: 9 | - composer install 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 Matthieu Moquet 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is furnished 8 | to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Camel 2 | 3 | [![Build status...](https://img.shields.io/travis/MattKetmo/camel.svg?style=flat)](http://travis-ci.org/MattKetmo/camel) 4 | [![Code quality...](https://img.shields.io/scrutinizer/g/MattKetmo/camel.svg?style=flat)](https://scrutinizer-ci.com/g/MattKetmo/camel/) 5 | [![License MIT](http://img.shields.io/badge/license-MIT-blue.svg?style=flat)](https://github.com/MattKetmo/camel/blob/master/LICENSE) 6 | [![Packagist](http://img.shields.io/packagist/v/mattketmo/camel.svg?style=flat)](https://packagist.org/packages/mattketmo/camel) 7 | 8 | Tiny library to handle words case transformation. 9 | 10 | The main idea is to split the given word into several words and assemble them 11 | in another format. 12 | 13 | Example: `camelCase => [camel, Case] => camel_case` 14 | 15 | ## Installation 16 | 17 | ```shell 18 | composer require mattketmo/camel 19 | ``` 20 | 21 | ## Usage 22 | 23 | ```php 24 | transform('hello_world'); // helloWorld 35 | echo $transformer2->transform('helloWorld'); // HELLO_WORLD 36 | ``` 37 | 38 | ## Supported formats 39 | 40 | - `camelCase` 41 | - `StudlyCaps` 42 | - `snake_case` 43 | - `SCREAMING_SNAKE_CASE` 44 | - `spinal-case` 45 | 46 | ## Unit Tests 47 | 48 | Install `phpunit` via Composer: 49 | 50 | ```shell 51 | composer install 52 | ``` 53 | 54 | Once installed, run the following command: 55 | 56 | ```shell 57 | vendor/bin/phpunit 58 | ``` 59 | 60 | ## License 61 | 62 | Camel is released under the MIT License. 63 | See the [bundled LICENSE file](LICENSE) for details. 64 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mattketmo/camel", 3 | "description": "Tiny library to handle words case transformation", 4 | "license": "MIT", 5 | "keywords": ["case", "transform", "camelcase", "snakecase", "lowercase"], 6 | "authors": [ 7 | { 8 | "name": "Matthieu Moquet", 9 | "email": "matthieu@moquet.net" 10 | } 11 | ], 12 | "autoload": { 13 | "psr-0": { 14 | "Camel": "src/" 15 | } 16 | }, 17 | "require-dev": { 18 | "phpunit/phpunit": "4.6.*" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 | 15 | 16 | tests 17 | 18 | 19 | 20 | 21 | 22 | . 23 | 24 | tests 25 | vendor 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /src/Camel/CaseTransformer.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Camel; 13 | 14 | use Camel\Format\FormatInterface; 15 | 16 | /** 17 | * Global transformer used to manage format conversion. 18 | * 19 | * @author Matthieu Moquet 20 | */ 21 | class CaseTransformer implements CaseTransformerInterface 22 | { 23 | /** 24 | * @var FormatInterface Initial case format 25 | */ 26 | protected $from; 27 | 28 | /** 29 | * @var FormatInterface Final case format 30 | */ 31 | protected $to; 32 | 33 | /** 34 | * @param FormatInterface $from 35 | * @param FormatInterface $to 36 | */ 37 | public function __construct(FormatInterface $from, FormatInterface $to) 38 | { 39 | $this->from = $from; 40 | $this->to = $to; 41 | } 42 | 43 | /** 44 | * {@inheritdoc} 45 | */ 46 | public function transform($word) 47 | { 48 | $words = $this->from->split($word); 49 | 50 | return $this->to->join($words); 51 | } 52 | } -------------------------------------------------------------------------------- /src/Camel/CaseTransformerInterface.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Camel; 13 | 14 | /** 15 | * Transform the case of a word. 16 | * 17 | * @author Matthieu Moquet 18 | */ 19 | interface CaseTransformerInterface 20 | { 21 | /** 22 | * Transform a word from a case format to an other. 23 | * 24 | * @param string $word The initial word 25 | * 26 | * @return string The transformed word 27 | */ 28 | public function transform($word); 29 | } -------------------------------------------------------------------------------- /src/Camel/Format/CamelCase.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Camel\Format; 13 | 14 | /** 15 | * Format to handle camelCase. 16 | * 17 | * @author Matthieu Moquet 18 | */ 19 | class CamelCase extends StudlyCaps 20 | { 21 | /** 22 | * {@inheritdoc} 23 | */ 24 | public function join(array $words) 25 | { 26 | return lcfirst(parent::join($words)); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Camel/Format/FormatInterface.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Camel\Format; 13 | 14 | /** 15 | * Handler to convert from a case to another. 16 | * 17 | * The idea is to split the given word into several words and then assemble them 18 | * with another format. 19 | * 20 | * Example: camelCase => [camel, Case] => camel_case 21 | * 22 | * @author Matthie Moquet 23 | */ 24 | interface FormatInterface 25 | { 26 | /** 27 | * Split a word in the initial case into several words. 28 | * 29 | * @param string $word The initial word 30 | * 31 | * @return array An array of string 32 | */ 33 | public function split($word); 34 | 35 | /** 36 | * Joins array of words to render the desired case. 37 | * 38 | * @param array words Array of string 39 | * 40 | * @return string The final word 41 | */ 42 | public function join(array $words); 43 | } 44 | -------------------------------------------------------------------------------- /src/Camel/Format/ScreamingSnakeCase.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Camel\Format; 13 | 14 | /** 15 | * Format to handle SCREAMING_SNAKE_CASE. 16 | * 17 | * @author Matthieu Moquet 18 | */ 19 | class ScreamingSnakeCase extends SnakeCase 20 | { 21 | /** 22 | * {@inheritdoc} 23 | */ 24 | public function join(array $words) 25 | { 26 | return strtoupper(parent::join($words)); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Camel/Format/SnakeCase.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Camel\Format; 13 | 14 | /** 15 | * Format to handle sneak_case. 16 | * 17 | * @author Matthieu Moquet 18 | */ 19 | class SnakeCase implements FormatInterface 20 | { 21 | /** 22 | * {@inheritdoc} 23 | */ 24 | public function split($word) 25 | { 26 | return explode('_', $word); 27 | } 28 | 29 | /** 30 | * {@inheritdoc} 31 | */ 32 | public function join(array $words) 33 | { 34 | // Ensure words are lowercase 35 | $words = array_map('strtolower', $words); 36 | 37 | return implode('_', $words); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Camel/Format/SpinalCase.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Camel\Format; 13 | 14 | /** 15 | * Format to handle spinal-case. 16 | * 17 | * @author Denis Roussel 18 | */ 19 | class SpinalCase implements FormatInterface 20 | { 21 | /** 22 | * {@inheritdoc} 23 | */ 24 | public function split($word) 25 | { 26 | return explode('-', $word); 27 | } 28 | 29 | /** 30 | * {@inheritdoc} 31 | */ 32 | public function join(array $words) 33 | { 34 | // Ensure words are lowercase 35 | $words = array_map('strtolower', $words); 36 | 37 | return implode('-', $words); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Camel/Format/StudlyCaps.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Camel\Format; 13 | 14 | /** 15 | * Format to handle StudlyCaps. 16 | * 17 | * @author Matthieu Moquet 18 | */ 19 | class StudlyCaps implements FormatInterface 20 | { 21 | /** 22 | * {@inheritdoc} 23 | */ 24 | public function split($word) 25 | { 26 | // Match camelCase 27 | $pattern = '/ # Match position between camelCase "words". 28 | (?<=[a-z]) # Position is after a lowercase, 29 | (?=[A-Z]) # and before an uppercase letter. 30 | /x'; 31 | 32 | $words = preg_split($pattern, $word); 33 | 34 | return $words; 35 | } 36 | 37 | /** 38 | * {@inheritdoc} 39 | */ 40 | public function join(array $words) 41 | { 42 | // Ensure words are lowercase 43 | $words = array_map('strtolower', $words); 44 | 45 | // UC first each words 46 | $words = array_map('ucfirst', $words); 47 | 48 | return implode('', $words); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /tests/Camel/Tests/CaseTransformerTest.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Camel\Tests; 13 | 14 | use Camel\CaseTransformer; 15 | use Camel\Format; 16 | 17 | class CaseTransformerTest extends \PHPUnit_Framework_TestCase 18 | { 19 | public function testTransform() 20 | { 21 | $camelCase = new Format\CamelCase(); 22 | $snakeCase = new Format\SnakeCase(); 23 | 24 | $transformer = new CaseTransformer($camelCase, $snakeCase); 25 | $this->assertEquals('hello_world', $transformer->transform('helloWorld')); 26 | 27 | $transformer = new CaseTransformer($snakeCase, $camelCase); 28 | $this->assertEquals('helloWorld', $transformer->transform('hello_world')); 29 | } 30 | } -------------------------------------------------------------------------------- /tests/Camel/Tests/Format/CamelCaseTest.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Camel\Tests\Format; 13 | 14 | use Camel\Format\CamelCase; 15 | 16 | class CamelCaseTest extends FormatTest 17 | { 18 | public function getFormatInstance() 19 | { 20 | return new CamelCase(); 21 | } 22 | 23 | public function provideValidJoins() 24 | { 25 | return array( 26 | array(array('hello', 'world'), 'helloWorld'), 27 | array(array('HeLlO', 'wOrLd'), 'helloWorld'), 28 | array(array('HELLO', 'WORLD'), 'helloWorld'), 29 | array(array('hello', 'my', 'world'), 'helloMyWorld'), 30 | ); 31 | } 32 | 33 | public function provideValidSplits() 34 | { 35 | return array( 36 | array('helloWorld', array('hello', 'World')), 37 | array('helloMyWorld', array('hello', 'My', 'World')), 38 | ); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /tests/Camel/Tests/Format/FormatTest.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Camel\Tests\Format; 13 | 14 | abstract class FormatTest extends \PHPUnit_Framework_TestCase 15 | { 16 | protected $format; 17 | 18 | public function setUp() 19 | { 20 | $this->format = $this->getFormatInstance(); 21 | } 22 | 23 | /** 24 | * @dataProvider provideValidJoins 25 | */ 26 | public function testJoin(array $inputWords, $expectedWord) 27 | { 28 | $this->assertEquals($this->format->join($inputWords), $expectedWord); 29 | } 30 | 31 | /** 32 | * @dataProvider provideValidSplits 33 | */ 34 | public function testSplit($inputWord, array $expectedWords) 35 | { 36 | $this->assertEquals($this->format->split($inputWord), $expectedWords); 37 | } 38 | 39 | abstract public function getFormatInstance(); 40 | 41 | abstract public function provideValidJoins(); 42 | 43 | abstract public function provideValidSplits(); 44 | } 45 | -------------------------------------------------------------------------------- /tests/Camel/Tests/Format/ScreamingSnakeCaseTest.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Camel\Tests\Format; 13 | 14 | use Camel\Format\ScreamingSnakeCase; 15 | 16 | class ScreamingSnakeCaseTest extends FormatTest 17 | { 18 | public function getFormatInstance() 19 | { 20 | return new ScreamingSnakeCase(); 21 | } 22 | 23 | public function provideValidJoins() 24 | { 25 | return array( 26 | array(array('hello', 'world'), 'HELLO_WORLD'), 27 | array(array('HeLlO', 'wOrLd'), 'HELLO_WORLD'), 28 | array(array('HELLO', 'WORLD'), 'HELLO_WORLD'), 29 | array(array('hello', 'my', 'world'), 'HELLO_MY_WORLD'), 30 | ); 31 | } 32 | 33 | public function provideValidSplits() 34 | { 35 | return array( 36 | array('hello_world', array('hello', 'world')), 37 | array('HELLO_WORLD', array('HELLO', 'WORLD')), 38 | array('HELLO_MY_WORLD', array('HELLO', 'MY', 'WORLD')), 39 | ); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /tests/Camel/Tests/Format/SnakeCaseTest.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Camel\Tests\Format; 13 | 14 | use Camel\Format\SnakeCase; 15 | 16 | class SnakeCaseTest extends FormatTest 17 | { 18 | public function getFormatInstance() 19 | { 20 | return new SnakeCase(); 21 | } 22 | 23 | public function provideValidJoins() 24 | { 25 | return array( 26 | array(array('hello', 'world'), 'hello_world'), 27 | array(array('HeLlO', 'wOrLd'), 'hello_world'), 28 | array(array('HELLO', 'WORLD'), 'hello_world'), 29 | array(array('hello', 'my', 'world'), 'hello_my_world'), 30 | ); 31 | } 32 | 33 | public function provideValidSplits() 34 | { 35 | return array( 36 | array('hello_world', array('hello', 'world')), 37 | array('HELLO_WORLD', array('HELLO', 'WORLD')), 38 | array('hello_my_world', array('hello', 'my', 'world')), 39 | ); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /tests/Camel/Tests/Format/SpinalCaseTest.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Camel\Tests\Format; 13 | 14 | use Camel\Format\SpinalCase; 15 | 16 | class SpinalCaseTest extends FormatTest 17 | { 18 | public function getFormatInstance() 19 | { 20 | return new SpinalCase(); 21 | } 22 | 23 | public function provideValidJoins() 24 | { 25 | return array( 26 | array(array('hello', 'world'), 'hello-world'), 27 | array(array('HeLlO', 'wOrLd'), 'hello-world'), 28 | array(array('HELLO', 'WORLD'), 'hello-world'), 29 | array(array('hello', 'my', 'world'), 'hello-my-world'), 30 | ); 31 | } 32 | 33 | public function provideValidSplits() 34 | { 35 | return array( 36 | array('hello-world', array('hello', 'world')), 37 | array('HELLO-WORLD', array('HELLO', 'WORLD')), 38 | array('hello-my-world', array('hello', 'my', 'world')), 39 | ); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /tests/Camel/Tests/Format/StudlyCapsTest.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Camel\Tests\Format; 13 | 14 | use Camel\Format\StudlyCaps; 15 | 16 | class StudlyCapsTest extends FormatTest 17 | { 18 | public function getFormatInstance() 19 | { 20 | return new StudlyCaps(); 21 | } 22 | 23 | public function provideValidJoins() 24 | { 25 | return array( 26 | array(array('hello', 'world'), 'HelloWorld'), 27 | array(array('HeLlO', 'wOrLd'), 'HelloWorld'), 28 | array(array('HELLO', 'WORLD'), 'HelloWorld'), 29 | array(array('hello', 'my', 'world'), 'HelloMyWorld'), 30 | ); 31 | } 32 | 33 | public function provideValidSplits() 34 | { 35 | return array( 36 | array('HelloWorld', array('Hello', 'World')), 37 | array('helloWorld', array('hello', 'World')), 38 | array('HelloMyWorld', array('Hello', 'My', 'World')), 39 | ); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /tests/bootstrap.php: -------------------------------------------------------------------------------- 1 | add('Camel\Tests', __DIR__); 6 | --------------------------------------------------------------------------------