The last and final version update of the famous PHP Spintax class, this is ultimately recursive and easy to use. I hope that users online may fidn this class useful. It is free and open source, use it freely as you need. It’s simple to use read more below on how to use the Spintax Class.
How to use:
Just include the class and use the code below.
1 2 3 4 5 | <?php include("spintax.class.php"); $spintax = new Spintax; // Add true to the spin functions to debug and see each line as it is spun in the process $spintax->spin("{{Hello|Hi} my name is {Ron|Ronald}|Another random {sentence|{statement|phrase|saying}}}"); |
That’s all!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | <?php class Spintax { function spin($str, $test=false) { if(!$test){ do { $str = $this->regex($str); } while ($this->complete($str)); return $str; } else { do { echo "<b>PROCESS: </b>";var_dump($str = $this->regex($str));echo "<br><br>"; } while ($this->complete($str)); return false; } } function regex($str) { preg_match("/{[^{}]+?}/", $str, $match); // Now spin the first captured string $attack = explode("|", $match[0]); $new_str = preg_replace("/[{}]/", "", $attack[rand(0,(count($attack)-1))]); $str = str_replace($match[0], $new_str, $str); return $str; } function complete($str) { $complete = preg_match("/{[^{}]+?}/", $str, $match); return $complete; } } |
Bug fixes – ultimately recursive now
8 Comments on “Recursive PHP Spintax Class 3.0”
[...] is the completely true recursive renovated class that makes use of regex. Get 3.0 NOW! PHP Recursive Spintax Class 3.0 12345678910111213141516171819202122232425262728293031323334<?php class Spintax { [...]
I want to thank you from this class. It made possible to deploy my tool on site. I’m not sure how code will stick on comments here, but I will try to send you my variation of your code so you can further develop yours if needed:
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
class Spintax
{
# this is just a wrapper for shorter static calls
function process($text, $template = array()) {
$c = new SpintaxBase();
if ($template) {
array_walk($template, array($c, 'filter_template'));
$c->template = $template;
}
return $c->get($text);
}
}
// modified from: http://ronaldarichardson.com/2011/09/23/recursive-php-spintax-class-3-0/
class SpintaxBase
{
# template left marker, separator and right marker for default spintax format
# you can change the format by setting this variable before calling get method for example:
# $c->template = array('[spin]', '~', '[/spin]');
public $template = array('{', '|', '}');
public $match_str;
# sanitize template chars to work with regexp
public function filter_template(&$val) {
$val = str_replace(array('[', ']', '/', '~'), array('\[', '\]', '\\/', '~'), $val);
}
# main getter
public function get($text) {
if ($text) {
$this->match_str = '/'.$this->template[0].'[^'.$this->template[0].$this->template[2].']+?'.$this->template[2].'/';
do {
$text = $this->_capture($text);
} while (preg_match($this->match_str, $text));
}
return $text;
}
private function _capture($text) {
preg_match($this->match_str, $text, $match);
if (isset($match[0])) {
$words = explode($this->template[1], $match[0]);
$replace = preg_replace('/['.$this->template[0].$this->template[2].']/', '', $words[rand(0, count($words)-1)]);
$text = str_replace($match[0], $replace, $text);
}
return $text;
}
}
Cool, I have already made spintax editors with syntax highlighting, a desktop version and web based version, will be sure to share soon.
I’ll be watching this space closely then! Now meanwhile I did something you might be interested too, namely javascript and coffee script version of the spinner. I can’t resist to share them too as a contribution to your site. I noticed your Python version and was inspired to this port:
coffeescript:
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
replace_regexp_str = /[{}]/gi
match_regexp_str = /{[^{}]+?}/gi
spin = (txt) ->
if txt
txt = capture(txt) while txt.match(match_regexp_str)
txt
capture = (txt) ->
match = txt.match(match_regexp_str)
if (match[0])
words = match[0].split(split_str)
replace = words[Math.floor(Math.random()*words.length)].replace(replace_regexp_str, '')
txt = txt.replace(match[0], replace)
txt
alert spin('This is {my nested {spintax|spuntext} formatted string|your nested {spintax|spuntext} formatted string} test.')
which turns easily to javascript via http://jashkenas.github.com/coffee-script/ evaluator:
var capture, match_regexp_str, replace_regexp_str, spin, split_str;
split_str = '|';
replace_regexp_str = /[{}]/gi;
match_regexp_str = /{[^{}]+?}/gi;
spin = function(txt) {
if (txt) {
while (txt.match(match_regexp_str)) {
txt = capture(txt);
}
}
return txt;
};
capture = function(txt) {
var match, replace, words;
match = txt.match(match_regexp_str);
if (match[0]) {
words = match[0].split(split_str);
replace = words[Math.floor(Math.random() * words.length)].replace(replace_regexp_str, '');
txt = txt.replace(match[0], replace);
}
return txt;
};
alert(spin('This is {my nested {spintax|spuntext} formatted string|your nested {spintax|spuntext} formatted string} test.'));
One case came to my mind; are you sure replace part doesn’t replace all occurrence of one word to same synonym? Say I have a phrase “{one|two|three}{one|two|three}” would it give only: one one or two two or three three? I know, its a small test run to find out
Awesome share, I will have to make use of the JavaScript version.
Also:
The replace doesn’t work like that, the regex finds the lowest level of “{}” first then spins it then replace, and all of this happens one match at a time. So they are not all being replaced at the same time.
So the outcome will be random each spin. try it.
Yea, I tested and it works. No problems with deep nested sets or repeating options. Way to go, looking forward more cool stuff from this site
Ronald, Thank you for sharing this. This class is very, very useful.
But I tested and this class replace all occurrence of one word to same synonym at the same time.
This variation of your code replace one match at a time (sorry, It is not elegant but it works):
Replace the line:
By the following lines:
2
3
4
5
6
$match_0 = str_replace("|", "\|", $match[0]);
$match_0 = str_replace("{", "\{", $match_0);
$match_0 = str_replace("}", "\}", $match_0);
$reg_exp = "/".$match_0."/";
$str = preg_replace($reg_exp, $new_str, $str, 1);
@fransbern it actually replaces one match at time, and never all at once under any circumstance. Put it in test mode to see what I mean.
Leave a Reply