Yii2: Override 3rd party mail views - yii2

How do we override mail view files of a 3rd party module/component?
Let's assume a module is using the following code to send an email:
Yii::$app->mailer->compose([
'html' => '#myvendor/mymodule/mail/email-html',
'text' => '#myvendor/mymodule/mail/email-text',
])
->setTo([$email => $name])
->setSubject('Hi');
->send();
How would we override these individual email views #myvendor/mymodule/mail/email-html and #myvendor/mymodule/mail/email-text?

You can override these two aliases in your config:
'aliases' => [
'#myvendor/mymodule/mail/email-html' => '#app/views/mail/email-html',
'#myvendor/mymodule/mail/email-text' => '#app/views/mail/email-text',
],

Configure and rewrite the $viewPath property in the mail file in the module.
example:
public $viewPath = '#myvendor/mymodule/mail';
First, create new html and text files. Create both files.
Create both files.
mail/newHTML
mail/trxt/NewTEXT
$mailer = Yii::$app->mailer;
$mailer->viewPath = $this->viewPath;
$mailer->getView()->theme = Yii::$app->view->theme;
return $mailer->compose(['html' => $view, 'text' => 'text/' . $view], $params)
->setTo($to)
->setFrom($this->sender)
->setSubject($subject)
->send();
If you want to change the path for only one:
Use before code:
Yii :: $ app-> mailer-> viewPath = '# myvendor / newPath';
Yii::$app->mailer->compose([ #code...
  If the VIEW file: Only need to change the name for HTML and TEXT file, (both)
Update:
It can be override or through a component and ...
//new file: path\widgets\Mailer.php
namespace path\widgets;
use yourpath\Mailer as DefaultMailer; //path:mymodule/mail
class Mailer extends DefaultMailer{
public $viewPath = '#myvendor/mymodule/mail';
public function changeviewPath($_path){
$this->viewPath; = $_path;
}
}
// for use. Changes
use path\widgets\Maile; // New path
// Use before the usual code
$mailer->changeviewPath('newpath\mail');
To change the address of the files in the component. Depending on your email module, it varies
example:
'modules' => [
'myMudul' => [
'class' => 'PathModule\Module',
'mailer' => [
#code ..
],
],
...

Related

Can I display pictures outside backend web folder in yii2?

I have a little problem. I can’t view images outside the backend web folder.
Aliases in common\config\main:
'aliases' => [
'#upload' => dirname(dirname(__DIR__)).'/upload',
],
View Dataprovider:
[
'format' => 'raw',
'label' => 'Immagine',
'value' => function ($data) {
return Html::img(Yii::getAlias('#upload') . $data->codice_prodotto . '/' . $data->immagine, ['width' => '70px', 'class' => 'img-thumbnail']);
},
],
Can I resolve? Thanks.
If your file is not accessible for http server, so you can't directly download it.
You can:
Move uploads directory to directory accessible for the http-server
Create action that will read the file from private directory and stream it to the browser (you can use yii\web\Response::sendFile() function for that)
Streaming file to the browser
Please read this official docs article to understand this deeply: https://www.yiiframework.com/doc/api/2.0/yii-web-response#sendFile()-detail
Action code example for your case: *
public function actionFile($filename)
{
$storagePath = Yii::getAlias('#upload');
// check filename for allowed chars (do not allow ../ to avoid security issue: downloading arbitrary files)
if (!preg_match('/^[a-z0-9]+\.[a-z0-9]+$/i', $filename) || !is_file("$storagePath/$filename")) {
throw new \yii\web\NotFoundHttpException('The file does not exists.');
}
return Yii::$app->response->sendFile("$storagePath/$filename", $filename);
}
And view Dataprovider configuration: *
[
'format' => 'raw',
'label' => 'Immagine',
'value' => function ($data) {
return Html::img(Url::to(['/path/to-streaming-action/file', 'filename' => $data->codice_prodotto . '/' . $data->immagine]), ['width' => '70px', 'class' => 'img-thumbnail']);
},
],
* Notice that this code is not ready to copy-paste, please read it carefully and try to understand the principle before implement it in your code.

How to add a role to user when having basic User model in Yii2

Building a lightweight app using basic installation of Yii2.
I need to assign a role for a user but don't want to have users and user roles stored in database.
How can I set a role for users defined in User->users class?
Default User model and default user definition look like this:
class User extends \yii\base\BaseObject implements \yii\web\IdentityInterface
{
public $id;
public $username;
public $password;
public $authKey;
public $accessToken;
private static $users = [
'100' => [
'id' => '100',
'username' => 'admin',
'password' => 'admin',
'authKey' => 'test100key',
'accessToken' => '100-token',
],
You can use RBAC PhpManager for that that will store all roles info in files instead.
First configure your AuthManager component in config/web.php:
// ...
'components' => [
// ...
'authManager' => [
'class' => 'yii\rbac\PhpManager',
],
// ...
],
By default it uses 3 files to keep the data:
#app/rbac/items.php
#app/rbac/assignments.php
#app/rbac/rules.php
So make sure there is folder rbac in your application's root and that it's write-able by the www process. If you want to place the files somewhere else (or rename them) you can provide the new path in the configuration like:
'authManager' => [
'class' => 'yii\rbac\PhpManager',
'itemFile' => // new path here for items,
'assignmentFile' => // new path here for assignments,
'ruleFile' => // new path here for rules,
],
The rest now is just like in the Authorization Guide.
Prepare roles and permissions (example in console command - by running this command once you set all roles; remember that if you want to run it in console you need also configure console.php with the same component).
Assign role to a user (example - here it's done during the signup but you can do it also in the above command).
Now you can control access with direct check or behavior configuration.

Yii2 render database content

There is a textarea where user can edit some templates and can use variables like:
{{model.user.name}}
Application need to replace this variables with data and display HTML output.
We can write a small function that will replace variables from template with data but we need to use a template engine like Twig or Smarty.
https://github.com/yiisoft/yii2-twig
https://github.com/yiisoft/yii2-smarty
Now we can use ViewRenderer from Smarty or Twig.
$render = new ViewRenderer();
$content = $render->render($this->view,'template.twig',[
'model' => $model,
]);
But I see this error:
Unable to find template "template.twig" (looked into: .).
How can I use Smarty or Twig to render a template with the content from database in Yii2 ?
I found Mustache ( https://github.com/bobthecow/mustache.php ) and I'm using like this:
$m = new \Mustache_Engine();
echo $m->render("Hello {{model.client.firma}}",['model' => $model]);
You don't create a renderer manually, you configure your application components, like this:
[
'components' => [
'view' => [
'class' => 'yii\web\View',
'renderers' => [
'twig' => [
'class' => 'yii\twig\ViewRenderer',
'cachePath' => '#runtime/Twig/cache',
// Array of twig options:
'options' => [
'auto_reload' => true,
],
'globals' => ['html' => '\yii\helpers\Html'],
'uses' => ['yii\bootstrap'],
],
// ...
],
],
],
]
You are telling Yii that there is a renderer to handle templates with the .twig extension.
Then, all you need to do is add the .twigextension when calling render in your controller actions:
public function actionIndex()
{
return $this->render('index.twig');
Then put your twig templates in the view folders where the views normally go.
Read the documentation for the twig extension: Twig Extension for Yii 2
If you want to only use twig templates, you can avoid specifying the extension (.twig) if you set the default extension:
'components' => [
'view' => [
'defaultExtension' => 'twig',
You should create a twig component which will wrap around Twig_Environment. You can add yii\twig\Extension extension if you need. Then you should use it like this:
$renderedTemplate = Yii::$app->twig->render($template, $context);
If you really need to render a template from a string variable you may implement your own Twig_LoaderInterface. There is a Twig_Loader_String, but it's deprecated and you should not use it.

CakePHP 3 Auth on model other than User

I'm working on a project rebuild using CakePHP, and following the new Authentication documentation here:
http://book.cakephp.org/3.0/en/controllers/components/authentication.html
From what I'm reading, Cake3 uses the userModel='User' by default, but it has the option to set it to whatever you want. In my case, I have all the auth data in the 'Account' model (i.e. userModel => 'Account').
So, in my Account Entity, I added the following code:
protected function _setPassword($password)
{
return (new DefaultPasswordHasher)->hash($password);
}
Additionally, in my accounts table, my 'passwd' field is set to varchar(255) [I've read that's required for some reason].
When I use my default baked 'add' and 'edit' methods, the password is stored in plain text, and not hashed. The ONLY way I've found to get around this is to create a custom method in the AccountsTable class then call it using this kludge:
$this->request->data['passwd'] = $this->Accounts->hashPassword($this->request->data['passwd']);
My Auth component looks like this...
$this->loadComponent('Auth', [
'loginAction' => [
'controller' => 'Accounts',
'action' => 'login'
],
'authError' => 'Unauthorized Access',
'authenticate' => [
'Form' => [
'fields' => [
'username' => 'username',
'password' => 'passwd'
],
'userModel'=>'Accounts'
]
]
]);
Is there a way to do this without dinking around with the raw request data?
Your mutator is named wrongly, the convention for mutators is _set followed by the camel cased field/property name. So since your field name is passwd, not password, it has to be named _setPasswd instead.
protected function _setPasswd($password)
{
return (new DefaultPasswordHasher)->hash($password);
}
See also Cookbook > Entities > Accessors & Mutators

how to pass alphanumeric parameter in yii2 controller action

My code is
class WorkshopsController extends Controller
{
public $layout = false;
public function actionIndex($address)
{
echo $address;
return $this->render('workshops.twig');
}
}
I want to pass any place address to above given action. how can i do that in Yii2. Address can be like "Mazyad Road, Mazyad - Al Ain - أبو ظبي - United Arab Emirates"
You need to request you workshops/index page with address query parameter example.com/workshops/index?address=some address. Yii will automaticaly call your action and pass query params into it.
EDIT
If you wish to use pretty url, you must specify urlManager rules for it. E.g.
rules => [
'workshops/<address>' => 'workshops/index',
],
Also if you wish your page open when addess parameter not specified you can define rules like this:
[
'pattern' => 'workshops/<address>',
'route' => 'workshops/index',
'defaults' => ['address' => ''],
]