I'm using this function to convert text to title case:
function strtotitle($title) {
$smallwordsarray = array( 'of','a','the','and','an','or','nor','but','is','if','then','else','when', 'at','from','by','on','off','for','in','to','into','with','it', 'as' );
// Split the string into separate words
$words = explode(' ', $title);
foreach ($words as $key => $word) {
// If this word is the first, or it's not one of our small words, capitalise it
// with ucwords().
if ($key == 0 or !in_array($word, $smallwordsarray))
$words[$key] = ucwords($word);
}
// Join the words back into a string
$newtitle = implode(' ', $words);
return $newtitle;
}
The issue is that if text is bold, italic etc then the function does not work and will not title case the word.
For example: "This is a simple sentence" will be converted to "This is a Simple Sentence". But "This is a simple sentence" will be converted to "This is a simple Sentence".
Any help greatly appreciated.
If you are talking about HTML tags and you want to save it, you can use this implementation:
<?php
/* Your old string */
$string = "<b>asd</b>";
/* Remove html code */
$old = strip_tags($string);
/* Upper case the first letter */
$new = ucfirst($old);
/* Replace old word to new word in $string */
$real = str_replace($old,$new,$string);
/* Here the new string and the old string */
echo $real." ".$string;
?>
So the solution in your code looks like :
function strtotitle($title) {
$smallwordsarray = array( 'of','a','the','and','an','or','nor','but','is','if','then','else','when', 'at','from','by','on','off','for','in','to','into','with','it', 'as' );
// Split the string into separate words
$words = explode(' ', $title);
foreach ($words as $key => $word) {
// If this word is the first, or it's not one of our small words, capitalise it
// with ucwords().
if ($key == 0 or !in_array(strip_tags($word), $smallwordsarray)) {
$old = strip_tags($word);
$new = ucfirst($old);
$words[key] = str_replace($old,$new,$word);
}
}
// Join the words back into a string
$newtitle = implode(' ', $words);
return $newtitle;
}
<?php
function strtotitle($title) {
$smallwordsarray = array( 'of','a','the','and','an','or','nor','but','is','if','then','else','when', 'at','from','by','on','off','for','in','to','into','with','it', 'as' );
$words = $temp = explode(' ', strip_tags($title));
foreach ($temp as $key => $word) {
if ($key == 0 or !in_array($word, $smallwordsarray)) $temp[$key] = ucwords($word);
}
foreach($words as $index => $word) $title = str_replace($word, $temp[$index], $title);
return $title;
}
var_dump(strtotitle('This is a simple sentence'));
var_dump(strtotitle('This is a <b>simple</b> <i>sentence</i>'));
You could use strip_tags this way:
function strtotitle($title) {
$smallwordsarray = array( 'of','a','the','and','an','or','nor','but','is','if','then','else','when', 'at','from','by','on','off','for','in','to','into','with','it', 'as' );
// Remove HTML tags
$titleWithoutTags = strip_tags($title);
// Split the string into separate words
$words = explode(' ', $titleWithoutTags);
foreach ($words as $key => $word) {
// If this word is the first, or it's not one of our small words, capitalise it
// with ucwords().
if ($key == 0 or !in_array($word, $smallwordsarray))
$words[$key] = ucwords($word);
}
// Join the words back into a string
$newtitle = implode(' ', $words);
return $newtitle;
}
I have a script below that detects for words in my word filter (an array), and determines whether a string is clean or not.
What I have below works well when the words are used with spacing. But ifiwritesomething without spaces, it doesn't detect.
How can I make it such that it searches the whole string instead of words? I tried removing the explode function but I got some errors...
$string = 'goodmorningnoobs';
$array = array("idiot","noob");
if(0 == count(array_intersect(array_map('strtolower', explode(' ', $string)), $array))){
echo"clean";
} else {
echo "unclean";
}
Can anyone help?
$clean = true;
foreach ( $array as $word ) {
if ( stripos($string, $word) !== false ) {
$clean = false;
break;
}
}
echo $clean ? 'clean' : 'unclean';
How about?
$hasWords = preg_match('/'. implode('|', $words) .'/', $string);
echo $hasWords ? 'unclean' : 'clean';
Example input string: "[A][B][C]test1[/B][/C][/A] [A][B]test2[/B][/A] test3"
I need to find out what parts of text are NOT between the A, B and C tags. So, for example, in the above string it's 'test2' and 'test3'. 'test2' doesn't have the C tag and 'test3' doesn't have any tag at all.
If can also be nested like this:
Example input string2: "[A][B][C]test1[/B][/C][/A] [A][B]test2[C]test4[/C][/B][/A] test3"
In this example "test4" was added but "test4" has the A,B and C tag so the output wouldn't change.
Anyone got an idea how I could parse this?
This solution is not clean but it does the trick
$string = "[A][B][C]test1[/B][/C][/A] [A][B]test2[/B][/A] test3" ;
$string = preg_replace('/<A[^>]*>([\s\S]*?)<\/A[^>]*>/', '', strtr($string, array("["=>"<","]"=>">")));
$string = trim($string);
var_dump($string);
Output
string 'test3' (length=5)
Considering the fact that everyone of you tags is in [A][/A] What you can do is: Explode the [/A] and verify if each array contains the [A] tag like so:
$string = "[A][B][C]test1[/B][/C][/A] [A][B]test2[/B][/A] test3";
$found = ''; // this will be equal to test3
$boom = explode('[/A]', $string);
foreach ($boom as $val) {
if (strpos($val, '[A] ') !== false) { $found = $val; break; }
}
echo $found; // test3
try the below code
$str = 'test0[A]test1[B][C]test2[/B][/C][/A] [A][B]test3[/B][/A] test4';
$matches = array();
// Find and remove the unneeded strings
$pattern = '/(\[A\]|\[B\]|\[C\])[^\[]*(\[A\]|\[B\]|\[C\])[^\[]*(\[A\]|\[B\]|\[C\])([^\[]*)(\[\/A\]|\[\/B\]|\[\/C\])[^\[]*(\[\/A\]|\[\/B\]|\[\/C\])[^\[]*(\[\/A\]|\[\/B\]|\[\/C\])/';
preg_match_all( $pattern, $str, $matches );
$stripped_str = $str;
foreach ($matches[0] as $key=>$matched_pattern) {
$matched_pattern_str = str_replace($matches[4][$key], '', $matched_pattern); // matched pattern with text between A,B,C tags removed
$stripped_str = str_replace($matched_pattern, $matched_pattern_str, $stripped_str); // replace pattern string in text with stripped pattern string
}
// Get required strings
$pattern = '/(\[A\]|\[B\]|\[C\]|\[\/A\]|\[\/B\]|\[\/C\])([^\[]+)(\[A\]|\[B\]|\[C\]|\[\/A\]|\[\/B\]|\[\/C\])/';
preg_match_all( $pattern, $stripped_str, $matches );
$required_strings = array();
foreach ($matches[2] as $match) {
if (trim($match) != '') {
$required_strings[] = $match;
}
}
// Special case, possible string on start and end
$pattern = '/^([^\[]*)(\[A\]|\[B\]|\[C\]).*(\[\/A\]|\[\/B\]|\[\/C\])([^\[]*)$/';
preg_match( $pattern, $stripped_str, $matches );
if (trim($matches[1]) != '') {
$required_strings[] = $matches[1];
}
if (trim($matches[4]) != '') {
$required_strings[] = $matches[4];
}
print_r($required_strings);
I want to normalize (so canonicalize) a string into the normal form for names:
First letter of the name is uppercase
The difficulty by this is now to follow this rule with second and third name.
My method:
public function namilize($string)
{
$strings = explode(' ', $string);
foreach ($strings as $string) {
$string = ucfirst(strtolower($string));
}
$string = implode(' ', $strings);
return $string;
}
Somehow the
$string = ucfirst(strtolower($string));
fails.
What do I have to correct?
Is there a better way?
Regards
EDIT:
Hi,
thank you all for all the comments and answers.
I found another "modern" method:
public function namilize($string)
{
$string = mb_convert_case($string, MB_CASE_TITLE, mb_detect_encoding($string));
}
When I now would additionally add some regex for Mc and O's than it would be complete :)
public function namilize($name) {
$name = strtolower($name);
$normalized = array();
foreach (preg_split('/([^a-z])/', $name, NULL, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY) as $word) {
if (preg_match('/^(mc)(.*)$/', $word, $matches)) {
$word = $matches[1] . ucfirst($matches[2]);
}
$normalized[] = ucfirst($word);
}
return implode('', $normalized);
}
Note that this will work for names like John O'Brian, James McManus, etc. For other names with prefixes like McManus, simply add the prefix to the preg_match(). Obviously, this runs the possibility of false positives, but no method is going to be 100% foolproof.
You have to pass the $string by reference, note the &:
public function namilize($string)
{
$strings = explode(' ', $string);
foreach ($strings as &$string) {
$string = ucfirst(strtolower($string));
}
$string = implode(' ', $strings);
return $string;
}
Or use the function suggested by #thetaiko ucwords($string)
The $string inside the foreach will only store the last iteration (or the last name). This doesn't really matter though because the variable in the foreach is never used for output. The implode just undoes what you did with the explode so you will end up with the exact same output as the input. I changed the variable names to be more descriptive in this example:
function namilize($name_in)
{
$a_names = explode(' ', $name_in); //explode string into array
foreach ($a_names as $name) {
$a_fullname[] = ucfirst(strtolower($name)); //build array of proper case names
}
$string = implode(' ', $a_fullname); //convert array into string
return $string;
}
I am trying to test if a string made up of multiple words and has any values from an array at the end of it. The following is what I have so far. I am stuck on how to check if the string is longer than the array value being tested and that it is present at the end of the string.
$words = trim(preg_replace('/\s+/',' ', $string));
$words = explode(' ', $words);
$words = count($words);
if ($words > 2) {
// Check if $string ends with any of the following
$test_array = array();
$test_array[0] = 'Wizard';
$test_array[1] = 'Wizard?';
$test_array[2] = '/Wizard';
$test_array[4] = '/Wizard?';
// Stuck here
if ($string is longer than $test_array and $test_array is found at the end of the string) {
Do stuff;
}
}
By end of string do you mean the very last word? You could use preg_match
preg_match('~/?Wizard\??$~', $string, $matches);
echo "<pre>".print_r($matches, true)."</pre>";
I think you want something like this:
if (preg_match('/\/?Wizard\??$/', $string)) { // ...
If it has to be an arbitrary array (and not the one containing the 'wizard' strings you provided in your question), you could construct the regex dynamically:
$words = array('wizard', 'test');
foreach ($words as &$word) {
$word = preg_quote($word, '/');
}
$regex = '/(' . implode('|', $words) . ')$/';
if (preg_match($regex, $string)) { // ends with 'wizard' or 'test'
Is this what you want (no guarantee for correctness, couldn't test)?
foreach( $test_array as $testString ) {
$searchLength = strlen( $testString );
$sourceLength = strlen( $string );
if( $sourceLength <= $searchLength && substr( $string, $sourceLength - $searchLength ) == $testString ) {
// ...
}
}
I wonder if some regular expression wouldn't make more sense here.