Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RFC] Custom backend routes #512

Merged
merged 18 commits into from Jan 24, 2017
Merged

[RFC] Custom backend routes #512

merged 18 commits into from Jan 24, 2017

Conversation

sheeep
Copy link
Member

@sheeep sheeep commented Jun 2, 2016

One of the problems when developing custom applications with a CMS part is the fact that you'll end up using two different backends. The one for your application and the one for the Contao part. Having a possibility to uniform these two would help application developer to create an application backend rapidly as they could use all sort of already existing stuff; like form templates, error messages, log viewer and the like. Currently the Contao backend is optimised for DCA views (even though it certainly allows for custom backend views, eg. Isotope). This pull request enables you to easily create custom backend views and feed them data from Symfony controllers.

This is a PoC and RFC. So comment away.

Problems

  • The CustomBackendViewListener is used to append the controller response to the backend templates' main attribute. But this should not be done if it is not a custom backend route. Otherwise the base template will be loaded twice. This is why there is a new request parameter _custom_backend_view. Could be named better.
  • There is currently no way to overwrite the headline attribute of the base template to set a custom title. This needs to be fixed somehow. (Same goes for <title></title>)
  • TL_SCRIPT is always set to the current _route. This is not /contao anymore when using a custom backend route. One place where this failed was in the navigation method of the BackendUser, where the list of linked modules was built. It previously relied on TL_SCRIPT which I briefly replaced with a $router->generate call. Are there any other places you could think of where this could be a problem?

How to test this

In order to create a backend route, create a standard controller and add the following parameters to the Route annotation (you could also configure this in a YML/XML file)

  • _custom_backend_view: This parameters distinguishes custom from already exsting backend calls.
  • _backend_module: Not necessarily needed, but we determine the active backend module through this.
// src/AppBundle/Controller/BackendController.php
namespace AppBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;

/**
 * @Route("/contao", defaults={
 *     "_scope" = "backend",
 *     "_token_check" = true,
 *     "_custom_backend_view" = true,
 *     "_backend_module" = "test"
 * })
 */
class BackendController extends Controller
{
    /**
     * @Route("/test", name="backend.test")
     * @Template("AppBundle::test.html.twig")
     */
    public function testAction()
    {
        return [
            'content' => 'Content'
        ];
    }
}

For reference: Here is the test template.

