Drupal8.x and Symfony Developing Minding BC on Upgrades – Ajax Core Component: Part III Series

Screenshot 2014-05-24 05.02.33

So today I grabbed the Ajax core component. At first it seemed daunting because I did not know what I was going to find in so many flat directory structure. But after a bit of analysis I discovered that the many XCommand classes were really very simple implementations of a commond XCommandInterface. So the first thing I did was to move all those classes into a Command directory. These commands have nothing to do with the Command classes as we know them from Symfony.

Let me explain. It seems like in Drupal the requirement to communicate via JSON responses and in particular Ajax responses needed to be standardized. Drupal needs this because on this bus for ajax communications all other moving parts that are ajax related on the front end will revolve their actions. These actions are called commands, and it is pretty much information useful on the front side, possibly used by the javascript that runs on the front end.

So the ajax system, as we call it, comprises of many JavaScript libraries that are served and then the hub or bus for communications that is server side and therefore have to have a type of container or standard place where to put information and where to read information when doing JSON communications, that is request and responses that pertain to dynamic calls from the client.

In this ajax system, the part in PHP, server side, and that pertain to the Ajax core component, there are only 4 moving pieces namely: the AjaxResponse, the AjaxResponseRenderer, an AjaxSubscriber, and the Commands.

AjaxResponse is an extension of the Symfony’s JsonResponse where the commands are computed, rendered with the Drupal inner renderer functions that deal with arrays and the part that is still not OO, but that is wrapped, so that we can end up with a JsonResponse object that has a drupalized-array-of-commands payload on the JsonResponse.

The extension of the JsonResponse breaks the BC promise from Symfony in that it overrides a public method on a non api class. I did the PR to drupal here https://drupal.org/node/2273717 and filed an issue in Symfony asking for workarounds here https://github.com/symfony/symfony/issues/10985.

// AjaxResponse extends JsonResponse
<?php
  /**
   * {@inheritdoc}
   *
   * Sets the response's data to be the array of AJAX commands.
   */
  public function prepare(Request $request) {
    $this->prepareResponse($request);
    return $this;
  }
 
  /**
   * Sets the rendered AJAX right before the response is prepared.
   *
   * @param \Symfony\Component\HttpFoundation\Request $request
   *   The request object.
   */
  public function prepareResponse(Request $request) {
    if ($this->data == '{}') {
      $this->setData($this->ajaxRender($request));
    }
  }

We will see what happens. For certain at least there may have been a need to replug that call to the parent::prepare($request) that was missing. If not well the refactor of the tests seemed to me reasonable and also the folder organization. Drupal still have some ugly organization, think of flat folder structure and you get a pretty good picture. Another nuance regarding this is that digging inside let’s you see that there are 2 layers, one where it is all OO and the other where the drupal_x calls are still creeping in.

I have found some tickets that were opened and discussed but then closed and nothing was done. There were good chances to refactor and remove those calls but there seems to be a lack of interest in getting rid completely of these hooks and array manipulation. The array manipulations obscure the parts of the class where they are cornered. Even in the tests, you have to see these &getCommand ampersands just to, and I don’t know the real reason, to have access to an internal array inside the class. This is poor OO and it is a crutch on the side of the Drupal developers that they probably need to deal with. This causes impacts on every side though, tests that are not optimal, thereby violating the principles of closed classes or unit testing.

The next element is the AjaxResponseRenderer, it basically builds an AjaxResponse by calling conditionally and adding some specific commands, and then calling the monster of drupal_render to convert these commands further into the payload to send inside the AjaxResponse. Nothing to see here, just the render command and well what I have explained above.

The AjaxSubscriber is a bit interesting, it lacks a test, so I don’t know what is its use case, however it seems to set the format of an incoming Request. This is weird as it sets drupal fields that relate to application/vnd.drupal-x, maybe to ensure by forcing these into every incoming request for a specific call pattern. Smells like a workaround and not a robust solution.

Then comes the Commands, there is a diverse selection of commands and use cases. From adding some css into the page, adding more markup, setting dialogs, modals, invoking some js, etc. There are commands for that, you name it!

So that is it for this component. I hope you have had fun reading this, I stayed a bit late just to get this out.

Please think about supporting me. Thank you and mind I am doing this all with a lot of excitement and passion for developing.

undeservedly doing this with joy, your friend @cordoval

Leave a Reply

Your email address will not be published. Required fields are marked *