GaretJax / phpbrowscap

Standalone replacement for php's native get_browser() function
MIT License
429 stars 69 forks source link

an idea to implement priority patterns #45

Open oschonrock opened 10 years ago

oschonrock commented 10 years ago

Thanks for a great, particularly like the speed! 15x faster than get_browser (4ms vs 60ms!)

Motivation: We found that Googlebot-Mobile was not being identified as a crawler. The reason was Google prepends the identfying string with a random mobile UA (eg iPhone). Because the Googlebot-Mobile pattern is quite low down in the list in the current browscap.ini getBrowser() was matching the robot as a genuine iPhone.

Proposed solution: Rather then getting the author of browscap.ini to change the order of the patterns, which may take a long time or not be desirable for all users of that file. We wrote a class extending Browscap which allows the user of the class to specify some partial patterns as "priority". During _buildCache (so we only have do this once!) it matches for these partial patterns and move them to the front.

Here is our code, feel free to use/copy/include it if you think it's helpful.

 $this->_patterns[$pattern]);
    unset($this->_patterns[$pattern]);
    $this->_patterns = $temp + $this->_patterns;
  }

  /**                                                                                                                                                                                
   *                                                                                                                                                                                 
   */
  protected function isProrityPattern($pattern)
  {
    foreach ($this->priority_patterns as $priority_pattern)
    {
      if (stripos($pattern, $priority_pattern) !== false)
      {
        return true;
      }
    }
    return false;
  }

  /**                                                                                                                                                                                
   *                                                                                                                                                                                 
   */
  protected function applyPrioritiesToPatterns()
  {
    foreach ($this->_patterns as $pattern => $pattern_data)
    {
      if ($this->isProrityPattern($pattern))
      {
        $this->movePatternToTop($pattern);
      }
    }
  }

  /**                                                                                                                                                                                
   * Parses the array to cache and creates the PHP string to write to disk                                                                                                           
   *                                                                                                                                                                                 
   * @return string the PHP string to save into the cache file                                                                                                                       
   */
  protected function _buildCache()
  {
    $this->applyPrioritiesToPatterns();
    return parent::_buildCache();
  }

}
oschonrock commented 10 years ago

sorry, try again on the code:

use phpbrowscap\Browscap;
class PrioritisedBrowscap extends Browscap
{
  /**                                                                                                                                                                                
   *                                                                                                                                                                                 
   */
  protected $priority_patterns = array(
    // this will match the phone ua in front of it if left low down the list                                                                                                         
    'Googlebot\-Mobile', // note that the '-' is escaped in the pattern for some reason                                                                                              
    );
  /**                                                                                                                                                                                
   *                                                                                                                                                                                 
   */
  protected function movePatternToTop($pattern)
  {
    $temp = array($pattern => $this->_patterns[$pattern]);
    unset($this->_patterns[$pattern]);
    $this->_patterns = $temp + $this->_patterns;
  }
  /**                                                                                                                                                                                
   *                                                                                                                                                                                 
   */
  protected function isProrityPattern($pattern)
  {
    foreach ($this->priority_patterns as $priority_pattern)
    {
      if (stripos($pattern, $priority_pattern) !== false)
      {
        return true;
      }
    }
    return false;
  }
  /**                                                                                                                                                                                
   *                                                                                                                                                                                 
   */
  protected function applyPrioritiesToPatterns()
  {
    foreach ($this->_patterns as $pattern => $pattern_data)
    {
      if ($this->isProrityPattern($pattern))
      {
        $this->movePatternToTop($pattern);
      }
    }
  }
  /**                                                                                                                                                                                
   * Parses the array to cache and creates the PHP string to write to disk                                                                                                           
   *                                                                                                                                                                                 
   * @return string the PHP string to save into the cache file                                                                                                                       
   */
  protected function _buildCache()
  {
    $this->applyPrioritiesToPatterns();
    return parent::_buildCache();
  }
}
quentin389 commented 10 years ago

Hi, sorry for the delay.

It's not a simple issue... please read this: https://github.com/browscap/browscap/issues/33

So unfortunately I have to fix problems like that separately for each erroneous match :|

And that means, that the idea of adding an optional priority that overrides the automatic order makes a lot of sense.

I can't promise when I'll look at the code and implement it, but I'm keeping this issue in mind.