Question: How do I enable the Routes from my component's router.php in a plugin?
I'm working on a custom Plugin which redirects the route from default user profile:
index.php?option=com_users&view=profile (SEF: /component/users/profile)
to my own component where I've got additional settings
index.php?option=com_mycomponent&view=profile (SEF: /alias/profile)
my front-end plugin:
class plgSystemMyPlugin extends JPlugin
{
// constructor
function plgSystemMyPlugin( &$subject, $params ) {
parent::__construct( $subject, $params );
}
// run after the framework has loaded and the application initialize method has been called
function onAfterInitialise() {
// when component users and view profile are called
if( isset($_GET['option'], $_GET['view'])
&& $_GET['option'] == 'com_users'
&& $_GET['view'] == 'profile' )
{
$route = JRoute::_('index.php?option=com_mycomponent&view=profile' );
JFactory::getApplication()->redirect($route, null, null, true);
}
}
}
In my component all links are routed correctly ie:
index.php?option=com_mycomponent&view=profile => /alias/profile
in the plugin JRoute translates it as follows:
index.php?option=com_mycomponent&view=profile => /component/mycomponent/profile
can not use:
core hacks
.htaccess
Joomla Redirect Plugin
in the plugin xml file you should add new parameter that will allow you to choose the desired Itemid(menuitem)
so it should look like this
<param name="menuitem" name="my_itemid" title="Target Itemid" description=""/>
Then you will need to choose desired menuitem that has the alias that you wanted from the plugin parameters in the administrator area
then in the plugin itself just use like this:
$route = JRoute::_('index.php?Itemid='.$this->params->get('my_itemid') );
and this is valid too
$route = JRoute::_('index.php?option=com_mycomponent&view=profile&Itemid='.$this->params->get('my_itemid') );
Related
I wanted to change the pages 'register user', 'change password' and 'user edit'.
This is not possible in the Drupal frontend, and you also have to pay a lot of attention in the code.
In forums you will usually find little help and if then rather not
satisfactory.
Therefore, I like to share my solution to save the one or other headache.
The three forms are already available from Drupal standard, if you want to change them you have to access the route and redirect.
For this you first create a module like 'my_forms'.
Second the form or a page that you want to hook into the website. e.g.
'ForgotPasswordForm'
Create a folder inside your my_forms 'Routing' and a file like 'RouteSubscriber.php'
code:
<?php
namespace Drupal\my_forms\Routing;
class RouteSubscriber extends RouteSubscriberBase{
protected function alterRoutes( RouteCollection $collection ){
//enter code here
}
}
Now you can change the route to the diffrent pages by adding following -
code:
//edit the 'forgot password' page
if ( $route = $collection->get( 'user.pass' ) ){
$route->setDefault( '_form', '\Drupal\my_forms\Form\ForgotPasswordForm' );
}
The keyword 'user.pass' allows you to change the routing. setDefault redirects the route to your own form.
//edit the 'register' page
if ( $route = $collection->get( 'user.register' ) )
{
$route->setDefaults( array(
'_title' => 'Register',
'_controller' => '\Drupal\myy_forms\Controller\LocalTaskController::offerRegistrationPage'
)
);
}
The keyword for the registration is 'user.register'. By setting the route with setDefaults you can also change the name of the link/button. In this case I used a controller to print out a normal page inside the registration. (more at the end of the post)
if ( $route = $collection->get( 'entity.user.edit_form' ) ){
//enter code here
}
For the 'user edit' page you need to use the keyword 'entity.user.edit_form'.
Last step is to clear your cashes, to register the changes in your Drupal website and refresh your page.
Load simple page with a Drupal Controller:
namespace Drupal\my_forms\Controller;
class LocalTaskController extends ControllerBase{
/** #var NodeStorage $nodeStorage */
protected $nodeStorage;
/** #var EntityViewBuilder $viewBuilder */
protected $viewBuilder;
function __construct( $nodeStorage, $viewBuilder )
{
$this->nodeStorage = $nodeStorage;
$this->viewBuilder = $viewBuilder;
}
public static function create( ContainerInterface $container )
{
$nodeStorage = $container->get( 'entity.manager' )->getStorage( 'node' );
$viewBuilder = $container->get( 'entity_type.manager' )->getViewBuilder( 'node' );
return new static( $nodeStorage, $viewBuilder );
}
public function offerRegistrationPage()
{
$node = $this->nodeStorage->load( 24 );
$renderArray = $this->viewBuilder->view( $node );
return [
'#type' => '#markup',
'#markup' => render( $renderArray ),
];
}
The '24' is the nid of the simple page, which should be displayed instead of the standard registration.
I have a application where after update user should be redirected to previous page from pagination.
let's say there is a gridview and user is at page 3. Then he update some record at that page. There should be a redirect to index page 3. What if, while user is updating record, before save, he opens another controller/action in new tab. Then ReturnUrl is now that new action and after save the record he is updating, he is redirected to that new url.
I've tried to set in every action "index" Url::remember(); and then in action "update" - return $this->goBack().
Also return $this->redirect(Yii::$app->request->referrer);, but it stays at same page.
There is a way to store every index URL in session, but in large project that means many sessions.
You could provide the returnUrl to the link, say:
Url::to(['update','id'=>$model->url,'returnUrl'=> Yii::$app->request->url]);
Then in your controller, use $this->request->queryParams['returnUrl'] to redirect to the previousUrl.
To take it one step further, to always provide the returnUrl, you could extend the Url Helper class:
namespace app\helpers;
use yii\helpers;
class Url extends yii\helpers\Url
public function toRouteAndReturn($route, array $params = [], $scheme = false) {
$params['returnUrl'] = Yii::$app->request->url;
return parent::toRoute($route,$params,$scheme);
}
You could provide in your main config:
'on afterAction' => function($event) {
if(!Yii::$app->getResponse()->isSent && !empty(Yii::$app->getRequest()->queryParams['returnUrl']) {
Yii::$app->getResponse()->redirect(Yii::$app->getRequest()->queryParams['returnUrl']);
}
}
Then you could use app\helpers\Url::toRouteAndReturn() instead of yii\helpers\Url::toRoute() to have it return to the previous url.
You can try below Solution.
First in your index page, get current page url and encode it.
$current_url=base64_encode(\Yii::$app->request->getUrl());
Append this url with your update link as below.
'urlCreator' => function ($action, $model, $key, $index) use ($current_url) {
if ($action === 'update') {
$url = Yii::$app->request->baseUrl . '/controllerName/update?id=' . $model->id.'&prev='.$current_url;
return $url;
}
// ......
}
In Controller, in Update method decode url as below and use for redirection.
public function actionUpdate($id)
{
$model = $this->findModel($id);
$prev=base64_decode($_REQUEST['prev']);
// ......
return $this->redirect($prev); // you will redirect from where update method is called
// ......
}
Isn't it quite easy to pass page param into your update url (<model/update>) like <model>/update?id=<id>&page=<page>?
in your index.php view, edit your ActionColumn as follow:
[
'class' => 'yii\grid\ActionColumn',
'urlCreator' => function ($action, $model, $key, $index) {
return \yii\helpers\Url::to([$action, 'id' => $model->id, 'page' => Yii::$app->request->getQueryParam('page', null)]);
},
],
As you can see, I'm getting page param from request url and pass it to models' action buttons
And when you click to update model, the page that we entered from is stored/placed in url.
Controller:
public function actionUpdate($id, $page = null)
{
$model = $this->findModel($id);
...
if($model->save()) {
return $this->redirect(['index', 'page' => $page]);
}
...
}
Finally, after we successfully update the model, the action redirects us to previous index page.
I'm working on a system where we want to queue up a batch of emails and then send them using a queue (so I can't use \Zend\Mail directly). The goal is to not have HTML inside the models that are creating the emails but instead have them in a view file. I'm trying to call the partial view helper inside the models (which I did in ZF1) but can't find anything on the web on how to do this. Is this possible in ZF2 or is there a better way? I've managed it before where we've had the HTML inside the models and it's been a mess. :-)
You can just create a template somewhere, pull the renderer from your service locator, and render away:
<?php
// this assumes you're in some AbstractActionController,
// but you could be in some service class that has the
// renderer injected, etc.
// template vars
$vars = array(/* .... */);
// create a ViewModel
$vm = new \Zend\View\Model\ViewModel($vars);
// path to your email template, compatible with your template map config.
$tpl = 'mymodule/emails/some-email-template.phtml';
$vm->setTemplate($tpl);
// get the renderer from the ServiceManager, so it's all nicely configured.
$renderer = $this->getServiceLocator()->get('Zend\View\Renderer\RendererInterface');
// render some HTML
$html = $renderer->render($vm);
You could do it this way:
1. In the module.config define those HTML mail content template views.
'view_manager' => array(
(...)
'template_map' => array(
'mail_content_1' => __DIR__ . '/../view/<MODULE_NAME>/mail_content_1.phtml',
),
(...)
)
2. Load the Template View in your model and get the HTML.
use Zend\View\Model\ViewModel;
public function getMailHTML() {
$view = new ViewModel;
$variables = array( "parm1" => "value1" );
//SET THE VARIABLES, LIKE IN PARTIALS
$view->setVariables( $variables );
//SET THE TEMPLATE VIEW KEY DEFINED IN THE module.config
$view->setTemplate( 'mail_content_1' );
//YOU'LL HAVE TO BE ABLE TO USE THE ServiceManager IN YOUR MAIL MODELS.
//RENDERING THE VIEW YOU'LL GET THE HTML
return $this->serviceManager->get( 'viewrenderer' )->render( $view );
}
By default you have the following URL-syntax in ZF: /module/controller/action. What i want, is to build an menu-system where i can use any URL I want.
Lets say I make an menu-item called 'news'. When i call http://www.site.com/news i want to have the folowing loaded:
module: news
controller: frontpage
action: display
These config-values must be configured in the database-record for the menu-item.
How can I do this in zend? I spend a lot of time searching for it, but I still can't figure out how to. Does anybody?
I'd suggest using a front controller plugin to scan your database for all the entries, create routing rules based on those entries and add them to the router (see this).
Of course caching strategy is recommended so that you don't do a lot of processing on every request.
You can create a plugin and in routeStartup define something that intercept your request and route /module/controller/action to /action, but for this all your action names must be unique :
class My_CustomRouterPlugin extends Zend_Controller_Plugin_Abstract
{
public function routeStartup(Zend_Controller_Request_Abstract $request)
{
$fc = Zend_Controller_Front::getInstance();
$action =$fc->getRequest()->getActionName();
$router = $fc->getRouter();
$model= new myModel();
$myPage = $model->getPageByAction($action);
$route = new Zend_Controller_Router_Route('/action', array(
'module' => $myPage->getModule();
'controller' => $myPage->getController();
'action' => $action;
));
$router->addRoute($action, $route);
return $router;
}
}
In myModel define a method can get you an object(or an array) that contains module, controller names (from you DB ).
and register this plugin in your bootstrap:
$front->registerPlugin(new My_CustomRouterPlugin());
I am using sessions in zend framework.
the question is i need to know is there a difference between
new Zend_Session_Namespace("default");
and
new Zend_Session_Namespace("Default");
in my application, I have used both, it seems the code is not working correctly,
if there is a difference, what is the correct one to use.
here is my code
<?php
class Admin_DashboardController extends Zend_Controller_Action
{
function init()
{
//
}
/**
* Add hotelId to default session
* redirect to admin/hotels if hotelId is not avialble
*/
public function indexAction()
{
$params = $this->getRequest()->getParams();
$hotelid = NULL;
$config_session = new Zend_Session_Namespace("default");
$config_session->hotelid = $params['id'];
if(isset($params['id']) && !empty($params['id'])){
}else{
//redirect user to select hotels page
$redirector = new Zend_Controller_Action_Helper_Redirector();
$url = array(
'action' => 'admin/hotels/index'
);
$redirector->gotoRouteAndExit($url);
}
}
}
All Zend_Session_Namespace does internally is create a named array inside the $_SESSION superglobal. As array keys in PHP are case sensitive, "Default" and "default" will be treated as separate namespaces.
You can use whichever one you want, just be consistent if you expect to use the same data.