| Current Path : /var/www/html/helpdesk/vendor/codeception/base/src/Codeception/Lib/Connector/ |
| Current File : /var/www/html/helpdesk/vendor/codeception/base/src/Codeception/Lib/Connector/Yii2.php |
<?php
namespace Codeception\Lib\Connector;
use Codeception\Lib\Connector\Yii2\Logger;
use Codeception\Lib\Connector\Yii2\TestMailer;
use Codeception\Util\Debug;
use Symfony\Component\BrowserKit\Client;
use Symfony\Component\BrowserKit\Cookie;
use Symfony\Component\BrowserKit\Response;
use Yii;
use yii\base\ExitException;
use yii\web\HttpException;
use yii\web\Response as YiiResponse;
class Yii2 extends Client
{
use Shared\PhpSuperGlobalsConverter;
/**
* @var string application config file
*/
public $configFile;
public $defaultServerVars = [];
/**
* @var array
*/
public $headers;
public $statusCode;
/**
* @var \yii\web\Application
*/
private $app;
/**
* @var \yii\db\Connection
*/
public static $db; // remember the db instance
/**
* @var TestMailer
*/
public static $mailer;
/**
* @return \yii\web\Application
*/
public function getApplication()
{
if (!isset($this->app)) {
$this->startApp();
}
return $this->app;
}
public function resetApplication()
{
$this->app = null;
}
public function startApp()
{
$config = require($this->configFile);
if (!isset($config['class'])) {
$config['class'] = 'yii\web\Application';
}
if (static::$db) {
// If the DB conection already exists, make sure to pass it as early as possible
// to prevent application from new connection creating during bootstrap
$config['components']['db'] = static::$db;
}
/** @var \yii\web\Application $app */
$this->app = Yii::createObject($config);
$this->persistDb();
$this->mockMailer($config);
\Yii::setLogger(new Logger());
}
public function resetPersistentVars()
{
static::$db = null;
static::$mailer = null;
\yii\web\UploadedFile::reset();
if (method_exists(\yii\base\Event::className(), 'offAll')) {
\yii\base\Event::offAll();
}
}
/**
*
* @param \Symfony\Component\BrowserKit\Request $request
*
* @return \Symfony\Component\BrowserKit\Response
*/
public function doRequest($request)
{
$_COOKIE = $request->getCookies();
$_SERVER = $request->getServer();
$this->restoreServerVars();
$_FILES = $this->remapFiles($request->getFiles());
$_REQUEST = $this->remapRequestParameters($request->getParameters());
$_POST = $_GET = [];
if (strtoupper($request->getMethod()) === 'GET') {
$_GET = $_REQUEST;
} else {
$_POST = $_REQUEST;
}
$uri = $request->getUri();
$pathString = parse_url($uri, PHP_URL_PATH);
$queryString = parse_url($uri, PHP_URL_QUERY);
$_SERVER['REQUEST_URI'] = $queryString === null ? $pathString : $pathString . '?' . $queryString;
$_SERVER['REQUEST_METHOD'] = strtoupper($request->getMethod());
parse_str($queryString, $params);
foreach ($params as $k => $v) {
$_GET[$k] = $v;
}
$app = $this->getApplication();
$app->getResponse()->on(YiiResponse::EVENT_AFTER_PREPARE, [$this, 'processResponse']);
// disabling logging. Logs are slowing test execution down
foreach ($app->log->targets as $target) {
$target->enabled = false;
}
$this->headers = [];
$this->statusCode = null;
ob_start();
// recreating request object to reset headers and cookies collections
$app->set('request', $app->getComponents()['request']);
$yiiRequest = $app->getRequest();
if ($request->getContent() !== null) {
$yiiRequest->setRawBody($request->getContent());
$yiiRequest->setBodyParams(null);
} else {
$yiiRequest->setRawBody(null);
$yiiRequest->setBodyParams($_POST);
}
$yiiRequest->setQueryParams($_GET);
try {
$app->trigger($app::EVENT_BEFORE_REQUEST);
$app->handleRequest($yiiRequest)->send();
$app->trigger($app::EVENT_AFTER_REQUEST);
} catch (\Exception $e) {
if ($e instanceof HttpException) {
// Don't discard output and pass exception handling to Yii to be able
// to expect error response codes in tests.
$app->errorHandler->discardExistingOutput = false;
$app->errorHandler->handleException($e);
} elseif (!$e instanceof ExitException) {
// for exceptions not related to Http, we pass them to Codeception
$this->resetApplication();
throw $e;
}
}
$content = ob_get_clean();
// catch "location" header and display it in debug, otherwise it would be handled
// by symfony browser-kit and not displayed.
if (isset($this->headers['location'])) {
Debug::debug("[Headers] " . json_encode($this->headers));
}
$this->resetApplication();
return new Response($content, $this->statusCode, $this->headers);
}
protected function revertErrorHandler()
{
$handler = new ErrorHandler();
set_error_handler([$handler, 'errorHandler']);
}
public function restoreServerVars()
{
$this->server = $this->defaultServerVars;
foreach ($this->server as $key => $value) {
$_SERVER[$key] = $value;
}
}
public function processResponse($event)
{
/** @var \yii\web\Response $response */
$response = $event->sender;
$request = Yii::$app->getRequest();
$this->headers = $response->getHeaders()->toArray();
$response->getHeaders()->removeAll();
$this->statusCode = $response->getStatusCode();
$cookies = $response->getCookies();
if ($request->enableCookieValidation) {
$validationKey = $request->cookieValidationKey;
}
foreach ($cookies as $cookie) {
/** @var \yii\web\Cookie $cookie */
$value = $cookie->value;
if ($cookie->expire != 1 && isset($validationKey)) {
$data = version_compare(Yii::getVersion(), '2.0.2', '>')
? [$cookie->name, $cookie->value]
: $cookie->value;
$value = Yii::$app->security->hashData(serialize($data), $validationKey);
}
$c = new Cookie(
$cookie->name,
$value,
$cookie->expire,
$cookie->path,
$cookie->domain,
$cookie->secure,
$cookie->httpOnly
);
$this->getCookieJar()->set($c);
}
$cookies->removeAll();
}
/**
* Replace mailer with in memory mailer
* @param $config
* @param $app
*/
protected function mockMailer($config)
{
if (static::$mailer) {
$this->app->set('mailer', static::$mailer);
return;
}
// options that make sense for mailer mock
$allowedOptions = [
'htmlLayout',
'textLayout',
'messageConfig',
'messageClass',
'useFileTransport',
'fileTransportPath',
'fileTransportCallback',
'view',
'viewPath',
];
$mailerConfig = [
'class' => 'Codeception\Lib\Connector\Yii2\TestMailer',
];
if (isset($config['components']['mailer']) && is_array($config['components']['mailer'])) {
foreach ($config['components']['mailer'] as $name => $value) {
if (in_array($name, $allowedOptions, true)) {
$mailerConfig[$name] = $value;
}
}
}
$this->app->set('mailer', $mailerConfig);
static::$mailer = $this->app->get('mailer');
}
/**
* @param $app
*/
protected function persistDb()
{
// always use the same DB connection
if (static::$db) {
$this->app->set('db', static::$db);
} elseif ($this->app->has('db')) {
static::$db = $this->app->get('db');
}
}
}