Skip to content

Commit

Permalink
Merge pull request #25 from bolt/add-string-functions
Browse files Browse the repository at this point in the history
Add startsWith, ensureStartsWith and ensureEndsWith
  • Loading branch information
bobdenotter authored Dec 30, 2019
2 parents 515fd6e + 19f8778 commit 2b75c4a
Show file tree
Hide file tree
Showing 6 changed files with 108 additions and 47 deletions.
16 changes: 6 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,9 @@

This library provides utility functions to help simplify menial tasks.

The Bolt team believes the PHP error reporting system is a mistake. Many
built-in functions utilize it, leading to inconsistent results and head
scratching.

This library provides some wrappers around some of these functions. Our code
should always throw exceptions instead of triggering errors/warnings/notices
(excluding deprecation warnings).
Where possible, this library provides some wrappers around some built-in
functions. Our code should always throw exceptions instead of triggering
errors/warnings/notices (excluding deprecation warnings).

Table of Contents:

Expand All @@ -24,10 +20,11 @@ Table of Contents:

## Arr

## Assert
Functions to deal with arrays.

Additional assertions built on `Webmozart\Assert`
## Assert

Additional assertions built on `Webmozart\Assert`.

### `isArrayAccessible`

Expand All @@ -38,7 +35,6 @@ implementing `ArrayAccess`.
isArrayAccessible($value, string $message = ''): void
```


### `isInstanceOfAny`

Throws `InvalidArgumentException` if `$value` is not an instance of one of the
Expand Down
10 changes: 5 additions & 5 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@
],
"require": {
"php": "^7.1",
"seld/jsonlint": "^1.4",
"webmozart/assert": "^1.2"
"seld/jsonlint": "^1.7",
"webmozart/assert": "^1.6"
},
"require-dev": {
"phpunit/phpunit": "^6.4",
"symfony/phpunit-bridge": "^3.3",
"symplify/easy-coding-standard": "^5.2"
"phpunit/phpunit": "^6.5",
"symfony/phpunit-bridge": "^3.4",
"symplify/easy-coding-standard": "^7.0.2"
},
"extra": {
"branch-alias": {
Expand Down
49 changes: 20 additions & 29 deletions easy-coding-standard.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
imports:
- { resource: 'vendor/symplify/easy-coding-standard/config/clean-code.yml' }
- { resource: 'vendor/symplify/easy-coding-standard/config/common.yml' }
- { resource: 'vendor/symplify/easy-coding-standard/config/php70.yml' }
- { resource: 'vendor/symplify/easy-coding-standard/config/php71.yml' }
- { resource: 'vendor/symplify/easy-coding-standard/config/psr2.yml' }
- { resource: 'vendor/symplify/easy-coding-standard/config/psr12.yml' }
- { resource: 'vendor/symplify/easy-coding-standard/config/symfony.yml' }
- { resource: 'vendor/symplify/easy-coding-standard/config/symfony-risky.yml' }
- { resource: 'vendor/symplify/easy-coding-standard/config/set/clean-code.yaml' }
- { resource: 'vendor/symplify/easy-coding-standard/config/set/common.yaml' }
- { resource: 'vendor/symplify/easy-coding-standard/config/set/php70.yaml' }
- { resource: 'vendor/symplify/easy-coding-standard/config/set/php71.yaml' }
- { resource: 'vendor/symplify/easy-coding-standard/config/set/psr2.yaml' }
- { resource: 'vendor/symplify/easy-coding-standard/config/set/psr12.yaml' }
- { resource: 'vendor/symplify/easy-coding-standard/config/set/symfony.yaml' }
- { resource: 'vendor/symplify/easy-coding-standard/config/set/symfony-risky.yaml' }

services:
# most of these services are taken from symplify.yml
Expand Down Expand Up @@ -62,23 +62,15 @@ services:
'position_after_anonymous_constructs': 'same'

PhpCsFixer\Fixer\ClassNotation\NoBlankLinesAfterClassOpeningFixer: ~
PhpCsFixer\Fixer\ClassNotation\OrderedClassElementsFixer:
order:
- 'use_trait'
PhpCsFixer\Fixer\ClassNotation\VisibilityRequiredFixer:
elements:
- 'const'
- 'method'
- 'property'
PhpCsFixer\Fixer\Operator\BinaryOperatorSpacesFixer: ~
PhpCsFixer\Fixer\Operator\TernaryOperatorSpacesFixer: ~
PhpCsFixer\Fixer\Operator\UnaryOperatorSpacesFixer: ~
PhpCsFixer\Fixer\FunctionNotation\ReturnTypeDeclarationFixer: ~
PhpCsFixer\Fixer\Whitespace\NoTrailingWhitespaceFixer: ~

PhpCsFixer\Fixer\Operator\ConcatSpaceFixer:
spacing: 'one'

PhpCsFixer\Fixer\Semicolon\NoSinglelineWhitespaceBeforeSemicolonsFixer: ~
PhpCsFixer\Fixer\ArrayNotation\NoWhitespaceBeforeCommaInArrayFixer: ~
PhpCsFixer\Fixer\ArrayNotation\WhitespaceAfterCommaInArrayFixer: ~
Expand All @@ -93,17 +85,16 @@ services:

parameters:
cache_directory: var/cache/ecs
exclude_checkers:
- 'PhpCsFixer\Fixer\ClassNotation\ClassAttributesSeparationFixer'
- 'PhpCsFixer\Fixer\ClassNotation\OrderedClassElementsFixer'
- 'PhpCsFixer\Fixer\ControlStructure\YodaStyleFixer'
- 'PhpCsFixer\Fixer\Operator\ConcatSpaceFixer'
- 'PhpCsFixer\Fixer\Operator\IncrementStyleFixer'
- 'PhpCsFixer\Fixer\Operator\UnaryOperatorSpacesFixer'
- 'PhpCsFixer\Fixer\Phpdoc\PhpdocAnnotationWithoutDotFixer'
- 'PhpCsFixer\Fixer\Phpdoc\PhpdocSummaryFixer'
- 'PhpCsFixer\Fixer\Whitespace\BlankLineBeforeStatementFixer'
- 'SlevomatCodingStandard\Sniffs\TypeHints\TypeHintDeclarationSniff'
- 'Symplify\CodingStandard\Sniffs\Debug\CommentedOutCodeSniff' #to be removed after beta release
skip:
PHP_CodeSniffer\Standards\Generic\Sniffs\CodeAnalysis\AssignmentInConditionSniff.FoundInWhileCondition: ~
PhpCsFixer\Fixer\ClassNotation\ClassAttributesSeparationFixer: ~
PhpCsFixer\Fixer\ClassNotation\OrderedClassElementsFixer: ~
PhpCsFixer\Fixer\ControlStructure\YodaStyleFixer: ~
PhpCsFixer\Fixer\Operator\ConcatSpaceFixer: ~
PhpCsFixer\Fixer\Operator\IncrementStyleFixer: ~
PhpCsFixer\Fixer\Operator\UnaryOperatorSpacesFixer: ~
PhpCsFixer\Fixer\Phpdoc\PhpdocAnnotationWithoutDotFixer: ~
PhpCsFixer\Fixer\Phpdoc\PhpdocSummaryFixer: ~
PhpCsFixer\Fixer\Whitespace\BlankLineBeforeStatementFixer: ~
SlevomatCodingStandard\Sniffs\TypeHints\TypeHintDeclarationSniff: ~
Symplify\CodingStandard\Sniffs\Debug\CommentedOutCodeSniff: ~ #to be removed before beta release
Symplify\CodingStandard\Sniffs\Debug\DebugFunctionCallSniff: ~ #to be removed before beta release
16 changes: 13 additions & 3 deletions src/Arr.php
Original file line number Diff line number Diff line change
Expand Up @@ -170,15 +170,18 @@ public static function has($data, string $path): bool
Assert::stringNotEmpty($path);

$path = explode('/', $path);
$part = array_shift($path);

while (($part = array_shift($path)) !== null) {
while ($part !== null) {
if (! ($data instanceof ArrayAccess) && ! is_array($data)) {
return false;
}
if (! (isset($data[$part]) || array_key_exists($part, $data))) {
return false;
}
$data = $data[$part];

$part = array_shift($path);
}

return true;
Expand Down Expand Up @@ -210,12 +213,15 @@ public static function get($data, string $path, $default = null)
Assert::stringNotEmpty($path);

$path = explode('/', $path);
$part = array_shift($path);

while (($part = array_shift($path)) !== null) {
while ($part !== null) {
if ((! is_array($data) && ! ($data instanceof ArrayAccess)) || ! isset($data[$part])) {
return $default;
}
$data = $data[$part];

$part = array_shift($path);
}

return $data;
Expand Down Expand Up @@ -276,7 +282,9 @@ public static function set(&$data, string $path, $value): void

$invalidKey = null;
$current = &$data;
while (($key = array_shift($queue)) !== null) {
$key = array_shift($queue);

while ($key !== null) {
if (! is_array($current) && ! ($current instanceof ArrayAccess)) {
throw new RuntimeException(
sprintf(
Expand Down Expand Up @@ -326,6 +334,8 @@ public static function set(&$data, string $path, $value): void
}

$invalidKey = $key;

$key = array_shift($queue);
}
}

Expand Down
39 changes: 39 additions & 0 deletions src/Str.php
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,45 @@ public static function endsWith(string $subject, string $search, bool $caseSensi
return $search === '' || mb_substr($subject, -mb_strlen($search)) === $search;
}

/**
* Returns whether the subjects starts with the search string.
*/
public static function startsWith(string $subject, string $search, bool $caseSensitive = true): bool
{
if (! $caseSensitive) {
$subject = mb_strtolower($subject);
$search = mb_strtolower($search);
}

return $search === '' || mb_substr($subject, 0, mb_strlen($search)) === $search;
}

/**
* Ensure a string ends with a given string. If it doesn't already end in
* it, this function will append it.
*/
public static function ensureEndsWith(string $subject, string $desiredEnd): string
{
if (! self::endsWith($subject, $desiredEnd)) {
$subject .= $desiredEnd;
}

return $subject;
}

/**
* Ensure a string starts with a given string. If it doesn't already start
* with it, this function will prepend it.
*/
public static function ensureStartsWith(string $subject, string $desiredStart): string
{
if (! self::startsWith($subject, $desiredStart)) {
$subject = $desiredStart . $subject;
}

return $subject;
}

/**
* Returns the class name without the namespace.
*
Expand Down
25 changes: 25 additions & 0 deletions tests/StrTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,31 @@ public function testEndsWith()
$this->assertFalse(Str::endsWith('FooBar', 'Foo'));
}

public function testStartsWith()
{
$this->assertTrue(Str::startsWith('FooBar', 'Foo'));
$this->assertTrue(Str::startsWith('FooBar', 'foo', false));
$this->assertFalse(Str::startsWith('FooBar', 'Qux'));
}

public function testEnsureEndsWith()
{
$this->assertsame('FooBar_', Str::ensureEndsWith('FooBar_', '_'));
$this->assertsame('FooBar_', Str::ensureEndsWith('FooBar', '_'));
$this->assertSame('FooBar__', Str::ensureEndsWith('FooBar__', '__'));
$this->assertSame('FooBar___', Str::ensureEndsWith('FooBar', '___'));
$this->assertsame('FooBar', Str::ensureEndsWith('FooBar', 'FooBar'));
}

public function testEnsureStartsWith()
{
$this->assertsame('_FooBar', Str::ensureStartsWith('FooBar', '_'));
$this->assertsame('_FooBar', Str::ensureStartsWith('_FooBar', '_'));
$this->assertSame('__FooBar', Str::ensureStartsWith('__FooBar', '__'));
$this->assertSame('___FooBar', Str::ensureStartsWith('FooBar', '___'));
$this->assertsame('FooBar', Str::ensureStartsWith('FooBar', 'FooBar'));
}

public function testClassName()
{
$this->assertSame('StrTest', Str::className($this));
Expand Down

0 comments on commit 2b75c4a

Please sign in to comment.