protected function doExecute() { $path = $this->getHttpQuery(); $response = $this->client->request("GET", $path); if ($response instanceof ErrorResponse) { // Create view, if it does not exist yet $this->createDesignDocument(); $response = $this->client->request("GET", $path); } if ($response->status >= 400) { throw HTTPException::fromResponse($path, $response); } return $response; }
protected function doExecute() { $path = $this->getHttpQuery(); $method = "GET"; $data = null; if ($this->getParameter("keys") !== null) { $method = "POST"; $data = json_encode(array("keys" => $this->getParameter("keys"))); } $response = $this->client->request($method, $path, $data); if ($response instanceof ErrorResponse && $this->doc) { $this->createDesignDocument(); $response = $this->client->request($method, $path, $data); } if ($response->status >= 400) { throw HTTPException::fromResponse($path, $response); } return $response; }
/** * Commit any recent changes to the specified database to disk. * * @return array * @throws HTTPException */ public function ensureFullCommit() { $path = '/' . $this->databaseName . '/_ensure_full_commit'; $response = $this->httpClient->request('POST', $path); if ($response->status != 201) { throw HTTPException::fromResponse($path, $response); } return $response->body; }
/** * POST /db/_replicate * * @param string $source * @param string $target * @param bool|null $cancel * @param bool|null $continuous * @param string|null $filter * @param array|null $ids * @param string|null $proxy * @return array */ public function replicate($source, $target, $cancel = null, $continuous = null, $filter = null, array $ids = null, $proxy = null) { $params = array('target' => $target, 'source' => $source); if ($cancel !== null) { $params['cancel'] = (bool) $cancel; } if ($continuous !== null) { $params['continuous'] = (bool) $continuous; } if ($filter !== null) { $params['filter'] = $filter; } if ($ids !== null) { $params['doc_ids'] = $ids; } if ($proxy !== null) { $params['proxy'] = $proxy; } $path = '/_replicate'; $response = $this->httpClient->request('POST', $path, json_encode($params)); if ($response->status >= 400) { throw HTTPException::fromResponse($path, $response); } return $response->body; }
/** * Flush Operation - Write all dirty entries to the CouchDB. * * @return void */ public function flush() { $this->detectChangedDocuments(); if ($this->evm->hasListeners(Event::onFlush)) { $this->evm->dispatchEvent(Event::onFlush, new Event\OnFlushEventArgs($this)); } $config = $this->dm->getConfiguration(); $bulkUpdater = $this->dm->getCouchDBClient()->createBulkUpdater(); $bulkUpdater->setAllOrNothing($config->getAllOrNothingFlush()); foreach ($this->scheduledRemovals as $oid => $document) { $bulkUpdater->deleteDocument($this->documentIdentifiers[$oid], $this->documentRevisions[$oid]); $this->removeFromIdentityMap($document); if ($this->evm->hasListeners(Event::postRemove)) { $this->evm->dispatchEvent(Event::postRemove, new Event\LifecycleEventArgs($document, $this->dm)); } } foreach ($this->scheduledUpdates as $oid => $document) { $class = $this->dm->getClassMetadata(get_class($document)); if ($this->evm->hasListeners(Event::preUpdate)) { $this->evm->dispatchEvent(Event::preUpdate, new Event\LifecycleEventArgs($document, $this->dm)); $this->computeChangeSet($class, $document); // TODO: prevent association computations in this case? } $data = $this->metadataResolver->createDefaultDocumentStruct($class); // Convert field values to json values. foreach ($this->originalData[$oid] as $fieldName => $fieldValue) { if (isset($class->fieldMappings[$fieldName])) { if ($fieldValue !== null && isset($class->fieldMappings[$fieldName]['embedded'])) { // As we store the serialized value in originalEmbeddedData, we can simply copy here. $fieldValue = $this->originalEmbeddedData[$oid][$class->fieldMappings[$fieldName]['jsonName']]; } else { if ($fieldValue !== null) { $fieldValue = Type::getType($class->fieldMappings[$fieldName]['type'])->convertToCouchDBValue($fieldValue); } } $data[$class->fieldMappings[$fieldName]['jsonName']] = $fieldValue; } else { if (isset($class->associationsMappings[$fieldName])) { if ($class->associationsMappings[$fieldName]['type'] & ClassMetadata::TO_ONE) { if (\is_object($fieldValue)) { $fieldValue = $this->getDocumentIdentifier($fieldValue); } else { $fieldValue = null; } $data = $this->metadataResolver->storeAssociationField($data, $class, $this->dm, $fieldName, $fieldValue); } else { if ($class->associationsMappings[$fieldName]['type'] & ClassMetadata::TO_MANY) { if ($class->associationsMappings[$fieldName]['isOwning']) { // TODO: Optimize when not initialized yet! In ManyToMany case we can keep track of ALL ids $ids = array(); if (is_array($fieldValue) || $fieldValue instanceof \Doctrine\Common\Collections\Collection) { foreach ($fieldValue as $key => $relatedObject) { $ids[$key] = $this->getDocumentIdentifier($relatedObject); } } $data = $this->metadataResolver->storeAssociationField($data, $class, $this->dm, $fieldName, $ids); } } } } else { if ($class->hasAttachments && $fieldName == $class->attachmentField) { if (is_array($fieldValue) && $fieldValue) { $data['_attachments'] = array(); foreach ($fieldValue as $filename => $attachment) { if (!$attachment instanceof \Doctrine\CouchDB\Attachment) { throw CouchDBException::invalidAttachment($class->name, $this->documentIdentifiers[$oid], $filename); } $data['_attachments'][$filename] = $attachment->toArray(); } } } } } } // respect the non mapped data, otherwise they will be deleted. if (isset($this->nonMappedData[$oid]) && $this->nonMappedData[$oid]) { $data = array_merge($data, $this->nonMappedData[$oid]); } $rev = $this->getDocumentRevision($document); if ($rev) { $data['_rev'] = $rev; } $bulkUpdater->updateDocument($data); } $response = $bulkUpdater->execute(); $updateConflictDocuments = array(); if ($response->status == 201) { foreach ($response->body as $docResponse) { if (!isset($this->identityMap[$docResponse['id']])) { // deletions continue; } $document = $this->identityMap[$docResponse['id']]; if (isset($docResponse['error'])) { $updateConflictDocuments[] = $document; } else { $this->documentRevisions[spl_object_hash($document)] = $docResponse['rev']; $class = $this->dm->getClassMetadata(get_class($document)); if ($class->isVersioned) { $class->reflFields[$class->versionField]->setValue($document, $docResponse['rev']); } } if ($this->evm->hasListeners(Event::postUpdate)) { $this->evm->dispatchEvent(Event::postUpdate, new Event\LifecycleEventArgs($document, $this->dm)); } } } else { if ($response->status >= 400) { throw HTTPException::fromResponse($bulkUpdater->getPath(), $response); } } foreach ($this->visitedCollections as $col) { $col->takeSnapshot(); } $this->scheduledUpdates = $this->scheduledRemovals = $this->visitedCollections = array(); if (count($updateConflictDocuments)) { throw new UpdateConflictException($updateConflictDocuments); } }
/** * Get revision difference. * * @param array $data * @return array * @throws HTTPException */ public function getRevisionDifference($data) { $path = '/' . $this->databaseName . '/_revs_diff'; $response = $this->httpClient->request('POST', $path, json_encode($data)); if ($response->status != 200) { throw HTTPException::fromResponse($path, $response); } return $response->body; }
/** * @return array * @throws HTTPException * @throws \Exception */ public function getReplicationLog() { $sourceLog = null; $targetLog = null; $replicationDocId = '_local' . '/' . $this->task->getRepId(); $sourceResponse = $this->source->findDocument($replicationDocId); $targetResponse = $this->target->findDocument($replicationDocId); if ($sourceResponse->status == 200) { $sourceLog = $sourceResponse->body; } elseif ($sourceResponse->status != 404) { throw HTTPException::fromResponse('/' . $this->source->getDatabase() . '/' . $replicationDocId, $sourceResponse); } if ($targetResponse->status == 200) { $targetLog = $targetResponse->body; } elseif ($targetResponse->status != 404) { throw HTTPException::fromResponse('/' . $this->target->getDatabase() . '/' . $replicationDocId, $targetResponse); } return array($sourceLog, $targetLog); }
/** * Lazy Load Data from CouchDB if necessary * * @return void */ private function lazyLoad() { if ($this->stub) { $response = $this->httpClient->request('GET', $this->path, null, true); // raw request if ($response->status != 200) { throw HTTPException::fromResponse($this->path, $response); } $this->stub = false; $this->binaryData = $response->body; $this->data = \base64_encode($this->binaryData); } }
/** * @expectedException \Doctrine\CouchDB\HTTP\HTTPException */ public function testGetReplicationLogRaisesExceptionWhenPeerNotReachable() { $this->response->status = 500; $this->source->expects($this->once())->method('findDocument')->willThrowException(HTTPException::fromResponse(null, $this->response)); $task = new ReplicationTask(); $replication = new Replication($this->source, $this->target, $task); list($sourceLog, $targetLog) = $replication->getReplicationLog(); $this->assertEquals($targetLog, array("log" => "source_replication_log")); $this->assertEquals($sourceLog, null); }
/** * Get changes as a stream. * * This method similar to the getChanges() method. But instead of returning * the set of changes, it returns the connection stream from which the response * can be read line by line. This is useful when you want to continuously get changes * as they occur. Filtered changes feed is not supported by this method. * * @param array $params * @param bool $raw * @return resource * @throws HTTPException */ public function getChangesAsStream(array $params = array()) { // Set feed to continuous. if (!isset($params['feed']) || $params['feed'] != 'continuous') { $params['feed'] = 'continuous'; } $path = '/' . $this->databaseName . '/_changes'; $connectionOptions = $this->getHttpClient()->getOptions(); $streamClient = new StreamClient($connectionOptions['host'], $connectionOptions['port'], $connectionOptions['username'], $connectionOptions['password'], $connectionOptions['ip'], $connectionOptions['ssl']); foreach ($params as $key => $value) { if (isset($params[$key]) === true && is_bool($value) === true) { $params[$key] = $value ? 'true' : 'false'; } } if (count($params) > 0) { $query = http_build_query($params); $path = $path . '?' . $query; } $stream = $streamClient->getConnection('GET', $path, null); $headers = $streamClient->getStreamHeaders($stream); if (empty($headers['status'])) { throw HTTPException::readFailure($connectionOptions['ip'], $connectionOptions['port'], 'Received an empty response or not status code', 0); } elseif ($headers['status'] != 200) { $body = ''; while (!feof($stream)) { $body .= fgets($stream); } throw HTTPException::fromResponse($path, new Response($headers['status'], $headers, $body)); } // Everything seems okay. Return the connection resource. return $stream; }