Last active
December 16, 2019 06:09
-
-
Save fer-ri/8470520 to your computer and use it in GitHub Desktop.
PHP Spinner Updated – Spin articles for SEO
Taken from http://www.paul-norman.co.uk/2010/09/php-spinner-updated-spin-articles-for-seo/
All credit goes to him
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// Example 1 | |
$string = '{{The|A}} {{quick|speedy|fast}} {{brown|black|red}} {{fox|wolf}} {{jumped|bounded|hopped|skipped}} over the {{lazy|tired}} {{dog|hound}}'; | |
echo '<p>'; | |
for($i = 1; $i <= 5; $i++) | |
{ | |
echo Spinner::detect($string, false).'<br />'; | |
// or Spinner::flat($string, false).'<br />'; | |
} | |
echo '</p>'; | |
// Example 2 | |
$string = '{{A {{simple|basic}} example|An uncomplicated scenario|The {{simplest|trivial|fundamental|rudimentary}} case|My {{test|invest{{igative|igation}}}} case}} to illustrate the {{function|problem}}'; | |
echo '<p>'; | |
for($i = 1; $i <= 5; $i++) | |
{ | |
echo Spinner::detect($string, false).'<br />'; | |
// or Spinner::nested($string, false).'<br />'; | |
} | |
echo '</p>'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
class Spinner | |
{ | |
# Detects whether to use the nested or flat version of the spinner (costs some speed) | |
public static function detect($text, $seedPageName = true, $openingConstruct = '{{', $closingConstruct = '}}', $separator = '|') | |
{ | |
if(preg_match('~'.$openingConstruct.'(?:(?!'.$closingConstruct.').)*'.$openingConstruct.'~s', $text)) | |
{ | |
return self::nested($text, $seedPageName, $openingConstruct, $closingConstruct, $separator); | |
} | |
else | |
{ | |
return self::flat($text, $seedPageName, false, $openingConstruct, $closingConstruct, $separator); | |
} | |
} | |
# The flat version does not allow nested spin blocks, but is much faster (~2x) | |
public static function flat($text, $seedPageName = true, $calculate = false, $openingConstruct = '{{', $closingConstruct = '}}', $separator = '|') | |
{ | |
# Choose whether to return the string or the number of permutations | |
$return = 'text'; | |
if($calculate) | |
{ | |
$permutations = 1; | |
$return = 'permutations'; | |
} | |
# If we have nothing to spin just exit (don't use a regexp) | |
if(strpos($text, $openingConstruct) === false) | |
{ | |
return $$return; | |
} | |
if(preg_match_all('!'.$openingConstruct.'(.*?)'.$closingConstruct.'!s', $text, $matches)) | |
{ | |
# Optional, always show a particular combination on the page | |
self::checkSeed($seedPageName); | |
$find = array(); | |
$replace = array(); | |
foreach($matches[0] as $key => $match) | |
{ | |
$choices = explode($separator, $matches[1][$key]); | |
if($calculate) | |
{ | |
$permutations *= count($choices); | |
} | |
else | |
{ | |
$find[] = $match; | |
$replace[] = $choices[mt_rand(0, count($choices) - 1)]; | |
} | |
} | |
if(!$calculate) | |
{ | |
# Ensure multiple instances of the same spinning combinations will spin differently | |
$text = self::str_replace_first($find, $replace, $text); | |
} | |
} | |
return $$return; | |
} | |
# The nested version allows nested spin blocks, but is slower | |
public static function nested($text, $seedPageName = true, $openingConstruct = '{{', $closingConstruct = '}}', $separator = '|') | |
{ | |
# If we have nothing to spin just exit (don't use a regexp) | |
if(strpos($text, $openingConstruct) === false) | |
{ | |
return $text; | |
} | |
# Find the first whole match | |
if(preg_match('!'.$openingConstruct.'(.+?)'.$closingConstruct.'!s', $text, $matches)) | |
{ | |
# Optional, always show a particular combination on the page | |
self::checkSeed($seedPageName); | |
# Only take the last block | |
if(($pos = mb_strrpos($matches[1], $openingConstruct)) !== false) | |
{ | |
$matches[1] = mb_substr($matches[1], $pos + mb_strlen($openingConstruct)); | |
} | |
# And spin it | |
$parts = explode($separator, $matches[1]); | |
$text = self::str_replace_first($openingConstruct.$matches[1].$closingConstruct, $parts[mt_rand(0, count($parts) - 1)], $text); | |
# We need to continue until there is nothing left to spin | |
return self::nested($text, $seedPageName, $openingConstruct, $closingConstruct, $separator); | |
} | |
else | |
{ | |
# If we have nothing to spin just exit | |
return $text; | |
} | |
} | |
# Similar to str_replace, but only replaces the first instance of the needle | |
private static function str_replace_first($find, $replace, $string) | |
{ | |
# Ensure we are dealing with arrays | |
if(!is_array($find)) | |
{ | |
$ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment