protected function actionBucket()
 {
     header('Content-Type: text/plain');
     echo "Database API v{$this->wurfl->release_version}; " . $this->wurfl->getSetting(TeraWurfl::$SETTING_WURFL_VERSION) . "\n";
     $this->wurfl->dumpBuckets();
     exit;
 }
 protected function actionDebug(TeraWurflCLIArgument $arg)
 {
     switch ($arg->value) {
         case "constIDgrouped":
             $matcherList = WurflConstants::$matchers;
             foreach ($matcherList as $matcher) {
                 $matcherClass = $matcher . "UserAgentMatcher";
                 $file = $this->wurfl->rootdir . "UserAgentMatchers/{$matcherClass}.php";
                 require_once $file;
                 $properties = get_class_vars($matcherClass);
                 if (empty($properties['constantIDs'])) {
                     continue;
                 }
                 echo "\n{$matcherClass}\n\t" . implode("\n\t", $properties['constantIDs']);
             }
             break;
         case "constIDunique":
             $matcherList = WurflConstants::$matchers;
             $ids = array();
             foreach ($matcherList as $matcher) {
                 $matcherClass = $matcher . "UserAgentMatcher";
                 $file = $this->wurfl->rootdir . "UserAgentMatchers/{$matcherClass}.php";
                 require_once $file;
                 $properties = get_class_vars($matcherClass);
                 $ids = array_merge($ids, $properties['constantIDs']);
             }
             $ids = array_unique($ids);
             sort($ids);
             echo implode("\n", $ids);
             break;
         case "constIDsanity":
             $matcherList = WurflConstants::$matchers;
             $errors = 0;
             foreach ($matcherList as $matcher) {
                 $matcherClass = $matcher . "UserAgentMatcher";
                 $file = $this->wurfl->rootdir . "UserAgentMatchers/{$matcherClass}.php";
                 require_once $file;
                 $properties = get_class_vars($matcherClass);
                 if (empty($properties['constantIDs'])) {
                     continue;
                 }
                 foreach ($properties['constantIDs'] as $key => $value) {
                     $deviceID = is_null($value) ? $key : $value;
                     try {
                         $this->wurfl->db->getDeviceFromID($deviceID);
                     } catch (Exception $e) {
                         $errors++;
                         echo "Error: {$matcherClass} references an invalid WURFL ID: {$deviceID}\n";
                     }
                 }
             }
             if ($errors === 0) {
                 echo "Done. No errors detected.\n";
             } else {
                 echo "Done. {$errors} error(s) detected.\n";
             }
             break;
         case "createProcs":
             echo "Recreating Procedures.\n";
             $this->wurfl->db->createProcedures();
             echo "Done.\n";
             break;
         case "benchmark":
             $quiet = true;
         case "batchLookup":
             if (!isset($quiet)) {
                 $quiet = false;
             }
             $fh = fopen($this->arguments->file->value, 'r');
             $i = 0;
             $start = microtime(true);
             while (($ua = fgets($fh, 258)) !== false) {
                 $ua = rtrim($ua);
                 $this->wurfl->getDeviceCapabilitiesFromAgent($ua);
                 if (!$quiet) {
                     echo $ua . "\n";
                     echo $this->wurfl->capabilities['id'] . ": " . $this->wurfl->capabilities['product_info']['brand_name'] . " " . $this->wurfl->capabilities['product_info']['model_name'] . "\n\n";
                 }
                 $i++;
             }
             fclose($fh);
             $duration = microtime(true) - $start;
             $speed = round($i / $duration, 2);
             echo "--------------------------\n";
             echo "Tested {$i} devices in {$duration} sec ({$speed}/sec)\n";
             if (!$quiet) {
                 echo "*printing the UAs is very time-consuming, use --debug=benchmark for accurate speed testing\n";
             }
             break;
         case "batchLookupUndetected":
             $fh = fopen($this->arguments->file->value, 'r');
             $i = 0;
             $start = microtime(true);
             while (($line = fgets($fh, 1024)) !== false) {
                 if (strpos($line, "\t") !== false) {
                     list($ua, $uaprof) = @explode("\t", $line);
                 } else {
                     $ua = rtrim($line);
                 }
                 $this->wurfl->getDeviceCapabilitiesFromAgent($ua);
                 $m = $this->wurfl->capabilities['tera_wurfl']['match_type'];
                 if ($m == 'recovery' || $m == 'none') {
                     echo $line;
                 }
                 $i++;
             }
             fclose($fh);
             $duration = microtime(true) - $start;
             $speed = round($i / $duration, 2);
             echo "--------------------------\n";
             echo "Tested {$i} devices in {$duration} sec ({$speed}/sec)\n";
             break;
         case "batchLookupFallback":
             $ids = file($this->arguments->file->value, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
             foreach ($ids as $id) {
                 $fallback = array();
                 if ($this->wurfl->db->db_implements_fallback) {
                     $tree = $this->wurfl->db->getDeviceFallBackTree($id);
                     foreach ($tree as $node) {
                         $fallback[] = $node['id'];
                     }
                 } else {
                     die("Unsupported on this platform\n");
                 }
                 echo implode(', ', $fallback) . "\n";
             }
             break;
         case "dumpBuckets":
             echo "Database API v{$this->wurfl->release_version}; " . $this->wurfl->getSetting(TeraWurfl::$SETTING_WURFL_VERSION) . "\n";
             $this->wurfl->dumpBuckets();
             break;
     }
 }