/** * Requests the data to be identified by a formerly prepared request. * * Prepares the curl object, executes it and checks * for transport level errors, throwing the appropriate exceptions. * * @return string XML representation of the response. * * @throws \PHPCR\NoSuchWorkspaceException if it was not possible to reach the server (resolve host or connect) * @throws \PHPCR\ItemNotFoundException if the object was not found * @throws \PHPCR\RepositoryExceptions if on any other error. * @throws \PHPCR\PathNotFoundException if the path was not found (server returned 404 without xml response) * * @uses curl::errno() * @uses curl::exec() */ public function execute($getCurlObject = false) { if ($this->credentials instanceof \PHPCR\SimpleCredentials) { $this->curl->setopt(CURLOPT_USERPWD, $this->credentials->getUserID() . ':' . $this->credentials->getPassword()); } else { $this->curl->setopt(CURLOPT_USERPWD, null); } $headers = array('Depth: ' . $this->depth, 'Content-Type: ' . $this->contentType, 'User-Agent: ' . self::USER_AGENT); $headers = array_merge($headers, $this->additionalHeaders); $this->curl->setopt(CURLOPT_RETURNTRANSFER, true); $this->curl->setopt(CURLOPT_CUSTOMREQUEST, $this->method); $this->curl->setopt(CURLOPT_URL, $this->uri); $this->curl->setopt(CURLOPT_HTTPHEADER, $headers); $this->curl->setopt(CURLOPT_POSTFIELDS, $this->body); if ($getCurlObject) { $this->curl->parseResponseHeaders(); } $response = $this->curl->exec(); $httpCode = $this->curl->getinfo(CURLINFO_HTTP_CODE); if ($httpCode >= 200 && $httpCode < 300) { if ($getCurlObject) { return $this->curl; } return $response; } switch ($this->curl->errno()) { case CURLE_COULDNT_RESOLVE_HOST: case CURLE_COULDNT_CONNECT: throw new \PHPCR\NoSuchWorkspaceException($this->curl->error()); } // TODO extract HTTP status string from response, more descriptive about error // use XML error response if it's there if (substr($response, 0, 1) === '<') { $dom = new \DOMDocument(); $dom->loadXML($response); $err = $dom->getElementsByTagNameNS(Client::NS_DCR, 'exception'); if ($err->length > 0) { $err = $err->item(0); $errClass = $err->getElementsByTagNameNS(Client::NS_DCR, 'class')->item(0)->textContent; $errMsg = $err->getElementsByTagNameNS(Client::NS_DCR, 'message')->item(0)->textContent; $exceptionMsg = 'HTTP ' . $httpCode . ': ' . $errMsg; switch ($errClass) { case 'javax.jcr.NoSuchWorkspaceException': throw new \PHPCR\NoSuchWorkspaceException($exceptionMsg); case 'javax.jcr.nodetype.NoSuchNodeTypeException': throw new \PHPCR\NodeType\NoSuchNodeTypeException($exceptionMsg); case 'javax.jcr.ItemNotFoundException': throw new \PHPCR\ItemNotFoundException($exceptionMsg); case 'javax.jcr.nodetype.ConstraintViolationException': throw new \PHPCR\NodeType\ConstraintViolationException($exceptionMsg); //TODO: map more errors here? //TODO: map more errors here? default: // try to generically "guess" the right exception class name $class = substr($errClass, strlen('javax.jcr.')); $class = explode('.', $class); array_walk($class, function (&$ns) { $ns = ucfirst(str_replace('nodetype', 'NodeType', $ns)); }); $class = '\\PHPCR\\' . implode('\\', $class); if (class_exists($class)) { throw new $class($exceptionMsg); } throw new \PHPCR\RepositoryException($exceptionMsg . " ({$errClass})"); } } } if (404 === $httpCode) { throw new \PHPCR\PathNotFoundException("HTTP 404 Path Not Found: {$this->method} {$this->uri}"); } elseif (405 == $httpCode) { throw new \Jackalope\Transport\Davex\HTTPErrorException("HTTP 405 Method Not Allowed: {$this->method} {$this->uri}", 405); } elseif ($httpCode >= 500) { throw new \PHPCR\RepositoryException("HTTP {$httpCode} Error from backend on: {$this->method} {$this->uri} \n\n{$response}"); } $curlError = $this->curl->error(); $msg = "Unexpected error: \nCURL Error: {$curlError} \nResponse (HTTP {$httpCode}): {$this->method} {$this->uri} \n\n{$response}"; throw new \PHPCR\RepositoryException($msg); }
/** * Tidies up the current cUrl connection. */ public function __destruct() { if ($this->curl) { $this->curl->close(); } }