Having trouble getting some code to auto-capitalize words properly

Thank you so much Malasho!

That works, the only error I see is that for some reason if there is a word wrapped in quotations like this: “word” it outputs as “Word”

Was this what you were referencing earlier about adding other symbols besides a hyphen to the code? If so, could you show me as an example of how to add one more so that I can then add any others I need in the future? Like for the quotation marks, the ascii character code is 34 so where do I add that in?

Thank you so much!!

Sorry I couldn’t get back to you sooner.

It won’t do any good to add the ascii value for the double quote in this case. The problem looks like it is related to the code wrapping. I have added a line to ensure that any html encoding are decoded in the final string. I’m a little worried though that the problem may lie outside of the control of the script.
[php]if (is_subclass_of($this, ‘vB_DataManager_ThreadPost’) && is_array($this->validfields[‘title’]))
{
$this->validfields[‘title’][VF_CODE] = ’
global $exclude_words, $capital_words, $max_length;
$exclude_words = array(“a”,“an”,“and”,“at”,“but”,“by”,“for”,“in”,“nor”,“of”,“on”,“or”,“so”,“the”,“to”,“up”,“yet”); // Exclude analyzing these words
$capital_words = array(“brb”,“lol”,“usa”); // Capital exclusives (leave in lowercase in array)
$start_indicators = array(".","?","!");
$max_length = 5; // Maximum word length, anything over is case-lowered

$retval = $dm->verify_title($data);

$start = 1;

    $words = explode(" ",$data);

foreach($words as $word)
{
$ignore = $do = $chunk = array();
$part = 0;
for($i=0;$i<strlen($word);$i++)
{
$char = ord($word[$i]);
if($char!= 39 && ($char<65 || ($char>90 && $char<97) || $char>122))
{
$ignore[++$part] = chr($char);
$part++;
}
else $do[$part] .= chr($char);
}

    $changed = array();
    foreach ($do as $k=>$wordpart)
      {
        $lcWordPart = strtolower($wordpart);
        if(!in_array($lcWordPart,$exclude_words) || $start == 1)
          {
            if(in_array($lcWordPart,$capital_words)) $changed[$k] = strtoupper($wordpart);
            elseif(strlen($wordpart) >=$max_length && !in_array($lcWordPart,$capital_words)) $changed[$k] = ucwords(strtolower($wordpart));
            else $changed[$k] = ucwords(strtolower($wordpart));
            $start = 0;
          }
        else $changed[$k] = strtolower($wordpart);
      }
      
    $chunk = $changed+$ignore;
    ksort($chunk);
    $string[] = implode($chunk);
    $puncTest = substr(end($string),-1);
    $start = in_array($puncTest,$start_indicators);
 }

                
$data = implode(" ",$string);
$data = html_entity_decode($data);

return $retval;
';

}[/php]

Malasho,

Thank you so much again for sticking with this. Can not thank you enough.

It looks like you are correct – I tried your latest code version and still get the " surrounding any word that has quotation marks around it.

Would this mean it is definitely something outside the realm of this code that is responsible for that? If I remove this code plugin, the forum software does handle the quotation mark correctly when entered in a sentence.

Is there any way to figure out which piece of our code is the one responsible for mess up?

Thank you so much!

My pleasure!

I am still looking for a possible solution, but I am convinced that it has to do with the wrapper and the way it is handled (outside of the actual code). I took the code back out of the wrapper and tested specifically with a double-quoted work. The output was correct.

In looking the code over, I did see one thing that should be changed:else $do[$part] .= chr($char);
should be changed to:else if(isset($do[$part])) $do[$part] .= chr($char); else $do[$part] = chr($char);

This will not throw an error, but it should throw a warning since the first iteration of each word will be trying to concatenate the next character to a non-existent (as of that moment) index. I would go ahead and make this change, as it is the “right” way to do it.

I would also go ahead and remove the html_entity_decode line that we added, as it didn’t make a difference and is unnecessary.

I’ll keep looking for a possible solution to the html_entity issue and get back to you shortly.

Forgot to mention that it looks like that darn equal sign is back in there. I think I accidentally grabbed an older version when I was redoing the script at some point. You should go ahead and remove it.

Sorry.

I went ahead and made the changes you showed and this is now the code that I am using.

Unfortunately now it is no longer capitalizing anything at all :frowning:

Did I mess up?

