/** * Processes data objects to SQL * * @param \stdClass $item to be processed * * @return string the SQL queries */ protected function processDataItemToSQL(\stdClass $item) { $exceptionClass = \iveeCore\Config::getIveeClassName('CrestException'); $sdeClass = \iveeCore\Config::getIveeClassName('SDE'); $update = array(); if (!isset($item->id)) { throw new $exceptionClass("specialityID missing from specialities CREST data"); } $specialityID = (int) $item->id; if (!isset($item->name)) { throw new $exceptionClass("name missing from specialities CREST data"); } $update['specialityName'] = $item->name; $insert = $update; $insert['specialityID'] = $specialityID; $sql = $sdeClass::makeUpsertQuery('iveeSpecialities', $insert, $update); if (!isset($item->groups)) { throw new $exceptionClass("groups missing from specialities CREST data"); } foreach ($item->groups as $group) { if (!isset($group->id)) { throw new $exceptionClass("groupID missing from specialities CREST data"); } $update = array('groupID' => (int) $group->id); $insert = $update; $insert['specialityID'] = $specialityID; $sql .= $sdeClass::makeUpsertQuery('iveeSpecialityGroups', $insert, $update); } return $sql; }
/** * Invalidate any cache entries that were update in the DB * * @return void */ protected function invalidateCaches() { $assemblyLineClass = Config::getIveeClassName('AssemblyLine'); $assemblyLineClass::deleteFromCache($this->updatedIds); //we also need to invalidate the Station names cache as Outpost names can change $cacheClass = Config::getIveeClassName('Cache'); $cache = $cacheClass::instance(); $cache->deleteItem(Station::getClassHierarchyKeyPrefix() . 'Names'); }
/** * Inserts history data into the DB * * @return void */ public function insertIntoDB() { $combinedSql = ''; $latestDate = 0; $oldestDate = 9999999999; $existingDates = array(); $sdeClass = \iveeCore\Config::getIveeClassName('SDE'); $emdrClass = \iveeCore\Config::getIveeClassName('EmdrConsumer'); //find newest and oldest dates in data rows foreach ($this->rows as $day) { $rowdate = (int) strtotime($day[0]); //track newest date if ($rowdate > $latestDate) { $latestDate = $rowdate; } //track oldest date if ($rowdate < $oldestDate) { $oldestDate = $rowdate; } } //get dates with existing history data $res = $sdeClass::instance()->query("SELECT UNIX_TIMESTAMP(date)\n FROM iveePrices\n WHERE typeID = " . $this->typeID . "\n AND regionID = " . $this->regionID . "\n AND date <= '" . date('Y-m-d', $latestDate) . "'\n AND date >= '" . date('Y-m-d', $oldestDate) . "';"); while ($tmp = $res->fetch_array(MYSQL_NUM)) { $existingDates[(int) $tmp[0]] = 1; } //iterate over data rows received from EMDR foreach ($this->rows as $day) { $rowdate = (int) strtotime($day[0]); //if row already exists if (isset($existingDates[$rowdate])) { //do update for 8 latest days of already existind dates, skip all other existing rows if ($rowdate + 8 * 24 * 3600 < $latestDate) { continue; } $updateData = array('tx' => (int) $day[1], 'vol' => (int) $day[2], 'low' => (double) $day[3], 'high' => (double) $day[4], 'avg' => (double) $day[5]); $where = array('typeID' => $this->typeID, 'regionID' => $this->regionID, 'date' => date('Y-m-d', $rowdate)); //build update query $combinedSql .= $sdeClass::makeUpdateQuery('iveePrices', $updateData, $where); } else { // do insert for all missing data $insertData = array('typeID' => $this->typeID, 'regionID' => $this->regionID, 'date' => date('Y-m-d', $rowdate), 'tx' => (int) $day[1], 'vol' => (int) $day[2], 'low' => (double) $day[3], 'high' => (double) $day[4], 'avg' => (double) $day[5]); //build insert query $combinedSql .= $sdeClass::makeUpsertQuery('iveePrices', $insertData); } } //add stored procedure call to complete the update $combinedSql .= "CALL iveeCompleteHistoryUpdate(" . $this->typeID . ", " . $this->regionID . ", '" . date('Y-m-d H:i:s', $this->generatedAt) . "'); COMMIT;"; //run all queries $sdeClass::instance()->multiQuery($combinedSql); if (VERBOSE) { $ec = $emdrClass::instance(); echo "H: " . $ec->getTypeNameById($this->typeID) . ' (' . $this->typeID . '), ' . $ec->getRegionNameById($this->regionID) . ' (' . $this->regionID . '), ' . count($this->rows) . " days" . PHP_EOL; } }
/** * Fetches the weekle averages of vol and tx, triggering a CREST history update if data is too old * * @param int $typeId of the type * @param int $regionId of the region * * @return array */ protected function getWeeklyAverages($typeId, $regionId) { $sql = "SELECT UNIX_TIMESTAMP(lastHistUpdate) as lastHistUpdate,\n avgVol, avgTx\n FROM " . Config::getIveeDbName() . ".trackedMarketData\n WHERE typeID = " . $typeId . "\n AND regionID = " . $regionId . ";"; $row = static::$sde->query($sql)->fetch_assoc(); //if history update was run today, use that value if ($row['lastHistUpdate'] > mktime(0, 0, 0)) { return array('avgVol' => (double) $row['avgVol'], 'avgTx' => (double) $row['avgTx'], 'lastHistUpdate' => (int) $row['lastHistUpdate'], 'lastPriceUpdate' => time()); } //history data was too old, trigger CREST update $this->marketProcessor->getNewestHistoryData($typeId, $regionId, false); //fetch from DB again $row = static::$sde->query($sql)->fetch_assoc(); return array('avgVol' => (double) $row['avgVol'], 'avgTx' => (double) $row['avgTx'], 'lastHistUpdate' => (int) $row['lastHistUpdate'], 'lastPriceUpdate' => time()); }
/** * @expectedException iveeCore\Exceptions\KeyNotFoundInCacheException */ public function testGetTypeAndCache() { //get cache object for direct calls $cacheClass = Config::getIveeClassName('Cache'); $cacheInstance = $cacheClass::instance(); //empty cache entry for type $cacheInstance->deleteItem('iveeCore\\Type_645'); //get type via Type $type = Type::getById(645); $this->assertTrue($type instanceof Manufacturable); //fetch item directly from cache $this->assertTrue($type == $cacheInstance->getItem('iveeCore\\Type_645')); $this->assertTrue($type == Type::getByName('Dominix')); //test cache invalidation Type::deleteFromCache(array(645)); //this should throw an exception $cacheInstance->getItem('iveeCore\\Type_645'); }
/** * Saves the data to the database. * * @return void */ public function insertIntoDB() { //lookup SDE class $sdeClass = Config::getIveeClassName('SDE'); $sdeDb = $sdeClass::instance(); $sql = ''; $count = 0; foreach ($this->data as $item) { $sql .= $this->processDataItemToSQL($item); $count++; if ($count % 100 == 0 or $count == count($this->data)) { $sdeDb->multiQuery($sql . ' COMMIT;'); $sql = ''; } } $this->invalidateCaches(); $this->updatedIds = []; }
/** * Inserts or updates the pricing values in the DB. * * @param array $priceData with the values * @param int $typeId * @param int $regionId * * @return void */ protected function upsertPriceDb(array $priceData, $typeId, $regionId) { $sdeClass = Config::getIveeClassName('SDE'); //clear columns that don't belong in this update if (isset($priceData['avgVol'])) { unset($priceData['avgVol']); } if (isset($priceData['avgTx'])) { unset($priceData['avgTx']); } if (isset($priceData['lastHistUpdate'])) { unset($priceData['lastHistUpdate']); } if (isset($priceData['lastPriceUpdate'])) { unset($priceData['lastPriceUpdate']); } if (count($priceData) > 0) { //check if row already exists $res = static::$sde->query("SELECT regionID\n FROM " . Config::getIveeDbName() . ".marketPrices\n WHERE regionID = " . (int) $regionId . "\n AND typeID = " . (int) $typeId . "\n AND date = '" . date('Y-m-d', time()) . "';"); $where = array('typeID' => $typeId, 'regionID' => $regionId, 'date' => date('Y-m-d', time())); //if row already exists if ($res->num_rows == 1) { //build update query $this->submitSql($sdeClass::makeUpdateQuery(Config::getIveeDbName() . '.marketPrices', $priceData, $where)); } else { //build insert query $this->submitSql($sdeClass::makeUpsertQuery(Config::getIveeDbName() . '.marketPrices', array_merge($priceData, $where))); } } //add stored procedure call to complete the update $this->submitSql("CALL " . Config::getIveeDbName() . ".completePriceUpdate(" . (int) $typeId . ", " . (int) $regionId . ", '" . date('Y-m-d H:i:s', time()) . "');"); if ($this->verboseBatch) { static::printTypeAndRegion('P', $typeId, $regionId); } //TODO: Decide if we should invalidate caches or not. }
/** * Invalidate any cache entries that were update in the DB * * @return void */ protected function invalidateCaches() { //Team caches do not need to be invalidated as teams are immutable //Delete Systems from cache where teams are $assemblyLineClass = \iveeCore\Config::getIveeClassName('SolarSystem'); $assemblyLineClass::getInstancePool()->deleteFromCache($this->updatedIDs); }
/** * Parse a CREST response content-type to a representation name * * @param string $contentType to parse * * @return string * @throws \iveeCore\Exceptions\CrestException when parsing is not successful */ protected function parseContentTypeToRepresentation($contentType) { $matches = array(); preg_match(\iveeCore\Config::CREST_CONTENT_TYPE_REPRESENTATION_PATTERN, $contentType, $matches); if (count($matches) == 2) { return $matches[1]; } $exceptionClass = \iveeCore\Config::getIveeClassName('CrestException'); throw new $exceptionClass("Couldn't parse CREST response content type to representation"); }
* This command line PHP script pulls industry related data from EVE's CREST API and stored it to iveeCore's DB tables. * You should set it up to run every few hours (as a cronjob, for instance) to have updated system industry indices, * teams and adjustedPrice data available at all times. * * @category IveeCore * @package IveeCoreScripts * @author Aineko Macx <*****@*****.**> * @license https://github.com/aineko-m/iveeCore/blob/master/LICENSE GNU Lesser General Public License * @link https://github.com/aineko-m/iveeCore/blob/master/update_crest.php */ echo " ____ ____ _____ ____ _____ __ _____ _______ _____\n / ___| _ \\| ____/ ___|_ _| / _| ___ _ __ |_ _\\ \\ / / ____| ____|\n| | | |_) | _| \\___ \\ | | | |_ / _ \\| '__| | | \\ \\ / /| _| | _|\n| |___| _ <| |___ ___) || | | _| (_) | | | | \\ V / | |___| |___\n \\____|_| \\_\\_____|____/ |_| |_| \\___/|_| |___| \\_/ |_____|_____|" . PHP_EOL; error_reporting(E_ALL); ini_set('display_errors', 'on'); //include the iveeCore configuration, expected to be in the same directory, with absolute path require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . 'iveeCoreInit.php'; //do industry systems update $crestIndustrySystemsUpdaterClass = \iveeCore\Config::getIveeClassName('CrestIndustrySystemsUpdater'); $crestIndustrySystemsUpdaterClass::doUpdate(); //do market prices update $crestMarketPricesUpdaterClass = \iveeCore\Config::getIveeClassName('CrestMarketPricesUpdater'); $crestMarketPricesUpdaterClass::doUpdate(); //do industry facilities update $crestIndustryFacilitiesUpdaterClass = \iveeCore\Config::getIveeClassName('CrestIndustryFacilitiesUpdater'); $crestIndustryFacilitiesUpdaterClass::doUpdate(); //do specialities update $crestSpecialitiesUpdaterClass = \iveeCore\Config::getIveeClassName('CrestSpecialitiesUpdater'); $crestSpecialitiesUpdaterClass::doUpdate(); //do Industry Teams update $crestTeamsUpdaterClass = \iveeCore\Config::getIveeClassName('CrestTeamsUpdater'); $crestTeamsUpdaterClass::doUpdate(); echo 'Peak memory usage: ' . ceil(memory_get_peak_usage(true) / 1024) . 'KiB' . PHP_EOL;
/** * Throws NotOnMarketException. * * @paran iveeCore\SdeType $type that isn't on the market * * @return void * @throws \iveeCore\Exceptions\NotOnMarketException */ protected function throwNotOnMarketException(SdeType $type) { $exceptionClass = Config::getIveeClassName('NotOnMarketException'); throw new $exceptionClass($type->getName() . ' cannot be bought or sold on the market'); }
/** * Invalidate any cache entries that were update in the DB * * @return void */ protected function invalidateCaches() { $assemblyLineClass = Config::getIveeClassName('SolarSystem'); $assemblyLineClass::deleteFromCache($this->updatedIds); }
/** * Creates new curl handle and adds to curl multi handle. Also creates the corresponding Response object. * * @param resource $multiHandle the CURL multi handle * @param string $href to be requested * @param string $key for the Response * @param array $stdOptions the CURL options to be set * @param callable $getAuthHeader that returns an appropriate bearer authentication header, for instance * Client::getBearerAuthHeader(). We do this on-the-fly as during large multi GET batches the access token might * expire. * @param array $header to be used in each request * * @return \iveeCrest\Response */ protected function addHandleToMulti($multiHandle, $href, $key, array $stdOptions, callable $getAuthHeader, array $header) { $ch = curl_init(); curl_setopt_array($ch, $stdOptions); curl_setopt($ch, CURLOPT_URL, $href); //add auth header on the fly curl_setopt($ch, CURLOPT_HTTPHEADER, array_merge($getAuthHeader(), $header)); //instantiate new Response object $responseClass = Config::getIveeClassName('Response'); $response = new $responseClass($key); //add the CURL header callback function curl_setopt($ch, CURLOPT_HEADERFUNCTION, array($response, 'handleCurlHeaderLine')); curl_multi_add_handle($multiHandle, $ch); return $response; }
/** * Gets all necessary data from SQL. * * @return array with attributes queried from DB * @throws \iveeCore\Exceptions\NoPriceDataAvailableException when a typeId is not found */ protected function queryAttributes() { //lookup IveeCore class $sdeClass = Config::getIveeClassName('SDE'); $row = $sdeClass::instance()->query("SELECT UNIX_TIMESTAMP(date) as priceDate,\n averagePrice,\n adjustedPrice\n FROM " . Config::getIveeDbName() . ".globalPrices\n WHERE typeID = " . $this->id . "\n ORDER BY date DESC LIMIT 1;")->fetch_assoc(); if (empty($row)) { self::throwException('NoPriceDataAvailableException', "No global price data for " . $this->getType()->getName() . " (typeId=" . $this->id . ") found"); } return $row; }
/** * Perform the complete update * * @return void */ public static function doUpdate() { //get CrestFetcher class name and instantiate $crestFetcherClass = \iveeCore\Config::getIveeClassName('CrestFetcher'); $cf = new $crestFetcherClass(); echo get_called_class() . ' getting data from CREST... '; //fetch the data, check returned representation name $data = $cf->getCrestData(static::$path, static::$representationName); echo "Done" . PHP_EOL . 'Saving data in DB... '; //store in DB $citu = new static($data); $citu->insertIntoDB(); echo 'Done' . PHP_EOL; }
/** * Invalidate any cache entries that were update in the DB * * @return void */ protected function invalidateCaches() { $globalPriceDataClass = Config::getIveeClassName('GlobalPriceData'); $globalPriceDataClass::deleteFromCache($this->updatedIds); }
/** * Fetches the typeIds of the items that need updating in a region * * @param int $regionId to be checked * @param int $cutoffTs the unix timestamp to be used to decide if data is too old * @param string $dateColumn the DB column to check the timestamp on, either 'lastHistUpdate' or 'lastPriceUpdate' * @param \iveeCrest\EndpointHandler $eph to be used * * @return array */ protected static function getTypeIdsToUpdate($regionId, $cutoffTs, $dateColumn, EndpointHandler $eph) { //get matket typeIds from CREST $marketTypeIds = array_keys($eph->getMarketTypeHrefs()); //get the subset Ids that need updating and are not Dust-only $res = static::$sde->query("SELECT typeID\n FROM invTypes\n WHERE typeID IN (" . implode(', ', $marketTypeIds) . ")\n AND typeID < 350000\n AND typeID NOT IN (\n SELECT typeID\n FROM " . Config::getIveeDbName() . ".trackedMarketData\n WHERE regionID = " . (int) $regionId . "\n AND " . $dateColumn . " > '" . date('Y-m-d H:i:s', $cutoffTs) . "'\n )\n ORDER BY typeID ASC;"); $ret = []; while ($tmp = $res->fetch_array(MYSQL_NUM)) { $ret[] = (int) $tmp[0]; } return $ret; }
/** * Returns a MaterialMap object representing the reprocessing materials of the item. * * @param \iveeCore\IndustryModifier $iMod for reprocessing context * @param int $batchSize number of items being reprocessed, needs to be multiple of portionSize * * @return \iveeCore\MaterialMap * @throws \iveeCore\Exceptions\NotReprocessableException if item is not reprocessable * @throws \iveeCore\Exceptions\InvalidParameterValueException if batchSize is not multiple of portionSize */ public function getReprocessingMaterialMap(IndustryModifier $iMod, $batchSize) { if (!$this->isReprocessable()) { self::throwException('NotReprocessableException', $this->name . ' is not reprocessable'); } if ($batchSize % $this->portionSize != 0) { self::throwException('InvalidParameterValueException', 'Reprocessing batch size needs to be multiple of ' . $this->portionSize); } //get station for reprocessing at $station = $iMod->getBestReprocessingStation(); //the CharacterModifier $charMod = $iMod->getCharacterModifier(); //if (compressed) ore or ice if ($this->getCategoryId() == 25) { //Reprocessing, Reprocessing Efficiency and specific Processing skills $yield = $station->getReprocessingEfficiency() * (1 + 0.03 * $charMod->getSkillLevel(3385)) * (1 + 0.02 * $charMod->getSkillLevel(3389)) * (1 + 0.02 * $charMod->getSkillLevel($this->getReprocessingSkillId())) * $charMod->getReprocessingImplantYieldFactor(); } else { //Apply Scrapmetal Processing skill $yield = $station->getReprocessingEfficiency() * (1 + 0.02 * $charMod->getSkillLevel(12196)); } $materialsClass = Config::getIveeClassName('MaterialMap'); $rmat = new $materialsClass(); $numPortions = $batchSize / $this->portionSize; foreach ($this->getMaterials() as $typeId => $quantity) { $rmat->addMaterial($typeId, round($quantity * $yield * $numPortions * $charMod->getReprocessingTaxFactor($station->getCorporationId()))); } return $rmat; }
/** * Gathers multipage endpoint responses and joins them into one array, using the passed callback functions to * traverse and index the data. The result of this (potentially expensive) operation can be cached. * * @param string $endpointHref the URL to the first page of the endpoint * @param callable $indexFunc function to be used to extract the ID from/for an individual Response object * @param callable $elementFunc function to be used to extract the desired data from an individual Response object * @param string $accept the representation to request from CREST * @param bool $cache whether the gathered data should be cached or not * @param int $ttl the time to live to be used for caching of the gathered data * @param string $subCommandKey to avoid cache namespace collisions when different gather requests access the same * endpoint URL, an additional subcommand key can be specified. * * @return array */ public function gather($endpointHref, callable $indexFunc = null, callable $elementFunc = null, $accept = null, $cache = true, $ttl = 3600, $subCommandKey = null) { $dataKey = 'gathered:' . $endpointHref . (isset($subCommandKey) ? ',' . $subCommandKey : ''); //we introduce another caching layer here because gathering and reindexing multipage data is expensive, even //when the individual CREST responses are already cached. try { $dataObj = $this->cache->getItem($dataKey); } catch (KeyNotFoundInCacheException $e) { //setup a cacheable array object $dataClass = Config::getIveeClassName('CacheableArray'); $dataObj = new $dataClass($dataKey, time() + $ttl); //gather all the pages into one compact array $dataObj->data = $this->gather2($endpointHref, $indexFunc, $elementFunc, $accept, false); if ($cache) { $this->cache->setItem($dataObj); } } return $dataObj->data; }
/** * iveeCore CREST updater CLI driver. * * PHP version 5.4 * * To run from the command line interface, use 'php updater.php'. * If using HHVM instead of PHP use 'hhvm -v Eval.Jit=1 -v Eval.JitProfileInterpRequests=0 updater.php'. * The program will print further options how to control the updates to be run. * * @category IveeCore * @package IveeCoreScripts * @author Aineko Macx <*****@*****.**> * @license https://github.com/aineko-m/iveeCore/blob/master/LICENSE GNU Lesser General Public License * @link https://github.com/aineko-m/iveeCore/blob/master/cli/updater.php */ require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'iveeCoreInit.php'; use iveeCore\Config; //ensure only one instance of this script runs at a time using a lockfile $lock = DIRECTORY_SEPARATOR . 'tmp' . DIRECTORY_SEPARATOR . 'iveeCoreUpdater.lock'; $f = fopen($lock, 'w'); if (!flock($f, LOCK_EX | LOCK_NB)) { exit("iveeCore Updater already running\n"); } //run the updater $iveeUpdaterClass = Config::getIveeClassName('CrestIveeUpdater'); $iu = new $iveeUpdaterClass(); $iu->run($argv, Config::getTrackedMarketRegionIds()); //remove lock fclose($f); unlink($lock);
/** * Invalidate any cache entries that were update in the DB * * @return void */ protected function invalidateCaches() { $assemblyLineClass = \iveeCore\Config::getIveeClassName('SolarSystem'); $assemblyLineClass::getInstancePool()->deleteFromCache($this->updatedIDs); }
protected function setUp() { $this->client = new Client(Config::getAuthedCrestBaseUrl(), Config::getCrestClientId(), Config::getCrestClientSecret(), Config::getCrestClientRefreshToken(), Config::getUserAgent()); $this->handler = new EndpointHandler($this->client); }
/** * Gets the regionName for a regionID * * @param int $regionID of the region to get the name for * * @return string * @throws \iveeCore\Exceptions\TypeIdNotFoundException if the requested regionID is not found */ public function getRegionNameById($regionID) { if (isset($this->regions[(int) $regionID])) { return $this->regions[(int) $regionID]; } else { $exceptionClass = \iveeCore\Config::getIveeClassName('SystemIdNotFoundException'); throw new $exceptionClass((int) $regionID . ' not found among region IDs.'); } }
/** * Gets the endpoint for a market group. * * @param int $marketGroupId of the market group * * @return stdClass */ public function getMarketGroup($marketGroupId) { $marketGroups = $this->getMarketGroups(); if (!isset($marketGroups[$marketGroupId])) { $invalidArgumentExceptionClass = Config::getIveeClassName('InvalidArgumentException'); throw new $invalidArgumentExceptionClass('MarketGroupId=' . (int) $marketGroupId . ' not found in market groups'); } return $this->client->getEndpoint($marketGroups[$marketGroupId]->href, true, static::MARKET_GROUP_REPRESENTATION); }
/** * Gets item from Cache. * * @param string $key under which the item is stored * * @return \iveeCore\ICacheable * @throws \iveeCore\Exceptions\KeyNotFoundInCacheException if key is not found */ public function getItem($key) { if (!$this->cache->contains($key)) { $exceptionClass = Config::getIveeClassName('KeyNotFoundInCacheException'); throw new $exceptionClass("Key not found in cache."); } $item = $this->cache->fetch($key); $this->hits++; return $item; }
/** * Inserts price data into the DB * * @return void */ public function insertIntoDB() { if (isset($this->sell) or isset($this->buy)) { $sdeClass = \iveeCore\Config::getIveeClassName('SDE'); //check if row already exists $res = $sdeClass::instance()->query("SELECT regionID FROM iveePrices\n WHERE regionID = " . $this->regionID . "\n AND typeID = " . $this->typeID . "\n AND date = '" . date('Y-m-d', $this->generatedAt) . "';"); //if row already exists if ($res->num_rows == 1) { //update data $updatetData = array(); if (isset($this->sell)) { $updatetData['sell'] = $this->sell; } if (isset($this->buy)) { $updatetData['buy'] = $this->buy; } if (isset($this->avgSell5OrderAge)) { $updatetData['avgSell5OrderAge'] = $this->avgSell5OrderAge; } if (isset($this->avgBuy5OrderAge)) { $updatetData['avgBuy5OrderAge'] = $this->avgBuy5OrderAge; } if (isset($this->demandIn5)) { $updatetData['demandIn5'] = $this->demandIn5; } if (isset($this->supplyIn5)) { $updatetData['supplyIn5'] = $this->supplyIn5; } $where = array('typeID' => $this->typeID, 'regionID' => $this->regionID, 'date' => date('Y-m-d', $this->generatedAt)); //build update query $sql = $sdeClass::makeUpdateQuery('iveePrices', $updatetData, $where); } else { //insert data $insertData = array('typeID' => $this->typeID, 'regionID' => $this->regionID, 'date' => date('Y-m-d', $this->generatedAt)); if (isset($this->sell)) { $insertData['sell'] = $this->sell; } if (isset($this->buy)) { $insertData['buy'] = $this->buy; } if (isset($this->avgSell5OrderAge)) { $insertData['avgSell5OrderAge'] = $this->avgSell5OrderAge; } if (isset($this->avgBuy5OrderAge)) { $insertData['avgBuy5OrderAge'] = $this->avgBuy5OrderAge; } if (isset($this->demandIn5)) { $insertData['demandIn5'] = $this->demandIn5; } if (isset($this->supplyIn5)) { $insertData['supplyIn5'] = $this->supplyIn5; } //build insert query $sql = $sdeClass::makeUpsertQuery('iveePrices', $insertData); } //add stored procedure call to complete the update $sql .= "CALL iveeCompletePriceUpdate(" . $this->typeID . ", " . $this->regionID . ", '" . date('Y-m-d H:i:s', $this->generatedAt) . "'); COMMIT;" . PHP_EOL; //execute the combined queries $sdeClass::instance()->multiQuery($sql); if (VERBOSE) { $ecClass = \iveeCore\Config::getIveeClassName('EmdrConsumer'); $ec = $ecClass::instance(); echo "P: " . $ec->getTypeNameById($this->typeID) . ' (' . $this->typeID . '), ' . $ec->getRegionNameById($this->regionID) . ' (' . $this->regionID . ')' . PHP_EOL; } } }