Access Protected Method from Plugin Cakephp [duplicate] - php

This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
Fatal error: Call to undefined method CookieComponent::del()
I am creating a plugin that uses a login method from my SiteUsers controller, but I am getting the error message:
Call to undefined method SiteUsersController::_doLogIn()
Plugin Site Users Controller:
class SiteUsersController extends AppController {
public $name = 'SiteUsers';
/**
* login_competition
*
*/
public function login_challenge() {
$this->autoRender = false;
if (!$this->_doLogIn($this->request->data['SiteUser'])) {
$this->Session->setFlash('ERROR');
}
}
$this->redirect('/');
}
}
Site User Controller in main App
class SiteUsersController extends AppController {
public $name = 'SiteUsers';
/**
* _doLogIn()
*
* #param unknown_type $data
* #return string|string
*/
protected function _doLogIn($data) {
$this->_user = $this->SiteUser->getUserByEmailPassword(Sanitize::clean($data));
if (!empty($this->_user)) {
$this->Session->Write('SiteUser.id', $this->_user['SiteUser']['id']);
$this->Session->Write('SiteUser.first_name', $this->_user['SiteUser']['first_name']);
$this->Session->Write('SiteUser.username', $this->_user['SiteUser']['username']);
return true;
}
return false;
}
}

I would suggest you to move your _doLogIn into component. That way you don't have to make it public and users won't get to it directly through browser and it will be available to all controllers.
Current _doLogIn could be rewritten to use new components method so sitewide there is no big deal if it is used widely.
Just in case ;) http://book.cakephp.org/2.0/en/controllers/components.html

Related

Decorating Shopware6 api controller for saves pluginreader data to entity

After installing the plugin and editing the available fields in the configuration, I would like to save these fields to my entity.
so I created the Config class to make the field getter from the plugin configuration like:
class Config
{
public const SYSTEM_CONFIG_DOMAIN = 'myEntity.config.';
/** #var SystemConfigService $systemConfigService */
protected static $systemConfigService;
public function __construct(SystemConfigService $systemConfigService)
{
self::$systemConfigService = $systemConfigService;
}
}
public static function message(): string
{
return (string)self::$systemConfigService->get(self::SYSTEM_CONFIG_DOMAIN . 'message');
}
I found such a controller in platforms:
/**
* #Route("/api/v{version}/_action/system-config/batch", name="api.action.core.save.system-config.batch", methods={"POST"})
*/
public function batchSaveConfiguration(Request $request): JsonResponse
{
foreach ($request->request->all() as $salesChannelId => $kvs) {
if ($salesChannelId === 'null') {
$salesChannelId = null;
}
$this->saveKeyValues($salesChannelId, $kvs);
}
//save to my entity here
return new JsonResponse([$request->request->all()]);
}
And in this controller I would like to add my message from pluginConfig to my entity.
Is this a good idea and how can I thank it? Could I ask for more code than usual because I'm just learning sw6?
If you just want to add data to your plugin configuration you should use a config installer instead of a controller.

How to access a global service function within a twig extension using Symfony?