[php]if (is_subclass_of($this, ‘vB_DataManager_ThreadPost’) && is_array($this->validfields[‘title’]))
{
$this->validfields[‘title’][VF_CODE] = ’
global $exclude_words, $capital_words, $max_length;
$exclude_words = array(“a”,“an”,“and”,“at”,“but”,“by”,“for”,“in”,“nor”,“of”,“on”,“or”,“so”,“the”,“to”,“up”,“yet”); // Exclude analyzing these words
$capital_words = array(“brb”,“lol”,“usa”); // Capital exclusives (leave in lowercase in array)
$start_indicators = array(".","?","!");
$max_length = 5; // Maximum word length, anything over is case-lowered

$retval = $dm->verify_title($data);
$start = 1;

$words = explode(" ",$data);

foreach($words as $word)
  {
    $ignore = $do = $chunk = array();
    $part = 0;
    for($i=0;$i<strlen($word);$i++)
      {
        $char = ord($word[$i]);
        if($char!= 39 && ($char<65 || ($char>90 && $char<97) || $char>122))
          {
            $ignore[++$part] = chr($char);
            $part++;
          }
        else if(isset($do[$part])) $do[$part] .= chr($char);
		else $do[$part] = chr($char);
      }

    $changed = array();
    foreach ($do as $k=>$wordpart)
      {
        $lcWordPart = strtolower($wordpart);
        if(!in_array($lcWordPart,$exclude_words) || $start == 1)
          {
            if(in_array($lcWordPart,$capital_words)) $changed[$k] = strtoupper($wordpart);
            elseif(strlen($wordpart) > $max_length && !in_array($lcWordPart,$capital_words)) $changed[$k] = ucwords(strtolower($wordpart));
            else $changed[$k] = ucwords(strtolower($wordpart));
            $start = 0;
          }
        else $changed[$k] = strtolower($wordpart);
      }
      
    $chunk = $changed+$ignore;
    ksort($chunk);
    $string[] = implode($chunk);
    $puncTest = substr(end($string),-1);
    $start = in_array($puncTest,$start_indicators);
 }

                
$data = implode(" ",$string);
    
return $retval;
';

}[/php]

Actually I was wrong.

The code is working. I had made a mistake by not activating the plugin properly.

Just the double quotes issue still but I guess that’s not something we can resolve?

Thank you so much!

EDIT - It took me a while to put this together and after posting I saw your last post. I removed an initial paragraph.

I turned on full error reporting and no errors, warnings or notices were generated. Just to make sure this suggestion was valid, I reverted the code to how it was and it threw a bunch of notices - “Notice: Undefined offset: 0”.

I have been going through the source code for vBulletin suite and I do believe that the html entity issue is definitely being generated by the suite, not the code we are using. I believe that the greater than and less than symbols will also generate the html entities. I found a function: htmlspecialchars_uni that specifically looks for these three (including the double quote) characters.

