Yii2 - Attach a component on runtime - php

I did asked a question setting value in component dynamically from database, providing example for swiftmailer. The same was answered perfectly here
but that answer applies to mailer component only, so how I can achieve the similar functionality for example, I need to added in my config.php values like:
'pp' => [
'class' => 'app/components/paypal', // note: this has to correspond with the newly created folder, else you'd get a ReflectionError
// Next up, we set the public parameters of the class
'client_id' => 'YOUR-CLIENT-ID-FROM-PAYPAL',
'client_secret' => 'YOUR-CLIENT-SECRET-FROM-PAYPAL',
// You may choose to include other configuration options from PayPal
// as they have specified in the documentation
],

If you need to provide these credentials from the database on runtime you can define it via your code using the setComponents() method of the yii\base\Application class where you are retrieving the settings from the database for paypal and remove it from the config file.
Add the following lines to set the component on runtime and then call the desired method
Yii::$app->setComponents(
[
'pp' => [
'class' => 'app/components/paypal', //note: this has to correspond with the newly created folder, else you'd get a ReflectionError
// Next up, we set the public parameters of the class
'client_id' => 'YOUR-CLIENT-ID-FROM-PAYPAL',
'client_secret' => 'YOUR-CLIENT-SECRET-FROM-PAYPAL'
// You may choose to include other configuration options from PayPal
// as they have specified in the documentation
]
]
);
//now you can call the desired method for the pp with the above credentials
Yii::$app->pp->checkout();

Related

How to set env in controller for dacastro4 laravel-gmail package?