{# src/AppBundle/Resources/views/test.html.twig #}
{% extends "@ContaoCore/Backend/be_page.html.twig" %}

{% block panel %}
    Panel
{% endblock %}

{% block errors %}
    An error occured
{% endblock %}

{% block content %}
    {{ content }}
{% endblock %}

Create a backend module and insert it to the list of active backend modules. The previously added parameter _backend_module is now used to determine if the module is active or not.

// src/AppBundle/EventListener/UserNavigationListener.php
namespace AppBundle\EventListener;

use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Routing\RouterInterface;

class UserNavigationListener
{
    protected $requestStack;
    protected $router;

    public function __construct(RequestStack $requestStack, RouterInterface $router)
    {
        $this->requestStack = $requestStack;
        $this->router = $router;
    }

    public function onGetUserNavigation($arrModules, $blnShowAll)
    {
        $arrModules['content']['modules']['test'] = [
            'title' => 'A backend route test module',
            'label' => 'Test',
            'class' => 'navigation test',
            'href'  => $this->router->generate('backend.test')
        ];

        if ($this->requestStack->getCurrentRequest()->attributes->get('_backend_module') === 'test') {
            $arrModules['content']['modules']['test']['class'] .= ' active';
        }

        return $arrModules;
    }
}

Add it as a service and enable it to be executed by the Hook.

# app/config/config.yml
services:
    app.user_navigation_listener:
        class: "AppBundle\\EventListener\\UserNavigationListener"
        arguments:
            - "@request_stack"
            - "@router"
// src/AppBundle/Resources/contao/config/config.php
$GLOBALS['TL_HOOKS']['getUserNavigation'][] = ['app.user_navigation_listener', 'onGetUserNavigation'];

The whole thing looks like this in the end.

screen shot 2016-06-02 at 15 02 18

@aschempp
Copy link
Member

aschempp commented Jun 2, 2016

You should take a look at #444 that uses a Symfony controller to render a Contao backend view.

@leofeyer
Copy link
Member

leofeyer commented Jun 3, 2016

I like the PR. We should definitely discuss the open topics and the implementation details at the next core meeting.

@leofeyer
Copy link
Member

@sheeep What's the status on this one?

@discordier
Copy link
Contributor

Current implementation is at a different branch: https://github.com/sheeep/core-bundle/commits/features/refactor-backend-modules
It depends on https://github.com/sheeep/core-bundle/issues/1, where we wrote the TODO list.

@leofeyer leofeyer changed the title [RFC] Custom backend routes [WIP] Custom backend routes Oct 20, 2016
@sheeep
Copy link
Member Author

sheeep commented Jan 23, 2017

Since 3c06d92 the supported blocks changed. A current example of a backend view template would look like this:

{% extends "@ContaoCore/Backend/be_page.html.twig" %}

{% block headline %}
    Not only the content of the `title`-tag but also the title of the content section.
{% endblock %}

{% block error %}
    Will be placed within the error block.
{% endblock %}

{% block main %}
    Main Content.
{% endblock %}

Also, you don't need to specify a backend route with the route attribute custom_backend_route = true anymore.

This implementation gets rid of the route attribute 'custom_backend_view = true'.
It introduces a new twig function to wrap specific content blocks with the be_main
template of the Contao backend. This way is more intuitive and a less explicit approach.
@leofeyer leofeyer added this to the 4.4.0 milestone Jan 23, 2017
@@ -202,3 +202,13 @@ services:
- "_contao_fe_attributes"
calls:
- ["setName", ["contao_frontend"]]

contao.twig.base_template_wrapper:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be contao.twig.base_template_extension?

@leofeyer leofeyer changed the title [WIP] Custom backend routes [RFC] Custom backend routes Jan 24, 2017
@leofeyer leofeyer merged commit 33be460 into contao:develop Jan 24, 2017
@leofeyer
Copy link
Member

Big thanks @sheeep!

*/
public function renderContaoBackendTemplate(array $blocks = [])
{
$scope = $this->requestStack->getCurrentRequest()->attributes->get('_scope');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should use the ScopeMatcher service instead

agoat pushed a commit to agoat/contao-core-bundle that referenced this pull request Apr 10, 2017
* Make Symfony 3.2 the minimum requirement (see contao#630).

* Set the encryption key from the kernel secret by default (see contao#660).

* Stop using the deprecated QuestionHelper::setInputStream() method.

* Update Dropzone to version 4.

* Prefer the caret operator over the tilde operator in the composer.json file.

* Add the contao.root_dir parameter (see contao#662).

* Update the change log.

* Stop using the contao-components/all meta package.

* Update the README.md file.

* Deprecate the contao:version command (see contao#668).

* Update the installation path.

* Auto-select the active page in the quick navigation/link module (see contao/core#8587).

* Look up the form class and allow to choose the type (see contao/core#8527).

* Add PHP Toolbox support (see contao#565).

* Remove the arrow brackets in the book navigation template (see contao/core#8607).

* Add a bottom padding to the buttons layer.

* Add the contao.web_dir parameter (see contao/installation-bundle#40).

* Fix the tests.

* Match security firewall based on request scope (see contao#677).

* Fix an issue found by Scrutinizer.

* Use the contao.web_dir parameter in the Combiner (see contao#679).

* Fix the tests.

* Add stripRootDir() method to System class (see contao#683).

* Add the contao.image.target_dir parameter (see contao#684).

* The ContaoCoreExtension::overwriteImageTargetDir() is not deprecated.

* Support custom backend routes (see contao#512).

* Use the scope matcher instead of checking the request attribute (see contao#688).

* Replace every occurrence of $contaoFramework with $framework.

* Fix an issue found by Scrutinizer.

* Fix deprecations in unit tests (see contao#687).

* Added a DBAL field type for UUIDs (see contao#415).

* Support importing form field options from a CSV field (see contao#444).

* Fix the coding style and the unit tests.

* Add the Doctrine field type in the config.yml file.

doctrine:
    dbal:
        types:
            binary_string:
                class: "Contao\\CoreBundle\\Doctrine\\DBAL\\Types\\BinaryStringType"
                commented: true

* Add a basic unit test for the BackendCsvImportController class.

* Update the change log.

* Fix rebuilding the search index (see contao#689).

* Also handle „no origin“ and „empty origin“ in the CORS provider.

* Remove an unused use statement.

* Remove the security.yml file and update the README.md file.

* Improve the e-mail extraction in the text element (thanks to Martin Auswöger).

* Rename the Test namespace to Tests.

* Update the composer.json file.

* Update the .php_cs file.

* Raise the minimum PHP version to 5.6 (see contao#701).

* Support using objects in callback arrays (see contao#699).

* Use try-finally blocks to close all output buffers when downloading a file (see contao#714).

* Fix the coding style.

* Only prefix an all numeric alias when standardizing (see contao#707).

* Adjust the test namespaces.

* Allow to manually pass a value to any widget (see contao#674).

* Add a change log entry and fix the tests.

* Disable the picker buttons if the main window does not show a picker.

* Use the file manager instead of the file picker.

* Use the site structure instead of the page picker.

* Always show the selected nodes.

* Add the menu builder.
@fritzmg
Copy link
Contributor

fritzmg commented Aug 1, 2018

Question: do I need to set the _locale manually within a custom back end controller? I have a custom back end route where I use the translator, e.g.

$framework = $this->get('contao.framework');
$framework->initialize();
$translator = $this->get('translator');
$goBack = $translator->trans('MSC.goBack', [], 'contao_default');

However, some users report that they do not see any translations. They only see MSC.goBack in this example. Thus I am wondering if may be simply the _locale is missing from the request.

@ausi
Copy link
Member

ausi commented Aug 1, 2018

This seems weird. The Contao translator uses $GLOBALS['TL_LANGUAGE'] and always falls back to en. At least the english message should be shown in all cases.

@fritzmg
Copy link
Contributor

fritzmg commented Aug 1, 2018

Yeah I thought so as well. Also I cannot reproduce it locally.

@dmolineus
Copy link
Contributor

dmolineus commented Aug 2, 2018

However, some users report that they do not see any translations.

@fritzmg Hint: The integrated contao translator is a Contao 4.5 feature. I experienced the missing labels on Contao 4.4 LTS.

There are some backports available, f.e. as part of https://github.com/contao-community-alliance/translator

@fritzmg
Copy link
Contributor

fritzmg commented Aug 2, 2018

Oh, haha. I did not know that :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants