/** * Get transaction response by object * @param object|array $object * @return $response */ public function filterByObject($objectOrArray) { $response = new Response(); if (!is_array($objectOrArray)) { $objectOrArray = array($objectOrArray); } foreach ($objectOrArray as $object) { if (!is_object($object)) { throw new \InvalidArgumentException("can't findTransactionByObject if not object"); } // iterate over t foreach ($this->queue as $transaction => $transactionQueue) { foreach ($transactionQueue as $key => $task) { if ($object === $task or $object === $task->getObject()) { $response->add($transaction, $task, isset($this->exceptions[$transaction][$key]) ? $this->exceptions[$transaction][$key] : $this->status[$transaction][$key]); } } } } return $response; }
/** * Add a item to the queue for persitance on flush * * @param $trancation * @param $onFailure * * @return bool */ public function flush($transaction = null, $onFailure = self::FLUSH_ABORT, $throwExceptions = true) { if (is_null($transaction)) { $transaction = self::TRANSACTIONS_ALL; } if (is_null($onFailure)) { $onFailure = self::FLUSH_ABORT; } $response = new Response(); $exceptions = []; $haveAnyTransactionsFailed = false; // simulate $simulate = $this->debug & self::DEBUG_SIMULATE; // profiler $profiler = new Profiler("Record manager"); $profiler->log(); // debugging query show $debugQuery = null; if ($this->debug & self::DEBUG_SHOW_QUERY) { $debugQuery = function ($e, $event, $data) { echo $data . "\n"; }; $this->db->debug->on(Debug::INFO, $debugQuery); } // trap all throw exceptions so that we can properly unattach the $db->debug->on( Pg::QueryPassed $listener ) try { // iterate selected transactions foreach ($this->getQueue($transaction, true, true) as $transaction => $queue) { unset($this->queue[$transaction]); $taskResponse = null; $hasTransactionFailed = false; $beginTransaction = new Query("BEGIN TRANSACTION READ WRITE; /* %transaction:% */"); $beginTransaction->transaction = $transaction; $this->db->query($beginTransaction); $this->eventEmitter->emit(EventEmitter::TRANSACTION_START, $this, $transaction, $queue); // loop over our tasks foreach ($queue as $task) { // are we continuing to process? if ($hasTransactionFailed or $haveAnyTransactionsFailed && $onFailure === self::FLUSH_ABORT) { $taskResponse = Response::ABORTED; } else { try { $taskResponse = $task->execute($this->db, $simulate) ? Response::SUCCESS : Response::FAILED; } catch (\Exception $e) { // It'd be nice if we could just test for Query exceptions here but unfortunately PHPUnit dicks pretty hard with exception types. // @Mr Beale. I realise this violates the "only handle exceptions that you understand" rule but I can't find a way round this. Pete $taskResponse = $e; $exceptions[] = $e; } } // transaction success if ($taskResponse !== Response::SUCCESS) { $hasTransactionFailed = true; $haveAnyTransactionsFailed = true; } $response->add($transaction, $task, $taskResponse); } // end or rollback transaction $endTransaction = new Query("%commitOrRollback:% TRANSACTION; /* %transaction:% */"); $endTransaction->commitOrRollback = new Raw($hasTransactionFailed ? 'ROLLBACK' : 'COMMIT'); $endTransaction->transaction = $transaction; $this->db->query($endTransaction); // response rollback if ($hasTransactionFailed) { $response->rollback($transaction); } $profiler->log($transaction); } // if we've gathered any exceptions throw them here if ($throwExceptions and $exceptions) { throw $exceptions[0]; } $response->profilerAssign($profiler); } catch (\Exception $e) { $this->db->debug->removeListener(Pg::QUERY_PARSED, $debugQuery); throw $e; } return $response; }
public function testFilterByObject() { $response = new Response(); $obj = new \stdClass(); $exception = new \Exception("some exception here"); $task1 = new Base($this->entityManager->recordManager); $task1->setObject($obj); $task2 = new Base($this->entityManager->recordManager); // build two task response $response->add('success', $task1, Response::SUCCESS); $response->add('failed', $task2, $exception); $this->assertSame(count($response), 2); $this->assertFalse($response->isSuccess()); // lookup by $obj $responseSuccess = $response->filterByObject($obj); $this->assertTrue($responseSuccess->isSuccess()); $this->assertSame(count($responseSuccess), 1); // lookup by task1 $responseSuccess = $response->filterByObject($task1); $this->assertTrue($responseSuccess->isSuccess()); $this->assertSame(count($responseSuccess), 1); // lookup by task2 $responseFailed = $response->filterByObject($task2); $this->assertFalse($responseFailed->isSuccess()); $this->assertSame(count($responseFailed), 1); // lookup by task1,2 $responseAll = $response->filterByObject(array($task1, $task2)); $this->assertFalse($responseAll->isSuccess()); $this->assertSame(count($responseAll), 2); }