diff --git a/.travis.yml b/.travis.yml index 181f060..4bd046a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,10 +5,12 @@ branches: - master php: - - '5.3' - '5.4' - '5.5' + - '5.6' - '7.0' + - '7.1' + - '7.2' - hhvm matrix: @@ -25,4 +27,4 @@ script: - phpunit --coverage-clover build/logs/clover.xml after_success: - - sh -c 'if [ "$TRAVIS_PHP_VERSION" != "hhvm" ]; then CODECLIMATE_REPO_TOKEN=3496c3863e75bb8133ff86315341099827436e5aa313e1424559ec5b81fdf2ba ./vendor/bin/test-reporter; fi;' + - sh -c 'if [ "$TRAVIS_PHP_VERSION" = "5.6" ]; then CODECLIMATE_REPO_TOKEN=3496c3863e75bb8133ff86315341099827436e5aa313e1424559ec5b81fdf2ba ./vendor/bin/test-reporter; fi;' diff --git a/LICENSE b/LICENSE index efdbef2..2ee9c3a 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2016 Martin Brecht-Precht, Markenwerk GmbH +Copyright (c) 2016 Martin Brecht-Precht, Chroma Experience GmbH Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 63dbe89..4015c7f 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,13 @@ # PHP String Builder -[![Build Status](https://travis-ci.org/markenwerk/php-string-builder.svg?branch=master)](https://travis-ci.org/markenwerk/php-string-builder) -[![Test Coverage](https://codeclimate.com/github/markenwerk/php-string-builder/badges/coverage.svg)](https://codeclimate.com/github/markenwerk/php-string-builder/coverage) +[![Build Status](https://travis-ci.org/chroma-x/php-string-builder.svg?branch=master)](https://travis-ci.org/chroma-x/php-string-builder) +[![Test Coverage](https://codeclimate.com/github/chroma-x/php-string-builder/badges/coverage.svg)](https://codeclimate.com/github/chroma-x/php-string-builder/coverage) [![Dependency Status](https://www.versioneye.com/user/projects/57aa33adf27cc20050102f0e/badge.svg)](https://www.versioneye.com/user/projects/57aa33adf27cc20050102f0e) [![SensioLabs Insight](https://img.shields.io/sensiolabs/i/ec36917d-baa1-482c-8916-41e2a2c48d5c.svg)](https://insight.sensiolabs.com/projects/ec36917d-baa1-482c-8916-41e2a2c48d5c) -[![Code Climate](https://codeclimate.com/github/markenwerk/php-string-builder/badges/gpa.svg)](https://codeclimate.com/github/markenwerk/php-string-builder) -[![Latest Stable Version](https://poser.pugx.org/markenwerk/string-builder/v/stable)](https://packagist.org/packages/markenwerk/string-builder) -[![Total Downloads](https://poser.pugx.org/markenwerk/string-builder/downloads)](https://packagist.org/packages/markenwerk/string-builder) -[![License](https://poser.pugx.org/markenwerk/string-builder/license)](https://packagist.org/packages/markenwerk/string-builder) +[![Code Climate](https://codeclimate.com/github/chroma-x/php-string-builder/badges/gpa.svg)](https://codeclimate.com/github/chroma-x/php-string-builder) +[![Latest Stable Version](https://poser.pugx.org/chroma-x/string-builder/v/stable)](https://packagist.org/packages/chroma-x/string-builder) +[![Total Downloads](https://poser.pugx.org/chroma-x/string-builder/downloads)](https://packagist.org/packages/chroma-x/string-builder) +[![License](https://poser.pugx.org/chroma-x/string-builder/license)](https://packagist.org/packages/chroma-x/string-builder) A basic string builder library providing different string methods written in PHP. @@ -16,7 +16,7 @@ A basic string builder library providing different string methods written in PHP ```{json} { "require": { - "markenwerk/string-builder": "~1.0" + "chroma-x/string-builder": "~1.0" } } ``` @@ -32,7 +32,7 @@ require_once('path/to/vendor/autoload.php'); ### Building and modifying a string ```{php} -use Markenwerk\StringBuilder\StringBuilder; +use ChromaX\StringBuilder\StringBuilder; $builder = new StringBuilder('rolod muspi meroL'); $builder @@ -59,7 +59,13 @@ $result = $builder->buildSubstring(5); fwrite(STDOUT, ' 3. Built substring ' . $result . PHP_EOL); $result = $builder->charAt(5); -fwrite(STDOUT, ' 4. Character ' . $result . PHP_EOL); +fwrite(STDOUT, ' 4. Character at position 5 ' . $result . PHP_EOL); + +$result = $builder->firstChar(); +fwrite(STDOUT, ' 5. First character ' . $result . PHP_EOL); + +$result = $builder->lastChar(); +fwrite(STDOUT, ' 6. Last character ' . $result . PHP_EOL); ``` will output the following @@ -68,44 +74,46 @@ will output the following 1. Built string ä2wertzem ipsum dolor sit amet, conset 2. Built substring rt 3. Built substring rtzem ipsum dolor sit amet, conset - 4. Character r + 4. Character at position 5 r + 5. First character ä + 6. Last character t ``` ### Getting string properties ```{php} $result = $builder->length(); -fwrite(STDOUT, ' 5. String length ' . $result . PHP_EOL); +fwrite(STDOUT, ' 7. String length ' . $result . PHP_EOL); $result = $builder->size(); -fwrite(STDOUT, ' 6. Number of bytes ' . $result . PHP_EOL); +fwrite(STDOUT, ' 8. Number of bytes ' . $result . PHP_EOL); $result = $builder->indexOf('e'); -fwrite(STDOUT, ' 7. First occurence of "e" ' . $result . PHP_EOL); +fwrite(STDOUT, ' 9. First occurence of "e" ' . $result . PHP_EOL); $result = $builder->indexOf('e', 5); -fwrite(STDOUT, ' 8. First occurence of "e" after position 5 ' . $result . PHP_EOL); +fwrite(STDOUT, '10. First occurence of "e" after position 5 ' . $result . PHP_EOL); $result = $builder->lastIndexOf('e'); -fwrite(STDOUT, ' 9. Last occurence of "e" ' . $result . PHP_EOL); +fwrite(STDOUT, '11. Last occurence of "e" ' . $result . PHP_EOL); $result = $builder->lastIndexOf('e', 5); -fwrite(STDOUT, '10. Last occurence of "e" before the 5th last character ' . $result . PHP_EOL); +fwrite(STDOUT, '12. Last occurence of "e" before the 5th last character ' . $result . PHP_EOL); $result = $builder->contains('ipsum'); -fwrite(STDOUT, '12. Whether the string contains "ipsum" ' . $result . PHP_EOL); +fwrite(STDOUT, '13. Whether the string contains "ipsum" ' . $result . PHP_EOL); ``` will output the following ```{txt} - 5. String length 38 - 6. Number of bytes 39 - 7. First occurence of "e" 4 - 8. First occurence of "e" after position 5 8 - 9. Last occurence of "e" 37 -10. Last occurence of "e" before the 5th last character 29 -12. Whether the string contains "ipsum" + 7. String length 38 + 8. Number of bytes 39 + 9. First occurence of "e" 4 +10. First occurence of "e" after position 5 8 +11. Last occurence of "e" 37 +12. Last occurence of "e" before the 5th last character 29 +13. Whether the string contains "ipsum" ``` ### Exception handling @@ -113,7 +121,7 @@ will output the following All methods throw an `\InvalidArgumentException` if misconfigured except `indexOf` and `lastIndexOf` wich return `null` if the given subtring is not contained by the string to build. ```{php} -use Markenwerk\StringBuilder\StringBuilder; +use ChromaX\StringBuilder\StringBuilder; try { $builder = new StringBuilder(); @@ -145,7 +153,7 @@ Exception with message Position invalid ## Contribution Contributing to our projects is always very appreciated. -**But: please follow the contribution guidelines written down in the [CONTRIBUTING.md](https://github.com/markenwerk/php-string-builder/blob/master/CONTRIBUTING.md) document.** +**But: please follow the contribution guidelines written down in the [CONTRIBUTING.md](https://github.com/chroma-x/php-string-builder/blob/master/CONTRIBUTING.md) document.** ## License diff --git a/composer.json b/composer.json index 227b876..ba8d92f 100644 --- a/composer.json +++ b/composer.json @@ -1,30 +1,30 @@ { - "name": "markenwerk/string-builder", - "type": "library", - "description": "A string builder library providing different string methods written in PHP.", - "keywords": [ - "String", - "Builder" - ], - "homepage": "http://markenwerk.net/", - "license": "MIT", - "authors": [ - { - "name": "Martin Brecht-Precht", - "email": "mb@markenwerk.net", - "homepage": "http://markenwerk.net" - } - ], - "autoload": { - "psr-4": { - "Markenwerk\\StringBuilder\\": "src/" - } - }, - "require": { - "php": ">=5.3" - }, - "require-dev": { - "phpunit/phpunit": ">=4.8.26", - "codeclimate/php-test-reporter": "dev-master" - } + "name": "chroma-x/string-builder", + "type": "library", + "description": "A string builder library providing different string methods written in PHP.", + "keywords": [ + "String", + "Builder" + ], + "homepage": "https://chroma-x.de/", + "license": "MIT", + "authors": [ + { + "name": "Martin Brecht-Precht", + "email": "mb@chroma-x.de", + "homepage": "https://chroma-x.de" + } + ], + "autoload": { + "psr-4": { + "ChromaX\\StringBuilder\\": "src/" + } + }, + "require": { + "php": ">=5.4" + }, + "require-dev": { + "phpunit/phpunit": "~4.8", + "codeclimate/php-test-reporter": "dev-master" + } } diff --git a/src/StringBuilder.php b/src/StringBuilder.php index 93f53a6..8a83526 100644 --- a/src/StringBuilder.php +++ b/src/StringBuilder.php @@ -1,11 +1,14 @@ validateScalar($string); + if ($string !== null) { + ArgumentValidator::validateScalar($string); $this->string = (string)$string; } } @@ -35,10 +39,11 @@ public function __construct($string = null) * * @param string $string * @return $this + * @throws InvalidArgumentException */ public function append($string) { - $this->validateScalar($string); + ArgumentValidator::validateScalar($string); $this->string .= (string)$string; return $this; } @@ -48,10 +53,11 @@ public function append($string) * * @param string $string * @return $this + * @throws InvalidArgumentException */ public function prepend($string) { - $this->validateScalar($string); + ArgumentValidator::validateScalar($string); $this->string = (string)$string . $this->string; return $this; } @@ -62,14 +68,14 @@ public function prepend($string) * @param int $position * @param string $string * @return $this + * @throws InvalidArgumentException */ public function insert($position, $string) { - $this - ->validateUnsignedInteger($position) - ->validateScalar($string); + ArgumentValidator::validateUnsignedInteger($position); + ArgumentValidator::validateScalar($string); if ($position >= $this->length()) { - throw new \InvalidArgumentException('Position invalid'); + throw new InvalidArgumentException('Position invalid'); } $this->string = mb_substr($this->string, 0, $position) . (string)$string . mb_substr($this->string, $position); return $this; @@ -82,18 +88,18 @@ public function insert($position, $string) * @param int $length * @param string $string * @return $this + * @throws InvalidArgumentException */ public function replace($position, $length, $string) { - $this - ->validateUnsignedInteger($position) - ->validateUnsignedInteger($length) - ->validateScalar($string); + ArgumentValidator::validateUnsignedInteger($position); + ArgumentValidator::validateUnsignedInteger($length); + ArgumentValidator::validateScalar($string); if ($position >= $this->length()) { - throw new \InvalidArgumentException('Position invalid'); + throw new InvalidArgumentException('Position invalid'); } if ($position + $length > $this->length()) { - throw new \InvalidArgumentException('Length invalid'); + throw new InvalidArgumentException('Length invalid'); } $this->string = mb_substr($this->string, 0, $position) . (string)$string . mb_substr($this->string, $position + $length); return $this; @@ -105,17 +111,17 @@ public function replace($position, $length, $string) * @param int $position * @param string $character * @return $this + * @throws InvalidArgumentException */ public function setCharAt($position, $character) { - $this - ->validateUnsignedInteger($position) - ->validateScalar($character); + ArgumentValidator::validateUnsignedInteger($position); + ArgumentValidator::validateScalar($character); if ($position >= $this->length()) { - throw new \InvalidArgumentException('Position invalid'); + throw new InvalidArgumentException('Position invalid'); } if (mb_strlen((string)$character) !== 1) { - throw new \InvalidArgumentException('Expected a scalar value of length 1'); + throw new InvalidArgumentException('Expected a scalar value of length 1'); } $this->string = mb_substr($this->string, 0, $position) . (string)$character . mb_substr($this->string, $position + 1); return $this; @@ -143,16 +149,16 @@ public function reverse() * @param int $position * @param int $length * @return $this + * @throws InvalidArgumentException */ public function delete($position, $length = null) { - $this - ->validateUnsignedInteger($position) - ->validateUnsignedIntegerOrNull($length); + ArgumentValidator::validateUnsignedInteger($position); + ArgumentValidator::validateUnsignedIntegerOrNull($length); if ($position >= $this->length()) { - throw new \InvalidArgumentException('Position invalid'); + throw new InvalidArgumentException('Position invalid'); } - if (is_null($length)) { + if ($length === null) { $this->string = mb_substr($this->string, 0, $position); } else { $this->string = mb_substr($this->string, 0, $position) . mb_substr($this->string, $position + $length); @@ -165,12 +171,13 @@ public function delete($position, $length = null) * * @param int $position * @return $this + * @throws InvalidArgumentException */ public function deleteCharAt($position) { - $this->validateUnsignedInteger($position); + ArgumentValidator::validateUnsignedInteger($position); if ($position >= $this->length()) { - throw new \InvalidArgumentException('Position invalid'); + throw new InvalidArgumentException('Position invalid'); } $this->string = mb_substr($this->string, 0, $position) . mb_substr($this->string, $position + 1); return $this; @@ -181,10 +188,11 @@ public function deleteCharAt($position) * * @param string $substring * @return bool + * @throws InvalidArgumentException */ public function contains($substring) { - $this->validateScalar($substring); + ArgumentValidator::validateScalar($substring); return strpos($this->string, (string)$substring) !== false; } @@ -196,13 +204,13 @@ public function contains($substring) * @param string $string * @param int $offset * @return int + * @throws InvalidArgumentException */ public function indexOf($string, $offset = 0) { - $this - ->validateScalar($string) - ->validateEmpty($string) - ->validateUnsignedInteger($offset); + ArgumentValidator::validateScalar($string); + ArgumentValidator::validateEmpty($string); + ArgumentValidator::validateUnsignedInteger($offset); $index = mb_strpos($this->string, (string)$string, $offset); return $index === false ? null : $index; } @@ -215,13 +223,13 @@ public function indexOf($string, $offset = 0) * @param string $string * @param int $offset * @return int + * @throws InvalidArgumentException */ public function lastIndexOf($string, $offset = 0) { - $this - ->validateScalar($string) - ->validateEmpty($string) - ->validateUnsignedInteger($offset); + ArgumentValidator::validateScalar($string); + ArgumentValidator::validateEmpty($string); + ArgumentValidator::validateUnsignedInteger($offset); $index = mb_strrpos($this->string, (string)$string, -1 * $offset); return $index === false ? null : $index; } @@ -251,36 +259,56 @@ public function length() * * @param int $position * @return string + * @throws InvalidArgumentException */ public function charAt($position) { - $this->validateUnsignedInteger($position); + ArgumentValidator::validateUnsignedInteger($position); if ($position >= $this->length()) { - throw new \InvalidArgumentException('Position invalid'); + throw new InvalidArgumentException('Position invalid'); } return mb_substr($this->string, $position, 1); } + /** + * Returns first character + * + * @return string + */ + public function firstChar() + { + return mb_substr($this->string, 0, 1, mb_detect_encoding($this->string)); + } + + /** + * Returns last character + * + * @return string + */ + public function lastChar() + { + return mb_substr($this->string, -1, null, mb_detect_encoding($this->string)); + } + /** * Returns an substring defined by startPosition and length * * @param int $startPosition * @param int $length * @return string + * @throws InvalidArgumentException */ public function buildSubstring($startPosition, $length = null) { - $this - ->validateUnsignedInteger($startPosition) - ->validateUnsignedIntegerOrNull($length); + ArgumentValidator::validateUnsignedInteger($startPosition); + ArgumentValidator::validateUnsignedIntegerOrNull($length); if ($startPosition >= $this->length()) { - throw new \InvalidArgumentException('Start position ' . (string)$startPosition . ' invalid'); + throw new InvalidArgumentException('Start position ' . (string)$startPosition . ' invalid'); } - if (is_null($length)) { + if ($length === null) { return mb_substr($this->string, $startPosition); - } else { - return mb_substr($this->string, $startPosition, $length); } + return mb_substr($this->string, $startPosition, $length); } /** @@ -303,58 +331,4 @@ public function __toString() return $this->build(); } - /** - * @param mixed $value - * @return $this - */ - private function validateScalar($value) - { - if (!is_scalar($value)) { - $type = is_object($value) ? get_class($value) : gettype($value); - throw new \InvalidArgumentException('Expected a scalar value; got ' . $type); - } - return $this; - } - - /** - * @param mixed $value - * @return $this - */ - private function validateUnsignedInteger($value) - { - if (!is_int($value)) { - $type = is_object($value) ? get_class($value) : gettype($value); - throw new \InvalidArgumentException('Expected an unsigned integer; got ' . $type); - } - if ($value < 0) { - throw new \InvalidArgumentException('Expected an unsigned integer; got ' . $value); - } - return $this; - } - - /** - * @param mixed $value - * @return $this - */ - private function validateUnsignedIntegerOrNull($value) - { - if (is_null($value)) { - return $this; - } - return $this->validateUnsignedInteger($value); - } - - /** - * @param mixed $value - * @return $this - */ - private function validateEmpty($value) - { - $value = (string)$value; - if (empty($value)) { - throw new \InvalidArgumentException('Empty string is invalid'); - } - return $this; - } - } diff --git a/src/Util/ArgumentValidator.php b/src/Util/ArgumentValidator.php new file mode 100644 index 0000000..f114b24 --- /dev/null +++ b/src/Util/ArgumentValidator.php @@ -0,0 +1,66 @@ +assertEquals(9, $builder->indexOf('e', 4)); $this->assertNull($builder->indexOf('e', 10)); $this->assertEquals(9, $builder->lastIndexOf('e')); - $this->assertNull($builder->lastIndexOf('e',10)); + $this->assertNull($builder->lastIndexOf('e', 10)); $this->assertTrue($builder->contains('21b')); + $this->assertEquals('b', $builder->firstChar()); + $this->assertEquals('ö', $builder->lastChar()); $this->assertFalse($builder->contains('abc')); $this->assertEquals('öeb1212ewqb', $builder->reverse()->build()); $builder = new StringBuilder('0123456'); @@ -51,6 +53,12 @@ public function testBuilder() $this->assertEquals('02356', $builder->build()); } + public function testBuilderNull() + { + $builder = new StringBuilder(); + $this->assertNull($builder->build()); + } + public function testBuilderConstructFail() { $this->setExpectedException(get_class(new \InvalidArgumentException()));