Skip to content

Instantly share code, notes, and snippets.

@irazasyed
Last active February 21, 2024 17:29
Show Gist options
  • Star 76 You must be signed in to star a gist
  • Fork 48 You must be signed in to fork a gist
  • Save irazasyed/11256369 to your computer and use it in GitHub Desktop.
Save irazasyed/11256369 to your computer and use it in GitHub Desktop.
PHP: Text Spinner Class - Nested spinning supported.
<?PHP
/**
* Spintax - A helper class to process Spintax strings.
*/
class Spintax
{
/**
* Set seed to make the spinner predictable.
*/
public function seed(mixed $seed)
{
mt_srand(crc32($seed));
}
public function process(string $text)
{
return preg_replace_callback(
'/\{(((?>[^\{\}]+)|(?R))*?)\}/x',
function ($match) {
$text = $this->process($match[1]);
$parts = explode('|', $text);
return $parts[mt_rand(0, count($parts) - 1)];
},
$text
);
}
/**
* If you want highest randomness,
* this is the method to use.
* Note: Seed has no effect.
*
* Last updated: 2023-10-26
*/
public function spin(string $text)
{
$pattern = '/{([^{}]+)}/';
while (preg_match($pattern, $text)) {
$text = preg_replace_callback($pattern, function ($matches) {
$options = explode('|', $matches[1]);
return $options[ random_int(0, count($options) - 1) ];
}, $text);
}
return $text;
}
}
/* EXAMPLE USAGE */
$spintax = new Spintax();
$string = '{Hello|Howdy|Hola} to you, {Mr.|Mrs.|Ms.} {Smith|Williams|Davis}!';
echo $spintax->process($string);
/* NESTED SPINNING EXAMPLE */
echo $spintax->process('{Hello|Howdy|Hola} to you, {Mr.|Mrs.|Ms.} {{Jason|Malina|Sara}|Williams|Davis}');
@mamunur34
Copy link

Very interesting. Pretty cool. As it is very slim in size and heavy in working.

@patrykkp
Copy link

great! very useful - thanks!

@juanma386
Copy link

is posible? {
Mensaje001
|Mensaje 002
{
Mensaje 002-1
|
Mensaje 002-2
}
}
To infinity data spintax.

@kamiljanicki
Copy link

Hello! Generally class working great even with 3rd or 4th nesting level. But i think there is some mysterious bug.

Spintax works fine with short texts, but when text is longer than 8.000 character (whole text including synonims in brackets {}) then class cause HTTP errors (connecion reset).

I make a test in separated file where was only class definition, one object and variable with text.

Can somone help me with this?

In php ini i have declared 2GB of ram and unlimited time of execution.

Regards!

@PhiSYS
Copy link

PhiSYS commented Jul 3, 2019

I guess we could make the asterisk lazy for a little performance boost '/{(((?>[^\{\}]+)|(?R))*?)}/x'.

/\{(((?>[^\{\}]+)|(?R))*)\}/x 816 matches, 11424 steps (~30ms)
816 matches, 11424 steps, 30ms

/\{(((?>[^\{\}]+)|(?R))*?)\}/x 816 matches, 9792 steps (~13ms)
816 matches, 9792 steps, 13ms

@EmilioNicolas
Copy link

EmilioNicolas commented Jul 3, 2019

I guess we could make the asterisk lazy for a little performance boost '/{(((?>[^{}]+)|(?R))*?)}/x'.

I forked this optimized solution and added seed rand in order to fix the spin text with srand.

@jakama
Copy link

jakama commented Aug 4, 2020

Hello!

Great job. It is helping me a lot!

I'm trying to get the parts of the spintax text separately, but I only get the ones between {}

For example, in this text:
{Hi|Hello}{ Mr.|} Irfaq Syed. {How are you?|How about the day?}

I get:
{Hi | Hello}
{Mr. |}
{How are you? | How about the day?}

But not the text in the middle, that is, I don't get:

Irfaq Syed.

There is any Regex to get all, the spintax groups and the plain text?

Thanks!

@naufalkh
Copy link

naufalkh commented Jan 14, 2021

Very interesting!
How to make the reverse?
Input: Hello to you, Mr. Smith!
Output: {Hello|Howdy|Hola} to you, {Mr.|Mrs.|Ms.} {Smith|Williams|Davis}!

@herahadi
Copy link

herahadi commented Jul 5, 2022

how to output an array of all possible combinations?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment