Yii2 BaseMailer test environment not saving or sending - yii2

I'm running some unit tests, one of the tests checks that emails are generated and sent.
I have checked the docs, to force Yii to save the emails to a file rather than send I have configured mailer component as follows:
'mailer' => [
'class' => 'yii\swiftmailer\Mailer',
'viewPath' => '#common/mail',
// send all mails to a file by default. You have to set
// 'useFileTransport' to false and configure a transport
// for the mailer to send real emails.
'useFileTransport' => true
],
When running the tests I see the Yii::info message coming from the BaseMailer send() function.
[yii\mail\BaseMailer::send] 'Sending email "Direct Debit Payment Notification" to "test#test.co.uk"'
However the email doesn't get saved anywhere, should be runtime/mail, it is not sent anywhere either.
I have tried to set useFileTransport at runtime using:
$mailer = Yii::$app->mailer;
$mailer->useFileTransport = true;
$mailer->composer...
But nothing changes, any help is appreciated.

Codeception override your mailer settings ([1] [2]) to use custom mailer, which does not send or save anything. It makes sense - you don't want to send bunch of emails during testing.
You can use Codeception custom assertions or methods to test sent emails:
$I->seeEmailIsSent(3); // Test that three emails was sent
$messages = $I->grabSentEmails();
$I->assertEquals('admin#site,com', $messages[0]->getTo());

Looking at the Docs,yii\mail\BaseMailer::useFileTransport If enabled, this option enforces saving mail message data into the local files instead of regular sending. These files will be saved under yii\mail\BaseMailer::fileTransportPath, which is #runtime/mail by default.
So check your directory permissions if they are ok, you can change it to anyother directory that you know wont have permission issues by using fileTransportPath.
'mailer' => [
'class' => 'yii\swiftmailer\Mailer',
'viewPath' => '#common/mail',
// send all mails to a file by default. You have to set
// 'useFileTransport' to false and configure a transport
// for the mailer to send real emails.
'useFileTransport' => true,
'fileTransportPath'=>'your/path',
],

Related

Is it possible to set the path for all frontend AJAX request

My slugs looks like this:
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' => [
'<lang>/<p_page>/<p_category>/<p_product>' => 'splitter/manage-request',
'<lang>/<p_page>/<p_category>' => 'splitter/manage-request',
'<lang>/<p_page>' => 'splitter/manage-request',
'<lang>/' => 'splitter/manage-request',
'<lang>' => 'splitter/manage-request',
'' => 'splitter/manage-request',
],
],
I am sending all the requests to that SplitterController where I am parsing them. But I don't want the AJAXs to be send to it. Is it possible to give them some default route? To redirect them backend for example. I couldn't find information about it in the documentation? Appreciating links also is I missed it. Thank you!
According to my experience, there are probably the following options for your reference:
the first: The easiest way is to add a beforeAction() to your SplitterController, determine if it is an ajax request in beforeAction(), and redirect to your target address, for example:
public function beforeAction()
{
if (\Yii::$app->request->isAjax) {
return \Yii::$app->response->redirect($targetUrl);
}
return parent::beforeAction($action);
}
second: You can check if the request is an ajax request in the nginx configuration and then redirect to your target address
third: If you can't set up additional routing rules and configure the ajax request address, then you can consider implementing it by customizing UrlManager::parseRequest(), just check if it is an ajax request before it starts parsing the request, then redirect to your target. address
This answer is translated from Google Translate

Yii2 Make endpoint accessible through web and rest api

A customer has requested to have the exact same endpoints available through web interface as well as through REST API.
The same endpoint should be visible using web browser only when being logged in. When accessing it via REST API, a valid access token must be submitted.
The rule for this specific endpoint is defined as follows:
[
'class' => 'yii\rest\UrlRule',
'controller' => 'site',
'pluralize' => false,
'extraPatterns' => [
'POST upload-raw-data' => 'uploadRawData'
],
]
Now, when I try to access this endpoint, I've got these results:
Browser: no problem
Postman / POST: 404 error
Postman / GET: no problem
When trying the same with enableStrictParsing enabled, I've got 404 errors all around.
If I need to provide other parts of the code, I'll happily provide them.
I think I found the solution for my issue. The problem seems to have been the CSRF validation.
By disabling it for this specific action in beforeAction(), the POST call behaves as intended.
public function beforeAction($action) {
if ($action->id == 'upload-raw-data')
Yii::$app->controller->enableCsrfValidation = false;
return parent::beforeAction($action);
}
source: https://gist.github.com/guerreiro/9e9cb3154b9047f5d2a0

how to run action of frontend controller from backend in yii2

