Skip to content

Commit

Permalink
feat/add-support-for-pregMatch (#18)
Browse files Browse the repository at this point in the history
* Add support for `pregMatch()`.

* Update `README.md`.

* Add tests.

* Add tests.

* Update tests.

* Update DockBlock in `DataModelHelper.php`.

---------

Co-authored-by: david_smith <[email protected]>
  • Loading branch information
zero-to-prod and david_smith authored Nov 12, 2024
1 parent f9c4336 commit 1aa3e93
Show file tree
Hide file tree
Showing 4 changed files with 142 additions and 0 deletions.
28 changes: 28 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ class DataModelHelper

- [mapOf](#mapof): Create a map of any type by using
- [pregReplace](#pregreplace): Perform a regular expression search and replace.
- [pregMatch](#pregmatch): Perform a regular expression match.
- [isUrl](#isurl): Validates a url.

### `mapOf`
Expand Down Expand Up @@ -444,6 +445,33 @@ $User = User::from([
echo $User->name; // Outputs: 'Trophy!'
```

### `pregMatch`

Use `pregMatch` to perform a regular expression match.

```php
class User
{
use \Zerotoprod\DataModel\DataModel;
use \Zerotoprod\DataModelHelper\DataModelHelper;

#[Describe([
'cast' => [self::class, 'pregMatch'],
'pattern' => '/s/', // Required
'match_on' => 0 // Index of the $matches to return
'flags' => PREG_UNMATCHED_AS_NULL
'offset' => 0
])]
public string $name;
}

$User = User::from([
'name' => 'sarah',
]);

echo $User->name; // Outputs: 's'
```

### `isUrl`

Use `isUrl` to perform validate a url.
Expand Down
37 changes: 37 additions & 0 deletions src/DataModelHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -110,11 +110,48 @@ public static function pregReplace(mixed $value, array $context, ?ReflectionAttr
? null
: '';
}

$args = $Attribute?->getArguments()[0];

return preg_replace($args['pattern'], $args['replacement'] ?? '', $value);
}

/**
* Perform a regular expression match.
*
* NOTE: If property allows null, null will be returned.
*
* ```
* #[Describe([
* 'cast' => [self::class, 'pregMatch'],
* 'pattern' => '/s/', // Required
* 'match_on' => 0 // Index of the $matches to return
* 'flags' => PREG_UNMATCHED_AS_NULL
* 'offset' => 0
* ])]
* ```
*/
public static function pregMatch(mixed $value, array $context, ?ReflectionAttribute $Attribute, ReflectionProperty $Property)
{
if (!$value && $Property->getType()?->allowsNull()) {
return null;
}

if (!is_string($value)) {
return $value;
}

$args = $Attribute?->getArguments()[0];
preg_match($args['pattern'], $value, $matches, $args['flags'] ?? 0, $args['offset'] ?? 0);

if(isset($args['match_on']) && !isset($matches[$args['match_on']])) {
return;
}
return isset($args['match_on'])
? $matches[$args['match_on']]
: $matches;
}

/**
* Determine if a given value is a valid URL.
* ```
Expand Down
31 changes: 31 additions & 0 deletions tests/Unit/PregMatch/PregMatchTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

namespace Tests\Unit\PregMatch;

use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase;

class PregMatchTest extends TestCase
{
#[Test] public function pattern(): void
{
$User = User::from([
User::name => 'stop',
User::s => 'stop',
User::as_null => 'top',
User::offset => 'stop',
]);

self::assertEquals(['s'], $User->name);
self::assertEquals('s', $User->s);
self::assertNull($User->as_null);
self::assertEquals([], $User->offset);
}

#[Test] public function allowsNull(): void
{
$User = User::from();

self::assertNull($User->name);
}
}
46 changes: 46 additions & 0 deletions tests/Unit/PregMatch/User.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php

namespace Tests\Unit\PregMatch;

use Zerotoprod\DataModel\DataModel;
use Zerotoprod\DataModel\Describe;
use Zerotoprod\DataModelHelper\DataModelHelper;

class User
{
use DataModel;
use DataModelHelper;

public const name = 'name';
public const s = 's';
public const as_null = 'as_null';
public const offset = 'offset';

#[Describe([
'cast' => [self::class, 'pregMatch'],
'pattern' => '/s/',
])]
public ?array $name;

#[Describe([
'cast' => [self::class, 'pregMatch'],
'pattern' => '/s/',
'match_on' => 0
])]
public ?string $s;

#[Describe([
'cast' => [self::class, 'pregMatch'],
'pattern' => '/s/',
'match_on' => 0,
'flags' => PREG_UNMATCHED_AS_NULL
])]
public ?string $as_null;

#[Describe([
'cast' => [self::class, 'pregMatch'],
'pattern' => '/s/',
'offset' => 1
])]
public ?array $offset;
}

0 comments on commit 1aa3e93

Please sign in to comment.