Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions docs/filters.md
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,32 @@ The above example will output the following
Result was valid
```

### ToKebabCase

```php
new Membrane\Filter\String\ToKebabCase();
```

Converts string into KebabCase (i.e. no whitespaces, uppercase for first letter of each word).

```php
$string = "helloThere have_you heard-of OpenAPI?";
$pascalCase = new Membrane\Filter\String\ToKebabCase();

$result = $pascalCase->filter($string);

echo $result->value;
echo $result->isValid() ? 'is valid' : 'is invalid';
```

The above example will output the following

```text
hellothere-have-you-heard-of-openapi?
```

Note that _helloThere_ became _hellothere_. `ToKebabCase` does not split on capitals, otherwise _OpenAPI_ would become _open-a-p-i_ which is a less desirable result.

### ToPascalCase

```php
Expand Down
40 changes: 40 additions & 0 deletions src/Filter/String/ToKebabCase.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

declare(strict_types=1);

namespace Membrane\Filter\String;

use Membrane\Filter;
use Membrane\Result\Message;
use Membrane\Result\MessageSet;
use Membrane\Result\Result;

class ToKebabCase implements Filter
{
public function filter(mixed $value): Result
{
if (!is_string($value)) {
return Result::invalid($value, new MessageSet(null, new Message(
'Expected string value, received %s',
[gettype($value)],
)));
}

$result = preg_replace(['#[\s\-.,_/]+#', '#[^[:alnum:]-]#'], ['-'], $value);
assert(is_string($result));

$result = mb_strtolower($result);

return Result::noResult($result);
}

public function __toString(): string
{
return 'Convert text to kebab-case';
}

public function __toPHP(): string
{
return sprintf('new %s()', self::class);
}
}
113 changes: 113 additions & 0 deletions tests/Filter/String/ToKebabCaseTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
<?php

declare(strict_types=1);

namespace Filter\String;

use Membrane\Filter\String\ToKebabCase;
use Membrane\Result\{Message, MessageSet, Result};
use PHPUnit\Framework\Attributes\{CoversClass, DataProvider, Test, TestDox, UsesClass};
use PHPUnit\Framework\TestCase;

#[CoversClass(ToKebabCase::class)]
#[UsesClass(Message::class)]
#[UsesClass(MessageSet::class)]
#[UsesClass(Result::class)]
class ToKebabCaseTest extends TestCase
{
#[Test]
#[TestDox('toString() returns a description of its behaviour')]
public function itCaststoString(): void
{
self::assertSame(
'Convert text to kebab-case',
(new ToKebabCase())->__toString()
);
}

#[Test]
#[TestDox('__toPHP() returns a string of evaluable PHP')]
public function itCaststoPHP(): void
{
$sut = new ToKebabCase();

self::assertEquals($sut, eval('return ' . $sut->__toPHP() . ';'));
}

#[Test]
#[TestDox('It will return an invalid Result if it filters values that are not strings')]
public function returnsInvalidResultForNonStringValues(): void
{
$value = 5;
$expected = Result::invalid($value, new MessageSet(null, new Message(
'Expected string value, received %s',
[gettype($value)],
)));

self::assertEquals($expected, (new ToKebabCase())->filter($value));
}

#[Test]
#[TestDox('It filters strings to PascalCase')]
#[DataProvider('provideStringsToFilter')]
public function filtersStringsToKebabCase(string $value, Result $expected): void
{
self::assertEquals($expected, (new ToKebabCase())->filter($value));
}

public static function provideStringsToFilter(): array
{
return [
'"Hello, World!"' => [
'"Hello, World!"',
Result::noResult('hello-world'),
],
'camelCase' => [
'camelCase',
Result::noResult('camelcase'),
],
'kebab-case' => [
'kebab-case',
Result::noResult('kebab-case'),
],
'kebabber------case' => [
'kebabber------case',
Result::noResult('kebabber-case'),
],
'snake_case' => [
'snake_case',
Result::noResult('snake-case'),
],
'snakiest_____case' => [
'snakiest_____case',
Result::noResult('snakiest-case'),
],
'pets/{id}' => [
'pets/{id}',
Result::noResult('pets-id'),
],
'http://petstore.swagger.io/{version}/pets/{id}' => [
'http://petstore.swagger.io/{version}/pets/{id}',
Result::noResult('http-petstore-swagger-io-version-pets-id'),
],
'plain text' => [
'plain text',
Result::noResult('plain-text'),
],
'plain 1text' => [
'plain 1text',
Result::noResult('plain-1text'),
],
'plain 1 text' => [
'plain 1 text',
Result::noResult('plain-1-text'),
],
'sTuPiD-_-cAsE' => [
'sTuPiD-_-cAsE',
Result::noResult('stupid-case'),
],
];
}


}
4 changes: 2 additions & 2 deletions tests/Filter/String/ToPascalCaseTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,11 @@ public static function provideStringsToFilter(): array
Result::noResult('KebabCase'),
],
'snake_case to SnakeCase' => [
'snake-case',
'snake_case',
Result::noResult('SnakeCase'),
],
'snake_____case to SnakeCase' => [
'snake-case',
'snake_____case',
Result::noResult('SnakeCase'),
],
'plain text to PlainText' => [
Expand Down