/** * Creates a new cassette. * * @param string $name Name of the cassette. * @param Configuration $config Configuration to use for this cassette. * @param Storage $storage Storage to use for requests and responses. * @throws \VCR\VCRException If cassette name is in an invalid format. */ public function __construct($name, Configuration $config, Storage $storage) { Assertion::string($name, "Cassette name must be a string, " . \gettype($name) . " given."); $this->name = $name; $this->config = $config; $this->storage = $storage; }
/** * @inheritDoc */ public function enable(\Closure $requestCallback) { Assertion::isCallable($requestCallback, 'No valid callback for handling requests defined.'); self::$requestCallback = $requestCallback; stream_wrapper_unregister('http'); stream_wrapper_register('http', __CLASS__, STREAM_IS_URL); stream_wrapper_unregister('https'); stream_wrapper_register('https', __CLASS__, STREAM_IS_URL); $this->status = self::ENABLED; }
/** * @inheritDoc */ public function enable(\Closure $requestCallback) { Assertion::isCallable($requestCallback, 'No valid callback for handling requests defined.'); if (static::$status == self::ENABLED) { return; } $this->codeTransformer->register(); $this->processor->appendCodeTransformer($this->codeTransformer); $this->processor->intercept(); self::$requestCallback = $requestCallback; static::$status = self::ENABLED; }
/** * Creates a new JSON based file store. * * @param string $cassettePath Path to the cassette directory. * @param string $cassetteName Path to a file, will be created if not existing. */ public function __construct($cassettePath, $cassetteName) { $file = $cassettePath . DIRECTORY_SEPARATOR . $cassetteName; if (!file_exists($file)) { file_put_contents($file, '[]'); } Assertion::file($file, "Specified path '{$file}' is not a file."); Assertion::readable($file, "Specified file '{$file}' must be readable."); Assertion::writeable($file, "Specified path '{$file}' must be writeable."); $this->handle = fopen($file, 'r+'); $this->filePath = $file; }
/** * Creates a new YAML based file store. * * @param string $cassettePath Path to the cassette directory. * @param string $cassetteName Path to a file, will be created if not existing. * @param Parser $parser Parser used to decode yaml. * @param Dumper $dumper Dumper used to encode yaml. */ public function __construct($cassettePath, $cassetteName, Parser $parser = null, Dumper $dumper = null) { $file = $cassettePath . DIRECTORY_SEPARATOR . $cassetteName; if (!file_exists($file)) { file_put_contents($file, ''); } Assertion::file($file, "Specified path '{$file}' is not a file."); Assertion::readable($file, "Specified file '{$file}' must be readable."); Assertion::writeable($file, "Specified path '{$file}' must be writable."); $this->handle = fopen($file, 'r+'); $this->yamlParser = $parser ?: new Parser(); $this->yamlDumper = $dumper ?: new Dumper(); }
/** * @inheritDoc */ public function enable(\Closure $requestCallback) { self::$codeTransformer->register(); self::$processor->appendCodeTransformer(self::$codeTransformer); self::$processor->intercept(); Assertion::isCallable($requestCallback, 'No valid callback for handling requests defined.'); self::$requestCallback = $requestCallback; stream_wrapper_unregister('http'); stream_wrapper_register('http', __CLASS__, STREAM_IS_URL); stream_wrapper_unregister('https'); stream_wrapper_register('https', __CLASS__, STREAM_IS_URL); $this->status = self::ENABLED; }
/** * Creates a new file store. * * If the cassetteName contains PATH_SEPARATORs, subfolders of the * cassettePath are autocreated when not existing. * * @param string $cassettePath Path to the cassette directory. * @param string $cassetteName Path to the cassette file, relative to the path. * @param string $defaultContent Default data for this cassette if its not existing */ public function __construct($cassettePath, $cassetteName, $defaultContent = '[]') { Assertion::directory($cassettePath, "Cassette path '{$cassettePath}' is not existing or not a directory"); $this->filePath = rtrim($cassettePath, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . $cassetteName; if (!is_dir(dirname($this->filePath))) { mkdir(dirname($this->filePath), 0777, true); } if (!file_exists($this->filePath) || 0 === filesize($this->filePath)) { file_put_contents($this->filePath, $defaultContent); $this->isNew = true; } Assertion::file($this->filePath, "Specified path '{$this->filePath}' is not a file."); Assertion::readable($this->filePath, "Specified file '{$this->filePath}' must be readable."); $this->handle = fopen($this->filePath, 'r+'); }
/** * Returns http_version, code and message from a HTTP status line. * * @param string $status HTTP status line, e.g. HTTP/1.1 200 OK * @return array Parsed 'http_version', 'code' and 'message'. */ public static function parseStatus($status) { Assertion::startsWith($status, 'HTTP/', "Invalid HTTP status '{$status}', expected format like: 'HTTP/1.1 200 OK'."); $part = explode(' ', $status, 3); return array('http_version' => substr(strrchr($part[0], '/'), 1), 'code' => $part[1], 'message' => isset($part[2]) ? $part[2] : ''); }
/** * Inserts a cassette to record responses and requests on. * * @api * * @param string $cassetteName Name of the cassette (used for the cassette filename). * * @return void * @throws VCRException If videorecorder is turned off when inserting a cassette. */ public function insertCassette($cassetteName) { Assertion::true($this->isOn, 'Please turn on VCR before inserting a cassette, use: VCR::turnOn().'); if (!is_null($this->cassette)) { $this->eject(); } $storage = $this->factory->get('Storage', array($cassetteName)); $this->cassette = new Cassette($cassetteName, $this->config, $storage); $this->enableLibraryHooks(); }
/** * @param string|array $status */ protected function setStatus($status) { if (is_array($status)) { $this->status = $status; if (!empty($status['http_version'])) { $this->httpVersion = $status['http_version']; } } else { Assertion::numeric($status, 'Response status must be either an array or a number.'); $this->status['code'] = $status; } }
/** * Sets a cURL option on a Request. * * @param Request $request Request to set cURL option to. * @param integer $option cURL option to set. * @param mixed $value Value of the cURL option. * @param resource $curlHandle cURL handle where this option is set on (optional). */ public static function setCurlOptionOnRequest(Request $request, $option, $value, $curlHandle = null) { switch ($option) { case CURLOPT_URL: $request->setUrl($value); break; case CURLOPT_FOLLOWLOCATION: $request->getParams()->set('redirect.disable', !$value); break; case CURLOPT_MAXREDIRS: $request->getParams()->set('redirect.max', $value); break; case CURLOPT_CUSTOMREQUEST: $request->setMethod($value); break; case CURLOPT_POST: if ($value == true) { $request->setMethod('POST'); } break; case CURLOPT_POSTFIELDS: // todo: check for file @ if (is_array($value)) { foreach ($value as $name => $fieldValue) { $request->setPostField($name, $fieldValue); } if (count($value) == 0) { $request->removeHeader('Content-Type'); } } else { $request->setBody($value); } break; case CURLOPT_HTTPHEADER: foreach ($value as $header) { $headerParts = explode(': ', $header, 2); if (isset($headerParts[1])) { $request->setHeader($headerParts[0], $headerParts[1]); } } break; case CURLOPT_HEADER: case CURLOPT_WRITEFUNCTION: case CURLOPT_HEADERFUNCTION: // Ignore writer and header functions. // These options are stored and will be handled later in handleOutput(). break; case CURLOPT_READFUNCTION: // Guzzle provides a callback to let curl read the body string. // To get the body, this callback is called manually. $bodySize = $request->getCurlOptions()->get(CURLOPT_INFILESIZE); Assertion::notEmpty($bodySize, "To set a CURLOPT_READFUNCTION, CURLOPT_INFILESIZE must be set."); $body = call_user_func_array($value, array($curlHandle, fopen('php://memory', 'r'), $bodySize)); $request->setBody($body); break; default: $request->getCurlOptions()->set($option, $value); break; } }
/** * Validates a specified cassette path. * * @param string $cassettePath Path to a cassette. * @throws VCRException If cassette path is invalid. */ private function assertValidCassettePath($cassettePath) { Assertion::directory($cassettePath, "Cassette path '{$cassettePath}' is not a directory. Please either " . "create it or set a different cassette path using " . "\\VCR\\VCR::configure()->setCassettePath('directory')."); }
/** * Makes sure we've properly handled the POST body, such as ensuring that * CURLOPT_INFILESIZE is set if CURLOPT_READFUNCTION is set. * * @param Request $request Request to set cURL option to. * @param resource $curlHandle cURL handle associated with the request. */ public static function validateCurlPOSTBody(Request $request, $curlHandle = null) { $readFunction = $request->getCurlOption(CURLOPT_READFUNCTION); if (is_null($readFunction)) { return; } // Guzzle 4 sometimes sets the post body in CURLOPT_POSTFIELDS even if // they have already set CURLOPT_READFUNCTION. if ($request->getBody()) { return; } $bodySize = $request->getCurlOption(CURLOPT_INFILESIZE); Assertion::notEmpty($bodySize, "To set a CURLOPT_READFUNCTION, CURLOPT_INFILESIZE must be set."); $body = call_user_func_array($readFunction, array($curlHandle, fopen('php://memory', 'r'), $bodySize)); $request->setBody($body); }