We can verify that the htmlspecialchars_uni function is the culprit by doing the following: Locate the following file: /includes/class_core.php
At the bottom of the file (around line 4529 you will find the function we are looking for. Change this:[php]{
return str_replace([/php]

to this:

[php]{
return $text;
return str_replace([/php]

NOTE: THIS IS ONLY FOR TESTING - DO NOT LEAVE IT LIKE THIS. As soon as you are done testing to see if this is the culprit, you should return it to exactly the way it was. I would recommend copying the file first and then replacing the changed file with the original backup. Also I cannot test this, so I can’t make any promises…

Thank you for helping so much!

Will test this right now and report back :slight_smile:

You were right malasho!

After I did that last change, the double quotes worked perfectly!

So I suppose there’s no way to have our code on AND make the double quotes work unless we edit that file permanently?

Just so I have a better understanding of it, could you take a minute to explain which part of the code that we’re using is responsible for the double quotes not working? Is it because we’re exploding instead of using preg_split? (forgive me if this is a stupid question :slight_smile: )

Not a stupid question at all.

Actually, no part of our code is causing this. It has to do with the way vBulletin Suite processes the string that is provided in either the validfields[‘title’][VF_CODE] assignment or else the verify_title function. I have not determined which yet. It might be interesting to see what happens with this…[php]$this->validfields[‘title’][VF_CODE] = ’
$retval = $dm->verify_title(’"’);
return $retval;
';[/php] I suspect you will get " although it is possible that other factors (the length of the data, etc.) may interfere with it undergoing the same checking. If it outputs as " then maybe try a longer string (whatever you were using to test your function).

DISCLAIMER: this may not work at all, I may be overlooking some other necessary element, but I believe it will demonstrate that your code is not generating the issue.

We should be able to isolate the vBulletin function that is calling the htmlspecialcharacter_uni function, but it is a really bad idea to change any of the vBulletin functions. You don’t know what other things it may affect down the line, plus you will most likely lose your modifications with every update. (I am guessing here, not having used it or tracked the upgrade procedure).

I will continue to look through things tomorrow and see if I can identify a valid workaround. If you want to test it per above, that is fine, if it requires a lot of work, I wouldn’t worry about it.

I hope to have something more for you tomorrow (later today).

Thanks malasho!

I will try that out.

I’m not sure if when I asked previously it didn’t make sense or you may have just missed it in all the posts I was making but when I do disable our code, the double quotes work perfectly with vBulletin’s default code.

That is why I was thinking it is something that we are doing that is causing it, but I will try this last code snippet that you pasted and report back!

Using that code I am getting the error:

Parse error: syntax error, unexpected ‘"’

Whoops, I’m not used to having all my code wrapped in single quotes! Sorry.

Lets see about this…[php]$this->validfields[‘title’][VF_CODE] = ’
$retval = $dm->verify_title(");
return $retval;
';[/php]

Used this code:

[php]if (is_subclass_of($this, ‘vB_DataManager_ThreadPost’) && is_array($this->validfields[‘title’]))
{

$this->validfields[‘title’][VF_CODE] = ’
$retval = $dm->verify_title(");
return $retval;
';

}[/php]

Returned this error:

Parse error: syntax error, unexpected $end in /home/rehan/public_html/dev/includes/class_dm.php(504) : runtime-created function on line 4

Fatal error: Function name must be a string in /home/rehan/public_html/dev/includes/class_dm.php on line 505

and not sure which version of vB files you have with you but for reference I’m on version 4.2.0.

OK, the brain is going again. Looks like its time for bed!

I think this option should work…[php]if (is_subclass_of($this, ‘vB_DataManager_ThreadPost’) && is_array($this->validfields[‘title’]))
{

$this->validfields[‘title’][VF_CODE] = ’
$retval = $dm->verify_title(chr(34));
return $retval;
';

}[/php]

I’m not sure how else to get a double quote (ascii 34) to be passed literally… This should work and definitely will ensure that the actual character, not an html_entity version is being sent.

Ok that seems to be working. It is preserving the double quotes correctly. :slight_smile:

Interesting…

Not quite what I expected, considering that we were able to conclusively show that the vBulletin htmlspecialcharacter_uni function is being called somewhere along the line!

I would like to do a str_replace on the $data variable just before the return, but I am not coming up with a way to do what I would like inside the wrapper. I hate to do it, but I think I’m going to go to bed and maybe it will be obvious a little later…

Sorry

No need whatsoever to apologize!

Thank you so much for your continued assistance!! :smiley:

Hi Malasho,

I hate to trouble you again, but is there anything in our last snippet of code that would keep $max_length from no longer working?

It seems that if I type in a 4 letter word in all caps (which isn’t defined in $capital_words), it doesn’t stay uppercase as it should be staying since it is under the $max_length limit. I tried typing “a simple TEST” and the output was “A Simple Test” where it should be “A Simple TEST”.

THANK YOU!

This is the code I have right now:

[php]if (is_subclass_of($this, ‘vB_DataManager_ThreadPost’) && is_array($this->validfields[‘title’]))
{
$this->validfields[‘title’][VF_CODE] = ’
global $exclude_words, $capital_words, $max_length;
$exclude_words = array(“a”,“an”,“and”,“at”,“but”,“by”,“for”,“in”,“nor”,“of”,“on”,“or”,“so”,“the”,“to”,“up”,“yet”); // Exclude analyzing these words
$capital_words = array(“aku”,“uhs”,“pmdc”,“ibcc”,“mcat”,“mcq”,“cmh”,“fumc”,“amc”,“nust”,“dimc”,“fmc”,“cpmc”,“hec”,“mbbs”,“ptap”,“sat”,“bds”,“kpk”,“fbise”,“lmdc”,“rmc”,“kemu”,“kemc”,“aimc”,“us”,“lums”,“sat-ii”,“plab”,“usmle”,“sims”,“smh”,“fmh”,“imdc”,“uol”,“nmc”,“cs”,“mc”,“dmc”,“imed”); // Capital exclusives (leave in lowercase in array)
$start_indicators = array(".","?","!");
$max_length = 5; // Maximum word length, anything over is case-lowered

$retval = $dm->verify_title($data);
$start = 1;

$words = explode(" ",$data);

foreach($words as $word)
  {
    $ignore = $do = $chunk = array();
    $part = 0;
    for($i=0;$i<strlen($word);$i++)
      {
        $char = ord($word[$i]);
        if($char!= 39 && ($char<65 || ($char>90 && $char<97) || $char>122))
          {
            $ignore[++$part] = chr($char);
            $part++;
          }
        else if(isset($do[$part])) $do[$part] .= chr($char);
		else $do[$part] = chr($char);
      }

    $changed = array();
    foreach ($do as $k=>$wordpart)
      {
        $lcWordPart = strtolower($wordpart);
        if(!in_array($lcWordPart,$exclude_words) || $start == 1)
          {
            if(in_array($lcWordPart,$capital_words)) $changed[$k] = strtoupper($wordpart);
            elseif(strlen($wordpart) > $max_length && !in_array($lcWordPart,$capital_words)) $changed[$k] = ucwords(strtolower($wordpart));
            else $changed[$k] = ucwords(strtolower($wordpart));
            $start = 0;
          }
        else $changed[$k] = strtolower($wordpart);
      }
      
    $chunk = $changed+$ignore;
    ksort($chunk);
    $string[] = implode($chunk);
    $puncTest = substr(end($string),-1);
    $start = in_array($puncTest,$start_indicators);
 }

                
$data = implode(" ",$string);
    
return $retval;
';

}[/php]

Sponsor our Newsletter | Privacy Policy | Terms of Service