I am trying to implement Gmail API for CRM based on laravel, where users can store multiple Google credentials, and using those credentials users can log in with their Google account.
I used dacastro4 laravel-gmail package, but for dacastro4/laravel-gmail package by default design, those Google credentials are stored in .env file of the laravel project.
.env
GOOGLE_PROJECT_ID=
GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=
GOOGLE_REDIRECT_URI=
`
I tried setting the .env variable in the controller constructor function, but not working.
for example,
env('GOOGLE_PROJECT_ID',$project_id);
//OR
putenv("GOOGLE_PROJECT_ID=".$project_id);
//OR
config(['GOOGLE_PROJECT_ID' => $project_id])
Also tried setting in the vendor dacastro4 laravel-gmail package, but the database model is not accessible.
How can I set multiple Google credentials from the controller?
Thank You.
You can set this data using the config() method, seeing as that's how Laravel accesses .env variables.
Create a config file for your variables:
config/gmail.php
<?php
return [
'project_id' => env('GOOGLE_PROJECT_ID'),
'client_id' => env('GOOGLE_CLIENT_ID'),
'client_secret' => env('GOOGLE_CLIENT_SECRET'),
'redirect_url' => env('GOOGLE_REDIRECT_URI', '/'),
]
Then set values in your controller on the go using:
config(['gmail.project_id' => $project_id]);
and retrieve the values using:
config('gmail.project_id');

zf3 change locale depending on user selection

I have Zend Framework 3 Application with working translator using po files.
I have configured it like this in my \config\global.php file:
'translator' => [
'locale' => 'en_US',
'translation_file_patterns' => [
[
'type' => 'gettext',
'base_dir' => getcwd() . '/data/language/',
'pattern' => '/%s/general.mo',
],
],
],
When i change the value of the "locale" it works ok and finds the proper .po file.
I need to be able to set the locale depending on a user profile's value saved in the database.
I have checked the documentation from here http://zendframework.github.io/zend-i18n/translation/ and the tutorial from here https://docs.zendframework.com/tutorials/i18n/ but they just mention the setLocale() method with no explanation or example. There is similar thread here Zend framework 2 : How to set locale globaly? but it's for ZF2 and it doesn't provide working solution just some suggestions.
To summarize my question - how and where should i use the setLocale() method so it would be effective in the whole application and $this->translate($message) in all view files will use the new locale instead the default one used in the configuration file?
You just need to set the PHP locale. To do so, use \Locale::setDefault('en-GB');.
Have a look at SlmLocale, this specific file is where it's done.
While that was the easiest way, you could also use the setLocale function on the MvcTranslator I guess. For that, you would need to override the existing factory with your own factory, therefore decorating the original one.
If you look at the ConfigProvider file in zend-mvc-i18n, you can see that aliases and factories are used here to create the MVC translator. Then you can see how the factory in question works, it basically creates a decorate translator, as stated in the doc.
By default, the service manager always provide the same instance (shared service), just like a singleton.
What we will therefore do is override this configuration (ie. make sure your own module is after the Zend\Mvc\I18n in modules.config.php). Then, in the module configuration, we can provide our own translator.
Our translator basically consist of the translator from the documentation, on which the setLocale is called. In order to do so, we can use a delegator.
return [
'factories' => [
TranslatorInterface::class => TranslatorServiceFactory::class,
],
'delegators' => [
TranslatorInterface::class => [
\Application\Factory\TranslatorFactory::class,
],
],
];
And then the TranslatorFactory:
use Interop\Container\ContainerInterface;
use Zend\ServiceManager\Factory\DelegatorFactoryInterface;
class TranslatorFactory implements DelegatorFactoryInterface
{
public function __invoke(ContainerInterface $container, $name, callable $callback, array $options = null)
{
$translator = call_user_func($callback);
$translator->setLocale('en-GB');
return $translator;
}
}
That would be one way to do it (you get the container in that factory, so you could get some user data probably).
Another solution is to use the event system, and only declare the locale in the event listener where you retrieve your user details.

Yii2 make a path alias from information stored in DB

Right now I'm trying to implement themming for my Yii2 based project.
How I see the thing now:
User chooses an application theme from the list on the settings
page in backend.
Using yii2-settings I'm saving all the
configuration data in DB (pretty easy).
In the application
bootstrap.php I'm creating new alias called #theme. Basically it
should lead us to a application theme base path (used in search
paths, assets manager, e.t.c.).
According to official
documentation, that's how I configured my view component:
'view' => [
'theme' => [
'basePath' => '#theme',
'baseUrl' => '#theme',
'pathMap' => [
'#app/views' => '#theme',
'#app/widgets' => '#theme/widgets',
'#app/modules' => '#theme/modules',
],
],
],
An issue I have is with p.3. According to yii2-settings documentation that's how I supposed to read the settings:
$theme = Yii::$app->settings->get('name', 'general');
Yii::setAlias('#theme', realpath(dirname(__FILE__)."/../../themes/$theme"));
But obviously, it's not working for me because of yii2-settings component didn't initialized yet when bootstrap.php is called. I've been trying to initialize it later in the init() method of my base controller, then adjust other aliases manually, but I feel that way being somewhat 'unclean', and also it still fails because of #theme alias is also used in asset file which is Yii2 starting to publish before calling the controller's init method.
So does anyone has any thoughts of how to do that 'hacking' the code as less as possible? I know I could just move configuration to some file, then read it manually before the application initialization, but it's still not the way I want to go.
Maybe there's some way to override some system component to set the alias after db component is loaded, but before view component configuration? Or Yii loads this components in a different order? Anyway. Any help would be appreciated!
You could try an Application Event in bootstrap:
\Yii::$app->on(\yii\base\Application::EVENT_BEFORE_REQUEST, function ($event) {
$theme = Yii::$app->settings->get('name', 'general');
Yii::setAlias('#theme', realpath(dirname(__FILE__)."/../../themes/$theme"));
});
OR in configuration file:
[
'on beforeRequest' => function ($event) {
// ...
},
]
From Yii 2 docs:
EVENT_BEFORE_REQUEST This event is triggered before an application
handles a request. The actual event name is beforeRequest.
When this event is triggered, the application instance has been
configured and initialized. So it is a good place to insert your
custom code via the event mechanism to intercept the request handling
process. For example, in the event handler, you may dynamically set
the yii\base\Application::$language property based on some parameters.
Here's the final solution:
config/bootstrap.php:
// Setting a temporary path for components configuration - will be changed later
Yii::setAlias('#theme', realpath(dirname(__FILE__)."/../../themes/"));
config/main.php
'components' => [
'view' => [
'theme' => [
'basePath' => '#theme',
'baseUrl' => '#theme',
'pathMap' => [
'#app/views' => '#theme',
'#app/widgets' => '#theme/widgets',
'#app/modules' => '#theme/modules',
],
],
],
],
'on beforeRequest' => function ($event) {
$theme = Yii::$app->settings->get('theme', 'general');
Yii::setAlias('#theme', realpath(dirname(__FILE__)."/../../themes/$theme"));
},

Receive white screen when adding guards to bjyauthorize

I'm new to ZF2 and bjyauthorize - so in a way hoping this is a silly mistake on my part :D
I have setup the ZF2 skeleton app and zfcUser successfully and am trying to add bjyAuthorize to the mix. I am also using the Zend/Db connection type to mySQL - NOT DOCTRINE (:D). The versions I am using are PHP(5.5), ZF2(2.3.*), zfcUser(1.2.1), bjyAuthorize(1.4.0).
I have followed the instructions found to the letter in the GitHub Readme. It didn't take me long to realise that the example "bjyauthorize.global.php" file there contains way too many settings (as examples) and also has an incorrect field reference under "\BjyAuthorize\Provider\Role\ZendDb::class" ("role_id" s/b "roleid").
Basically, as soon as I uncomment either the route based or controller based guards in my config file (i don't intend to do both - just want one working) I get a white screen - no error message to be helpful - when trying to access my skeleton apps home page. I'm worried this is therefore a PHP syntax error on my part.
I have also included ZendDeveloperTools and not even the tool bar on the footer appears when I get this error.
Here is my config file:
<?php
return [
'bjyauthorize' => [
// set the 'guest' role as default (must be defined in a role provider)
'default_role' => 'guest',
/* this module uses a meta-role that inherits from any roles that should
* be applied to the active user. the identity provider tells us which
* roles the "identity role" should inherit from.
*
* for ZfcUser, this will be your default identity provider
*/
'identity_provider' => \BjyAuthorize\Provider\Identity\ZfcUserZendDb::class,
/* role providers simply provide a list of roles that should be inserted
* into the Zend\Acl instance. the module comes with two providers, one
* to specify roles in a config file and one to load roles using a
* Zend\Db adapter.
*/
'role_providers' => [
// this will load roles from the user_role table in a database
// format: user_role(role_id(varchar], parent(varchar))
\BjyAuthorize\Provider\Role\ZendDb::class => [
'table' => 'user_role',
'identifier_field_name' => 'id',
'role_id_field' => 'roleid',
'parent_role_field' => 'parent_id',
],
],
/* Currently, only controller and route guards exist
*
* Consider enabling either the controller or the route guard depending on your needs.
*/
'guards' => [
/* If this guard is specified here (i.e. it is enabled], it will block
* access to all controllers and actions unless they are specified here.
* You may omit the 'action' index to allow access to the entire controller
*/
// \BjyAuthorize\Guard\Controller::class => [
// ['controller' => 'zfcuser', 'roles' => ['guest']],
// ['controller' => ['Application\Controller\Index'], 'roles' => ['guest']],
// ],
// /* If this guard is specified here (i.e. it is enabled], it will block
// * access to all routes unless they are specified here.
// */
// \BjyAuthorize\Guard\Route::class => [
// ['route' => 'zfcuser', 'roles' => ['user']],
// ['route' => 'zfcuser/logout', 'roles' => ['user']],
// ['route' => 'zfcuser/login', 'roles' => ['guest']],
// ['route' => 'zfcuser/register', 'roles' => ['guest']],
// // Below is the default index action used by the ZendSkeletonApplication
// ['route' => 'home', 'roles' => ['guest', 'user']],
// ],
],
],
];
When I run as coded above without guards, I can login through site/user/login and the Zend Dev ToolBar shows me the correct role for that user. So that is at least positive.
Happy to provide any further info or settings - just trying to learn.
OK, so I feel quite silly now.
The DB schema that bjyauthorize ships with has the field "roleId" - in my code above I didn't take into account case sensitivity and had "roleid". Changed that and everything works perfectly.

Lithium all rows in cookies, session

Currently after login Lithium stores in session and cookies all rows from users table like password, hash etc. How to remove (don't allow to store) some of the information like password and hash?
The Session class stores what you tell it to! After Auth::check is done, you should only store the session identifier and/or absolutely necessary data in the cookie. Also make sure to use the Encryption provided by lithium (AES) out of the box.
For more detailed help, please post your login controller and all appropriate model/filters.
Passing options to Auth::check will get passed down to the adapter as well (plus some extras) -- for this I'm assuming you're using the Form adapter for the Auth class.
Try doing this when you perform your check: Auth::check('config', $data, array('fields' => array('fields', 'you', 'want'))
The key here is that array we tacked on the end with the fields key in it, this will be passed down to the Form adapter which takes in those options and uses them to query your model for a matching user. By telling it explicitly which fields to return, it will only pass those back to the Auth class for storing away.
Since this commit you can pass an option 'persist' => array('field1','..') to Auth::check, or set them as default in your bootstrap session config, to store only specified fields.
So either you set this in your bootstrap/session.php
Auth::config(array(
'user' => array(
'adapter' => 'Form',
'session' => array(
'persist' => array('_id','username')
),
'model' => 'Users'
)
));
or you define the fields, when calling Auth::check() - this will override everything from the config above!
Auth::check('user', $this->request, array(
'persist' => array('username','email')
))
Note: If not defined explicitly the password is never stored by default.

Categories