Пример #1
0
 /**
  * @see Souk::auction
  * take the item out of the seller's account and place it in escrow when creating the auction.
  * set up the quantity, which can be an integer or some other quantity from stockpile.
  */
 function auction($l, array $data = NULL)
 {
     // wrap in a try/catch block so we can handle the transaction correctly, and rollback
     // if need be.
     try {
         // kick off a transaction. if there isn't one attached, create one.
         Transaction::start();
         // convert the data coming in, probably an array,into a Listing.
         $listing = Util::listing($l);
         // if no seller passed in, use the current user.
         if (!isset($listing->seller)) {
             $listing->seller = $this->user();
         }
         // if no quantity specified, default to 1.
         if (!isset($listing->quantity)) {
             $listing->quantity = 1;
         }
         // connect to the seller's item account in stockpile
         $seller = $this->itemAccount($listing->seller);
         // also need their escrow account
         $escrow = $this->itemEscrow($listing->seller);
         // bind them together in a stockpile transfer object so we can move items from
         // their inventory into escrow. Prevents the seller from trading away the items while
         // simultaneously auctioning them off.
         $transfer = $this->transfer($seller, $escrow);
         // if the inventory type is serial, then we need a stockpile quantity object.
         // if an integer or some other value was passed in for quantity, convert it into
         // the appropriate stockpile_quantity so we are sure we are vending the proper
         // serials.
         if ($seller->coreType() == 'serial' && !$listing->quantity instanceof \Gaia\Stockpile\Quantity) {
             $listing->quantity = $seller->get($listing->item_id)->grab($listing->quantity);
         }
         // subtract the quantity from the inventory ... adds it transparently to escrow.
         $transfer->subtract($listing->item_id, $listing->quantity, $this->prepData($data, $listing, 'auction'));
         // now, we need to prep the quantity so that it can be stored in the listing in
         // the database. we assign an export of the object to the stockpile_quantity attribute of the listing
         // that way when we deserialize it back out, we can reconstruct the object.
         if ($listing->quantity instanceof \Gaia\Stockpile\Quantity) {
             $listing->stockpile_quantity = $listing->quantity->export();
         }
         // turn the quantity into a scalar representation so souk can write the quantity into the db row.
         $listing->quantity = $seller->quantify($listing->quantity);
         // make sure the listing we return is deserialized correctly
         $listing = $this->prepListing($this->core->auction($listing));
         // commit the transaction, if we created it internally.
         Transaction::commit();
         // all done.
         return $listing;
     } catch (Exception $e) {
         // ewww, something nasty happened. revert the transaction.
         Transaction::rollback();
         // toss the exception again up the chain.
         throw $e;
     }
 }
Пример #2
0
 /**
  * Get multiple listings back, by id
  * @return array
  */
 public function fetch(array $ids, $lock = FALSE)
 {
     // stub out the result set so when we populate the data later, we will be
     // returning the rows in the correct order as requested.
     // important when we do things like pass the list of ids from search into here,
     // where the ordering of ids matters.
     $result = array_fill_keys($ids, NULL);
     // we have to query by shard, which means we need to parse all the ids passed in
     // and group them by shard.
     $shardlist = array();
     foreach ($ids as $id) {
         list($shard, $row_id) = Souk\Util::parseId($id);
         if (!isset($shardlist[$shard])) {
             $shardlist[$shard] = array();
         }
         $shardlist[$shard][] = $row_id;
     }
     if ($lock && !Transaction::atStart()) {
         Transaction::add($this->db);
     }
     // loop through the ids grouped by shard
     foreach ($shardlist as $shard => $row_ids) {
         // query always by shard and row_id. this query is a primary key lookup
         // so it should always be very efficient.
         $table = $this->table($shard);
         if (\Gaia\Souk\Storage::isAutoSchemaEnabled()) {
             $this->create($table);
         }
         $sql = "SELECT row_id, bid, proxybid, bidcount, item_id, quantity, price, step, created, expires, buyer, seller, bidder, reserve, closed, touch FROM {$table} WHERE row_id IN (?)";
         if ($lock) {
             $sql .= ' FOR UPDATE';
         }
         $rs = $this->execute($sql, $row_ids);
         // grab the rows returned and populate the result as Souk\listings.
         $row_ids = array();
         while ($row = $rs->fetch()) {
             $row_id = $row_ids[] = $row['row_id'];
             unset($row['row_id']);
             $listing = Souk\Util::listing($row);
             $listing->id = Souk\Util::composeId($shard, $row_id);
             $result[$listing->id] = $listing;
         }
         $rs->free();
         // did we get any rows back? if not, move on to the next shard.
         if (count($row_ids) < 1) {
             continue;
         }
         // populate the listing with the serialized attributes that didn't map to any of
         // the predefined columns in souk. in most cases this table will be empty, but
         // we query it anyway to be sure.
         // don't need a row lock on this table because we have one on the main listing table.
         // since we always access these two tables in tandem, the prior row lock should
         // serialize the requests and work for both.
         $table_attr = $table . '_attr';
         $sql = "SELECT row_id, attributes FROM {$table_attr} WHERE row_id IN ( %i )";
         $rs = $this->execute($sql, $row_ids);
         // no rows? no problem, just skip it. that is expected.
         if ($rs->affected() < 1) {
             continue;
         }
         // someone stored attributes! merge them in.
         // stored as json in the db. deserialize and layer on top of the listing object.
         while ($row = $rs->fetch()) {
             $id = Souk\Util::composeId($shard, $row['row_id']);
             if (!isset($result[$id])) {
                 continue;
             }
             $attributes = json_decode($row['attributes'], TRUE);
             if (!is_array($attributes)) {
                 continue;
             }
             $listing = $result[$id];
             foreach ($attributes as $k => $v) {
                 if ($k == 'id') {
                     continue;
                 }
                 $listing->{$k} = $v;
             }
         }
         // free the query result.
         $rs->free();
     }
     // remember how we populated with nulls at the beginning?
     // remove any that are still null, now that we are done.
     foreach (array_keys($result, NULL, TRUE) as $k) {
         unset($result[$k]);
     }
     // return the result.
     return $result;
 }