/** * Process bulk add/remove/etc operations * * @param Bin $rec * @param string $bulk_op * @param array $data * @param string $notes */ protected function run_bulk($rec, $bulk_op, $data, $notes = null) { // check for write-authz on bin (for everything EXCEPT random) if ($bulk_op != 'bulk_random' && !$rec->user_may_write($this->user)) { $msg = "Insufficient authz for {$bulk_op}"; throw new Rframe_Exception(Rframe::BAD_AUTHZ, $msg); } $this->bulk_op = $bulk_op; // rethrow any exceptions as 'data' exceptions try { if ($bulk_op == 'bulk_add') { $this->bulk_rs = AIR2Bin::add_sources($rec, $data, $notes); } if ($bulk_op == 'bulk_addsub') { $this->bulk_rs = AIR2Bin::add_submissions($rec, $data, $notes); } if ($bulk_op == 'bulk_addsearch') { $this->bulk_rs = AIR2Bin::add_search($this->user, $rec, $data, $notes); } if ($bulk_op == 'bulk_addtank') { $tanks = array(); $data = is_array($data) ? array_unique($data) : array($data); foreach ($data as $uuid) { $t = AIR2_Record::find('Tank', $uuid); if (!$t) { throw new Exception("Invalid tank_uuid({$uuid})"); } $tanks[] = $t; } foreach ($tanks as $t) { $counts = AIR2Bin::add_tank($rec, $t, $notes); foreach ($counts as $key => $val) { if (!isset($this->bulk_rs[$key])) { $this->bulk_rs[$key] = 0; } $this->bulk_rs[$key] += $counts[$key]; } } } if ($bulk_op == 'bulk_addbin') { $bins = array(); $data = is_array($data) ? array_unique($data) : array($data); foreach ($data as $uuid) { $b = AIR2_Record::find('Bin', $uuid); if (!$b) { throw new Exception("Invalid bin_uuid({$uuid})"); } if (!$b->user_may_read($this->user)) { throw new Exception("Invalid bin_uuid({$uuid})"); } $bins[] = $b; } foreach ($bins as $b) { $counts = AIR2Bin::add_bin($rec, $b, $notes); foreach ($counts as $key => $val) { if (!isset($this->bulk_rs[$key])) { $this->bulk_rs[$key] = 0; } $this->bulk_rs[$key] += $counts[$key]; } } } if ($bulk_op == 'bulk_remove') { $this->bulk_rs = AIR2Bin::remove_sources($rec, $data); } if ($bulk_op == 'bulk_removeall') { $this->bulk_rs = AIR2Bin::remove_all_sources($rec, $data); } if ($bulk_op == 'bulk_random') { $this->bulk_rs = AIR2Bin::randomize($this->user, $rec, $data); } if ($bulk_op == 'bulk_tag') { $this->bulk_rs = AIR2Bin::tag_sources($this->user, $rec, $data); } if ($bulk_op == 'bulk_annot') { $this->bulk_rs = AIR2Bin::annotate_sources($this->user, $rec, $data); } } catch (Rframe_Exception $e) { throw $e; //re-throw as-is } catch (Exception $e) { throw new Rframe_Exception(Rframe::BAD_DATA, $e->getMessage()); } }
/** * Create new bins, with random content from an original bin * * @param User $u * @param Bin $bin * @param array $params * @return array $counts */ public static function randomize($u, $bin, $params) { $stats = self::init_stats($stats = array('total', 'insert', 'duplicate', 'invalid')); $stats['bin_uuids'] = array(); $num = isset($params['num']) ? $params['num'] : 1; $size = isset($params['size']) ? $params['size'] : null; // sanity checking $conn = AIR2_DBManager::get_master_connection(); $q = "select count(*) from bin_source where bsrc_bin_id = ?"; $total = $conn->fetchOne($q, array($bin->bin_id), 0); if ($num < 0 || $num > 20 || $num > $total) { throw new Exception("Invalid num {$num} for randomize!"); } if ($size && ($size < 1 || $size * $num > $total)) { throw new Exception("Invalid size {$size} for randomize (total={$total} num={$num})!"); } // calculate size of each bin $bin_sizes = array_fill(0, $num, $size ? $size : 0); if (!$size) { $sz_idx = 0; for ($i = 0; $i < $total; $i++) { $bin_sizes[$sz_idx]++; $sz_idx = ($sz_idx + 1) % $num; } } // select in random order (mysql does this faster now than previous versions) $q = "select bsrc_src_id from bin_source where bsrc_bin_id = ? order by RAND()"; if ($size) { $q .= " limit " . $num * $size; } $src_ids = $conn->fetchColumn($q, array($bin->bin_id), 0); // create bins, and insert items $curr_offset = 0; foreach ($bin_sizes as $bidx => $bsize) { $b = new Bin(); $b->bin_user_id = $u->user_id; $b->bin_name = "{$bin->bin_name} - Random " . ($bidx + 1); $b->bin_desc = "Random output from bin: '{$bin->bin_name}'"; $b->save(); $stats['bin_uuids'][] = $b->bin_uuid; $add_ids = array_slice($src_ids, $curr_offset, $bsize); $curr_offset += $bsize; $bstats = AIR2Bin::add_sources($b, $add_ids); $stats['insert'] += $bstats['insert']; $stats['total'] += $bstats['total']; } return $stats; }