I'd like to have a global function which is available in all controllers as well as in a twig extension.
The function currently looks like this:
namespace Symfony\Bundle\FrameworkBundle\Controller;
class BaseController extends Controller {
/**
* Check if the user is assigned to one of the given airlines
*
* #param Array $airlines
*
* #return boolean
*/
public function HAS_AIRLINE(Array $airlines) {
if ($airlines == null)
return false;
// Get current user
$user = $this->get('security.context')->getToken()->getUser();
foreach ($airlines as $airline) {
if($user->hasAirline($airline))
return true;
}
return false;
}
I implemented this function into the BaseController.php, so I can use it in all other controllers. This works perfectly fine so far.
Now I want to use this function in a twig extension as well, but I don't know how. I do have the following function in my twig extension:
/*
* Check if the current user has one of the given roles by using the function provided by the base controller
*/
public function hasAirline($airlines= Array())
{
if($airlines == null)
return false;
// How can I now use the function from my BaseController?
return HAS_AIRLINE($airlines);
}
I already tried to define the BaseController as a service and use the service in the twig extension, but I couldn't manage that.
Could someone please help me? I feel like there is something I did not understand about Symfony yet, but the docs do not really help me.
Thank you,
MRE
You can move the logic in your User entity:
class User
{
public function hasAirline($airlines)
{
foreach ($airlines as $airline)
{
if ($this->getAirlines()->contains($airline))
{
return true;
}
}
return false;
}
}
This will work if getAirlines() return an ArrayCollection from Doctrine2, this allow the use of the contains() method.
Then you can use this in the controller:
public function HAS_AIRLINE(Array $airlines) {
return $this->get('security.context')->getToken()->getUser()
->hasAirline($airlines);
}
Or in Twig with app.user:
{{ set hasAirline = app.user.hasAirline(airlines) }}

yii2 correct application architecture (pass data to layout)

i need to send data from controllers to main layout (something like notifier of a new messages in top menu) i need it in all app(global)
i found one way to to pass variables to layout
Yii::$app->controller->myvar
from class property to layout, but i think it's not best way to duplicate code to all controllers, maybe i suppose to extend base Controller and set my logic here?
Tell me please the best practice to do what i want.
ps. Tnx and sorry for my English
In the controller, you can use
$this->view->params['name'] = 123
and in the layout
<?= $this->params['name'] ?>
1) You can use yii global app params
Yii::$app->params['foo'] = 'bar'; // controller
and
echo Yii::$app->params['foo']; // in view/layout/controllers/elsewhere
2) You can use session. Create a controller, that will be extended by others, with these 3 functions:
<?php
namespace common\components;
use Yii;
use yii\web\Controller;
class BaseController extends Controller
{
/**
* Set user flash notice
* #param $message
* #return mixed
*/
public function setFlash($key, $message){
return Yii::$app->session->setFlash($key, $message);
}
/**
* Has user flash notice
* #param $message
* #return mixed
*/
public function hasFlash($key){
if(Yii::$app->session->hasFlash($key)) return True;
else return false;
}
/**
* Get user flash notice
* #param $message
* #return mixed
*/
public function getFlash($key){
return Yii::$app->session->getFlash($key);
}
}
now in your controllers
use common\components\BaseController;
...
class MyController extends BaseController
...
$this->setFlash('foo','bar'); // setting flash var
and in your views
echo $this->context->getFlash('foo'); // getting flash var
or
echo Yii::$app->controller->getFlash('foo'); // getting flash var
The below line add in config\main.php
'user'=>array( 'class'=>'WebUser', // enable cookie-based authentication 'allowAutoLogin'=>true, ),
After that create new file in protected\components\WebUser.php, In this WebUser.php file
class WebUser extends CWebUser
{
private $_model;
function Update()
{
return $this->myvar='this is my variable';
}
}
You can access in layout file like this echo Yii::app()->user->update();

Laravel ioc automatic resolution - works from controller but not from custom class

Namespaces omitted for brevity...
I have written the following service provider and registered in config/app.php:
class OfferServiceProvider extends ServiceProvider
{
public function register()
{
$this->registerLossControlManager();
}
protected function registerLossControlManager()
{
$this->app->bind('LossControlInterface', 'LossControl');
}
}
Here is my LossControlInterface
interface LossControlInterface
{
/**
* #param int $demandId
* #param float $offerTotal
* #param float $productTotal
* #param null|int $partnerId
* #return mixed
*/
public function make($demandId, $offerTotal, $productTotal, $partnerId = null);
/**
* #return float
*/
public function getAcceptableLoss();
/**
* #return bool
*/
public function isAcceptable();
/**
* #return bool
*/
public function isUnacceptable();
/**
* #return null
*/
public function reject();
}
Now within the controller, I can inject the LossController as follows:
use LossControlInterface as LossControl;
class HomeController extends BaseController {
public function __construct(LossControl $lossControl)
{
$this->lossControl = $lossControl;
}
public function getLossThresholds()
{
$lossControl = $this->lossControl->make(985, 1000, null);
var_dump('Acceptable Loss: ' . $lossControl->getAcceptableLoss());
var_dump('Actual Loss: ' . $lossControl->calculateLoss());
var_dump('Acceptable? ' . $lossControl->isAcceptable());
}
}
However if I try to dependency inject the LossControlInterface from within a custom class called by a command:
[2014-09-02 13:09:52] development.ERROR: exception 'ErrorException' with message 'Argument 11 passed to Offer::__construct() must be an instance of LossControlInterface, none given, called in /home/vagrant/Code/.../ProcessOffer.php on line 44 and defined' in /home/vagrant/Code/.../Offer.php:79
It appears as though I am unable to dependency inject the interface into a custom class, but I can when dependency injecting into a controller.
Any thoughts on what Im doing wrong or have omitted to get the automatic resolution working?
The IoC is automatic within controllers, and you don't see the injection because Laravel handles the construction of controllers for you. When creating any other custom class by using the new keyword, you will still need to send in all of the parameters needed to it's constructor:
$myClass = new ClassWithDependency( app()->make('Dependency') );
You can hide this, to a degree, by funneling creation of your custom class through a service provider:
// Your service provider
public function register()
{
$this->app->bind('ClassWithDependency', function($app) {
return new ClassWithDependency( $app->make('Dependency') );
});
}
Then just have the IoC make it whenever you need it:
$myClass = app()->make('ClassWithDepenency');
In your case, you can change your code to look like this:
private function setOffer(Offer $offer = null) {
$this->processOffer = $offer ?:
new Offer( app()->make('LossControlInterface') );
}
A perhaps cleaner approach could be to create a service provider and an OfferFactory which gets injected into your controller. The controller can then request the factory to create the offer whenever it needs one:
// Controller
public function __construct(OfferFactory $offerFactory)
{
$this->offerFactory = $offerFactory;
}
public function setOffer(Offer $offer = null)
{
$this->processOffer = $offer ?: $this->offerFactory->createOffer();
}
// OfferFactory
class OfferFactory
{
public function createOffer()
{
return app()->make('Offer');
}
}
This has the benefit of completely decoupling your controller from the logic behind the creation of the offer, yet allowing you to have a spot to add any amount of complexity necessary to the process of creating offers.
In Laravel 5.2 the simplest solution for your particular problem would be to replace
new Offer();
with
App::make('Offer');
or even shorter
app('Offer');
which will use Laravel Container to take care of dependencies.
If however you want to pass additional parameters to the Offer constructor it is necessary to bind it in your service provider
App::bind('Offer', function($app, $args) {
return new Offer($app->make('LossControl'), $args);
});
And voila, now you can write
app('Offer', [123, 456]);
In laravel 5.4 (https://github.com/laravel/framework/pull/18271) you need to use the new makeWith method of the IoC container.
App::makeWith( 'App\MyNameSpace\MyClass', [ $id ] );
if you still use 5.3 or below, the above answers will work.

Zend Framework url redirect

<?php
class PI_Controller_Plugin_AssetGrabber extends Zend_Controller_Plugin_Abstract
{
public function dispatchLoopStartup(Zend_Controller_Request_Abstract $request)
{
/*
The module name
*/
$moduleName = $request->getModuleName();
/*
This modules requires the user to be loggedin in order to see the web pages!
*/
$loginRequiredModules = array('admin');
if (in_array($moduleName,$loginRequiredModules)) {
$adminLogin = new Zend_Session_Namespace('adminLogin');
if (!isset($adminLogin->loggedin)) {
/*--------------------------------------
Here I want to redirect the user
*/
$this->_redirect('/something');
}
}
}
}
I'm trying to do a redirect $this->_redirect('/something') but doesn't work! Do you know how can I do a redirect in this case?
Best Regards,
... rest of code
if (!isset($adminLogin->loggedin)) {
$baseUrl = new Zend_View_Helper_BaseUrl();
$this->getResponse()->setRedirect($baseUrl->baseUrl().'/something');
}
... rest of code
<?php
class AlternativeController extends Zend_Controller_Action
{
/**
* Redirector - defined for code completion
*
* #var Zend_Controller_Action_Helper_Redirector
*/
protected $_redirector = null;
public function init()
{
$this->_redirector = $this->_helper->getHelper('Redirector');
}
public function myAction()
{
/* Some Awesome Code */
$this->redirector('targetAction', 'targetController');
return; //Never reached!
}
}
You need to get the redirector helper, then you can define the targetAction and targetController with the redirector. That should do it.
Either use Zend_Controller_Action_HelperBroker to get the redirect helper or do the redirect directly from the Request object.
See the examples given in
Redirect in Front Controller plugin Zend

Categories