Is it possible to run action of frontend controller from backend?
this code works if called action is in backend too. can i specify in runAction that controller/action is in frontend?
Yii::$app->runAction('controller/action')
Also i' m tried something like
$c=new controller();
$s->action();
too but it seems it not working too. //new controller() need some parameters and i have no idea what it is.
The yii\base\Application object has a public property controllerNamespace, which defaults to app\\controllers. You need to change it accordingly to changing default controller namespace.
Change namespace in action:
Yii::$app->controllerNamespace = 'frontend\controllers' and use runAction
A way could be this .
In your backend application config you could create an additional 'UrlManager' component
name eg: urlManagerFrontEnd
return [
'components' => [
'urlManager' => [
// here is your backend URL rules
],
'urlManagerFrontEnd' => [
'class' => 'yii\web\urlManager',
'baseUrl' => 'http://your_path/frontend/web/index.php',
'enablePrettyUrl' => true,
'showScriptName' => false,
],
],
];
Then you should invoke following to compose front-end URL:
Yii::$app->urlManagerFrontEnd->createUrl();
and add the controller/action you prefer
remeber that
runAction()
Runs an action within this controller with the specified action ID and
parameters.
http://www.yiiframework.com/doc-2.0/yii-base-controller.html#runAction()-detail
this mean that cannot run an action of another controller or of another application ..
If you need a service then you must configure a RESTFull or you simply need a redirection you can use redirect

Yii2: How to read a cookie, which was set by JavaScript

I set a cookie in web/js/site.js:
$.cookie("sidebar", "hidden", { path: '/' });
I read the cookie with PHP:
$sidebar_toggle_state = $_COOKIE['sidebar'];
Is it possible to use also the Yii Request Component to read such cookies? The following code doesn't read the cookie:
$sidebar_toggle_state = Yii::$app->request()->cookies()->getValue('sidebar', '');
See: http://www.yiiframework.com/doc-2.0/guide-runtime-sessions-cookies.html#cookies
When I set a new cookie through the Yii Response Component:
Yii::$app->response->cookies->add(new yii\web\Cookie([
'name' => 'sidebar',
'value' => 'hidden',
]));
Then the value of the cookie looks like this (because the cookie is protected):
3976220a3c8e46bb641aef1da3accfb1652bffd5bb9de503a9d6882e8a69f6f9a%3A2%3A%7Bi%3A0%3Bs%3A7%3A%22sidebar%22%3Bi%3A1%3Bs%3A6%3A%22hidden%22%3B%7D
Such cookie can the Yii Request Component read. But can it read also unprotected cookies?
Or, is it possible to set the Yii protected cookies with JavasSript / jQuery (without using AJAX)?
To read a cookie set by Javascript, you have, in configurations, config/web.php to set some request components properties to be false like the following:
'components' => [
'request' => [
// !!! insert a secret key in the following (if it is empty) - this is required by cookie validation
'cookieValidationKey' => 'SomeRandomStringChars',
'enableCookieValidation' => false,
'enableCsrfValidation' => false,
],
This will allow reading cookies that have been set using Javascript like the following:
Yii::$app->getRequest()->getCookies()->getValue('theme');
Warning!
The above solution may has security issues, because we canceled the enableCookieValidation and enableCsrfValidation for all cookies. So there is another solution that allows jumping those validations for a specific cookie, suppose the theme cookie that we just have used in the example above, we will utilize the second parameter of getValue() method, i.e the default value, like the following:
Yii::$app->getRequest()->getCookies()->getValue('theme', (isset($_COOKIE['theme']))? $_COOKIE['theme']: 'theme')
The above solution will let you keeping both, enableCookieValidation and enableCsrfValidation to be true and only bypass them for a specific cookie.

Yii2 isGuest giving exception in console application

In console application when I used Yii::$app->user->isGuest it is giving the below exception:
Exception 'yii\base\UnknownPropertyException' with message 'Getting unknown prop
erty: yii\console\Application::user'
I even tried adding the user in components array in config file. But it didn't worked. Any idea what am I doing wrong?
In Console application Yii->$app->user does not exist. So, you need to configure user component in config\console.php.
like as,
config\console.php
'components' => [
.........
......
'user' => [
'class' => 'yii\web\User',
'identityClass' => 'app\models\User',
//'enableAutoLogin' => true,
],
'session' => [ // for use session in console application
'class' => 'yii\web\Session'
],
.......
]
To check it works or not using below code.
public function actionIndex($message = 'hello world')
{
echo $message . "\n";
$session = \Yii::$app->session->set('name', 'ASG');
if(\Yii::$app->session) // to check session works or not
echo \Yii::$app->session->get('name')."\n";
print_R(\Yii::$app->user);
}
More info about your problem : Link
Note : There's no session in console.
The reason is simple. Guide says about application components (user is a component):
user: represents the user authentication information. This component
is only available in Web applications Please refer to the
Authentication section for more details.
So Yii::$app->user it not available in console applications.
As a consequence you have to consider using this component in model classes that are also used by console applications.
Extra note: it is internally used by BlameableBehavior, however, this makes no problems since user will be null if a model gets saved/created and no user is available.