How to override template/view of SilverStripe's User Defined Form - silverstripe

I am developing a simple SilverStripe project for learning purpose. I am using SilverStripe User Defined Form module to create form pages.
The way the user defined form module renders the form in the template/ view is using the $UserDefinedForm variable in the content field. Now, I need to do some customization to the built-in User Defined Form template. So I decided to override the controller and page.
This is my EventPage
<?php
namespace {
use SilverStripe\UserForms\Model\UserDefinedForm;
class EventPage extends UserDefinedForm
{
}
}
This is my EventPageController
<?php
namespace {
use SilverStripe\UserForms\Control\UserDefinedFormController;
class EventPageController extends UserDefinedFormController
{
}
}
This is my EventPage.ss
<h1>Event Page</h1>
$UserDefinedForm
This page is overridden, but the form is not rendered. How can I render the form?

A complete answer might help.
ContactPage.php
namespace InsiteApps\CMS\Model {
use SilverStripe\UserForms\Control\UserDefinedFormController;
use SilverStripe\UserForms\Model\UserDefinedForm;
class ContactPage extends UserDefinedForm
{
private static $table_name = 'ContactPage';
}
class ContactPageController extends UserDefinedFormController
{
}
}
In your theme, templates folder (the folder structure is dependant on your namespace)
templates/InsiteApps/CMS/Model/Layout/ContactPage.ss
<div class="contact-page-form">
$Form
</div>

Related

Sonata Admin Class : add KnpMenu links pointing Admin class with custom route

Using SonataAdminBundle with Symfony2, I'm looking for a solution to access some Admin classes with a specific route.
For example, I have a ContractAdmin class with boolean fields such as "Enabled".
What I would like is to add in the left KnpMenu of sonata admin, some links pointing to the same Admin class but with a custom route (other than the default "list" route), for example:
Contracts
All Contracts
Contracts enabled (Listing only enabled contract)
Contracts not yet enabled (Listing only not enabled contract)
This would avoid me to use filters.
So, how could I create and put these links to the menu which target the corresponding admin class controller with a custom route?
Thank you ;)
I've solved it declaring a custom CRUDController for this admin class and adding the actions needed calling listAction method :
class ContractAdminController extends Controller {
public function contractsEnabledAction() {
return $this->listAction();
}
I've declared this custom route into the Admin class :
protected function configureRoutes(RouteCollection $collection) {
parent::configureRoutes($collection);
$collection->add('contracts_enabled', 'contractsEnabled/');
}
Then, overriding the createQuery method in the admin class, I'm using the request "_route" attribute like that :
public function createQuery($context = 'list') {
$query = parent::createQuery($context);
switch ($this->getRequest()->get("_route")) {
case "admin_acme_contract_contracts_enabled" :
$query->andWhere(
$query->expr()->eq($query->getRootAliases()[0] . '.enabled', ':param')
);
$query->setParameter('param', true);
break;
}
return $query;
}

Get data in twig function

Is it bad practice to get data from db in twig function or I should pass it to view in controller?
My function is some kind of interface widget that is used on all pages of site admin section. Then on data change I will have to make changes in all actions. But when I get data directly in extension class our teamlead tells that it's bad MVC.
It would be best if you pass it to a view from a controller.
Your team leader is right. What you can do is create an action specific to render that widget. I.e create a custom widget, let's say you want to show the number of current active users:
class WidgetController extends Controller
{
public function usersCountWidgetAction()
{
return $this->render('widget/usersCount.html.twig', array(
"usersCount" => $this->getUsersCount();
));
}
public function getUsersCount()
{
// call the manager and get the result
}
}
Now in all your other twigs you can use
{{ render(controller('AppBundle:Widget:usersCountWidget')) }}

Different Twig-Layout for Authentication in special controller?

I open a modal with an iFrame, which serve restriced pages of a special controller. So, when I'm not logged in, the iFrame redirects to the general login-route, which actually extends the standard-layout file.
Now, what I want to achieve is, that if the the user isn't logged in and opens up the modal, the login/registration page should extend a different layout (without navigation bar etc.).
So, how can I set a different layout for the authentication views, only if the user is redirected to it through the modal? Any advice?
Thanks!
I would pass along a request parameter from the IFrame, to let the controller know that the request came from the modal, e.g. path/to/your/page?ref=modal-iframe:
Then in the controller I would check if the request parameter is present and correct or the user is logged in. In that case you go on outputing your template, otherwise redirect to the general login route.
use Symfony\Component\HttpFoundation\Request;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class MyController extends Controller
{
/*
* #Template("YourBundle:User:login_registration.html.twig")
*/
public function myAction(Request $request)
{
$securityContext = $this->container->get('security.context');
if (($request->get('ref') && $request->get('ref') == 'modal-iframe') ||
$securityContext->isGranted('IS_AUTHENTICATED_REMEMBERED')) {
return array();
}
else {
return new RedirectResponse($this->generateUrl('login'));
}
}
}
The template would then take care of loading the correct layout, depending on whether the user is logged in or not:
{% extends (app.user ? "layout1.html" : "layout2.html") %}

How can I render a controller action within a twig extension?

I do have a twig extension which has a method that uses another method from a different controller to render a json output via dependency jsonResponse.
How can I render a controller within a twig extension?
The following code below doesn't seem to work, because render() needs a view file instead of a controller. And I am now referencing to a controller.
class AreaExtension extends \Twig_Extension {
public function add()
{
$outputJson = $this->container->get('templating')->render(new ControllerReference('CMSCoreBundle:Area:index'));
}
}
$ref = new ControllerReference('CMSCoreBundle:Area:index');
$this->handler->render( $ref, 'inline', $options );
Where $this->handler is the fragment.handler service.
In your case:
$outputJson = $this->container->get('fragment.handler')->render(new ControllerReference('CMSCoreBundle:Area:index'));
You can find a full example in this symfony twig extension, see:
https://github.com/symfony/symfony/blob/4.1/src/Symfony/Bridge/Twig/Extension/HttpKernelExtension.php#L28
and
https://github.com/symfony/symfony/blob/4.1/src/Symfony/Bridge/Twig/Extension/HttpKernelRuntime.php#L41

Symfony2 FOSUserBundle login form styling

I already have register form styled (I changed some widgets by adding fields.html.twig and load it globally) but the styles won't be applied to login form elements, as the html tags are rendered here directly, not using Symfony's helpers. Should I rewrite FOS Security controller to get the form variable or something?
Currently the SecurityController:renderLogin action doesn't return a variable containing a FormView instance.
The form's HTML code (and therefore the classes you could use for styling) is hardcoded into the login template.
You have the following two options for overriding the template containing the HTML code.
1) override the template in app/Resources/FOSUserBundle
You can simply override the template FosUserBundle:Security:login.html.twig by putting a login.html.twig into the folder
app/Resources/FOSUserBundle/views/Security/
Just make sure you include ...
{% extends "FOSUserBundle::layout.html.twig" %}
... in your newly created template.
2) override the template using bundle inheritance
Another way of overriding the template would be using bundle inheritance.
Therefore you would create a new bundle that extends FOSUserBundle by returning 'FOSUserBundle' in it's getParent() method.
class ExtendingBundle extends Bundle
{
public function getParent()
{
return 'FOSUserBundle';
}
}
Don't forget to register the bundle in app/AppKernel.php.
Now you can store your new login.html.twig template at
src\Vendor\ExtendingBundle\Resources\views\login.html.twig
documentation
Read more about template inheritance in the documentation.

Resources