TeraWurfl
[ class tree: TeraWurfl ] [ index: TeraWurfl ] [ all elements ]

Source for file TeraWurflLoader.php

Documentation is available at TeraWurflLoader.php

  1. <?php
  2. /**
  3.  * Tera_WURFL - PHP MySQL driven WURFL
  4.  * 
  5.  * Tera-WURFL was written by Steve Kamerman, and is based on the
  6.  * Java WURFL Evolution package by Luca Passani and WURFL PHP Tools by Andrea Trassati.
  7.  * This version uses a MySQL database to store the entire WURFL file, multiple patch
  8.  * files, and a persistent caching mechanism to provide extreme performance increases.
  9.  * 
  10.  * @package TeraWurfl
  11.  * @author Steve Kamerman <stevekamerman AT gmail.com>
  12.  * @version Stable 2.1.3 $Date: 2010/09/18 15:43:21
  13.  * @license http://www.mozilla.org/MPL/ MPL Vesion 1.1
  14.  */
  15. /**
  16.  * Loads the WURFL file from a local file or remote URL into the Tera-WURFL database.
  17.  * @package TeraWurfl
  18.  *
  19.  */
  20.     
  21.     public static $WURFL_LOCAL "local";
  22.     public static $WURFL_REMOTE "remote";
  23.     public static $WURFL_REMOTE_CVS "remote_cvs";
  24.     public static $WURFL_PATCH "patch";
  25.     
  26.     // Properties
  27.     public $errors;
  28.     public $version;
  29.     public $last_updated;
  30.     
  31.     protected $table;
  32.     protected $file;
  33.     protected $wurfl;
  34.     
  35.     protected $devices;
  36.     protected $tables;
  37.     protected $parser;
  38.     
  39.     public $mainDevices = 0;
  40.     public $patchAddedDevices = 0;
  41.     public $patchMergedDevices = 0;
  42.     
  43.     /**#@+
  44.      * @var int Performance tracking variable
  45.      */
  46.     protected $timestart;
  47.     protected $timevalidate;
  48.     protected $timesort;
  49.     protected $timepatch;
  50.     protected $timedatabase;
  51.     protected $timecache;
  52.     protected $timeend;
  53.     /**#@-*/
  54.     
  55.     protected $PRESERVE_CACHE = true;
  56.     
  57.     // Constructor
  58.     public function __construct(TeraWurfl &$wurfl){
  59.         $this->errors = array();
  60.         $this->wurfl = $wurfl;
  61.         $this->devices = array();
  62.         $this->tables = array();
  63.         $this->file = TeraWurfl::absoluteDataDir().TeraWurflConfig::$WURFL_FILE;
  64.         $this->table = TeraWurflConfig::$TABLE_PREFIX;
  65.         $this->parser = TeraWurflXMLParser::getInstance();
  66.     }
  67.     
  68.     // Public Methods
  69.     /**
  70.      * Loads the WURFL and patch files into the database
  71.      * @return Bool Success
  72.      */
  73.     public function load(){
  74.         $this->wurfl->toLog("Loading WURFL",LOG_INFO);
  75.         if(!is_readable($this->file)){
  76.             $this->wurfl->toLog("The main WURFL file could not be opened: ".$this->file,LOG_ERROR);
  77.             $this->errors[]="The main WURFL file could not be opened: ".$this->file;
  78.             return false;
  79.         }
  80.         $this->timestart = microtime(true);
  81.         // Parse XML data into $this->devices array
  82.         $this->parser->open($this->fileTeraWurflXMLParser::$TYPE_WURFL);
  83.         $this->parser->process($this->devices);
  84.         $this->mainDevices = count($this->devices);
  85.         $this->version = $this->parser->wurflVersion;
  86.         $this->last_updated = $this->parser->wurflLastUpdated;
  87.         $this->wurfl->toLog("Loading Patches",LOG_INFO);
  88.         if(!$this->loadPatches()) return false;
  89.         $this->wurfl->toLog("Validating WURFL Data",LOG_INFO);
  90.         if(!$this->validate()) return false;
  91.         $this->wurfl->toLog("Sorting WURFL Data",LOG_INFO);
  92.         if(!$this->sort()) return false;
  93.         $this->wurfl->toLog("Loading data into DB",LOG_INFO);
  94.         if(!$this->loadIntoDB()) return false;
  95.         $this->timecache = microtime(true);
  96.         if($this->PRESERVE_CACHE){
  97.             $this->wurfl->toLog("Rebuilding cache",LOG_INFO);
  98.             $this->wurfl->db->rebuildCacheTable();
  99.         }else{
  100.             $this->wurfl->db->createCacheTable();
  101.         }
  102.         $this->timeend = microtime(true);
  103.         $this->wurfl->db->updateSetting(TeraWurfl::$SETTING_PATCHES_LOADED,TeraWurflConfig::$PATCH_FILE);
  104.         $this->wurfl->db->updateSetting(TeraWurfl::$SETTING_WURFL_VERSION,$this->version);
  105.         $this->wurfl->db->updateSetting(TeraWurfl::$SETTING_WURFL_DATE,$this->last_updated);
  106.         $this->wurfl->db->updateSetting(TeraWurfl::$SETTING_LOADED_DATE,time());
  107.         $this->wurfl->toLog("Finished loading WURFL {$this->version} ({$this->last_updated}) in ".round($this->totalLoadTime(),2)." seconds",LOG_WARNING);
  108.         return true;
  109.     }
  110.     /**
  111.      * Validates the data from the WURFL file or Patch file
  112.      * @return Bool Vaild
  113.      */
  114.     public function validate(){
  115.         $this->timevalidate = microtime(true);
  116.         $before_errors count($this->errors);
  117.         foreach($this->devices as $id => &$device){
  118.             if(!$id == "generic"){
  119.                 // Must have a valid wurfl ID
  120.                 if(strlen($id)==0){
  121.                     $this->wurfl->toLog("Skipping WURFL entry (invalid ID):\n".var_export($device,true),LOG_WARNING);
  122.                     $this->errors["Skipping WURFL entry (invalid ID):\n".var_export($device,true);
  123.                     continue;
  124.                 }
  125.                 // Must have a valid User Agent unless it's "generic"
  126.                 if(strlen($device['user_agent'])==0){
  127.                     $this->wurfl->toLog("Skipping WURFL entry (invalid User Agent):\n".var_export($device,true),LOG_WARNING);
  128.                     $this->errors["Skipping WURFL entry (invalid User Agent):\n".var_export($device,true);
  129.                     continue;
  130.                 }
  131.                 // Must have a valid fall_back
  132.                 if(!$this->validID($device['fall_back'])){
  133.                     $this->wurfl->toLog("Invalid Fallback '".$device['fall_back']."':\n".var_export($device,true),LOG_WARNING);
  134.                     $this->errors["Invalid Fallback '".$device['fall_back']."':\n".var_export($device,true);
  135.                     continue;
  136.                 }
  137.             }
  138.         }
  139.         return ($before_errors == count($this->errors));
  140.     }
  141.     /**
  142.      * Sorts the validated data from $this->devices into their respective UserAgentMatcher tables ($this->tables)
  143.      * based on the UserAgentMatcher that matches the device's user agent
  144.      * @return Bool Success
  145.      */
  146.     public function sort(){
  147.         $this->timesort = microtime(true);
  148.         foreach($this->devices as $id => &$device){
  149.             // This will return something like "Nokia", "Motorola", or "CatchAll"
  150.             $matcher = UserAgentFactory::userAgentType($this->wurfl,$device['user_agent']);
  151.             // TeraWurfl_Nokia
  152.             $uatable $this->table.'_'.$matcher;
  153.             if(!isset($this->tables[$uatable]))$this->tables[$uatable]=array();
  154.             $this->tables[$uatable][$device['id']]=$device;
  155.         }
  156.         // Destroy the devices array
  157.         $this->devices = array();
  158.         return true;
  159.     }
  160.     /**
  161.      * Loads the WURFL devices into the database.
  162.      * @return Bool Completed without error
  163.      */
  164.     public function loadIntoDB(){
  165.         $this->timedatabase = microtime(true);
  166.         if($this->wurfl->db->loadDevices($this->tables)){
  167.             return true;
  168.         }else{
  169.             $this->errors = array_merge($this->errors,$this->wurfl->db->errors);
  170.             return false;
  171.         }
  172.     }
  173.     /**
  174.      * Loads the patch files from TeraWurflConfig::PATCH_FILE
  175.      * @return Bool Success
  176.      */
  177.     public function loadPatches(){
  178.         if(!TeraWurflConfig::$PATCH_ENABLE) return true;
  179.         $this->timepatch = microtime(true);
  180.         // Explode the patchfile string into an array of patch files (normally just one file)
  181.         $patches explode(';',TeraWurflConfig::$PATCH_FILE);
  182.         foreach($patches as $patch){
  183.             $patch_devices = array();
  184.             $this->wurfl->toLog("Loading patch: ".$patch,LOG_WARNING);
  185.             $patch_parser TeraWurflXMLParser::getInstance();
  186.             $patch_parser->open(TeraWurfl::absoluteDataDir().$patchTeraWurflXMLParser::$TYPE_PATCH);
  187.             $patch_parser->process($patch_devices);
  188.             foreach($patch_devices as $id => &$device){
  189.                 if($this->validID($id)){
  190.                     // Merge this device on top of the existing device
  191.                     TeraWurfl::mergeCapabilities($this->devices[$id],$device);
  192.                     $this->patchMergedDevices++;
  193.                 }else{
  194.                     // Add this new device to the table
  195.                     $this->devices[$id$device;
  196.                     $this->patchAddedDevices++;
  197.                 }
  198.             }
  199.             unset($this->parser);
  200.         }
  201.         return true;
  202.     }
  203.     public function getParserName(){
  204.         return get_class(TeraWurflXMLParser::getInstance());
  205.     }
  206.  
  207.     /**#@+
  208.      * Get performance information
  209.      * @return int Duration in seconds
  210.      */
  211.     public function totalLoadTime(){
  212.         return ($this->timeend - $this->timestart);
  213.     }
  214.     public function parseTime(){
  215.         return ($this->timepatch - $this->timestart);
  216.     }
  217.     public function patchTime(){
  218.         return ($this->timevalidate - $this->timepatch);
  219.     }
  220.     public function validateTime(){
  221.         return ($this->timesort - $this->timevalidate);
  222.     }
  223.     public function sortTime(){
  224.         return ($this->timedatabase - $this->timesort);
  225.     }
  226.     public function databaseTime(){
  227.         return ($this->timecache - $this->timedatabase);
  228.     }
  229.     public function cacheRebuildTime(){
  230.         return ($this->timeend - $this->timecache);
  231.     }
  232.     /**#@-*/
  233.     
  234.     /**
  235.      * Is WURFL Device ID Valid?
  236.      * @param String WURFL ID
  237.      * @return Bool
  238.      */
  239.     protected function validID($id){
  240.         if(strlen($id)==0) return false;
  241.         return array_key_exists($id,$this->devices);
  242.     }

Documentation generated on Sun, 19 Sep 2010 00:16:02 +0000 by phpDocumentor 1.4.3