Toss a coin to your T-Regx!

Hello, back again! :) We've added a "Sponsor" button on github.com/T-Regx.

Sponsor

If you like T-Regx going in the right direction, now you have the opportunity to throw us buck or two.


And a heads up, in the new 0.9.6 release, we'll add a really smart asInt() and fluent() methods; which are already present, but will get an upgrade.

You see, match()->first() calls preg_match() and that makes sense. Also match()->fluent() calls preg_match_all(), because later fluent()->map() or fluent()->filter()->first() can be called, for example. And that also, sorta makes sense. But, unfortunately match()->fluent()->first() and match()->asInt()->first() also call preg_match_all(), and that's a bit wasteful.

So now we're introducing a change (similar to Java 8 Streams) that will call preg_match() for fluent()->first() and asInt()->first().

Release 0.9.5 - Alternation in prepared patterns!

This release brings alternation in prepared patterns!

Up to this point, there was no reasonable way to create a pattern from a variable number of inputs, for example you allow your users to input 0, 1 or more tags, which later should be used in a pattern. In procedural world, probably array_map() with preg::quote() would do the job, but wait! You don't have to code, it's already here:

Pattern::bind('^user:@id/findBy:@tags/all$', [
'id' => $user->id,
'tags' => $_GET['tags']
]);

In other words:

Pattern::bind('My tag is: "@tags"', ['tags' => ['one', 'two', 'three']]);

creates a pattern:

/My tag is: "(one|two|three)"/

Rest assured:

  • the values are quoted with preg::quote(), to protect you from malicious code
  • the group is non-capturing (use 'My tag is: "(@tags)"' for a capturing group, to be used with group())

The alternation is really smart too - if you use i or u flag, T-Regx will perform certain optimization, for example:

Pattern::inject('Find: @ :)', [['foo', 'bar', 'FOO']], 'i');

then it wil collapse foo and FOO, since i flag is used:

/Find: (foo|bar) :)/

That's it in this release! Stay tuned :)

Release 0.9.4 - Exception changes and groupBy()

This release brings updates in exceptions (namespaces, new detailed exceptions) and a groupBy() method.

Exceptions

In previous release we renamed SafeRegexException to PregException. In this, we're renaming CleanRegexException to PatternException. So now, those two general exceptions sync nicely with their base methods:

try {
return preg::match('/Foo/', $subject);
} catch (PregException $e) {
try {
return pattern('Foo')->test($subject);
} catch (PatternException $e) {

They both extend RegexException - base for all exceptions thrown by T-Regx. So that's the first thing.

The second exception update - previously, every exception thrown based on preg_last_error() method was RuntimePregException. Now, each error has a dedicated exception, which can be caught separately:

try {
return preg::match($pattern, $subject);
} catch (BacktrackLimitPregException $exception) {
} catch (Utf8OffsetPregException $exception) {

The detailed list of changes is in ChangeLog.md.

groupBy()

This release also comes with a brand new method - groupBy() which groups matches by a capturing group (name or index). It can match strings, offsets and also map them with map() and flatMap(). Additionally, it can be chained with filter() to leave out unwanted matches:

return pattern('(\d)(?<unit>cm|mm)')->match($strings)
->filter(function (Match $match) {
return $match->group(1)->toInt() % 2 == 0;
})
->groupBy('unit')
->map(function (Match $match) {
return $match->group(1)->toInt() * 100;
});

Release 0.9.3 - Minor changes

That's a really quick update, we just found a PHP bug report #78853, that's probably going to be fixed in future versions of PHP, but we decided to include the bugfix in T-Regx so it's fixed in PHP 7.1 (if you're using T-Regx :)

Apart from that, we added preg::last_error_msg(), which returns the same data as preg::last_error(), but in in human-readable string. There are suggestions on PHP source code, that this method might become part of standard PHP library, so we at T-Regx thought we might include it already :) And if it's not included, after all, that's still a good idea to have this method :)

And there are some breaking changes, that should increase readability, for example this exception:

try {
return preg::match('/pattern/', $word)
}
catch (PregException $e) {

seems a bit more intuitive than

catch (SafeRegexException $e) {

So to name the exception based on a class/method, not the module :)

And FIY, the next feature we're working at T-Regx is groupBy(), which should complete groupByCallback() functionality already present in T-Regx. So expect that method first! :)

That's it for today, thanks guys!

Release 0.9.2 - You're in for a treat!

๐Ÿ˜Ž T-Regx The Dinosaur is really proud to announce its first beta version! Despite the beta suffix, it's 100% suitable for production use. It doesn't have any known bugs - check out the issues. There is a few breaking changes (since that's a 0.* version), but there are also a looot of improvements and new feautres. What's new in this release:

Here's a release on github: https://github.com/T-Regx/T-Regx/releases/tag/v0.9.2 (see Changelog.md).

  • Breaking changes
    • Methods pattern()/Pattern::of() no longer "magically" guess whether a pattern is delimited or not. Pattern::of() assumes pattern is delimited, new Pattern::pcre() takes an old-school delimited pattern.
    • Constructor new Pattern() is no longer a part of T-Regx API. Use Pattern::of()/pattern()
    • Renamed Match.parseInt() to Match.toInt() (the same for MatchGroup)
    • Removed pattern()->match()->test()/fails(). From now on, use pattern()->test()/fails()
    • Removed is():
      • is()->delimited()
      • is()->usable()
      • is()->valid() is changed to valid()
    • Removed split()->ex(), changed split()->inc() to split()
  • Features
    • Added Match.group().replace() ๐Ÿ”ฅ
    • Added pattern()->match()->fluent() ๐Ÿ”ฅ
    • Added pattern()->match()->asInt()
    • Added pattern()->match()->distinct() (leaves only unique matches)
    • Added prepared pattern method Pattern::inject()/Pattern::bind() (see below)
    • In pattern()->match()->groups():
      • Added groups()->forEach()/iterate()
      • Added groups()->flatMap()
      • Added groups()->map()
      • Added group()->fluent()
      • Added groups()->names() (and namedGroups()->names())
      • Added groups()->count() (and namedGroups()->count())
    • Added match()->offsets()->fluent()
    • Added match()->group(string)->offsets()->fluent()
    • Added pattern()->forArray()->strict() which throws for invalid values, instead of filtering them out
  • SafeRegex
    • Added preg::grep_keys() ๐Ÿ”ฅ, that works exactly like preg::grep(), but filters by keys (also accepts PREG_GREP_INVERT)
  • Enhancements/updates
    • Method by()->group()->orElse() now receives lazy-loaded Match, instead of a subject
    • Added withReferences() to CompositePattern.chainedReplace()
    • Previously named Pattern::inject() is renamed to Pattern::bind()
    • The Pattern::bind() (old Pattern::inject()) still accepts values as an associative array, but new Pattern::inject() receives values without regard for the keys.
    • Fixed passing invalid types to forArray(). Previously, caused fatal error due to internal preg_grep() implementation.
  • Other
    • Now MalformedPatternException is thrown, instead of CompileSafeRegexException, when using invalid PCRE syntax.
    • Returning Match from replace()->callback() (instead of Match.text() as string)
    • Match +12 is no longer considered a valid integer for isInt()/toInt()
    • Unnamed group will be represented as null in Match.groupNames(), instead of being simply ignored
    • helper() method, Pattern and PatternBuilder now return interface PatternInterface, instead of Pattern class. Pattern class now only holds static utility methods, and PatternImpl holds the pattern implementation.
  • Maintenance

Foot note:

  • Apart from PHP type hints, every version up to this point could be run on PHP 5.3 (if one removes type hints from code, one can run T-Regx on PHP 5.3). Every error, exception, malfunction, inconsistency was handled correctly by T-Regx. From this version on (0.9.2), handling of the errors and inconsistencies is dropped, since T-Regx now only supports PHP 7.1.

Hope you guys will like and enjoy it!

Don't forget about T-Regx

Some of you might have noticed that not many new features have been added to 0.9.2 release candidate, since few weeks. But rest assured! :D Work on T-Regx hasn't slowed a bit! We've just put more effort on a more side-part of T-Regx.

Thanks to the keen eye of T-Regx user, Andreas Leathley, it stroke us that phpDoc in public methods of preg class (so preg::match(), preg::replace(), etc.) were not only outdated, they were incorrect at times. Thanks Andreas! :)

At first, we only wanted to correct the mistakes, but I quickly realized that mere phpDoc inherited from preg_*() methods is not enough :/ That could be easily found on php.net, what T-Regx users could really benefit from is a really extensive, rich, long, detailed and robust documentation.

That's why we've spent a little over a week to create an application that's capable of generating a complex and rich phpDoc for preg class (of course we'll use it for more classes in T-Regx). Main updates for the documentation will include:

  • Robust description of every parameter of every preg_*()
  • Detailed description of every flag used (e.g. PREG_OFFSET_CAPTURE)
  • Rich description of each method, it's relation, similarities and differences to other methods

And it will be much easier to maintain, because every class will have a phpDoc that's not written, but generated.

I'm pretty certain T-Regx is going to have a documentation you've never seen before :D

Of course, there are also some minor changes:

  • We've added pattern()->match()->group()->fluent()
  • Added callback for pattern()->match()->group()->first()
  • Updated detailed description in CONTRIBUTING.md

Keep looking forward to T-Regx 0.9.2! :)

The best Stargazers' Revolutions

I have imagined this moment for a long time. Is it real? Could it be T-Regx got 60 stars ? :D

But what's new.

There is preg_grep() function for filtering an array by a pattern, unfortunately there's no flag or another method to filter it by keys. There is a T-Regx method forArray()->filterByKeys(), but there was no such solution in SafeRegex.

That's why we added preg::grep_keys, which works exactly like preg_grep() but filters an array by keys, instead of values. It's going to be release in 0.9.2.

List of all changes incoming in 0.9.2 is available in ChangeLog.md, with fluent(), unique(), in-place replacements and more.

"The best Stargazers!" Reloaded

Holy guacamole! There were only 30 stars a few weeks ago and we have 40 already!? :D You guys gave us even more reason to release T-Regx 0.9.2 even sooner! Two new features are coming:

  • In-group replacing ๐Ÿ˜ฒ You can now replace a single group inside your subject (not only in replace(), in any method with Match details)
  • Additional prepared patterns method - Pattern::bind()

So keep an eye for 0.9.2 release.

Match details update

Most changes in T-Regx since the last Blog post were to Match details. We added user data (getUserData()/setUserData()) which can be used in chained calls (e.g. filter()->map()).

The second change is isInt()/parseInt() which allow you to handle "real" integers safetly - without the fear of "PHP smart" integers (e.g. PHP thinks that "1e3" is 1000). T-Regx understands that robust applications can't allow numbers to be 10e4 - it should be treated as an invalid integer by default!

And last, Match.group(int|string) is now validated (T-Regx was waiting a bit for this change!). We believe that using an invalid group name is a sign of a bug, so using group(-1) or group('!@#') now throws \InvalidArgumentException, as it's more suitable than assuming that -1 is just an unmatched group.