/**
  * Parse the different parts of a killmail into
  * a multidimensional array which can be further processed
  *
  * @param string $mail
  */
 public function parse($mail)
 {
     $this->plainMail = $mail;
     $victimActive = true;
     $involved = false;
     $destroyed = false;
     $dropped = false;
     $tokens = Kingboard_KillmailParser_Factory::findTokensForMail($mail);
     $currentAttacker = -1;
     // Clean the mail and explode by line
     $lines = explode(chr(10), $mail);
     $ids = new Kingboard_KillmailParser_IdFinder();
     $lastMainItem = null;
     reset($lines);
     while (count($lines) > 0) {
         $plainLine = array_shift($lines);
         try {
             // If it has a name token and a slash, we presume the contents
             // after the slash is the corporation name
             // This is done for NPC names and their corps, and a slash
             // is no valid item name, yet is valid in a killmail
             $strTools = Kingboard_Helper_String::getInstance();
             if ($strTools->stripos($tokens->name(), $plainLine) !== false && $strTools->strpos('/', $plainLine) !== false) {
                 $parts = explode('/', $plainLine);
                 $plainLine = array_shift($parts);
                 $corp = $tokens->corp() . implode('/', $parts);
                 // If the final blow token is present, move it from the corp name to attacker name
                 if ($strTools->stripos($tokens->finalBlow(), $corp)) {
                     $plainLine .= ' ' . $tokens->finalBlow();
                     $corp = str_replace($tokens->finalBlow(), '', $corp);
                 }
                 array_unshift($lines, $corp);
                 reset($lines);
                 unset($parts, $corp);
             }
             $line = new Kingboard_KillmailParser_Line($plainLine, $tokens);
             switch ($line->getType()) {
                 case Kingboard_KillmailParser_Line::TYPE_TIME:
                     $this->killTime = $line->getValue();
                     break;
                 case Kingboard_KillmailParser_Line::TYPE_NAME:
                     if ($involved) {
                         $currentAttacker++;
                         $this->attackers[$currentAttacker] = array('characterName' => '', 'characterID' => 0, 'typeID' => 0, 'corporationName' => '', 'corporationID' => 0, 'allianceName' => '', 'allianceID' => 0, 'shipType' => '', 'shipTypeID' => 0, 'factionName' => '', 'factionID' => 0, 'weaponType' => '', 'weaponTypeID' => 0, 'finalBlow' => false, 'securityStatus' => 0.0);
                         $this->attackers[$currentAttacker]['finalBlow'] = $line->hasFinalBlow();
                         $this->attackers[$currentAttacker]['characterName'] = $line->getValue();
                         $this->attackers[$currentAttacker]['characterID'] = $ids->getCharacterId($line->getValue());
                         $this->attackers[$currentAttacker]['entityType'] = Kingboard_Helper_EntityType::getEntityTypeByEntityId($this->attackers[$currentAttacker]['characterID']);
                         if ($this->attackers[$currentAttacker]['entityType'] == Kingboard_Helper_EntityType::ENTITY_NPC) {
                             $this->attackers[$currentAttacker]['shipTypeID'] = $this->attackers[$currentAttacker]['characterID'];
                             $this->attackers[$currentAttacker]['shipType'] = $this->attackers[$currentAttacker]['characterName'];
                             $this->attackers[$currentAttacker]['characterID'] = 0;
                             $this->attackers[$currentAttacker]['characterName'] = '';
                         }
                     } else {
                         $this->victim['characterName'] = $line->getValue();
                         $this->victim['characterID'] = $ids->getCharacterId($line->getValue());
                     }
                     break;
                 case Kingboard_KillmailParser_Line::TYPE_ALLIANCE:
                     if ($victimActive) {
                         $record =& $this->victim;
                     } elseif ($involved) {
                         $record =& $this->attackers[$currentAttacker];
                     }
                     if (!$line->isEmpty()) {
                         $record['allianceName'] = $line->getValue();
                         $record['allianceID'] = $ids->getAllianceId($line->getValue());
                     }
                     unset($record);
                     break;
                 case Kingboard_KillmailParser_Line::TYPE_CORP:
                     if ($victimActive) {
                         $record =& $this->victim;
                     } elseif ($involved) {
                         $record =& $this->attackers[$currentAttacker];
                     }
                     if (!$line->isEmpty()) {
                         $record['corporationID'] = $ids->getCorporationId($line->getValue());
                         $record['corporationName'] = $line->getValue();
                     }
                     unset($record);
                     break;
                 case Kingboard_KillmailParser_Line::TYPE_DAMAGE:
                     if ($victimActive) {
                         $this->victim['damageTaken'] = $line->getValue();
                     } elseif ($involved) {
                         $this->attackers[$currentAttacker]['damageDone'] = $line->getValue();
                     }
                     break;
                 case Kingboard_KillmailParser_Line::TYPE_FACTION:
                     if ($victimActive) {
                         $record =& $this->victim;
                     } elseif ($involved) {
                         $record =& $this->attackers[$currentAttacker];
                     }
                     if (!$line->isEmpty()) {
                         $record['factionID'] = $ids->getFactionId($line->getValue());
                         $record['factionName'] = $line->getValue();
                     }
                     unset($record);
                     break;
                 case Kingboard_KillmailParser_Line::TYPE_ITEM:
                     $flag = 0;
                     if ($line->isDrone()) {
                         $flag = 87;
                     } elseif ($line->isCargo()) {
                         $flag = 5;
                     }
                     $item = array('typeID' => $ids->getItemId($line->getValue()), 'typeName' => $line->getValue(), 'qtyDropped' => $dropped ? $line->getQty() : 0, 'qtyDestroyed' => !$dropped ? $line->getQty() : 0, 'flag' => $flag);
                     if ($line->inContainer()) {
                         if (!isset($this->items[$lastMainItem])) {
                             throw new Kingboard_KillmailParser_KillmailErrorException('Container for item not found');
                         }
                         if (!isset($this->items[$lastMainItem]['items'])) {
                             $this->items[$lastMainItem]['items'] = array();
                         }
                         $this->items[$lastMainItem]['items'][] = $item;
                     } else {
                         $lastMainItem = count($this->items);
                         $this->items[] = $item;
                     }
                     unset($item, $flag);
                     break;
                 case Kingboard_KillmailParser_Line::TYPE_SECURITY:
                     $value = (double) $line->getValue();
                     if ($victimActive) {
                         $this->location['security'] = $value;
                     } elseif ($involved) {
                         $this->attackers[$currentAttacker]['securityStatus'] = $value;
                     }
                     unset($value);
                     break;
                 case Kingboard_KillmailParser_Line::TYPE_SHIP:
                     if ($victimActive) {
                         $record =& $this->victim;
                     } elseif ($involved) {
                         $record =& $this->attackers[$currentAttacker];
                     }
                     if (!$line->isEmpty()) {
                         $record['shipType'] = $line->getValue();
                         $record['shipTypeID'] = $ids->getItemId($line->getValue());
                     }
                     unset($record);
                     break;
                 case Kingboard_KillmailParser_Line::TYPE_SWITCH_ATTACKERS:
                     $victimActive = false;
                     $involved = true;
                     break;
                 case Kingboard_KillmailParser_Line::TYPE_SWITCH_DROPPED:
                     $dropped = true;
                     break;
                 case Kingboard_KillmailParser_Line::TYPE_SYSTEM:
                     $this->location['solarSystemID'] = $ids->getSolarSystemId($line->getValue());
                     $this->location['solarSystemName'] = $line->getValue();
                     break;
                 case Kingboard_KillmailParser_Line::TYPE_MOON:
                     if (!$line->isEmpty()) {
                         $system = Kingboard_EveSolarSystem::getInstanceByCriteria(array('Moons.itemName' => $line->getValue()));
                         if ($system) {
                             $moons = $system->Moons;
                             foreach ($moons as $moon) {
                                 if ($moon['itemName'] == $line->getValue()) {
                                     $this->location['moon'] = $line->getValue();
                                     $this->location['moonID'] = $moon['itemID'];
                                     break;
                                 }
                             }
                         }
                     }
                     break;
                 case Kingboard_KillmailParser_Line::TYPE_WEAPON:
                     $this->attackers[$currentAttacker]['weaponTypeID'] = $ids->getItemId($line->getValue());
                     $this->attackers[$currentAttacker]['weaponType'] = $line->getValue();
                     break;
             }
         } catch (Kingboard_KillmailParser_KillmailErrorException $e) {
             $this->errors[] = $e->getMessage();
             continue;
         }
         // Save errors for log / output
         if ($line->hasError()) {
             $this->errors[] = $line->getError();
         }
     }
     // Now we need to clean up the items array
     $this->items = $this->cleanItemsArray($this->items);
     return $this;
 }
 public function feed_pull($options)
 {
     $this->cli->header('pulling all feeds');
     $feeds = Kingboard_EdkFeed::find();
     foreach ($feeds as $feed) {
         $url = $feed->url;
         $this->cli->message('pulling ' . $url);
         $sxo = simplexml_load_file($url);
         $processed = 0;
         $killcount = count($sxo->channel->item);
         $this->cli->message("processing {$killcount} kills.");
         foreach ($sxo->channel->item as $item) {
             $this->cli->message('processing ' . ++$processed . ' out of ' . $killcount);
             $mailtext = trim((string) $item->description);
             if (isset($item->apiID)) {
                 $apiId = (string) $item->apiID;
             } else {
                 $apiId = null;
             }
             try {
                 $mail = Kingboard_KillmailParser_Factory::parseTextMail($mailtext);
                 $mail->killID = $apiId;
                 $mail->save();
             } catch (Kingboard_KillmailParser_KillmailErrorException $e) {
                 $this->cli->error("Exception caught, mail was not processed");
                 $this->cli->error($e->getMessage());
                 $this->cli->error($e->getFile() . '::' . $e->getLine());
             }
         }
         $this->cli->positive('done');
     }
 }
 public function ek_import(array $options)
 {
     if (count($options) != 2 || !is_numeric($options[0]) || !is_numeric($options[1])) {
         $this->cli->error('need two numbers as parameters');
         return;
     }
     $processed = 0;
     $killcount = $options[1] - $options[0] + 1;
     for ($i = $options[0]; $i <= $options[1]; $i++) {
         $this->cli->message('processing ' . ++$processed . ' out of ' . $killcount);
         $mailtext = trim(join('', file("http://eve-kill.net/kingboard.php?kllid=" . $i)));
         $apiId = null;
         try {
             $mail = Kingboard_KillmailParser_Factory::parseTextMail($mailtext);
             $mail->killID = $apiId;
             $mail->save();
         } catch (Kingboard_KillmailParser_KillmailErrorException $e) {
             $this->cli->error("Exception caught, mail was not processed");
             $this->cli->error($e->getMessage());
             $this->cli->error($e->getFile() . '::' . $e->getLine());
         }
     }
 }
 public function testParseTextMail()
 {
     $mail = "2011.04.05 20:40\n\nVictim: Falci\nCorp: Project Stealth Squad\nAlliance: Majesta Empire\nFaction: NONE\nDestroyed: Nidhoggur\nSystem: 4NGK-F\nSecurity: 0.0\nDamage Taken: 504457\n\nInvolved parties:\n\nName: Colla Camins\nSecurity: -5.2\nCorp: Tormentum Insomniae\nAlliance: Raiden.\nFaction: NONE\nShip: Hound\nWeapon: Peripheral Weapon Navigation Diameter\nDamage Done: 66210\n\nName: ANGAL 2000 (laid the final blow)\nSecurity: -5.0\nCorp: FinFleet\nAlliance: Raiden.\nFaction: NONE\nShip: Hound\nWeapon: Caldari Navy Bane Torpedo\nDamage Done: 48805\n\nName: Magnifikus Erzverwirrer\nSecurity: -2.6\nCorp: FinFleet\nAlliance: Raiden.\nFaction: NONE\nShip: Purifier\nWeapon: Caldari Navy Mjolnir Torpedo\nDamage Done: 47561\n\nName: SmokeDog\nSecurity: -4.1\nCorp: Nex Exercitus\nAlliance: Raiden.\nFaction: NONE\nShip: Hound\nWeapon: Caldari Navy Bane Torpedo\nDamage Done: 47165\n\nName: Pheonix1985\nSecurity: 4.5\nCorp: FinFleet\nAlliance: Raiden.\nFaction: NONE\nShip: Nemesis\nWeapon: Caldari Navy Inferno Torpedo\nDamage Done: 43705\n\nName: time 3290\nSecurity: 1.0\nCorp: The Ankou\nAlliance: Raiden.\nFaction: NONE\nShip: Hound\nWeapon: Caldari Navy Bane Torpedo\nDamage Done: 40761\n\nName: Zhayan Joruni\nSecurity: 5.0\nCorp: The Ankou\nAlliance: Raiden.\nFaction: NONE\nShip: Hound\nWeapon: Caldari Navy Bane Torpedo\nDamage Done: 36200\n\nName: Hund\nSecurity: -3.7\nCorp: x13\nAlliance: Raiden.\nFaction: NONE\nShip: Manticore\nWeapon: Caldari Navy Juggernaut Torpedo\nDamage Done: 35981\n\nName: Kanuti\nSecurity: 4.9\nCorp: x13\nAlliance: Raiden.\nFaction: NONE\nShip: Purifier\nWeapon: Caldari Navy Mjolnir Torpedo\nDamage Done: 25984\n\nName: White Panter\nSecurity: -4.8\nCorp: Tormentum Insomniae\nAlliance: Raiden.\nFaction: NONE\nShip: Hound\nWeapon: Bane Torpedo\nDamage Done: 22427\n\nName: Abderraman III\nSecurity: 1.5\nCorp: Tormentum Insomniae\nAlliance: Raiden.\nFaction: NONE\nShip: Purifier\nWeapon: Caldari Navy Mjolnir Torpedo\nDamage Done: 21413\n\nName: DJ MULER\nSecurity: 1.9\nCorp: Tormentum Insomniae\nAlliance: Raiden.\nFaction: NONE\nShip: Hound\nWeapon: 'Malkuth' Siege Missile Launcher I\nDamage Done: 20963\n\nName: Namof Zomgbag\nSecurity: 4.2\nCorp: FinFleet\nAlliance: Raiden.\nFaction: NONE\nShip: Hound\nWeapon: 'Arbalest' Siege Missile Launcher\nDamage Done: 20611\n\nName: Mo Cuishle\nSecurity: -1.1\nCorp: Tormentum Insomniae\nAlliance: Raiden.\nFaction: NONE\nShip: Capsule\nWeapon: 'Malkuth' Siege Missile Launcher I\nDamage Done: 13264\n\nName: Galmar Masu\nSecurity: -9.8\nCorp: x13\nAlliance: Raiden.\nFaction: NONE\nShip: Arazu\nWeapon: Warrior II\nDamage Done: 7681\n\nName: Edsback\nSecurity: 0.5\nCorp: Capital Maintenance\nAlliance: None\nFaction: NONE\nShip: Manticore\nWeapon: 'Malkuth' Siege Missile Launcher I\nDamage Done: 3103\n\nName: Kajdil\nSecurity: -1.3\nCorp: Tormentum Insomniae\nAlliance: Raiden.\nFaction: NONE\nShip: Falcon\nWeapon: Warrior II\nDamage Done: 2623\n\nName: Comy 2\nSecurity: -5.0\nCorp: Nex Exercitus\nAlliance: Raiden.\nFaction: NONE\nShip: Rapier\nWeapon: Warp Disruptor II\nDamage Done: 0\n\nName: Alex Keys\nSecurity: 4.5\nCorp: FinFleet\nAlliance: Raiden.\nFaction: NONE\nShip: Falcon\nWeapon: 'Umbra' I White Noise ECM\nDamage Done: 0\n\n\nDestroyed items:\n\nCapital Remote Armor Repair System I\nCapital Shield Transporter I\nHeavy Energy Neutralizer II\nTriage Module I\nCapital Energy Transfer Array I\nCap Recharger II\nECCM - Ladar II\nDamage Control II\nArmor Explosive Hardener II\nCapital Armor Repairer I\nLarge Capacitor Control Circuit I, Qty: 3\n\nDropped items:\n\nSensor Booster II\nScan Resolution\nArmor Kinetic Hardener II\nArmor Thermic Hardener II\nEnergized Adaptive Nano Membrane II\nExotic Dancers (Cargo)\nVespa EC-600 (Drone Bay)\nOgre II (Drone Bay)\nCap Recharger II, Qty: 2\n";
     $this->assertInstanceOf('Kingboard_Kill', Kingboard_KillmailParser_Factory::parseTextMail($mail));
 }